Skill: design-system
The design-side twin of survey: once per repo it fixes the design canon in
docs/design-system.md — which tool screens are drawn with (figma / pencil / code), the
platform posture, where tokens come from, and the component inventory new screens must compose.
architecture-map.md §Frontend stays the inventory of the code; this file is the design
canon the design pipeline (ux-flows → screens) and implement/review read. The tool choice
is committed here — never in .claude/sdd.local.md (that file is per-developer and gitignored;
the canon is team-wide).
Question phrasing → ../_shared/ask-style.md. Canon prose follows
artifact_language — frontmatter keys/values (tool:, figma_file:, …), component names and
file anchors stay English → ../_shared/artifact-language.md.
Owner
Whoever owns the product's look (designer / frontend lead / the solo maintainer).
Inputs
- (Optional)
docs/architecture-map.md§Frontend / UI foundation + thefrontend:machine key — the code-side inventory this canon cites. - (Optional) an existing
docs/design-system.md— updated, never silently overwritten. - The design-tool MCPs available in this session (Figma / Pencil), if any → detected in step 3.
Protocol
- Check existing. If
docs/design-system.mdexists, show itstool+ posture + inventory summary and ask: reuse as-is (STOP — nothing to do) / update (continue, edits land in place) / rebuild. Never overwrite silently. - Scan the code side. Read
architecture-map.md§Frontend / UI foundation + thefrontend:key. Map absent, stale, orfrontend: ""on a repo that visibly has UI code → dispatch theexploreragent —subagent_type: "sdd:explorer"(fallbacksubagent_type: "Explore", per../_shared/agent-roster.md) — for the component library / tokens / styling approach / shared primitives, each with afile:line. A repo with no UI code at all is fine — the canon can start tool-side or empty (greenfield: the inventory grows asimplementregisters components). - Detect tools + ask ONE question set. Detect which design-tool MCPs the session actually has
(Figma / Pencil — probe the available tools, don't assume). Then one
AskUserQuestioncall (up to 3 questions in it, phrased per../_shared/ask-style.md): (a) tool — options from what's detected, the detected one first as «(Recommended)»;code(markdown wireframes inscreens.md) is always offered — it needs no MCP and never blocks; (b) platform posture — mobile-first / desktop-first / responsive-both; (c) token source — the code file(s) found in step 2 / the tool's variables / «none yet». - Write the canon. Fill
./templates/design-system.md→docs/design-system.md: frontmattertool+figma_file/pen_file(the one matching the tool; the other stays""), posture, token source, the component inventory — each row citingfile:line(code) or the node/URL (tool-side) — and the cross-screen conventions. - Bootstrap the tool library (
tool: pencilonly — figma links an existing file,codeneeds nothing). The canon naming apen_filethat doesn't exist or is an empty stub is the #1 way this skill «did nothing» — so materialize it: a. File. Absent → write the minimal stub topen_file({"version": "2.17", "children": []}). b. Open + verify. The Pencil MCP ignoresfilePath— it writes into whatever document is active in the app. Ask the user to open the file (macOS:open -a Pen <pen_file>), then verify viaget_app_statethat the active canvas ISpen_file. Mismatch → stop and repeat the ask; never write into a foreign document. c. Seed. Dispatch thepen-keeperagent —subagent_type: "sdd:pen-keeper"(no fallback: without the Pencil MCP this step degrades tocodemode per../_shared/tool-adapters.md) — with the canon path,pen_file, and the token source files. It re-checks the active document, seeds the variables (light + dark), ensures the foundations frame, and returns a reconcile report. d. Persist. Relay the report's user actions — always «Cmd+S in Pencil»: the app holds changes in memory and the MCP cannot save; confirm the file on disk actually changed (size/mtime) before calling the canon done. - Structural self-check — per
../_shared/self-check.md: re-read the file from disk and verify 5 items: (1)tool∈ {figma, pencil, code}; (2) the tool ↔ file fields agree —figma⇒figma_filenon-empty,pencil⇒pen_filenon-empty,code⇒ both""; (3) every inventory row carries a source anchor (file:lineor node/URL); (4) no<placeholder>stubs survive; (5)tool: pencil⇒ thepen_fileexists on disk and is larger than the empty stub (step 5 ran and the user saved). Fix + re-check ≤2 cycles; surface anything unresolved. - Commit + handoff. Propose commit
design-system: establish <tool> canon(on pencil — including the seededpen_file). Then emit the stage-handoff block per../_shared/handoff.md(utility variant) — What I did (incl. «self-check: 4/4 pass») + Review (docs/design-system.md) + Run next: resume your backbone stage (typically/sdd:ux-flows <slug>for the UI feature in flight);/clearoptional.
Definition of Done
docs/design-system.mdexists withtool∈ {figma, pencil, code}, a stated platform posture, a token source, and an inventory whose every row cites its source.- The tool ↔
figma_file/pen_filefields are consistent; the file is committed (team-wide canon, not a local setting). tool: pencil⇒ the.penlibrary exists on disk, holds the seeded token variables, and the user has saved it (the canon never points at a file that was never created).
Anti-patterns
- The tool choice in
sdd.local.md. That file is per-developer and gitignored — two teammates would draw in different tools. The canon is committed, in this one file. - Re-asking the tool per feature.
ux-flows/screensread the canon; the question is asked once, here. - Duplicating
architecture-map.md§Frontend. The map inventories the code; this file cites it and adds the design-side canon — never a second copy of the same rows. - Blocking on a missing MCP. No Figma/Pencil in the session →
codemode is always available; degrade, don't block (→../_shared/tool-adapters.md). - An inventory with no anchors. A component row that cites nothing is a guess — cite
file:lineor the tool node, or leave it out. - A canon that names a
pen_filenobody created.tool: pencilwithout step 5 is a dangling pointer — downstreamscreensopens nothing and silently degrades. - Writing into whatever document is open. The Pencil MCP targets the ACTIVE document and
ignores
filePath— skipping theget_app_stateidentity check pollutes a foreign file. - Assuming the MCP saved to disk. It edits in-memory; only the user's Cmd+S persists. Verify the file changed before committing.
References & template
./templates/design-system.md— the canon scaffold; inline comments are the per-section generation contract.../_shared/tool-adapters.md— the design-tool MCP degradation row.../_shared/agent-roster.md— the explorer contract (step 2).../../agents/pen-keeper.md— the .pen reconcile contract (step 5).