What Validation Rules Does the `lint` Command Enforce in Design.md?

The lint command in the Design.md CLI enforces 11 built-in validation rules that check for structural integrity, token completeness, accessibility compliance, and schema conformance across your DESIGN.md files.

The Design.md CLI provides a robust linting pipeline that parses your design system markdown, builds a typed model, and validates it against a strict rule set. Understanding the specific validation rules the lint command enforces helps you maintain consistent, accessible, and error-free design tokens before they reach production.

Structural and Schema Validation

The linter first ensures your document structure follows the expected schema and contains all required sections.

Unknown Key Detection

The unknown-key rule (implemented in packages/cli/src/linter/rules/unknown-key.ts) runs at the warning level to catch top-level YAML keys that appear to be typos of known schema keys. It computes the Levenshtein edit distance (maximum of 2) against the canonical SCHEMA_KEYS constant and suggests the closest valid match. The implementation uses a fast pre-filter on length difference before running the full levenshtein() algorithm to find the best match.

Required Sections

The missing-sections rule validates that required top-level sections—such as palette, typography, and tokens—are present in the markdown document. It checks the state.documentSections array against a constant list of required headings and emits a warning if any are absent.

Section Ordering

The section-order rule enforces conventional markdown organization by comparing the order of headings in state.documentSections against a predefined sequence (for example, ensuring Palette appears before Tokens). This rule runs at the info level and helps maintain consistent documentation structure across projects.

Token Integrity and References

These rules validate that your design tokens are complete, correctly typed, and properly referenced throughout the system.

Primary Token Requirement

The missing-primary rule (severity: error) ensures your design system defines a primary color or token required for generating a complete Tailwind theme. It scans state.tokens for the primary key and emits an error if absent, preventing incomplete palette generation.

Typography Definitions

The missing-typography rule checks for missing typography definitions—including font-size, line-height, and related properties—that the schema expects. It scans state.typography for required sub-keys and reports any gaps at the warning level.

Type Validation

The types rule (severity: error) validates that token values match their declared types in the schema—such as ensuring color strings follow valid formats and numeric sizes contain numbers. It checks each token against its type field and reports mismatches that could break downstream consumption.

Reference Integrity

The broken-ref rule detects YAML references ($ref) that point to non-existent tokens or sections. It walks the reference graph and reports dangling pointers at the error level, preventing broken dependencies in your design system.

Orphaned Tokens

The orphaned-tokens rule identifies tokens defined but never referenced elsewhere in the system. It traverses the token graph and reports any nodes with zero inbound edges as warnings, helping you eliminate unused variables that clutter the codebase.

Token Typo Detection

The token-like-ignored rule applies the same Levenshtein-distance heuristic as unknown-key but specifically to token names. It warns when a token appears to be a typo of a known token (for example, --primary-colr instead of --primary-color), catching misspellings before they propagate.

Accessibility and Quality Checks

WCAG Contrast Compliance

The contrast-ratio rule (severity: error) validates WCAG contrast ratios between foreground and background color pairs. It computes relative luminance and flags combinations that fall below accessibility thresholds—4.5:1 for normal text and 3:1 for large text—ensuring your design system meets accessibility standards.

Token Summary Reporting

The token-summary rule provides a high-level informational report of token counts per category (color, spacing, typography, etc.). It aggregates token keys by prefix and emits a summary finding for quick sanity-checking of your design system's scope.

How the Linter Executes Rules

When you invoke the lint command, the pipeline defined in packages/cli/src/linter/lint.ts executes three phases:

  1. Parsing: The ParserHandler converts the markdown into an AST.
  2. Model Building: The ModelHandler resolves tokens into a strongly-typed DesignSystemState.
  3. Rule Execution: The runLinter function (from packages/cli/src/linter/runner.ts) loads the DEFAULT_RULES array and executes each rule against the state, collecting Finding objects.

The runner aggregates findings by severity (error, warning, info) and returns a LintReport that the CLI formats for display.

Running the Linter

Command Line Usage

Execute the linter against your design document:


# From the repository root

npm install
npx design-md lint path/to/DESIGN.md

The command outputs a severity summary and specific findings:


✖ 3 errors, ⚠ 5 warnings, ℹ 2 infos
  - unknown-key: "colou" – did you mean "color"?
  - contrast-ratio: "primary" vs "background" contrast 2.9:1 (needs ≥ 4.5:1)
  - missing-primary: primary colour not defined

Programmatic API

Import the lint function to validate design systems in code:

import { lint } from '@design-md/cli';

const designMd = await readFile('DESIGN.md', 'utf-8');
const report = lint(designMd);

if (report.summary.errors) {
  console.error('Design system has errors – fix them before publishing.');
}

Custom Rule Injection

Override the default rule set by passing custom rules via LintOptions:

import { lint, LintOptions, LintRule } from '@design-md/cli';

const myRule: LintRule = {
  name: 'my-custom-rule',
  severity: 'info',
  description: 'Example of a custom rule.',
  run: (state) => [{ path: 'custom', message: 'All good!' }],
};

const opts: LintOptions = { rules: [myRule] };
const report = lint(designMd, opts);

Summary

  • The Design.md CLI lint command enforces 11 distinct validation rules located in packages/cli/src/linter/rules/.
  • Rules cover four domains: structural validation (unknown keys, section order), token integrity (missing primary, broken refs, orphaned tokens), accessibility (contrast ratios), and quality reporting (token summaries).
  • Severities range from error (blocking) to info (advisory), with critical issues like missing primary colors or failed contrast ratios preventing successful validation.
  • The linting pipeline runs through packages/cli/src/linter/lint.ts, which coordinates parsing, model building, and rule execution via runLinter and DEFAULT_RULES.
  • You can extend or override the default rule set programmatically using the LintOptions.rules array.

Frequently Asked Questions

How does the contrast-ratio rule calculate accessibility compliance?

The contrast-ratio rule computes the relative luminance of foreground and background color pairs according to WCAG 2.1 specifications. It validates that normal text meets a 4.5:1 contrast ratio and large text meets a 3:1 ratio, emitting an error for any pair that falls below these thresholds.

Can I disable specific validation rules?

Yes. While the CLI uses DEFAULT_RULES from packages/cli/src/linter/runner.ts by default, you can override the rule set programmatically by providing a custom rules array in the LintOptions parameter when calling the lint function directly.

What happens if I misspell a top-level YAML key?

The unknown-key rule detects likely misspellings by calculating the Levenshtein distance between your key and known schema keys. If the distance is 2 or less, it suggests the closest valid key, helping you catch typos like colou instead of color before they cause parsing failures.

Does the linter check for unused design tokens?

Yes. The orphaned-tokens rule traverses the token reference graph and reports any tokens with zero inbound references. This identifies defined variables that are never consumed, allowing you to clean up dead code from your design system.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →