The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Asdesigned listing page.
Is it as designed? Diff a rendered UI component against its Figma source and see exactly what drifted. Built for coding agents: give Claude Code or Cursor the tool and they can check their own work against the design.

That output is real — examples/button.html against a real Figma component. Five of those six were planted.
The sixth wasn't: <button> elements don't inherit font-family, so the page quietly fell back to Arial.
Nobody sees that in a screenshot review. The diff does.
Figma gives you the intent. The browser gives you the reality. asdesigned compares the two — and your coding agent can call it to check its own work.
Status: v0.2 — early, usable. Figma → spec, DOM → spec, diff, terminal + HTML report, MCP server, interaction states. One viewport per run — see what it doesn't cover.
Set FIGMA_TOKEN (a Figma personal access token with file content: read) in your environment or a .env file.
asdesigned ships an MCP server so Claude Code, Cursor, and other MCP clients can call it directly.
Tools: compare_design, inspect_element, inspect_figma.
All three understand states: compare_design takes states: ["default","hover","focus"], inspect_element takes a
single state, and inspect_figma takes variants: true to list what a component set designs.
Claude Code — .mcp.json in your project:
Cursor — .cursor/mcp.json, same shape.
A skill file describing when and how an agent should reach for the tool lives in
skills/asdesigned/SKILL.md — drop it into your agent's skills folder.
--states hover,focus,active,disabled (or --states all) compares each state as its own section.
The rendered side forces the matching pseudo-class before reading computed styles — :focus and
:focus-visible together, so modern focus rings aren't missed. The design side comes from the Figma
component set's variants: State=Hover, State=Focused, and the other spellings designers use
(Pressed, Rest, Inactive) all resolve. Point at the set or at any variant inside it; asdesigned
follows componentSetId to find the siblings.
A state the design doesn't define is skipped, not failed — asdesigned won't invent an expected
value. That skip is itself worth reading: no Focused variant means the focus ring was never
designed, which is a gap in the design file rather than a bug in the code. If every requested state
is undesigned the run reports NOTHING COMPARED and exits non-zero, so a states check can't
silently pass by checking nothing.
Exit code is 1 when drift is found, so compare works as a CI check.
Both sides are normalized into one flat StyleSpec — px numbers, RGBA colors, every field optional — and a pure
diff compares them with sensible tolerances (±1px, small color distance, zero tolerance on font weight).
Fields missing on one side are reported but don't fail the run; only real drift does.
Interaction states reuse all of that unchanged: one state is one spec pair, so diff never had to learn about them.
src/spec.ts — the shared formatsrc/diff.ts — the comparisonsrc/states.ts — state vocabulary and Figma variant→state matchingsrc/compare.ts — one comparison per state, and what to say when a state isn't designedsrc/readers/figma.ts — Figma REST → spec, including component-set variantssrc/readers/dom.ts — Playwright computed styles → spec, with pseudo-classes forced via CDPsrc/report.ts, src/report-html.ts — outputasdesigned compares one design node against one rendered element, at one viewport, across the UI states you ask for.
That covers the drift that shows up most: padding, sizing, colors, and inherited-font mistakes like the Arial fallback
above — plus hover, focus, active and disabled via --states.
Interaction states come with one requirement worth stating plainly: the design has to define them as variants.
A component set with State=Hover resolves; a flat frame, or a file where hover only exists as a prototype
interaction, gives asdesigned nothing to compare and the state is skipped. inspect <figma-url> --variants tells you
which states a component actually designs before you check them.
Not covered:
--viewport WxH, 1280×800 by default. Checking a component across
breakpoints means running compare once per breakpoint, each against the frame the designer drew for it. There's no
single command that sweeps them.And one boundary that isn't a roadmap item: between designed breakpoints there is no design truth. If the file has a 768 frame and a 1280 frame, nothing in it specifies 900px. asdesigned can tell you a component drifted at a width someone designed — never between two of them. No tool that treats the design as the source of truth can.
ASDESIGNED_BROWSER=/path/to/chrome uses an existing Chrome/Chromium instead of Playwright's download.
design-drift explores similar ground with pixel + element diffing and a
viewer. asdesigned is deliberately smaller — one verb, agent-first, 23 kB.MIT