design-md-writer ยท diff

git:20261031.137afa3 to git:20261101.f934ce3

52 added, 77 removed. Audit A to A.

---
name: design-md-writer
- description: "Write or audit a DESIGN.md (architecture, data flow, invariants, decisions) for agents; also covers UI token specs."
- when_to_use: "Use when creating or updating a design doc, or when agent changes keep landing in the wrong place."
+ description: "Write or audit a visual-identity DESIGN.md: design tokens plus rationale in the Google Labs format, for UI agents."
+ when_to_use: "Use when a UI needs a brand or style spec or a token file for ac:frontend-design; the architecture doc is ac:architecture-md-writer."
---
# DESIGN.md Writer
- DESIGN.md tells an agent how the system is built: which parts exist, what each owns, how data moves, which rules must hold, and where to make a given change. An agent reads it before it changes structure, then goes back to the code. This skill writes it, updates it, or audits an existing one, in the shape Claude reads best.
-
- Scope: one file (or the split files the size rule names), plus one pointer line in the rules file. It does not edit code, README or CHANGELOG, and it does not write the project's why and scope (that is `ac:project-md-writer`) or its commands and conventions (`ac:claude-md-rules-creator`). The UI token section is what `ac:frontend-design` reads and commits to; when it builds a screen it owns the visual direction, and this skill owns the file's shape. Report adjacent problems instead of fixing them.
-
- ## Which DESIGN.md
+ DESIGN.md tells an agent how an interface looks: exact token values (colours, type, radii, spacing, component styles) in YAML, and the reason for each in prose. `ac:frontend-design` builds from it, `ac:design-director` commits to it and critiques against it, and Google Stitch imports it as a design system. This skill writes it, updates it, or audits an existing one.
- The name now means two things.
+ Scope: one file plus one pointer. It records a visual direction; it does not choose one. A palette or typeface comes from an existing theme, from the user, or from `ac:design-director` through `ac:frontend-design`. It does not edit UI code, README or CHANGELOG, and it does not write the architecture doc (`ac:architecture-md-writer`), the project's why and scope (`ac:project-md-writer`) or its commands and conventions (`ac:claude-md-rules-creator`). Report adjacent problems instead of fixing them.
- - **Architecture** (default): how the system is built. Everything below applies.
- - **Visual identity**: design tokens plus rationale for a UI, in the format Google Labs published for coding agents. Choose it when the user asks for a brand or style spec, or when an existing DESIGN.md opens with YAML tokens. Read `${CLAUDE_SKILL_DIR}/references/visual-identity.md` and follow it instead of the workflow below.
- - A project that needs both keeps the visual file as `DESIGN.md`, because the format is named for that file, and writes the architecture doc as `docs/ARCHITECTURE.md` from the same template.
+ The format is Google Labs' `design.md`, spec version `alpha`; the CLI `@google/design.md` is at 0.4.0 (checked 2026-11-01). Expect changes, and read `${CLAUDE_SKILL_DIR}/references/visual-identity.md` for the schema, section order and tooling before writing.
## Where it sits
- | Layer | File | Loaded | Holds |
- |---|---|---|---|
- | Rules | CLAUDE.md, AGENTS.md | every session | commands, conventions, off-limits |
- | Why and scope | PROJECT.md | when read | what, scope, constraints |
- | How it is built | DESIGN.md | when read | components, flows, invariants, change guide |
+ | Layer | File | Holds |
+ |---|---|---|
+ | Rules | CLAUDE.md, AGENTS.md | commands, conventions, off-limits |
+ | How it is built | ARCHITECTURE.md | boundaries, invariants, flows |
+ | How it looks | DESIGN.md | tokens, component styles, visual rationale |
- DESIGN.md stays out of the always-loaded layer. Claude Code loads every CLAUDE.md from the working directory upward in full at launch and an `@import` costs the same, so a pointer line with a trigger is the cheaper wiring.
+ A path-scoped rule is the right wiring: `.claude/rules/ui.md` with `paths:` over the view files, pointing at DESIGN.md, so the tokens load when a session touches UI and stay out of every other turn.
## Pick the mode
- - No design doc exists: write.
- - One exists and is mostly right: update in place, keep its headings.
- - One exists and agents ignore it, or its quality is unknown: audit first and report ranked findings with line numbers; edit only when the user asked for the fix.
+ - No DESIGN.md exists: write.
+ - One exists and lints clean: update in place, keep its headings.
+ - One exists and agents ignore it, or its quality is unknown: audit first and report ranked findings; edit only when the user asked for the fix.
+ - The existing DESIGN.md describes architecture (no YAML tokens, sections like Components and Data flow): stop. Ask with `AskUserQuestion` whether to `git mv DESIGN.md ARCHITECTURE.md` (then `ac:architecture-md-writer` owns it) and write the visual file fresh. The move is the user's call.
## Workflow
### 1. Find what exists
- Glob `DESIGN.md`, `ARCHITECTURE.md`, `docs/DESIGN.md`, `docs/architecture*`; read the README, PROJECT.md and CLAUDE.md. Keep an existing location; otherwise use `docs/DESIGN.md`. Check which kind an existing DESIGN.md is.
+ Glob `DESIGN.md` and `docs/DESIGN.md`; find the theme: Tailwind config or `@theme` CSS, CSS custom properties, Flutter `ThemeData` and `ColorScheme`, an iOS asset catalog, a Stitch export under `.stitch/`. Read any `ac:design-director` output in the conversation.
- Success: you know the mode, the kind, the target path and what other files already say.
+ Success: you know the mode, the target path and which source supplies the values.
- ### 2. Map the code
+ ### 2. Collect the decisions
- Open the entry points, the module boundaries, the schema and the tests. Use `ac:explore` for a large repo and LSP for symbol-level questions. Never describe a component you have not opened. Ask the user, with AskUserQuestion in their language and your best guess first, only what the code cannot show: why a boundary sits where it does, and which alternatives were rejected.
+ Existing theme files are the source: derive the tokens from them and verify each value. A new identity takes its values from the chosen `ac:design-director` direction or `commit` plan (named hex values, typefaces, radius, spacing unit), verbatim. Ask the user, with `AskUserQuestion` in their language, only for brand intent the code cannot show: audience, tone, what to avoid.
- If you cannot ask (a subagent or a non-interactive run), omit what only the user knows and list the open question in the report.
+ With no theme and no direction, stop and say so: run `ac:frontend-design` phase 2, which asks `ac:design-director` for directions. A palette invented here is the generic default the whole chain exists to avoid.
- Success: you can name each component's responsibility and its dependencies from files you read.
+ Success: every token traces to a file, a director decision or a user answer.
### 3. Write from the template
- Read `${CLAUDE_SKILL_DIR}/assets/DESIGN.template.md` and fill it per the section contract. `${CLAUDE_SKILL_DIR}/references/example.md` shows a filled one; match its register.
+ Read `${CLAUDE_SKILL_DIR}/assets/DESIGN.template.md` and fill it. `${CLAUDE_SKILL_DIR}/references/example.md` shows a filled one that lints clean; match its register.
- Success: no placeholder left, no empty section, target 250 lines or fewer.
+ Success: no placeholder left, every colour has a role sentence, 150 lines or fewer.
- ### 4. Verify
+ ### 4. Lint and export
- Glob every path you cited, Grep every symbol, and run or read every verification command in the Invariants table. Delete what you cannot confirm.
+ ```bash
+ npx @google/design.md@0.4.0 lint DESIGN.md
+ ```
- Success: each claim traces to a file, a symbol or a command output.
+ It exits 1 on errors (a `broken-ref` is one) and prints warnings for contrast, missing primary, orphaned tokens and section order. Fix errors, read every warning, and rerun. The linter checks contrast only on component `backgroundColor` and `textColor` pairs, so check the text roles you use outside components (muted text on the surface) against 4.5:1 yourself.
- ### 5. Wire the pointer
+ Export when the project consumes the tokens: `--format css-tailwind` (Tailwind v4 `@theme`), `json-tailwind` (v3), `dtcg` or `css-vars`. There is no Flutter exporter; map the tokens by hand as `${CLAUDE_PLUGIN_ROOT}/skills/frontend-design/references/tokens-and-platforms.md` describes.
- Add one line to the rules file if none points here: "Before changing structure, read <target path>; update it in the same change when a component, flow or invariant moves." Put it in CLAUDE.md when one exists; use AGENTS.md only when the project has no CLAUDE.md, because Claude Code reads only the CLAUDE.md files when both exist. Use a plain path, not an `@import`.
+ Success: lint exits 0 and the warnings left are ones you can defend.
- Success: `grep -n DESIGN.md` on the rules file finds the line.
+ ### 5. Wire the pointer
- ## Section contract
+ Add the path-scoped rule through `ac:claude-md-rules-creator`, or one line in CLAUDE.md when the project has no UI path to scope: "Before changing UI, read DESIGN.md and build from its tokens." Use a plain path, not an `@import`.
- | Section | Holds | Rule |
- |---|---|---|
- | Overview | One paragraph and at most one text diagram | Under 20 lines of diagram; boundaries and data direction only |
- | Components | Per component: location, responsibility, depends on, local invariants (omit when none) | Responsibilities and boundaries, never a file inventory; a rule that spans components goes in Invariants |
- | Data flow | The two or three main paths, as numbered steps | Each step names `path` or `path:symbol` |
- | Data model | Entities that matter and their relations | Point to the schema file; do not copy it |
- | Interfaces | External APIs, events, file formats | Point to the source; add invariants types cannot express |
- | Invariants | Cross-cutting rules: rule, why, how to verify | The verify column is a test name or a command; component-local rules stay on the component |
- | Decisions | Design choices with reason and rejected alternatives | Product and scope choices live in PROJECT.md; each decision has one home |
- | Errors and testing | The error contract and where tests live | Two to five lines |
- | Change guide | Task, files to touch, coupled places to check | The section agents use most; write it from real changes |
- | Known gaps | Debt and unfinished seams | One line each, with the path |
- | Last reviewed | Date and trigger | Stamp on every edit |
+ Success: the rule or line exists and names DESIGN.md.
## Rules
- - Document design, not inventory. The code already shows file trees and function lists; record responsibilities, boundaries, flows and invariants.
- - Record only what code, git history and the README do not already show. Test each line: would an agent put a change in the wrong place without it?
- - State what is true now. No aspirations, no roadmap, no progress; a stale doc is worse than none.
- - Anchor to paths and symbol names, never line numbers.
- - Give each fact one home. Point to the schema, the config or PROJECT.md instead of copying.
- - Keep the headings exactly as in the contract, so agents can grep them. Prefer tables and numbered steps to paragraphs.
- - State a rule once with its reason. No capitals for emphasis.
- - Over 250 lines, split by component into `docs/design/<component>.md`. DESIGN.md keeps Overview, the diagram, one linked line per component, Decisions and the Change guide.
+ - Tokens carry exact values and prose carries the reason. A token without a role sentence gets used arbitrarily; a role sentence without a token gets approximated.
+ - One role per colour ("the sole driver for interaction"), not a mood. `primary` is required.
+ - Name every typeface with its source (system stack, a Google Fonts family, the project's own files). No list of acceptable typefaces is a mandate.
+ - Components reference tokens with `{path}` instead of repeating a value; a hover or pressed state is its own key (`button-primary-hover`). Define a colour only where a component uses it: the linter warns about an orphaned token, except for the standard family names (`primary`, `secondary`, `tertiary`, `error`, `surface`, `background`, `outline`) and for a family some component already references.
+ - Elevation has no token group in the spec: write the shadow values in prose under Elevation & Depth.
+ - Do's and Don'ts are concrete and checkable ("one primary button per view"). Carry the patterns the brief rules out, from `${CLAUDE_PLUGIN_ROOT}/skills/frontend-design/references/anti-slop.md`.
+ - Write the tokens in the front matter. The 0.4.0 parser also merges every fenced `yaml` block in the file into the tokens, although its bundled spec does not document them, so keep no illustrative `yaml` fence in a DESIGN.md: a repeated top-level key rejects the file.
+ - Sections keep the spec's order and names, so agents and the linter can find them. Leave a section out with `omitted:` and a reason, not with an empty heading.
+ - State what is true now. When the theme file and DESIGN.md disagree, that is an audit finding and the user decides which wins.
- Write in the project's documentation language, English by default.
## Update rules
- Update DESIGN.md in the same change as the code when a change:
-
- 1. Adds, removes or renames a component.
- 2. Moves a boundary or a dependency.
- 3. Alters a main data flow.
- 4. Breaks or adds an invariant.
- 5. Makes a Change guide row wrong.
-
- Then refresh the Last reviewed stamp. A change that touches none of these needs no edit.
+ Update DESIGN.md in the same change as the code when a change alters a token value in the theme, adds a component style, or changes the direction. Run `npx @google/design.md@0.4.0 diff DESIGN.md.old DESIGN.md` against the previous copy (it exits 1 on regressions) and lint again.
## Audit checklist
- - Every cited path and symbol exists.
- - Components describe responsibilities, not file listings.
- - Every invariant has a verify entry that runs.
- - The Change guide covers the last few real changes in the git log.
- - No decision also lives in PROJECT.md.
- - No status, roadmap or aspiration lines.
- - Under 250 lines, or split.
- - A pointer from the rules file exists.
+ - Lint exits 0, no `broken-ref`, and each warning is explained.
+ - Every colour has a role sentence; Do's and Don'ts are checkable rules.
+ - Token values match the theme files (grep both).
+ - Text roles on their surfaces meet 4.5:1 (3:1 for large text).
+ - Every typeface has a named source.
+ - It is a visual file: YAML tokens first, not an architecture doc.
+ - 300 lines or fewer, and a path-scoped pointer exists.
## References
| File | Load when |
|---|---|
- | `${CLAUDE_SKILL_DIR}/assets/DESIGN.template.md` | Writing or restructuring an architecture doc |
+ | `${CLAUDE_SKILL_DIR}/references/visual-identity.md` | Always, before writing: schema, section order, lint rules, exports |
+ | `${CLAUDE_SKILL_DIR}/assets/DESIGN.template.md` | Writing or restructuring the file |
| `${CLAUDE_SKILL_DIR}/references/example.md` | Matching register and level of detail |
- | `${CLAUDE_SKILL_DIR}/references/visual-identity.md` | The file is a UI token spec |
-
- Basis for the format: Kiro's spec design phase (`https://kiro.dev/docs/specs/index`: system architecture, data flow, error handling and testing strategy), Anthropic's memory docs (`https://code.claude.com/docs/en/memory.md`) and context engineering article (`https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents`). The Invariants table with a verify column, the Change guide and the update-in-the-same-change rule are this skill's own additions.