Free · open source · read only

Find where your AI agent will invent UI.

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.

npx roast-my-design-system@latest

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.

119-repo benchmark10 reputable systems355 agent sessions measuredZero dependencies
vercel/ai-chatbot · 80/100 · one file, light and dark
The idea

An agent copies what it finds. It invents where the repo has no answer.

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.

72 → 1

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.

21 → 7

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.

28 → 2

A Christmas theme across 10 products. Findings added without and with this tool. September 2026.

TaskModelWhenWithout roastRoast MCP and rulesRoast plugin with its edit hook
A new chart and a new component, 4 products, 3 runs eachSonnet 5Oct 202621 in 24 runsnot run7 in 24 runs
A new chart and a new component, 4 products, 3 runs eachHaiku 4.5Oct 202672 in 24 runsnot run1 in 24 runs
Add a panel, build a dashboard, tighten a list (80 sessions)Sonnet 5Sept 202679not run
A Christmas theme, 10 productsSonnet 5Sept 2026282not run
A new chart, 4 products, 5 runs eachSonnet 5Sept 202610 in 20 runsnot run0 in 20 runs
A new chart, 4 productsHaiku 4.5Sept 202625390 in 14 of 15 runs
Chart, status colour, empty state, new componentHaiku 4.5Sept 202642 in 16 runs49 in 16 runs3 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.

Three verbs

Roast. Teach. Guard.

1 · Roast

Find the real design system, the mess in it, and the gaps.

One scan, one score, every finding with its file path, and the first fixes ranked by what they are worth.

2 · Teach

Give the agent the answers.

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.

3 · Guard

Check every edit, so nobody has to remember to ask.

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.

What you get

A script does the counting. Claude writes the explanation.

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.

Where will your agent have to guess?

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.

A health score you can defend in a meeting

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.

Fixes you can make right now

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 finding, with its file path

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.

Rules that stop the mess coming back

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.

One file. Open it, Slack it, email it.

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.

Example roasts

Eleven real reports from public repos.

Hosted exactly as the tool writes them. Every number deterministic, every path real.

npx shadcn create, fresh
factory install
100/100
Read as a fresh install: "the score is the kit's, not yours". 13 colours, every theme variable in place, shadcn's own 24 bracket values named and not counted.
Unleash
MUI
60/100
1,109 files import the kit and the theme is read 6,166 times. 4 colours and 2 spacings per 100 kit files are written onto components.
Metabase
Mantine
47/100
Its own wrapper over Mantine counts as the kit, so 2,679 files are read instead of 392. Nothing written onto components, 2 spacings per 100 kit files.
SigNoz
Ant Design
51/100
2 colours and 7 spacings per 100 kit files written in style objects where the theme already has a value.
Apache Airflow
Chakra UI
43/100
No colours written onto components, 4 spacings per 100 kit files as pixel strings where a space step exists.
vercel/ai-chatbot
shadcn install
80/100
71 values like [13px] written outside the Tailwind scale, and 66 palette colours per 100 files where a theme variable exists. Claude's notes embedded.
excalidraw/excalidraw
55/100
78 off-scale spacing values and 90 !important declarations.
dubinc/dub
20/100
642 arbitrary bracket values, 21 duplicated components, and the chart-palette gap named.
telekom/scale
Stencil
55/100
95 Stencil components read by tag. 66 spacing values outside the scale where about 12 would do. Claude's notes embedded.
magicuidesign/magicui
registry
78/100
Counted on the components it publishes: 52 off-theme colours per 100 files in the code it ships, its docs site kept out and named.
adobe/spectrum-web-components
Lit
83/100
740 colour tokens with 8 hardcoded colours beside them, and 37 !important declarations.
Install

Four ways in. Same engine, same score.

Requires Node 18 or newer. Nothing else is installed, and nothing leaves your machine.

The command line no install

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

Claude Code, the full plugin recommended

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

The skill edition Claude Code and Codex

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

Cursor, Windsurf, any MCP client MCP

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.

Then say

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.
Live answers over MCP

What your agent gets while it works.

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.

roast_find_token #6b7280:
Nearest token: #607d8b, 11 channel steps from #6b7280. Unless the difference is a deliberate decision, use the token.
It writes the first draft anyway and runs roast_validate before saving:
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.
Second draft: 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.

ToolThe question it answers
roast_get_contextWhat should I know before touching UI here? Routed by the folder being edited
roast_find_componentIs there already a component for this, and which one is canonical? With one real usage example
roast_find_tokenI have #111111 or 13px in hand. What should I have used?
roast_validateI am about to save this. Does it break the system?
roast_reviewReview 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.

Every command

One scan powers all of it. The flags decide what lands on disk.

Combine freely. The full reference lives on GitHub.

CommandWhat you get
npx roast-my-design-system@latestThe scan and design-system-roast.html, opened in your browser
... <path>Scan a different repo than the current directory
... --applyThe 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
... --rulesThe same rules written to design-system-rules.md instead, for pasting by hand
... --checkThe working tree's changed files checked against the design system, in the terminal. Exits 1 on findings, so it slots into scripts
... --mcpThe 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
... --cardroast-card.svg: a shareable 1200x630 card with the score and worst findings. Pure SVG, embeds in a README
... --sarifdesign-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
... --jsonThe scan summary as JSON on stdout, for scripts and pipelines
... --theme light / --out <file> / --no-openLight report, custom report path, do not open the browser
/roast-my-design-system in Claude CodeThe 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 CodeThe same check as --check, in chat. Each changed file's findings with the fix named, the fixes applied on request, the check re-run
What it works on

Every repo is compared with repos built the same way.

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.

Frameworks
  • React: Next.js, Remix, Vite and plain React
  • Web components: Stencil, Lit, custom elements
Kits and styling
  • Tailwind, shadcn/ui, MUI, Mantine, Chakra UI, Ant Design
  • CSS Modules, Sass, Less, Emotion, styled-components, vanilla-extract, CVA, Stitches
Recognised, not measured yet
  • Vue, Angular, Svelte: named in the header, colours and spacing counted, components not measured. The report says so
  • HeroUI, NextUI, Radix Themes, Fluent UI, React Bootstrap, Grommet: named, no kit rules
What it measures

Yes, the median repo is already a mess. That is the point.

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.

MetricIdealMedian of 34 product reposMedian of 10 reputable systems
Distinct colours~2411914
Shades of greyup to 13284
Off-scale spacing values~12245
Typefaces2 to 331
Off-scale border radiiup to 10140
Duplicated components0169
Inline style blocks05112
Arbitrary Tailwind values~20560
Near-identical colour pairs071
!important declarations053
Components never imported000
Why the numbers hold
  • Deterministic. A zero-dependency Node script reads every file and returns the same numbers every run.
  • Read only. No network. No telemetry. The test suite fails if the package ever declares a dependency. Every release passes 468 checks before it is tagged, and is provenance signed on npm.
  • Honest gaps. What the scan cannot read says "not measured" and drops out of the score.
  • Honest exclusions. Tests, stories, docs sites, artwork and email templates are left out. Your own exclusions are printed in the report header.
  • A real benchmark. 119 public repos, with the builder and the repo list in the open, so the ruler can be checked, not just quoted.

Your AI can write the UI. This makes sure it writes your UI.

npx roast-my-design-system@latest