Your AI can write the UI. This makes sure it writes your UI. A scanner that scores your repo's design system 0 to 100, names the places where an agent will have to guess, writes the rules that teach it, and checks every edit it makes.
Run it at the root of a UI repo. About a second later a self-contained HTML report opens. No account, no network, no telemetry, nothing in your repo is changed. MIT.
An agent builds UI the way a new hire does on their first day: it looks around the repo and copies what it finds. We measured that on 10 real open-source products, in 355 agent sessions, with and without this tool. On everyday work the agent reused the components and values that were there and stayed on-system. It went off-system in the places where the repo had no answer to copy: a chart in a codebase with no chart palette, a theme in a codebase with no named surfaces. In each case it made the values up and hardcoded them.
Findings in 24 runs, without and with the plugin. Haiku 4.5 asked for a chart and a new component on 4 products. October 2026, roast 10.1.
Sonnet 5, same tasks. 5 of the 7 that remained were chart colours in a repo with no chart palette. The agent kept them and wrote a comment saying why.
A Christmas theme across 10 products. Findings added without and with this tool. September 2026.
| Task | Model | When | Without roast | Roast MCP and rules | Roast plugin with its edit hook |
|---|---|---|---|---|---|
| A new chart and a new component, 4 products, 3 runs each | Sonnet 5 | Oct 2026 | 21 in 24 runs | not run | 7 in 24 runs |
| A new chart and a new component, 4 products, 3 runs each | Haiku 4.5 | Oct 2026 | 72 in 24 runs | not run | 1 in 24 runs |
| Add a panel, build a dashboard, tighten a list (80 sessions) | Sonnet 5 | Sept 2026 | 7 | 9 | not run |
| A Christmas theme, 10 products | Sonnet 5 | Sept 2026 | 28 | 2 | not run |
| A new chart, 4 products, 5 runs each | Sonnet 5 | Sept 2026 | 10 in 20 runs | not run | 0 in 20 runs |
| A new chart, 4 products | Haiku 4.5 | Sept 2026 | 25 | 39 | 0 in 14 of 15 runs |
| Chart, status colour, empty state, new component | Haiku 4.5 | Sept 2026 | 42 in 16 runs | 49 in 16 runs | 3 in 51 runs |
Routine work stayed on-system with or without the tool. Work that needed something new did not. An agent does not always call a tool when it should: in October, Sonnet called the MCP tools in 7 of 24 sessions and Haiku in 2 of 24. The edit hook runs without being asked. That is the column with the lowest numbers.
Where did the agent invent? Where the repo had nothing to copy. Dub has no chart palette; its own charts hardcode 17 colours. Asked for a chart, Haiku hardcoded 9 more. So the mess an agent adds is a map of the gaps in your system. This tool draws the map.
Claude Code, headless, on 10 public products pinned to one commit each: cal.com, Dub, Metabase, Plausible, SigNoz, trigger.dev and four more. Every changed file was judged by this tool's rules at the end of the session and at the pinned commit. A finding counts only if the session added it. Nothing was rendered: zero findings means the code follows these rules, not that the design was reviewed. Method, tables and limits are in the research write-up, to be published separately.
One scan, one score, every finding with its file path, and the first fixes ranked by what they are worth.
Generated rules in every agent file you have, and a local MCP server that answers "is there a Button already?" from the code as it is right now.
An edit hook hands back only the findings an edit added. When the agent says it is done, a last review sends it back once if a problem it added is still there.
Every number in the report comes from a deterministic read of your files, the same numbers every run. Where an AI reads the scan for you, its text is labelled as written by AI and kept apart from the measurements.
The report opens with that question and answers it first: the places where the repo has no answer yet, with the files that prove each one and the single move that closes it, or "No gaps found". One gap is known for certain today, because the agent runs found it: charts that paint their colours by hand in a repo with no chart palette. Across 126 public repos, 43 look like that. The list grows only when a gap has been measured.
0 to 100, the same number every run, measured against three yardsticks: the ideal norms of a design system, the median of the 34 product repos at the core of a 119-repo benchmark, and 10 reputable systems (Primer, Polaris, Carbon, shadcn/ui and others). Monorepos get a score per package, so the tidy UI library stops hiding the messy app.
A list derived from your own numbers: what was found, where, why it matters, what to change, and what each move is worth to the score. Every move carries a copy button with a ready-made fix prompt for your agent. Fix, rescan, press the next button.
Every colour and its near-identical twin, every off-scale spacing value, typeface, duplicated or never-imported component, inline style block and !important. The colour usage bar shows where the colour comes from: theme names, Tailwind's palette, or strays written by hand. The adoption map draws your real system to scale, every component sized by its import count.
A generated design-system-rules.md with the canonical components, the file that holds your colour, spacing and type values, and the known duplicates to avoid. One flag writes it into every agent file you have: Claude, Cursor, GitHub Copilot and Windsurf. Every scan also checks the rules you already have for stale references.
The report is a single self-contained HTML page with a light and dark toggle built in. Claude's read of your scan is embedded as "What the repo teaches the agent", labelled as written by AI. The score alone can flatter; that section keeps a shared 85/100 honest.
Hosted exactly as the tool writes them. Every number deterministic, every path real.
Requires Node 18 or newer. Nothing else is installed, and nothing leaves your machine.
The scan and the report, from any terminal. Add --apply to write the agent rules into every agent file you have, --check to review what changed, --mcp to run it as a local MCP server.
npx roast-my-design-system@latest
Two skills, one local MCP server and two checks that run on their own. roast scans the whole repo and walks the fixes with you. review checks only what changed, in about a second. The edit hook runs after every file the agent touches; the end-of-turn review sends it back once if it left a problem behind.
/plugin marketplace add gregkozakiewicz/roast-my-design-system /plugin install roast-my-design-system@roast-my-design-system
One skill, no hooks, no server, no scripts inside the plugin: it runs the published scanner from npm when you ask for a roast. Built for the plugin directories. Same roast, same report, same rules file; the live guard stays with the full plugin.
/plugin marketplace add gregkozakiewicz/roast-my-design-system-skill /plugin install roast-my-design-system@roast-my-design-system-skill
codex plugin marketplace add gregkozakiewicz/roast-my-design-system-skill codex plugin add roast-my-design-system@roast-my-design-system-skill
The same engine as a local MCP server: five read-only tools the agent calls while it writes UI, from "is there a Button already?" to "review my changes". Verified end to end in Claude Code, Cursor and Windsurf (now Devin Desktop).
claude mcp add roast -- npx roast-my-design-system@latest --mcp
Cursor: put { "mcpServers": { "roast": { "command": "npx", "args": ["roast-my-design-system", "--mcp"] } } } in the project's .cursor/mcp.json. Windsurf's config is global, so add the repo path as a third argument to keep the scan to one repo.
Roast my design system.
How bad is my CSS? Scan this repo and show me the receipts.
Is there already a Button component in this repo, and which one should I use?
Review my UI changes against the design system.
The report and the rules file describe the repo as it was at scan time. The MCP server keeps the same engine running while your agent works, so questions get answered from the code as it is right now, and mistakes get caught before they land. One real exchange against Unleash, an MUI product at 60/100. The agent has a grey in hand and a padding in mind. Every answer is the server's own text, unedited.
Nearest token: #607d8b, 11 channel steps from #6b7280. Unless the difference is a deliberate decision, use the token.
2 findings: ✕ L5 Colour #6b7280 written onto an MUI component, and the theme has no such colour. Fix: Add it to the theme once (frontend/src/themes/dark-theme.ts), then read it there: color: 'text.secondary' in sx. ✕ L5 Pixel size p: 12px on an MUI component. Fix: 12px is between steps 1 (8px) and 2 (16px) on the default theme. Keep it with a comment, or use the nearest step in sx.
color: 'text.secondary' and p: 1.5. roast_validate again:No measured violations found. Checked: hardcoded colours vs the token set, near-identical colour twins, off-scale spacing, off-scale radii, font sizes and shadows, typefaces outside the system, arbitrary bracket values, static inline style blocks, !important, duplicate component definitions, chart colours against the chart palette, colours and pixel sizes written onto kit components where the theme has a value.
Four calls, under 800 tokens, and the new component reads the theme instead of adding colour number 44. Where a repo has charts but no palette, a new chart that paints by hand gets one warning naming the existing chart that does the same and asking for the palette once. That is the gap report, live.
| Tool | The question it answers |
|---|---|
roast_get_context | What should I know before touching UI here? Routed by the folder being edited |
roast_find_component | Is there already a component for this, and which one is canonical? With one real usage example |
roast_find_token | I have #111111 or 13px in hand. What should I have used? |
roast_validate | I am about to save this. Does it break the system? |
roast_review | Review my changed files. Reads the git diff itself, so no code is pasted back |
For pull requests, the sister package guard-my-design-system runs the same rules as a GitHub Action and fails the check when new mess arrives. The scanner also speaks SARIF, so findings can land in GitHub's Security tab in six lines of workflow.
Combine freely. The full reference lives on GitHub.
| Command | What you get |
|---|---|
npx roast-my-design-system@latest | The scan and design-system-roast.html, opened in your browser |
... <path> | Scan a different repo than the current directory |
... --apply | The generated agent rules injected into every agent file you have: CLAUDE.md, AGENTS.md, .cursorrules, .cursor/rules/, .windsurfrules and .github/copilot-instructions.md, inside a marked block. Re-running replaces only that block, never your own text |
... --rules | The same rules written to design-system-rules.md instead, for pasting by hand |
... --check | The working tree's changed files checked against the design system, in the terminal. Exits 1 on findings, so it slots into scripts |
... --mcp | The scan as a local MCP server: five tools your agent calls while writing UI, plus the roast-fix prompt that serves the top fix from a fresh scan |
... --card | roast-card.svg: a shareable 1200x630 card with the score and worst findings. Pure SVG, embeds in a README |
... --sarif | design-system-roast.sarif for GitHub code scanning: findings appear in the Security tab, annotated on files |
... --by "Dwayne Hicks" | A requester credit in the report header, next to the scan date |
... --notes <file.md> | An agent-written analysis embedded in the report as "What the repo teaches the agent", labelled as written by AI and kept apart from the measured numbers. The Claude Code skill passes it automatically |
... --section "Title" <file.md> | A further agent-written chapter after the notes, same styling, same label. Repeatable |
... --exclude lab/ | Leave a folder out of the scan, or list folders in a .roastignore file at the repo root. The report prints every exclusion in the header with its file count |
... --json | The scan summary as JSON on stdout, for scripts and pipelines |
... --theme light / --out <file> / --no-open | Light report, custom report path, do not open the browser |
/roast-my-design-system in Claude Code | The full experience: the roast in chat and embedded in the report, the rules offer, and the fix loop with Claude on your own numbers |
/roast-my-design-system:review in Claude Code | The same check as --check, in chat. Each changed file's findings with the fix named, the fixes applied on request, the check re-run |
A shadcn install with shadcn installs, a product on MUI, Mantine, Chakra or Ant Design with products on that kit, a Tailwind theme with Tailwind themes, a Lit or Stencil system with other web-component systems. A repo that uses two kits is told so, and its rules name both.
An agent arriving in it will copy the mess faithfully and, where the mess runs out, add some of its own. Benchmark rebuilt 3 October 2026, counted by the scan's own harvest.
| Metric | Ideal | Median of 34 product repos | Median of 10 reputable systems |
|---|---|---|---|
| Distinct colours | ~24 | 119 | 14 |
| Shades of grey | up to 13 | 28 | 4 |
| Off-scale spacing values | ~12 | 24 | 5 |
| Typefaces | 2 to 3 | 3 | 1 |
| Off-scale border radii | up to 10 | 14 | 0 |
| Duplicated components | 0 | 16 | 9 |
| Inline style blocks | 0 | 51 | 12 |
| Arbitrary Tailwind values | ~20 | 56 | 0 |
| Near-identical colour pairs | 0 | 7 | 1 |
| !important declarations | 0 | 5 | 3 |
| Components never imported | 0 | 0 | 0 |
Your AI can write the UI. This makes sure it writes your UI.