Inject DESIGN.md Context
Inject DESIGN.md context into a session
Section titled “Inject DESIGN.md context into a session”Goal: load a project’s committed visual identity (its
DESIGN.md) plus the format’s lint rules into agent context, so UI work stays on-brand without re-deriving the design system each session. Concepts and the decisions behind this surface live in the DESIGN.md explanation.
Prerequisites
Section titled “Prerequisites”- The project has a committed
DESIGN.mdat its root (or you want the clean no-op guidance for adopting one). - The
design-md-contextregistry skill is provisioned to the project (cdprov add skill design-md-context), or you invoke the script directly. jq; network for the firstnpxfetch of the pinned CLI (offline runs degrade gracefully — see below).
From a Claude Code session
Section titled “From a Claude Code session”Provisioned projects load the skill automatically; ask for the design system (“load the design tokens”, “apply the design system”) or run the script as the skill instructs. The skill treats the emitted envelope as authoritative design context for all subsequent UI generation.
From a regular terminal
Section titled “From a regular terminal”The script is a plain executable with no session dependency — there is no
global bin/ entrypoint because the skill is provisioned per-project
(web apps only), while bin/ is reserved for universal tooling:
~/.claude/registry/skills/design-md-context/scripts/design-context.sh /path/to/projectWorked example
Section titled “Worked example”A project with this DESIGN.md at its root:
---name: Heritagecolors: primary: "#1A1C1E" neutral: "#F7F5F2"typography: body-md: fontFamily: Public Sans fontSize: 1remrounded: md: 8pxspacing: md: 16px---
## Overview
Architectural minimalism — deep ink on warm limestone.Running the script:
$ ~/.claude/registry/skills/design-md-context/scripts/design-context.sh ~/projects/heritage-site{ "present": true, "path": "/Users/you/projects/heritage-site/DESIGN.md", "design_md": "---\nname: Heritage\ncolors:\n primary: \"#1A1C1E\"\n ...", "rules": { "rules": [ { "name": "broken-ref", "severity": "error", "description": "Broken/circular references and unknown component sub-tokens." }, { "name": "contrast-ratio", "severity": "warning", "description": "WCAG contrast ratio — warns when component backgroundColor/textColor pairs fall below the AA minimum of 4.5:1." } ] }, "rules_source": "spec-rules-only", "cli": "@google/design.md@0.3.0"}design_md is the verbatim file — inject tokens and prose. rules is what
the lint gate (#903) will enforce, so the agent designs within the rules
rather than discovering them at commit time.
On a project without a DESIGN.md:
$ ~/.claude/registry/skills/design-md-context/scripts/design-context.sh /tmp/some-cli-repo{ "present": false, "root": "/tmp/some-cli-repo", "guidance": "No DESIGN.md at the project root. To adopt one: author it by hand (YAML front-matter tokens + prose rationale), extract it from existing code, or generate it upstream via Google Stitch. See docs/explanation/design-md.md in the BoB source repo."}Exit code is 0 in both cases — absence is a legitimate state, not an error.
Degraded modes
Section titled “Degraded modes”| Condition | Behavior |
|---|---|
No DESIGN.md |
present: false + adoption guidance, exit 0. |
npx unreachable (offline) |
Envelope still emitted; rules: null, rules_source: "unavailable"; the skill’s built-in format essentials cover the gap. |
Missing jq |
Hard error, exit 1 — the only real failure mode. |
Output is deterministic for a given DESIGN.md — no timestamps, safe to
cache and diff.
Enable the lint gate
Section titled “Enable the lint gate”The same skill ships a lint gate with two wirings — session hook and CI
check — both delegating to scripts/design-lint-check.sh (exit 0 pass or
no-DESIGN.md no-op, 1 findings at threshold, 2 environment failure).
Session hook (lint on every agent edit)
Section titled “Session hook (lint on every agent edit)”Add to the project’s .claude/settings.json. The command is bare — the hook
reads stdin JSON per the BoB hook convention:
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "~/.claude/registry/skills/design-md-context/hooks/design-md-lint-hook.sh" } ] } ] }}Edits to any other file pass silently; a DESIGN.md edit that fails lint feeds the findings straight back to the agent (exit-2 stderr), so broken token references or WCAG contrast failures are fixed in the same turn they are introduced.
CI check
Section titled “CI check”Run the check script as a CI step (or a checks entry in dev.json so
warp-drive’s check-runner picks it up):
- name: DESIGN.md lint run: ~/.claude/registry/skills/design-md-context/scripts/design-lint-check.sh . --fail-on warning{ "checks": [ { "name": "design-md-lint", "kind": "lint", "command": "~/.claude/registry/skills/design-md-context/scripts/design-lint-check.sh ." } ] }Findings are structured JSON on stdout (severity, path, message, summary counts), so downstream tooling parses results instead of scraping text.
Windows: the CLI binary design.md breaks Windows cmd shims, so upstream
also ships a designmd alias. Both wirings invoke the package pin via
npx @google/design.md@0.3.0, which resolves the correct per-platform shim —
no OS branching needed in project config.
Enable the diff check (PR regression gate)
Section titled “Enable the diff check (PR regression gate)”scripts/design-diff-check.sh diffs the base-branch DESIGN.md against the
head and fails on regression — wire it as a PR check:
# .github/workflows/ci.yml — PRs need the base ref available- uses: actions/checkout@v4 with: { fetch-depth: 0 }- name: DESIGN.md diff gate run: ~/.claude/registry/skills/design-md-context/scripts/design-diff-check.sh . --gate removedPick the gate by how strict the design system is:
--gate |
Fails when | Use for |
|---|---|---|
removed (default) |
A token is removed or the file deleted | Most projects — additive change stays cheap. |
modified |
Removed or any token value changed | Locked-down brand systems. |
any |
Any token change, including additions | Systems where every token change needs design sign-off. |
none |
Never (advisory) | Annotate-only: parse the JSON and comment on the PR. |
A DESIGN.md that is new in the branch passes (nothing to regress against);
one deleted in the branch fails any non-advisory gate. --base <ref>
overrides the default merge-base comparison.
Export tokens for downstream consumers
Section titled “Export tokens for downstream consumers”design.md export derives build-ready token artifacts from the committed
DESIGN.md — it owns the token→Tailwind path wherever a DESIGN.md
exists. (scaffold-tokens.sh from the design-systems skill remains only
for projects with a standalone tokens.json and no DESIGN.md — never run
both, per the
reconciliation.)
--format |
Output | Consumer |
|---|---|---|
css-tailwind |
Tailwind v4 CSS @theme block of custom properties |
Tailwind v4 projects — import the CSS. |
json-tailwind (alias tailwind) |
Tailwind v3 theme.extend JSON |
Tailwind v3 tailwind.config.js. |
dtcg |
W3C Design Tokens (2025.10 schema) tokens.json |
Style Dictionary, Figma token plugins, any DTCG-aware pipeline. |
Worked example
Section titled “Worked example”Generating the Tailwind v4 theme for the Heritage project from the earlier example, committed as a derived artifact:
$ cd ~/projects/heritage-site$ npx @google/design.md@0.3.0 export DESIGN.md --format css-tailwind > src/styles/design-tokens.css$ cat src/styles/design-tokens.css@theme { --color-primary: #1a1c1e; --color-neutral: #f7f5f2; --font-body-md: "Public Sans"; --text-body-md: 1rem; --radius-md: 8px; --spacing-md: 16px;}The same source emits a Tailwind v3 config fragment —
$ npx @google/design.md@0.3.0 export DESIGN.md --format json-tailwind{ "theme": { "extend": { "colors": { "primary": "#1a1c1e", "neutral": "#f7f5f2" }, "fontFamily": { "body-md": ["Public Sans"] }, ... } }}— or a DTCG tokens.json (--format dtcg) for design-tool pipelines.
Re-export in CI after any DESIGN.md change (or in the same commit), so the
derived artifacts never drift from the owned source.