npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ucsd-decorator-kit

v2.4.0

Published

Agent-facing contract for building on the UC San Diego Decorator 5 design system.

Readme

UCSD Decorator Kit

The official agent-facing contract for building on the UC San Diego Decorator 5 design system.

Getting started

Building a new UC San Diego site with an AI agent:

mkdir my-site && cd my-site
npx ucsd-decorator-kit@latest init

To run an unreleased change — or if the registry is unreachable — every command on this page also works straight from the repository, which is what CI uses:

npx -y github:UCSD/decorator-kit init

That runs whatever is on main at the time, released or not, so use it to try a change, not to set up a site.

That installs ucsd-decorator-v5 — the Decorator itself — plus this kit, writes the rules in the format each AI tool reads, installs the skill, wires Dependabot and a CI workflow, and — for Claude Code — adds a Stop hook that runs the chrome integrity gate after every turn. It runs in the background and only speaks up if it finds a regression: see "Running it automatically".

Then open Claude Code, Cursor, Copilot or Antigravity in that directory and describe the site you want. There is nothing to point the tool at: the rule files sit at the project root, which is where all of them already look, and they name node_modules/ucsd-decorator-v5/dist/ as the source of truth for markup.

The agent will ask which layout to start from rather than picking one. That is deliberate — choosing a template unasked is exactly the class of decision this kit exists to prevent.

Not sure what it should look like? Say "help me get started"

If you know what the app has to do but not how it should look, tell your agent:

help me get started

Instead of writing markup, the agent interviews you first — six questions in one message, each with lettered options, so you can reply 1b, 2 students checking waitlists, 3b…:

  1. What are you building — an information site, a request or application form, a dashboard, a directory or admin tool, a knowledge base?
  2. Who uses it, and what is the one thing they must be able to do?
  3. Which campus area — advising, enrollment, research, housing, IT, facilities, library, HR?
  4. How will it be built and hosted — static HTML, a JavaScript framework, server-rendered templates, Cascade CMS?
  5. What data does it touch — public only, campus sign-in, student or personal records?
  6. The site name, and a short form for phones.

From your answers it recommends a layout and the modules and patterns to use, each linked to its card in the Decorator Kit Developer Guide so you can see it first. You pick the layout; the agent writes a BRIEF.md at the project root with the plan, then builds a first version from it inside the canvas, runs verify, and suggests next prompts. Later sessions read BRIEF.md before changing the page.

It works in Claude Code, Cursor, Copilot, and any agent that reads AGENTS.md, because the interview is a rule — rules/60-getting-started.md — compiled into every instruction file, with its full text in DECORATOR.md. For a chat AI with no kit installed, such as TritonGPT, paste the Starter interview prompt from the guide's Start here section instead.

Skip it when you already know the template, the page name, and the pieces you want: the agent only asks for what your request leaves out.

Already have a project

npx ucsd-decorator-kit add

add installs the rules and the skill and touches nothing else. It does not modify package.json, does not add CI, and never writes AGENTS.md — that filename is also the convention for a repository's own agent contract, and yours is the more specific document. Pass --with-decorator to add the Decorator dependency, --with-ci for the Dependabot config and workflow, --with-hook for the Claude Code Stop hook. The last one merges into an existing .claude/settings.json rather than overwriting it, so a project's own hooks and permissions survive.

Each of those three flags also adds ucsd-decorator-kit as a devDependency, at the version you ran, along with the decorator:* npm scripts. The workflow and the hook run the kit from node_modules, and without it installed they have nothing to run. A project that already lists the kit keeps its version.

Staying current

| Command | Does | |---|---| | npx ucsd-decorator-kit sync | rewrite the generated files after a kit upgrade | | npx ucsd-decorator-kit check | fail if they are stale — wire this into CI | | npx ucsd-decorator-kit drift | report whether the Decorator moved upstream | | npx ucsd-decorator-kit verify | run the chrome integrity gate against this project's actual markup — wire this into CI too |

Both ucsd-decorator-v5 and ucsd-decorator-kit are devDependencies, so Dependabot opens a pull request when either moves: the Decorator and the rules update through one mechanism. With the kit installed, npx ucsd-decorator-kit runs that installed copy. Without it, npx downloads the newest release on every run, so the kit version changes whenever a release ships, not when you upgrade. check fails the build if a kit upgrade landed without a sync, so a project cannot quietly run last year's rules.

drift covers the gap Dependabot cannot see — a push to UCSD/Decorator or a cdn.ucsd.edu deploy with no npm release.

Project canvas rules

A project will have rules of its own: house components, content conventions, how it loads data. Put them in canvas-rules/ at the project root, one Markdown file per topic. init and add create the directory with a README that explains it.

npx ucsd-decorator-kit sync

sync compiles every *.md file there, in filename order, into a "Project canvas rules" section at the end of CLAUDE.md, .cursorrules, .github/copilot-instructions.md, and AGENTS.md where the kit manages it. It skips the README. Every tool picks the rules up the same way it picks up the kit's, and check fails in CI if a file there changed without a sync.

Those files load in full in every session, so keep a canvas rule to what must hold every time. sync and check print a note when a project's rules push CLAUDE.md past 40,000 characters, the size at which Claude Code warns that it will impact performance.

The compiled section limits those rules to the canvas and ranks them below the kit's own. A rule file that anyone can add is not a review, so a chrome instruction in one gets refused rather than followed, just like a chrome request made in chat.

Component libraries

A canvas that needs more than the Decorator's own components gets them from canvas-components/: shadcn/ui, a charting library, web components. Give each library its own folder, holding the files the page loads and a README.md saying when and how to use it.

canvas-components/
  shadcn/
    README.md      compiled into DECORATOR.md by sync
    dist/app.css
    dist/app.js

sync lists each library in a "Project component libraries" section of the rule files, and compiles its README into DECORATOR.md, where agents read it before using the library. That section relaxes three Decorator look-and-feel rules inside the canvas: agents may use the library's components and classes, its icon set, and its heading styles. Typography stays on brand (Roboto, Teko, Brix Sans, or Refrigerator Deluxe), and no chrome, accessibility, or security rule relaxes.

A library's own CSS is the usual way one leaks into the shell, so verify holds canvas-components/ to a stricter standard than other site CSS. It scans minified files there too. It fails on any selector that names no class, id, or attribute (*, body, h1), unless the rule sets only custom properties. The README that init and add write into the folder covers the setup that keeps a library inside the canvas: no global reset, prefixed class names, and popups rendered inside the canvas.

check and verify answer different questions and are easy to conflate: check is about whether this kit's generated rule files are current, verify is about whether the project's built chrome is still correct. verify needs nothing this CLI doesn't already give it — node checks/chrome-contract.mjs --check works standalone, with --accept and --explain alongside it. See checks/README.md.

Where markup comes from

ucsd-decorator-v5 on npm is the source of truth. Decorator-V5.zip is not, despite being the download the documentation links to: measured 2026-08, the archive is behind the package on every file it ships, and its scripts/base.min.js is a January 2023 build missing the runtime behavior that governs the mobile drawer search. See references/distribution.md.

The problem this solves

The Decorator shell is identical on every page of a site. That is the point of it, and it is also why agent-authored changes to it are dangerous: a shell edit propagates to every page at once, and it usually propagates away from the campus standard rather than toward it.

Two real regressions motivated this kit:

  • An agent deleted the mobile drawer's search form and replaced it with a link to the search page. Visually near-identical; functionally it drops the scope selector and the typed query and submits nothing to the hosted search API.
  • An agent altered an embedded campus widget after reading the DOM it renders into.

Both happened under rules that already said "do not modify the header, nav, or footer." Prose was not the missing piece.

Three more reached production after the markup gate was live, and none of them changed a tag: site CSS rebuilt the drawer search, #chat-bubble { … !important } reshaped the TritonGPT launcher, and site JS deleted an id the Decorator assigns at runtime and styles the mobile drawer search through. A markup contract cannot see any of that, which is why there is a fourth tier.

What actually prevents it

Three things, in order of how much they matter.

1. A source of truth that is a file, not a rendered page. The rules tell agents to fetch official documentation — but that documentation is itself Decorator pages wrapped in chrome, so an agent following the rules faithfully still ends up reconstructing markup from a DOM. Worse, Jasny Bootstrap clones the offcanvas drawer into the body at runtime, so a live DOM contains navigation markup that exists in no file at all. Pin the templates; read from disk.

2. A named canvas. One writable region per project. Everything else is chrome, declared as a selector list that lives outside the markup it protects. In-file <!-- DO NOT EDIT --> markers do not work — the agent you are defending against can delete them too.

3. A gate that fails the build, with an interlock. Four tiers:

| Tier | Asks | Escape hatch | |---|---|---| | chrome/consistent/* | do all routes agree? | none needed | | chrome/golden/* | does chrome match the recorded contract? | --accept, after a human reads the diff | | chrome/structure/* | is it still a search form? | none | | chrome/styling/* | does site CSS or JS reach into the shell? | none — a reviewed exception with an expiry date |

This is not a design to go implement — it ships, as checks/chrome-contract.mjs and checks/lib/, reading contracts/. npx ucsd-decorator-kit verify runs it.

Tier 3 is the load-bearing one. When one shell feeds every route, a shell edit is perfectly consistent drift — tier 1 stays green. Tier 2 fails, but its remedy says "accept if intentional," and an agent that believes its own change is intentional will do exactly that, rebaselining the regression. So --accept refuses to write while tier 3 fails. That refusal is the design.

Tier 4 exists because tiers 1–3 all read markup, and the shell can be wrecked without touching any. Its protected token set is derived per run — every class and id inside a chrome region and nowhere inside the canvas — so it tracks the Decorator instead of a list someone has to remember to update. --accept refuses while it fails too, for a different reason: the markup is intact, so regenerating the golden would hide the finding rather than resolve it.

Contents

bin/cli.mjs                  init / add / sync / check / drift / verify
rules/                       canonical rule source
skills/ucsd-decorator/       the skill — SKILL.md plus references
library/                     Skills Library publishing staging (see below)
templates/                   Dependabot config, workflow, and the canvas-rules/
                             and canvas-components/ READMEs written into projects
scripts/lib/rules.mjs        the renderer, shared by the CLI and the compiler
scripts/compile-rules.mjs    rules/ -> CLAUDE.md, AGENTS.md, .cursorrules,
                             .github/copilot-instructions.md, DECORATOR.md
scripts/check-library.mjs    validates library/ against the sync contract
scripts/pin-decorator.mjs    dependency-free Decorator pinning, npm only
contracts/                   portable chrome regions, selector rules, and
                             styling policy — each with a JSON schema
checks/                      the chrome integrity gate: chrome-contract.mjs
                             (CLI) and lib/ (tiers 1-4) — runs standalone,
                             `bin/cli.mjs verify` is a thin wrapper around it
test/                        including the AGENTS.md refusal, the replayed
                             chrome-regression incidents, and an install of
                             the packed tarball
RELEASING.md                 how a version reaches npm

CLAUDE.md, AGENTS.md, .cursorrules, .github/copilot-instructions.md, and DECORATOR.md are generated. Edit rules/ and run:

node scripts/compile-rules.mjs

--check verifies the committed output is current; npm test runs it along with the library contract and the CLI tests.

What loads every session, and what loads on demand

Claude Code loads all of CLAUDE.md at the start of every session and warns once it passes 40,000 characters, and an @ import would not help, since an imported file loads at launch too. So the four rule files hold only what must hold in every session. Detail that one kind of task needs, such as measurements, tables, or a procedure, goes below a marker in its section of rules/:

<!-- on-demand: before you copy `two-column.html` or `three-column.html` -->

The rule files keep what sits above the marker and, in place of the rest, a line telling the agent to read that section in full in DECORATOR.md before that task. DECORATOR.md gets the whole section, and nothing imports it. A marker above a rule's first section moves the rest of that rule. Write the trigger as the task, starting "before you" or "when". test/rules.test.mjs holds the compiled CLAUDE.md to 25,000 characters, leaving a project's canvas rules room under the warning. Past that, move detail behind a marker rather than raise the budget.

Using the skill without the CLI

Claude Code — install as a plugin (/plugin marketplace add UCSD/decorator-kit), or copy skills/ucsd-decorator/ into a project's .claude/skills/.

Cursor, Copilot, Antigravity — the compiled instruction files are picked up automatically once present at the project root, with DECORATOR.md beside them.

Any tool that reads AGENTS.md — read this repository's copy in place, in a checkout beside your project, along with the DECORATOR.md it points to. Do not copy it in: your repository's own AGENTS.md, if it has one, is the more specific contract and the more important of the two. add will not write that file for the same reason.

Publishing to the TritonAI Skills Library

The public page at https://tritonai.ucsd.edu/skills/index.html is generated from a Skills Library repository, synced by tritonai-website and rendered from content/skills/library.json. Only paths matching <collection>/<name>/SKILL.md are read — nothing deeper.

Do not put this repository inside the Skills Library. The sync only reads <collection>/<name>/SKILL.md and nothing deeper, so a kit dropped at tritonai/ucsd-decorator-kit/ would leave the skill at .../skills/ucsd-decorator/SKILL.md — two levels too deep, and invisible. The kit is the upstream source; the Skills Library is one of its distribution channels, alongside the Claude Code plugin and the generated IDE rule files.

library/ holds the publish-ready shape:

library/tritonai/ucsd-decorator/SKILL.md   + references/  (published from skills/)
library/tritonai/ucsd-branding/SKILL.md    retirement pointer

library/tritonai/ucsd-decorator/ is a published copy of skills/ucsd-decorator/. Regenerate it with npm run sync:library; check:library fails if the two have drifted, because a hand-maintained duplicate is the same failure mode this kit exists to prevent.

ucsd-branding is the skill this one replaces. It is reduced to a pointer rather than deleted, so anyone already invoking that slug is told where it went instead of silently loading guidance that routes agents into rendered chrome.

Validate before publishing:

npm run check:library

It enforces exactly what the sync enforces — path shape, non-empty name and description, name matching the directory, maintainer on community skills, no duplicate names, and no nested SKILL.md files that would be silently ignored.

Copy library/tritonai/* into the Skills Library repository to publish.

The chrome integrity gate

npx ucsd-decorator-kit verify runs it against this project — four tiers, described above, reading nothing but files on disk. It needs no CLI, either: node checks/chrome-contract.mjs --check is the same thing, standalone, and checks/ ships inside the installed package. See checks/README.md for the full design, what's portable versus project-owned, and tier 4's CSS/JS scanning in detail.

tritonai-website runs its own, separately maintained implementation of this same four-tier design at 54-route scale — the project this engine was modeled on, not a consumer of it. It does not depend on this package; nothing here reads from or writes to that repository.

Related