figma-design-skills

Release License: MIT Claude Code plugin also Codex · Cursor · Copilot

Two composable, tool-agnostic skills for design-to-code fidelity — get the real design out of Figma, then prove the running app actually matches it. Packaged as a Claude Code plugin, and usable in OpenAI Codex, Cursor, GitHub Copilot, and any agent that reads AGENTS.md — see Use with other agents.

Most "is it pixel-perfect?" checks fail the same two ways: the design is read off a screenshot (so a 4px gap or a 600→400 weight slips through), and "looks done" is treated as a check (no measured feedback loop). These skills fix both — one extracts exact values, the other verifies them by measurement.

   ┌──────────────────────────┐         ┌──────────────────────────┐
   │  figma-design-extract    │  spec   │  design-fidelity-verify  │
   │  read Figma → spec table │ ──────► │  measure app → classify  │
   └──────────────────────────┘  table  └──────────────────────────┘
     exact tokens, not pixels             rendered values, not glances

The two skills

Skill One-liner
figma-design-extract Pull exact tokens, sizes, and structure out of a Figma node via the Figma MCP into a build-ready design-spec tableelement | property | Figma exact value | repo token | source component. Maps each Figma variable to your design tokens; logs drift instead of hardcoding.
design-fidelity-verify Run a bounded vision + numeric loop (~3 iterations) that reads the actually rendered values off the live app and classifies every spec row. Works for web (getComputedStyle) and mobile (the resolved style off the rendered React fiber, over Metro/CDP). Ships runnable readers.

They compose: figma-design-extract produces the spec table; design-fidelity-verify consumes it. Use either alone, or together for a full design→code→verified pipeline.

The workflow

  1. Extract. Share a Figma node URL. The extract skill reads structured values (get_variable_defs, get_metadata, get_design_context, get_screenshot) and produces a spec table mapped to your tokens. The screenshot is a visual reference only — never measured.
  2. Build. Implement the component from the table, reusing existing primitives. Every value is a token reference, not a literal.
  3. Verify. The verify skill runs the app, captures full-resolution, reads the rendered values with a bundled reader, and walks every spec row against the live render — fixing the highest-severity drift first, bounded to ~3 iterations, and reporting any residuals honestly.

Fidelity means the right token — so the verdicts say which

A failing row that reads CTA bg: expected #3366cc, got #3060c0 tells you nothing actionable. Did someone type a hex by hand? Reach for the wrong token? Is the token itself wrong? Three different fixes, and one of them isn't even in this repo.

So the numeric pass resolves each measured value back to a named token before labelling the row:

Verdict Meaning Where the fix lands
PASS Matches the spec.
DRIFT Resolves to a token, but not the spec's. Names both. The component reached for the wrong token.
HARDCODED Resolves to no token at all. A literal was typed in.
VARIANT The element is in a different state than the Figma node. Nothing — re-pick the node. Every delta below it is noise.
MISSING The selector matched nothing. Your targets. This run verified less than it looks.

Each drift is further tagged theme-level (one upstream fix, cross-app — never patch it locally) or component-level. Details in drift-classification.md.

Install

/plugin marketplace add jeltehomminga/figma-design-skills
/plugin install figma-design-skills@figma-design-skills

Both skills load on demand from their trigger phrases (e.g. a figma.com URL, or "verify the design"). You can also clone this repo and drop either skills/<name>/ folder into your ~/.claude/skills/ (personal) or .claude/skills/ (project).

Using another agent? One command installs these anywhere — see Use with other agents below.

Use with other agents

Cursor · OpenAI Codex · GitHub Copilot · Gemini CLI · Aider · Zed · and any agent that reads AGENTS.md.

The SKILL.md bodies are plain, tool-neutral markdown — the only Claude-specific part is auto-triggering via the description. To use a skill elsewhere, wire its body into your tool's instruction format. Every tool below speaks MCP, so the Figma / Playwright / Argent references work once you've configured those servers in that tool.

Easiest — npx skills add (skills.sh)

The skills.sh CLI installs these into the right format for whichever agent you use — Claude Code, Cursor, Codex, Copilot, Windsurf, Gemini, Cline:

npx skills add jeltehomminga/figma-design-skills

It discovers both skills from this repo's skills/ layout and .claude-plugin/ manifest automatically. The steps below are the manual fallback if you'd rather wire them in by hand.

Any tool — AGENTS.md (broadest reach)

This repo ships a root AGENTS.md that summarizes both skills and points to the full bodies. Tools that read AGENTS.md — Codex, Cursor, Copilot's coding agent, Gemini CLI, Aider, Jules, Zed, Windsurf, and 20+ others — pick it up automatically. Copy it (or the relevant parts) into your own project's AGENTS.md. (VS Code Copilot: enable the chat.useAgentsMdFile setting.)

OpenAI Codex — native skills

Codex reads the same SKILL.md format from .agents/skills/. From your project:

mkdir -p .agents/skills
cp -r path/to/figma-design-skills/skills/* .agents/skills/

Invoke with /skills or $figma-design-extract, or let Codex match on the description.

Cursor — project rule

Cursor uses .cursor/rules/*.mdc. Create one per skill — paste the skill body under MDC frontmatter:

---
description: <paste the skill's description>
alwaysApply: false
---
<paste the body of skills/figma-design-extract/SKILL.md>

Leave globs empty and @-mention it (@figma-design-extract), or set globs: "**/*.tsx" to auto-attach on relevant files.

GitHub Copilot — instructions file

Create .github/instructions/figma-design-extract.instructions.md:

---
applyTo: "**"
---
<paste the body of the skill>

Honored in VS Code and by the Copilot cloud agent. For always-on guidance instead, append the body to .github/copilot-instructions.md.

Configure the MCP servers (per tool)

The skills call MCP servers; each tool configures them separately:

Tool MCP config
Claude Code .mcp.json / .claude/mcp.json
OpenAI Codex ~/.codex/config.toml[mcp_servers.<name>]
Cursor .cursor/mcp.json
GitHub Copilot .github/mcp.json (Agent mode; root key servers)

Requirements

  • An agent — Claude Code, OpenAI Codex, Cursor, GitHub Copilot, or any MCP-capable coding agent (see Use with other agents).
  • Figma MCP server (Dev Mode MCP) — for figma-design-extract.
  • App-driving tooling — for design-fidelity-verify, a channel that can evaluate JavaScript in the running app:
    • Web: a browser/Playwright/Chrome MCP that can run JS in the page and screenshot.
    • Mobile: Argent (recommended), metro-mcp, agent-device, or another MCP exposing the Metro/CDP eval channel. A simctl-only wrapper can capture and place but can't run the numeric pass.

Extending without forking — the orchestrator pattern

These two skills are deliberately generic. Real teams have stack-specific deltas — where design tokens live, how to reach an authenticated screen, which device tooling is wired up. Don't fork the skills to add them. Wrap them:

your-org-fidelity            a thin org skill: routing, org deltas, guardrails
  ├─ Part A → figma-design-extract     (generic, this repo)
  ├─ Part B → design-fidelity-verify   (generic, this repo)
  └─ references/backend-<platform>.md  (YOUR capture + numeric-read channels)

The org skill owns only what's specific to you; both halves stay upstream and keep improving. "Backend" here means the measurement driver — the pair of (full-res capture, numeric-read channel) for one platform — not a server. This repo's scripts/ are the reference implementation of that backend; point your org skill at them, or swap in your own.

Tool- and stack-agnostic

The skills name specific tools (Tailwind, NativeWind, Restyle, Playwright, Argent) only as examples. The principles are what matter:

  • A value bound to a Figma variable maps to a named token in your code — never a hardcoded literal.
  • Fidelity is measured — the resolved value read off the running app — never eyeballed from a screenshot, and reported as the token it resolves to, not a raw hex/px delta.
  • Adapt the token syntax and the device tooling to whatever your repo already uses.

Background — why measured fidelity (and where it's debated)

This approach reflects current Figma guidance and practitioner consensus, with the honest caveats:

  • Tokens/variables are the source of truth. Figma: "Figma knows which specific token is used, and can provide the name of that variable to the LLM." (Figma blog). Reuse via Code Connect is "the #1 way to get consistent component reuse."
  • Don't measure from a screenshot. Fine-grained spatial estimation is a documented weak spot for multimodal models — surveyed across the field in Multimodal Spatial Reasoning in the Large Model Era — and the metric, sub-pixel judgment a fidelity check depends on is squarely in that weak spot. So exact values come from structured data, and the running app is measured, not eyeballed. The blind spot this closes is real — AI "has no visibility into the final, rendered output of its own code" (Builder.io).
  • Bounded loop. Self-correction saturates fast — one 2026 study of self-correcting vision agents finds correction "saturates after three retries" (arXiv:2601.11637), hence the ~3-iteration cap.
  • "Pixel-perfect" is contested framing. A credible camp argues the term is meaningless/harmful and the real goal is "intentional fidelity to design decisions" (Smashing Magazine, Josh Comeau). These skills keep "pixel-perfect" only as a trigger phrase; the pass/fail unit is the token, not the literal pixel.
  • Complement, don't replace, visual regression. Computed-style diffing verifies a first build (no baseline exists yet); tools like Chromatic / Percy / Applitools / Playwright toHaveScreenshot catch ongoing regressions. Use both.

License

MIT © Jelte Homminga