How to Compare Two DESIGN.md Files Using the design.md CLI

The design.md diff command compares two DESIGN.md documents and reports differences in design tokens, components, and lint findings, exiting with code 1 if the newer file introduces regressions.

The google-labs-code/design.md repository provides a specialized toolchain for managing design system documentation. When you need to compare two DESIGN.md files for changes, the built-in diff command offers a comprehensive solution that analyzes token maps, component definitions, and lint results. This guide explains how to use both the CLI interface and programmatic API to detect additions, removals, and modifications between design system versions.

Understanding the design.md diff Command

The design.md diff command is implemented in packages/cli/src/commands/diff.ts and orchestrates a multi-stage comparison pipeline. It uses the citty command-definition library to provide a clean CLI interface with automatic help generation. The command accepts two file paths (or STDIN references using -) and produces a structured report showing exactly what changed between the design system definitions.

Step-by-Step Diff Workflow

The comparison process follows a strict workflow that ensures accurate detection of design system changes.

Reading Input Files

The process begins with the readInput helper defined in packages/cli/src/utils.ts. This utility loads each file from the supplied path or from STDIN (-). If a file cannot be read, the utility prints a JSON error and exits with code 2.

Linting and Resolution

Both files are processed through the lint function from packages/cli/src/linter/lint.ts. This parses the markdown, resolves the design-system model, runs default lint rules, and returns a LintReport containing fully resolved token maps and a summary of findings.

Comparing Token Maps

The generic diffMaps utility in packages/cli/src/utils.ts walks two Map<string, V> objects and produces three arrays: added, removed, and modified. This utility handles all token categories including colors, typography, rounded corners, and spacing.

Component Serialization

Because components are stored as Map<string, ComponentDef>, the command converts each component's property map into a plain object before diffing. This serialization step ensures accurate comparison of component definitions between versions.

Report Generation and Exit Codes

The command assembles a structured object containing per-token diffs, lint-finding changes, and a boolean regression flag. This flag is set to true when the "after" file contains more errors or warnings than the "before" file. The process exits with code 1 on regression, code 2 on file read errors, and code 0 on success, enabling CI pipelines to detect breaking changes automatically.

CLI Usage Examples

You can compare DESIGN.md files directly from the command line using the design.md diff command.

Compare two files and get JSON output (default):

design.md diff ./examples/paws-and-paths/DESIGN.md ./examples/totality-festival/DESIGN.md

Generate a human-readable Markdown diff:

design.md diff ./design1.md ./design2.md --format markdown

Programmatic API Usage

For integration into Node.js applications, you can import the underlying utilities directly from the @google/design.md package.

import { readInput } from '@google/design.md/src/utils.js';
import { lint } from '@google/design.md/src/linter/index.js';
import { diffMaps } from '@google/design.md/src/utils.js';

// Load two files
const before = await readInput('path/to/before.md');
const after = await readInput('path/to/after.md');

// Lint both files
const beforeReport = lint(before);
const afterReport = lint(after);

// Diff token maps
const tokenDiff = {
  colors: diffMaps(beforeReport.designSystem.colors, afterReport.designSystem.colors),
  typography: diffMaps(beforeReport.designSystem.typography, afterReport.designSystem.typography),
  spacing: diffMaps(beforeReport.designSystem.spacing, afterReport.designSystem.spacing)
};

// Inspect the diff
console.log('Added colors:', tokenDiff.colors.added);
console.log('Removed colors:', tokenDiff.colors.removed);
console.log('Modified typography:', tokenDiff.typography.modified);

Key Implementation Files

The diff functionality is distributed across several modules in the packages/cli directory:

Summary

  • The design.md diff command in packages/cli/src/commands/diff.ts provides automated comparison of DESIGN.md files.
  • The diffMaps utility in packages/cli/src/utils.ts handles deep comparison of token maps and component definitions.
  • Exit codes (0, 1, 2) enable CI/CD integration for detecting design system regressions.
  • Output formats include JSON (default) and Markdown via the --format flag.
  • Programmatic access is available through readInput, lint, and diffMaps exports.

Frequently Asked Questions

How do I compare DESIGN.md files from standard input?

Use the hyphen character (-) as the file path for either argument. The readInput helper in packages/cli/src/utils.ts detects this and reads from STDIN instead of the filesystem, allowing you to pipe output from other commands directly into the diff tool.

What exit codes does the diff command return?

The command returns three specific exit codes: 0 indicates no regressions detected, 1 indicates the "after" file has more errors or warnings than the "before" file (regression), and 2 indicates a file read error occurred. These codes allow CI pipelines to fail builds automatically when design system changes introduce new issues.

Can I use the diff logic programmatically in my Node.js application?

Yes. Import readInput, lint, and diffMaps from @google/design.md/src/utils.js and @google/design.md/src/linter/index.js respectively. This allows you to programmatically compare token maps and component definitions without invoking the CLI, giving you fine-grained control over the comparison logic and output formatting.

What types of changes does the diff command detect?

The command detects changes across all design token categories including colors, typography, rounded corners, and spacing, as well as component definitions. It categorizes changes as added, removed, or modified and tracks lint finding differences between versions.

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 →