Lint Rules Overview
The @google/design.md CLI provides four sub-commands: lint (validate a file), diff (compare two files), export (emit tokens in other formats), and spec (print the format specification). In 0.4.0, eleven built-in rules cover structural correctness, broken references, WCAG contrast, token completeness, token-like keys the schema ignores, and the omitted declarations.
Last reviewed against @google/design.md 0.4.0 (released July 27, 2026). The changelog lists what changed in each release.
Invocation#
The CLI is shipped as the design.md binary inside @google/design.md. Use npx to run it without a global install:
npx @google/design.md <command> [args]
The binary name is design.md. An alias designmd is also registered in the package. Both point to the same entry point (dist/index.js). The package declares Node.js 18 or newer.
Commands#
lint#
Validate a DESIGN.md file for structural correctness and run all built-in lint rules.
npx @google/design.md lint <file> [--format json|markdown]
Arguments:
Exit codes: 1 if any error-severity findings are present; 0 otherwise; 2 if the file cannot be read.
Example output (a file with four colors, none of them named primary):
{
"findings": [
{
"severity": "warning",
"path": "colors",
"message": "No 'primary' color defined. The agent will auto-generate key colors, reducing your control over the palette.",
"rule": "missing-primary"
},
{
"severity": "info",
"message": "Design system defines 4 colors, 2 typography scales, 2 rounding levels, 2 spacing tokens.",
"rule": "token-summary"
}
],
"summary": { "errors": 0, "warnings": 1, "infos": 1 }
}
The JSON report#
Each entry in findings has these fields:
severity:error,warning, orinfo.path: where the finding points, such ascolorsorcomponents.button-primary. Findings about the file as a whole, such astoken-summaryandsection-order, have nopath.message: the human-readable explanation.rule: the id of the rule that produced the finding (added in 0.4.0). It matches the rule names below, except thatomitted-rulesreports under three ids of its own:declared-omission,redundant-omission, andunknown-omission.
The summary object counts findings by severity in errors, warnings, and infos.
Because rule findings name their rule, you can filter the report by rule id:
npx @google/design.md lint DESIGN.md | jq '[.findings[] | select(.rule == "contrast-ratio")]'
The viewer at /tool shows the same rule id next to each finding and links it to the matching page in this guide.
Checks without a rule field#
Some findings come from building the token model rather than from a lint rule, so they carry no rule field and appear before the rule findings. Invalid color values and invalid dimension units are reported this way, and 0.4.0 adds two more checks:
- A typography token with a property the spec does not define, such as a misspelled
lineHeigth, produces a warning attypography.<token>.<property>. - A flattened dot-notation key that collides with a nested group in
colors,rounded, orspacingproduces an error.
[
{
"severity": "error",
"path": "colors.brand.accent",
"message": "Grouped colors token flattens to 'brand-accent', which is already defined."
},
{
"severity": "warning",
"path": "typography.body-md.lineHeigth",
"message": "'lineHeigth' is not a recognized typography property. Valid properties: fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, fontFeature, fontVariation."
}
]
The collision error above comes from a colors map that defines both brand-accent and a nested brand: group with an accent entry. Defining the same path twice, once as a quoted "surface.dim" key and once as a nested group, reports Duplicate token path 'colors.surface.dim' detected. instead. Collision errors count toward summary.errors, so they make lint exit with code 1.
Reading from stdin#
lint, diff, and export accept - as a file path to read from stdin. In 0.4.0 the argument parser takes a bare - for an option, so lint - stops with Missing required positional argument: FILE. Put -- in front of it, and keep any options before the --:
cat DESIGN.md | npx @google/design.md lint -- -
cat DESIGN.md | npx @google/design.md export --format css-vars -- -
When stdin is an interactive terminal instead of a pipe, the CLI prints Reading from stdin… Press Ctrl+D when done. to stderr, so it no longer looks frozen while it waits for input.
Missing or unreadable files#
If the file does not exist or cannot be read, the CLI prints a one-line error to stderr instead of a stack trace, writes nothing to stdout, and exits with code 2:
Error: "DESIGN.md" not found. Create a DESIGN.md file or pass "-" to read from stdin.
A file without read permission reports could not be read: permission denied after the path. diff and export handle unreadable files the same way.
diff#
Compare two DESIGN.md files and report added, removed, and modified tokens, plus a finding-count delta.
npx @google/design.md diff <before> <after> [--format json]
Arguments:
Exit codes: 1 if the after-file has more errors or more warnings than the before-file (regression); 0 otherwise; 2 if either file cannot be read.
Example output (the after-file adds accent, changes tertiary, and drops an unrecognized radius: key that token-like-ignored had flagged):
{
"tokens": {
"colors": { "added": ["accent"], "removed": [], "modified": ["tertiary"] },
"typography": { "added": [], "removed": [], "modified": [] },
"rounded": { "added": [], "removed": [], "modified": [] },
"spacing": { "added": [], "removed": [], "modified": [] },
"components": { "added": [], "removed": [], "modified": [] }
},
"findings": {
"before": { "errors": 0, "warnings": 1, "infos": 1 },
"after": { "errors": 0, "warnings": 0, "infos": 1 },
"delta": { "errors": 0, "warnings": -1 }
},
"regression": false
}
export#
Export DESIGN.md tokens to another format. The --format flag is required.
npx @google/design.md export <file> --format <format> [--prefix <prefix>]
Arguments:
Export targets:
Exit codes: 0 whenever the export is written, even if the source file has lint errors or warnings; 1 for an unknown --format value; 2 if the file cannot be read. Since 0.4.0 the export exit code no longer depends on lint findings, and export does not print them, so run lint as its own step when a pipeline should fail on errors.
The css-vars format: each color becomes --color-<name> with a lowercase hex value, each spacing token --spacing-<name>, and each rounded token --rounded-<name>. Dots in grouped token names become hyphens. Typography and component tokens are not part of this format in 0.4.0; css-tailwind includes font families and sizes. For a file with two colors, two spacing tokens, one rounded token, a typography token, and a component, export --format css-vars --prefix ds prints:
:root {
--ds-color-primary: #2d5bff;
--ds-color-surface: #ffffff;
--ds-spacing-sm: 8px;
--ds-spacing-md: 16px;
--ds-rounded-md: 8px;
}
Examples:
# Tailwind v4 CSS
npx @google/design.md export DESIGN.md --format css-tailwind > tokens.css
# W3C DTCG JSON
npx @google/design.md export DESIGN.md --format dtcg > tokens.json
# Tailwind v3 JSON (theme.extend)
npx @google/design.md export DESIGN.md --format json-tailwind > tailwind-tokens.json
# Plain CSS custom properties with a namespace prefix
npx @google/design.md export DESIGN.md --format css-vars --prefix ds > variables.css
spec#
Print the DESIGN.md format specification and, optionally, the active lint rules table.
npx @google/design.md spec [--rules] [--rules-only] [--format markdown|json]
Options:
Built-in lint rules#
Every built-in rule runs on every lint invocation; 0.4.0 ships eleven. Findings are grouped by severity: error (the lint exit code becomes 1), warning (file accepted with caveats), info (informational, no action required). Each finding's rule field names the rule that produced it.
broken-ref#
Severity: error (for unresolved token references); warning (for unknown component sub-token names)
What triggers it: The rule fires in two situations:
- A component property value is a token reference (
{path.to.token}) that does not resolve to any defined token. This produces anerror-severity finding. - A component property name is not one of the eight recognized sub-tokens (
backgroundColor,textColor,typography,rounded,padding,size,height,width). This produces awarning-severity finding.
Example finding:
{
"severity": "error",
"path": "components.button-primary",
"message": "Reference {colors.accent} does not resolve to any defined token.",
"rule": "broken-ref"
}
How to fix: Check the reference path against the token names defined in colors, typography, rounded, or spacing. Ensure the token exists before referencing it.
Full guide: Fixing broken-ref errors in DESIGN.md
missing-primary#
Severity: warning
What triggers it: The colors map has at least one entry, but no key named primary is present. The omitted key does not affect this rule.
Example finding:
{
"severity": "warning",
"path": "colors",
"message": "No 'primary' color defined. The agent will auto-generate key colors, reducing your control over the palette.",
"rule": "missing-primary"
}
How to fix: Add a primary entry to colors:
colors:
primary: "#1A1C1E"
Full guide: Fixing missing-primary warnings in DESIGN.md
contrast-ratio#
Severity: warning
What triggers it: A component defines both backgroundColor and textColor as values that resolve to colors (literal hex or resolved references such as {colors.primary}), and the computed WCAG contrast ratio between the two is below 4.5:1 (the WCAG AA minimum for normal text). The rule skips components where either property is absent or does not resolve to a color.
Example finding:
{
"severity": "warning",
"path": "components.button-secondary",
"message": "textColor (#818a91) on backgroundColor (#f7f5f2) has contrast ratio 3.23:1, below WCAG AA minimum of 4.5:1.",
"rule": "contrast-ratio"
}
How to fix: Increase the lightness contrast between backgroundColor and textColor until their ratio meets or exceeds 4.5:1. Render the file in the tool to see every failing pair with its ratio.
Full guide: Fixing contrast-ratio warnings in DESIGN.md
orphaned-tokens#
Severity: warning
What triggers it: The rule fires only when components is non-empty. A color token defined in colors is considered orphaned when no component's resolved backgroundColor or textColor references it, AND the token's color family (derived by stripping on-, inverse-, -container, -fixed, -dim, -bright, -tint, -variant suffixes) is not referenced by any component either, AND the family is not one of the seven Material Design 3 standard families (primary, secondary, tertiary, error, surface, background, outline).
Example finding:
{
"severity": "warning",
"path": "colors.promo",
"message": "'promo' is defined but never referenced by any component.",
"rule": "orphaned-tokens"
}
How to fix: Either reference the token in a component definition, or remove it if it is no longer needed.
Full guide: The orphaned-tokens rule in DESIGN.md
token-summary#
Severity: info
What triggers it: Always fires when the file contains at least one token in any of colors, typography, rounded, spacing, or components. It emits a single informational message summarizing the token counts.
Example finding:
{
"severity": "info",
"message": "Design system defines 4 colors, 3 typography scales, 2 rounding levels, 2 spacing tokens, 1 component.",
"rule": "token-summary"
}
How to fix: No action required. This is an informational diagnostic.
Full guide: Understanding token-summary in DESIGN.md
missing-sections#
Severity: info
What triggers it: The colors map is non-empty, and either spacing or rounded (or both) have no entries. The rule emits a separate finding for each absent section and skips any group listed in the omitted key.
Example findings:
[
{
"severity": "info",
"path": "spacing",
"message": "No 'spacing' section defined. Layout spacing will fall back to agent defaults.",
"rule": "missing-sections"
},
{
"severity": "info",
"path": "rounded",
"message": "No 'rounded' section defined. Corner rounding will fall back to agent defaults.",
"rule": "missing-sections"
}
]
How to fix: Add spacing and/or rounded sections if you want to express layout and rounding choices explicitly:
rounded:
sm: 4px
md: 8px
lg: 16px
spacing:
sm: 8px
md: 16px
lg: 32px
If the design system has no spacing or rounding scale on purpose, list the group under omitted instead (see omitted-rules).
Full guide: The missing-sections rule in DESIGN.md
missing-typography#
Severity: warning
What triggers it: The colors map is non-empty, but the typography map has no entries. The warning is not reported when typography is listed in the omitted key.
Example finding:
{
"severity": "warning",
"path": "typography",
"message": "No typography tokens defined. Agents will use default font choices, reducing your control over the design system's typographic identity.",
"rule": "missing-typography"
}
How to fix: Add at least one typography token. The recommended starting set:
typography:
body-md:
fontFamily: Inter
fontSize: 16px
fontWeight: 400
lineHeight: 1.6
Full guide: Fixing missing-typography warnings in DESIGN.md
section-order#
Severity: warning
What triggers it: Two or more of the eight canonical Markdown sections are present, and they appear in a different order than the canonical sequence: Overview, Colors, Typography, Layout, Elevation & Depth, Shapes, Components, Do's and Don'ts. The rule checks only sections whose headings match a canonical name or alias; custom sections do not affect the check. Only the first out-of-order pair is reported.
Example finding:
{
"severity": "warning",
"message": "Section 'Components' appears before 'Typography', which is out of order. Expected order: Overview, Colors, Typography, Layout, Elevation & Depth, Shapes, Components, Do's and Don'ts",
"rule": "section-order"
}
How to fix: Reorder the ## sections in the Markdown body to match the canonical sequence. The export command does not reorder prose, but the fixer utility (available in the JavaScript API via fixSectionOrder) can reorder sections automatically.
Full guide: Fixing section-order warnings in DESIGN.md
unknown-key#
Severity: warning
What triggers it: A top-level YAML key is not one of the nine recognized schema keys (version, name, description, omitted, colors, typography, rounded, spacing, components), AND the Levenshtein distance between the unknown key and the nearest known key is 2 or fewer characters (suggesting a typo). The comparison ignores case, so Colors is flagged with a suggestion of colors.
Keys that are more than 2 edits away from every known key get no unknown-key warning. If their values look like design tokens, token-like-ignored reports them instead; keys with other values are ignored silently.
Example finding:
{
"severity": "warning",
"path": "colour",
"message": "Unknown key \"colour\" \u2014 did you mean \"colors\"?",
"rule": "unknown-key"
}
The CLI prints an em dash between the key and the suggestion. The example writes it as the JSON escape \u2014, which decodes to the same character. Because this colour key holds color values, the same file also gets a token-like-ignored warning for it.
How to fix: Correct the spelling of the top-level key to match the recognized schema key.
Full guide: Fixing unknown-key warnings in DESIGN.md
token-like-ignored#
Severity: warning (added in 0.4.0)
What triggers it: A top-level key that is not a schema key holds a map whose values look like design tokens: a hex color (#RGB, #RGBA, #RRGGBB, or #RRGGBBAA), a dimension string such as 8px, 1.5rem, or 50%, or a typography property name (fontFamily, fontSize, fontWeight, lineHeight, letterSpacing). Nested maps are checked too. Distance to a schema key does not matter, so brandColors: is caught even though it is too far from colors for unknown-key. Export commands drop such keys without a trace, which is what the warning is about.
Example finding:
{
"severity": "warning",
"path": "brandColors",
"message": "\"brandColors\" looks like a design-token map but is not a recognized schema key (colors, typography, spacing, rounded, components). It will be silently ignored by export commands. Rename it to a supported key or move its values under a recognized section.",
"rule": "token-like-ignored"
}
How to fix: Move the values under the matching schema group (colors, typography, spacing, rounded, or components), or rename the key if it is a misspelling of one.
Full guide: Fixing token-like-ignored in DESIGN.md
omitted-rules#
Severity: info for declared omissions; warning for redundant or unknown entries (added in 0.4.0)
What triggers it: The optional omitted key lists token groups that a file leaves out on purpose. The rule checks every entry and reports under three ids:
declared-omission(info): the group is listed and has no tokens.redundant-omission(warning): the group is listed but defines tokens, so the entry has no effect.unknown-omission(warning): the name is not one ofcolors,typography,spacing,rounded, orcomponents.
Listing spacing or rounded silences missing-sections for that group, and listing typography silences missing-typography.
Example finding:
{
"severity": "info",
"path": "omitted.spacing",
"message": "spacing intentionally omitted \u2014 no spacing tokens will be validated",
"rule": "declared-omission"
}
How to fix: Keep declared omissions; they document intent. Remove an entry once the group has tokens, and correct misspelled group names.
Full guide: The omitted key in DESIGN.md
Rule severity summary#
| Rule | Severity | Summary |
|---|---|---|
broken-ref | error / warning | Unresolved token reference (error); unknown component sub-token name (warning). |
missing-primary | warning | Colors defined but no primary key present. |
contrast-ratio | warning | Component background/text pair fails WCAG AA (4.5:1). |
orphaned-tokens | warning | Color token defined but never referenced by any component. |
token-summary | info | Always fires; reports a token count summary. |
missing-sections | info | Colors defined but spacing or rounded absent and not listed in omitted. |
missing-typography | warning | Colors defined but no typography tokens, and typography not listed in omitted. |
section-order | warning | Canonical Markdown sections appear out of the defined order. |
unknown-key | warning | Top-level YAML key looks like a typo of a known schema key. |
token-like-ignored | warning | Unknown top-level key holds token-like values that export would drop. |
omitted-rules | info / warning | Validates the omitted list: declared (info), redundant or unknown (warning). |
Print the upstream version of this table from the CLI at any time:
npx @google/design.md spec --rules-only
For the full field reference, see DESIGN.md Field Reference.
Was this page helpful?