Work with design systems in Figma
Two modes in one skill: inspect (read-only quality audits with reports) and build (creating, fixing, extending components and tokens). Inspect produces structured reports. Build produces working Figma files. Build mode optionally extends to Phase 6 (sync to code) — generates tokens.css, an audit script, and AI rules file for the user's codebase. Phase 6 is off by default and only triggers on explicit user request.
Between inspect and build, the skill always pauses for the user to decide what to do with the report.
Always pass skillNames: "work-with-design-systems" when calling use_figma as part of this skill. This is a logging parameter — it does not affect execution.
Prerequisites
You MUST invoke the figma-use skill (Skill tool: skill: "figma-use") before every use_figma call. It contains critical Plugin API rules, gotchas, and script templates. Never call use_figma without it.
IMPORTANT: Before working with design systems in Figma, load the working-with-design-systems/wwds.md reference from the figma-use skill to understand key concepts and guidelines.
Critical rules
These apply to BOTH modes — inspect and build.
- Work incrementally. One component (or one variant set) per
use_figmacall. Validate after each step. This is the single most important practice for avoiding bugs. - Never build on unvalidated work — match validation depth to change type.
- Structural change (new variant, restructured auto-layout, new property,
swapComponent):get_metadata+get_screenshotbefore next step. Visual properties may have shifted invisibly. - Binding / description / codeSyntax / scope / rename change: verify INSIDE the same script via
node.boundVariables/node.description/variable.codeSyntax/variable.scopesreads, return as part of the result. No externalget_screenshotneeded — Figma is deterministic on these. - End of batch: one
get_screenshotof the parent CS for visual sanity. Why:get_screenshotis the heaviest call and Figma MCP has a ~15 calls/min rate limit. Matching depth to risk frees that budget for the structural changes that actually need visual verification, and stops you hitting the rate limit on a binding pass that doesn't need it.
- Structural change (new variant, restructured auto-layout, new property,
- Bind visual properties to variables when a scale value exists. Fills, strokes, padding, itemSpacing, corner radius. For component-specific dimensions that don't match any scale value (e.g., 3px internal padding on a toggle track, 1px divider offset), hardcoded values are acceptable — document these exceptions in the component description.
- lineHeight variables must store pixel values, not percentages. Figma variables are unitless. When bound to lineHeight, the value is interpreted as pixels. If your DS defines line heights as percentages (e.g., 150%), convert before storing: fontSize × (percentage / 100). Text styles can store {unit: "PERCENT", value: 150} — variables cannot.
- Set codeSyntax.WEB on every variable. Without it, agents using
get_design_contextget raw Figma variable names instead of CSS token names. Set during creation, not as a separate pass. - Set explicit variable scopes. Never leave ALL_SCOPES. Background colors get FRAME_FILL + SHAPE_FILL. Text colors get TEXT_FILL. Spacing gets GAP + WIDTH_HEIGHT. Radius gets CORNER_RADIUS. Font size gets FONT_SIZE.
- TEXT properties with the same name merge across variants. If two variants both define
addComponentProperty("Label", "TEXT", ...), they become ONE shared property on the component set with one default value. For different defaults per variant: use different property names, leave text as direct content with instance text overrides, or accept the shared default. - TEXT component properties on every customizable text node. Without them, label overrides ("Label" → "Submit") revert on component update. Every customizable text node needs
componentPropertyReferences = { characters: key }. - Use slots for compound components. Compound components (Card, Modal, Dialog, ListItem, ReviewCard) that contain variable inner content MUST use named slots instead of detach patterns or text-only props. Without slots, agents and users detach the component to edit inner content, which breaks maintenance and the agent's ability to reason about composition. Slots are available in Figma as of March 2026. See
references/build/slots-guide.md. - Every public component MUST have a structured description. Figma MCP reads component descriptions and passes them to agents as context. Missing descriptions force the agent to guess purpose, behavior, and composition. Use the template in
references/build/component-description-template.md. Use plain-text formatting (UPPERCASE section headers, no markdown bold or##—get_design_contextescapes them) — see template's "MCP delivery format" section. Private base components (prefixed with.or_) may use a one-line note. - Never detach a component. If you need to vary inner content, use: variant, boolean property, instance swap, or named slot. Detaching breaks the design-to-code bridge — the detached frame becomes structurally invisible to agents and to inspect mode.
Mode selection
The skill operates in one of two modes. The first thing to do in any session is determine the mode.
Inspect mode triggers when the user says:
- "audit my design system" / "check component quality" / "review my DS"
- "find detached instances" / "check WCAG" / "score my components"
- "generate handoff docs" / "export component specs"
- "is this design system ready" / "what's broken in my file"
- Any request that asks for a report or evaluation without explicit "build" or "fix"
Build mode triggers when the user says:
- "create design system" / "build DS in Figma" / "generate component library"
- "set up tokens" / "add components" / "sync from code"
- "fix ALL_SCOPES" / "add codeSyntax" / "rebuild Variables"
- "add slots to my components" / "write descriptions"
- "export tokens.css" / "generate CLAUDE.md" / "sync to code" (these enter build mode and proceed directly to Phase 6 if rest of system is in good shape)
- Any request that asks for changes to the file or codebase
Ambiguous requests like "I have a Figma file with some issues — help me with my design system" — ASK the user explicitly:
Should I run a quality audit first (read-only report with scores and issues), or go straight to building/fixing? If you want both, I'll do inspect first, show you the report, then wait for your decision before changing anything.
Default behavior when explicitly mixed ("audit and fix"): start with inspect mode, produce report, pause, wait for user direction.
Inspect mode
Read-only. Never modifies the file. Produces structured reports.
Read references/inspect/overview.md before starting. It documents which modules to run for which user requests, the execution order, and the readiness scoring formula.
Inspect workflow
- Scope. Ask the user: full file or specific components? Which audit modules? Default is all six. Export format — markdown (default), JSON, both, or AI prompt.
- Inventory. Run
scripts/inspect/inventory.jsto list all component sets with variant counts and page locations. Present as a table for user confirmation. - Run modules for each component set in this order:
- Module 1 — Token compliance (
scripts/inspect/audit-tokens.js) — outputs errors and warnings separately - Module 2 — Interactive states (
scripts/inspect/audit-states.js) - Module 3 — Accessibility (
scripts/inspect/audit-accessibility.js) - Module 4 — Detached instances (
scripts/inspect/audit-detached.js) — runs once, file-wide - Module 5 — Naming quality (
scripts/inspect/audit-naming.js) - Module 6 — Component descriptions (no script — uses Claude reasoning, read `references/inspect/component-desc
- Module 1 — Token compliance (