CLI tool
google-labs-code/design.md avatar
google-labs-code/design.md

DESIGN.md: a token-plus-prose format that keeps coding agents on brand

A format specification for describing a visual identity to coding agents. DESIGN.md gives agents a persistent, structured understanding of a design system.

28,163 stars2,283 forksTypeScriptApache-2.0

At a glance

What is it?
DESIGN.md is a specification from google-labs-code for describing a visual identity to coding agents. It pairs YAML design tokens with markdown rationale, and ships a CLI that lints and diffs the file.
Who is it for?
Adopt DESIGN.md if you already hand a coding agent a repository and want its output to stop drifting from your palette, type scale and component tokens; the lint and diff commands give you a machine-checkable gate before a design change reaches generated UI. Skip it if your styling already lives in a typed theme object that a compiler validates, because you would be maintaining a second source of truth with no build-time enforcement.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What DESIGN.md solves, and for whom

A coding agent asked to build a settings page will invent a grey. It has no persistent knowledge of your palette, so every session re-derives spacing, corner radius and type scale from whatever it saw in the prompt. DESIGN.md is a file format intended to close that gap: a single document at the root of a repository that an agent reads before writing UI. The README describes the goal as giving agents "a persistent, structured understanding of a design system".

The audience is narrow and specific. It is for teams that already delegate UI work to an agent and have a design system worth preserving, and for design engineers who want the system expressed in something an agent can parse rather than in a Figma file it cannot open. It is not a component library, not a CSS framework, and not a runtime. Nothing in the specification generates styles; the file is an input to whatever writes the code.

Tokens are normative, prose is context

The format has two layers. YAML front matter delimited by --- fences at the top of the file holds the tokens. A markdown body organised into ## sections holds the rationale. The specification is explicit about precedence: the tokens are the normative values, and the prose provides context for how to apply them. That split is the whole design. A palette entry gives an agent #1A1C1E; the Overview section tells it that the result should read as "Architectural Minimalism meets Journalistic Gravitas", which is the difference between a correct hex value and a correct page.

The token schema covers colors, typography, rounded, spacing and components. Values can be any CSS color, including oklch() and named colors, or a dimension with a px, em or rem unit. Cross-references use brace syntax such as {colors.primary}, and components map a name to a group of sub-tokens:

yaml
components:
  button-primary:
    backgroundColor: "{colors.tertiary}"
    textColor: "{colors.on-tertiary}"
    rounded: "{rounded.sm}"
    padding: 12px

Valid component properties are backgroundColor, textColor, typography, rounded, padding, size, height and width. Variants are not a nested concept: hover, active and pressed states are separate component entries with related key names, so button-primary-hover sits beside button-primary as a peer. The body sections are also ordered. Overview, Colors, Typography, Layout, Elevation & Depth, Shapes, Components and Do's and Don'ts must appear in that sequence when present, though any of them may be omitted. The format is deliberately tolerant elsewhere: an unknown section heading is preserved rather than rejected, an unknown color or typography token name is accepted if its value is valid, and an unknown component property is accepted with a warning. A duplicate section heading is the one structural failure that rejects the file outright.

Installing the CLI and linting a first file

The tooling lives in the @google/design.md package on npm. The README gives the install as a plain npm command, and notes that Windows shells which treat @ specially need the package name quoted.

bash
npm install @google/design.md

If you would rather not add a dependency, the same package runs through npx and always resolves from the public registry:

bash
npx @google/design.md lint DESIGN.md

There is a Windows caveat worth reading before you file a bug. In PowerShell the direct npx form can produce no output, or open DESIGN.md in your markdown editor, because the .md suffix in the design.md bin name collides with the Windows file association during command resolution. The documented workaround points npx at the package with -p and invokes the dot-free designmd alias instead:

bash
npx -p @google/design.md designmd lint DESIGN.md

The README states that designmd resolves to the same entrypoint and behaves identically on every platform, and that the alias should also be used inside package.json scripts rather than the original bin name. Output defaults to JSON, and every command accepts a file path or - for stdin. A lint run returns findings with a severity, a path such as components.button-primary, a message, and a summary counting errors, warnings and infos. The README's own example shows a contrast finding reporting a ratio of 15.42:1 against WCAG AA. If npm fails with ENOVERSIONS, the README attributes it to npm not querying the public registry, whether from a custom registry= in .npmrc, a corporate mirror that has not synced the package, or a misconfigured @google:registry scope, and suggests checking npm config get registry and clearing the cache after fixing config.

Diffing two versions to catch token and prose regressions

The second command compares two revisions of a design system. It reports added, removed and modified tokens per category (colors, typography, rounded, spacing, components), the finding counts before and after with a delta, and a boolean regression flag.

bash
npx @google/design.md diff DESIGN.md DESIGN-v2.md

This is the more interesting half of the toolchain. A lint pass tells you whether one file is internally consistent; a diff tells you whether a change to the system altered a token that generated UI elsewhere depends on. Because the output is structured JSON with a regression boolean, it can gate a pull request without a human reading the whole report. The README does not document how the regression flag is computed, so treat it as a signal to inspect the token lists rather than as a verdict you can trust blind. The README also does not document rollback or a way to apply a diff, which is consistent with the tool being a checker rather than a migration tool.

Where the format gets in the way

The tolerance rules cut both ways. Accepting an unknown color token name if its value parses means a typo in a token name produces a valid-looking file with a token nobody references, and the linter will not stop you. The same applies to unknown typography names. Only duplicate section headings are fatal, so a file can accumulate near-duplicate tokens indefinitely and still lint clean apart from warnings.

Ordering is enforced but optionality is not symmetric: you can drop Elevation & Depth entirely, which is fine for a flat system and a silent gap for one that uses shadow to convey hierarchy. Components are the weakest part of the schema. Variants as sibling entries means button-primary-hover is a convention rather than a relationship the format understands, and nothing in the specification ties a hover entry back to its base. There is also no documented way to express a component that composes another, so a card containing a button has to repeat the button's tokens or reference them by hand. Finally, the file is only as good as the agent reading it. Nothing in the specification forces a coding agent to consult DESIGN.md, and there is no runtime that applies the tokens. If your agent ignores the file, the lint output is still green and the UI is still wrong.

How this differs from a typed theme object

The obvious alternative is a theme object in code, the pattern used by CSS-in-JS libraries and by Tailwind-style config files, where tokens are exported as a typed constant and imported by every component. The difference is enforcement. A typed theme object is checked by the compiler: rename a token and the build fails at every call site. DESIGN.md is checked by a linter that runs on the document, not on the code that consumes it, so a stale reference in a component is invisible to @google/design.md lint. What the format buys in exchange is that the artifact is readable by a model without a build step and carries prose the model can act on. A theme object has no place to record that the palette should evoke a matte finish. Teams that need both end up maintaining the file and the theme object, which is the real cost of adoption and the reason this format suits repositories where an agent, not a compiler, is the primary consumer.

Licence, releases and what maintenance looks like

The repository is Apache-2.0, which permits commercial use and modification and requires that you preserve the licence and notice files; it also includes a patent grant. That matters if you vendor the specification text or the CLI into an internal tool. This is not legal advice, and the LICENSE file at the repository root is the authority rather than this summary.

The last push to the default branch was on 2026-07-27, the same day as the 0.4.0 release. The two prior releases, 0.3.0 and 0.2.0, landed on 2026-06-15 and 2026-05-26, so the project has been shipping on a roughly monthly cadence across that window. The repository is not archived. The monorepo is managed with bun as the declared package manager and turbo for the build, test and lint scripts, with workspaces under packages/*. The full specification lives at docs/spec.md, and the README notes that the condensed reference it contains is not the complete document, so anything you implement against should be checked there. Upgrading between 0.x releases is where the cost sits: the token schema carries an optional version field whose current documented value is "alpha", and a pre-1.0 format can change shape between minor versions. Pin the CLI version in CI and read the release notes before bumping.

Editorial conclusion

Adopt DESIGN.md if you already hand a coding agent a repository and want its output to stop drifting from your palette, type scale and component tokens; the lint and diff commands give you a machine-checkable gate before a design change reaches generated UI. Skip it if your styling already lives in a typed theme object that a compiler validates, because you would be maintaining a second source of truth with no build-time enforcement. Before committing, verify three things: that your registry resolves @google/design.md, that your team can live with duplicate ## headings being a hard error, and that your agent actually reads the file rather than the prose alone.

Frequently asked questions

What is the design.md file?

It is a format specification for describing a visual identity to coding agents, combining machine-readable design tokens in YAML front matter with human-readable design rationale in markdown prose. The README states that the tokens are the normative values and the prose explains why those values exist and how to apply them.

How do I install design.md?

Install the CLI from npm with npm install @google/design.md, or run it without installing via npx @google/design.md lint DESIGN.md. On Windows shells that treat @ specially, the README says to quote the package name.

How do I use design.md in Claude?

The documented workflow is to place a DESIGN.md file in the repository and let the agent read it before generating UI; the README states that an agent reading the file will produce a UI with the specified typefaces, background and call-to-action colors. The repository materials do not document a Claude-specific integration.

How do I use design.md in Cursor?

The same file-based approach applies: the DESIGN.md sits in the repository and the coding agent reads it as context. No Cursor-specific setup is documented in the README or the repository files.

How do I make my own design.md file?

Write YAML front matter delimited by --- fences containing name, colors, typography, rounded, spacing and components tokens, then add ## sections in the required order. The full specification is at docs/spec.md, and the README's condensed reference lists the section order and the valid component properties.

Who created design.md?

The repository is published under the google-labs-code organisation and the npm package is scoped as @google/design.md. The homepage points to a specification page under stitch.withgoogle.com.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/google-labs-code-design-md.svg)](https://hysenlabs.com/projects/google-labs-code-design-md)