#ai-coding

How to Make Cursor and Claude Code Follow Your Design System

AI coding tools invent a new blue, a new grey and a new padding value in every file. Here is the setup that makes Cursor and Claude Code stick to your tokens, and how to check that they did.

·14 min read
How to Make Cursor and Claude Code Follow Your Design System

Someone recently found this site by typing a whole question into Google: "any recommendations for a tool that can get ai to respect our spacing and grid rules?" It's a good question, and a common one. You ask Cursor or Claude Code for a settings page and it comes back looking fine. Then you look closer. The button is bg-blue-500 when your brand color is teal. The card has 18px of padding when everything else uses 16 or 24. There's a grey you've never seen before.

The model isn't being careless. It simply doesn't know your rules, so it fills the gaps with what most code on the internet does. Telling it in chat helps for that one conversation. Next session, it's forgotten.

Before: three Save buttons the AI made in three chats, each a different blue (bg-blue-500, bg-[#2563eb], bg-sky-600) and size. After: three identical buttons, all bg-primary.
The same button asked for in three different chats. Without rules, you get three blues. With tokens and a rules file, you get the same button every time.

What works is a few small files that the tools read on their own, plus a quick check afterwards. This guide walks through all of it for Cursor and Claude Code, and the same setup works for Copilot, Windsurf and most other agents.

Quick answer: the setup that works in both tools

PieceFileWhat goes in it
Tokenstokens.css or your Tailwind @themeEvery color, spacing step, radius, shadow and font, as named variables
RulesAGENTS.md, CLAUDE.md, .cursor/rules/design-system.mdcShort, checkable rules that point at the tokens
Background (optional)DESIGN.mdThe reasoning: brand feel, when to use what
A checkTwo search commandsFinds any hex code or made-up value the AI slipped in

The tokens do most of the work. The rules file tells the AI the tokens exist and that it has to use them. The check tells you whether it actually did.

Why the AI ignores your design in the first place

A few things work against you, and it helps to know them before you write any rules:

  • Defaults are always within reach. If Tailwind's full palette is available, blue-500 and gray-600 are valid classes, and the model has seen them millions of times. It will use them.
  • Adjectives don't translate into values. "Clean, modern, generous spacing" means something different every time it's read. "Use --space-4 for card padding" doesn't.
  • Long instruction files get skimmed. Anthropic's own docs say to keep each CLAUDE.md under about 200 lines, because longer files are followed less reliably. Cursor's docs say to keep each rule under 500 lines.
  • Chat instructions don't carry over. Anything you typed in a previous session is gone. Only files in the project are read again.

So the goal is to take the guessing away: real values in code, a short list of firm rules, and nothing left for the model to fill in by itself.

Step 1: Put your tokens in code, not in a description

Design tokens are just named values. Instead of #0f766e scattered across forty files, there's one --color-primary and everything points to it. If you don't have tokens yet, that's the first job, because a rules file can't point at something that doesn't exist. Colors are usually the messiest part, and the Palette Builder will give you a full set with hover, focus and dark values already named.

In plain CSS it looks like this:

:root {
  --color-primary: #0f766e;
  --color-primary-hover: #115e59;
  --color-surface: #ffffff;
  --color-text: #0f172a;
  --color-text-muted: #475569;
  --color-border: #e2e8f0;
  --color-focus-ring: #14b8a6;

  --space-1: 4px;
  --space-2: 8px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;

  --radius-sm: 6px;
  --radius-md: 10px;
  --shadow-sm: 0 1px 2px rgb(15 23 42 / 0.08);
}

[data-theme="dark"] {
  --color-surface: #0f172a;
  --color-text: #f1f5f9;
  --color-text-muted: #94a3b8;
  --color-border: #1e293b;
}

Two details in there matter more than they look.

Hover and focus have their own tokens. If you only give the AI a primary color, it will make up a hover shade on the spot, usually by darkening something by an amount it picks. Name the states and that guess goes away. (Missing states are one of the color mistakes that make apps look cheap, with or without AI.)

Dark mode swaps the values, not the names. The component always uses var(--color-surface), and the theme decides what that means. The AI never has to write a dark-mode color, so it can't invent one.

If you use Tailwind v4: remove the default palette

This is the step most guides skip, and it makes the biggest difference. Adding your colors to Tailwind isn't enough, because the default ones are still there. Clear them first, then add yours:

@import "tailwindcss";

@theme {
  --color-*: initial;
  --font-*: initial;
  --radius-*: initial;
  --shadow-*: initial;

  --color-primary: #0f766e;
  --color-primary-hover: #115e59;
  --color-surface: #ffffff;
  --color-text: #0f172a;
  --color-text-muted: #475569;
  --color-border: #e2e8f0;

  --font-sans: "Inter", system-ui, sans-serif;
  --radius-md: 10px;
  --shadow-sm: 0 1px 2px rgb(15 23 42 / 0.08);
}

Now bg-blue-500 simply doesn't exist in your project. If the AI writes it, nothing gets styled, and you'll notice straight away instead of three weeks later. bg-primary and text-muted are the only colors left to reach for.

The same goes for fonts. With the defaults cleared, the AI can only use the fonts you defined, so pick them on purpose. The Font Pairing Builder checks whether a heading and body font actually work together. Font sizes deserve the same care: if yours don't come from a type scale yet, the Typography Builder will build one, so the AI picks from a short list of sizes instead of trying 15px, 17px and 19px.

Spacing is a little different. Tailwind v4 builds p-*, m-* and gap-* from one 4px base, so p-4 is 16px and p-6 is 24px. That's already a sensible scale. You just tell the AI which steps are allowed, which is what the rules file is for. If you're unsure which steps to allow, the 8pt grid guide has a ready-made scale, or you can build and preview your own in the Spacing Builder.

On Tailwind v3, the same idea applies: put your colors under theme.colors, not theme.extend.colors. Using extend keeps the whole default palette.

Step 2: Write a short rules file

This is the file the AI reads before it touches your UI. Keep it short and make every line something you could check. Here's a full example:

# Design system rules

Tokens live in src/styles/tokens.css. They are the only source of
colors, spacing, radius, shadows and fonts in this project.

## Always
- Use tokens for every visual value: var(--color-*), var(--space-*),
  var(--radius-*), var(--shadow-*), or the matching Tailwind class.
- Spacing steps allowed: 4, 8, 16, 24, 32, 48, 64px (p-1, p-2, p-4,
  p-6, p-8, p-12, p-16). Nothing in between.
- Buttons and links use --color-primary, and --color-primary-hover
  on hover.
- Every interactive element gets a visible focus style using
  --color-focus-ring.
- Reuse components from src/components/ui before writing new ones.

## Never
- No hex, rgb or hsl values outside tokens.css.
- No arbitrary Tailwind values like p-[18px] or bg-[#0f766e].
- No dark: color classes. Dark mode is handled by the tokens.
- No new fonts, shadows or radius values.

## If something is missing
Use the closest existing token and say so in your reply.
Don't add a new token without asking.

Notice what's not in there: no "make it look premium", no brand story, no list of every component prop. Those either can't be checked or change too often to keep in a file that loads on every task.

Don't skip the last part. Without it, when the AI needs a value you haven't defined, it quietly makes one up. With it, it uses the nearest token and tells you, so you can decide whether you really need a new one.

The "Never" list also assumes those decisions are already made. If your corners and shadows are still picked one component at a time, settle them first. A radius scale is usually four or five values, and so is a shadow elevation scale. The Radius Builder and Shadow Builder export both as tokens with the same naming as everything else.

Step 3: Put the rules where each tool looks

Each tool reads its own files, which is where most of the confusion comes from. Here's what each one reads today:

FileClaude CodeCursorNotes
CLAUDE.mdYes, every sessionNoCan pull in other files with @path
.cursor/rules/*.mdcNoYesMust be .mdc; a plain .md file there is ignored
AGENTS.mdBest through an @AGENTS.md importYes, in the project rootAlso read by Copilot, Codex and others
.cursorrulesNoOld formatStill works, but Cursor has moved to .cursor/rules

The simplest way to cover everything with one copy of your rules:

  1. Put the rules in AGENTS.md in the project root. Cursor picks it up from there.
  2. Create a CLAUDE.md next to it whose first line is @AGENTS.md. Claude Code then loads the same rules. You can add Claude-specific notes below that line.

One file to edit, every tool in sync. That beats keeping three copies that slowly drift apart.

Claude Code (through CLAUDE.md), Cursor, Copilot and Codex all read one AGENTS.md file, which points to tokens.css.
One rules file for every tool. The rules stay short because the actual values live in your token file.

Only want the rules on UI files?

If your project has a lot of backend code, you may not want design rules loading for every database task. Both tools can limit a rule to certain files.

In Cursor, make .cursor/rules/design-system.mdc:

---
description: Design system rules for UI code
globs: src/components/**/*.tsx, src/app/**/*.tsx, src/styles/**/*.css
alwaysApply: false
---

(your rules here)

In Claude Code, put the same rules in .claude/rules/design-system.md with a paths list at the top:

---
paths:
  - "src/components/**/*.tsx"
  - "src/app/**/*.tsx"
  - "src/styles/**/*.css"
---

(your rules here)

Now the rules show up when the AI works on a component, and stay out of the way when it doesn't.

Where DESIGN.md fits

You'll see DESIGN.md mentioned a lot. It's an open format Google Labs released in April 2026: a markdown file with your tokens at the top (in YAML) and plain-language explanation underneath, covering the overall feel, colors, typography, layout, elevation, shapes, components, and dos and don'ts. It's still marked alpha, so expect it to change.

It's useful for the part tokens can't hold: why the primary color is only for one action per screen, or why cards are flat and modals are raised. That kind of context helps the AI make sensible choices on new screens.

Two cautions. First, don't assume every tool reads it on its own. Add a line to your rules file that points to it, or import it in CLAUDE.md with @DESIGN.md. Second, don't end up with the same hex value in three places. If DESIGN.md holds token values, either generate your CSS from it or treat your CSS as the source and keep DESIGN.md to the explanation. Two lists of values will eventually disagree, and the AI won't know which one to believe.

Step 4: Check that it actually worked

Most setups stop at the rules file. But a rules file is a request, not a guarantee. The only way to know the AI followed it is to look.

Start with a test. Ask for something that needs a lot of design decisions, like "build a pricing section with three plans, a highlighted middle plan and a FAQ below it." Then run two searches over your code. If you want something to compare the result with, the pricing section templates are built the same way, from tokens only.

Find hard-coded colors outside your token file:

grep -rnE "#[0-9a-fA-F]{3,8}\b|rgba?\(|hsla?\(" src --include=*.tsx --include=*.jsx --include=*.css | grep -v tokens.css

Find made-up Tailwind values like p-[18px] or bg-[#333]:

grep -rnE -- "-\[(#|[0-9.]+(px|rem))" src

Both should come back empty. (The first one can also catch a link like href="#add", so skim past those.) If they don't, every result is a line where the AI made something up. You'll usually see a pattern: it keeps reaching for the same missing thing, a second shade of grey or a spacing value between two of your steps. That tells you whether to fix the rule or add a token.

Then look at the page in the browser, not just the code. Searches can't see three things:

  • Hover and focus. Tab through the page with the keyboard. Every button and link should show a clear focus ring.
  • Dark mode. Switch themes. Anything that stays white or turns unreadable has a value that isn't a token.
  • Correct but wrong. The AI can use only tokens and still use the wrong one, like muted text for a main heading. Only your eyes catch that.

Once the searches pass on a couple of test prompts, add them to your pre-commit hook or CI so they keep running without you thinking about it.

When your tokens change

Design systems change, and this is where a working setup usually breaks. Renaming --color-brand to --color-primary in the CSS, but not in the rules file, leaves the AI pointing at a token that no longer exists.

A few habits keep it clean:

  • Change the token file and the rules file in the same commit. If the rules mention a token name, they're part of the change.
  • Keep the old name for a while. Add --color-brand: var(--color-primary); so existing code keeps working, then remove it once a search shows nothing still uses it.
  • Write names, not values, in the rules where you can. "Buttons use --color-primary" survives a color change. "Buttons are #0f766e" doesn't.
  • Start a new session after a big change. A long-running chat can hold on to the old values it already read.

Generate the files instead of writing them by hand

Writing tokens and rules from scratch is the slow part. Every builder on this site has an Export tab with an AI Agent Rules option that writes a ready rules file for you: the rules, a "never do this" list, and every token with its value. You can save it as AGENTS.md, CLAUDE.md, a Cursor rule (.cursor/rules/design-system.mdc, with the header Cursor needs already added) or the Copilot and Windsurf file names. The same tab exports the matching CSS variables and a Tailwind v4 or v3 theme, so the tokens and the rules always agree.

The Spacing Builder Export tab with AI Agent Rules selected and the file name set to .cursor/rules/design-system.mdc, showing the Cursor header and the baseline rules.
The Spacing Builder's export, saved as a Cursor rule. The header at the top is what tells Cursor to load it on every task.

If you're starting from nothing, one rules file is easier to manage than six. The Design Language Studio walks through colors, fonts, type scale, spacing, radius and shadows in one go and exports a single rules file that covers all of them. Before you hand it to the AI, you can try the whole system on real layouts in Section Studio, so you find a weak color or a cramped gap yourself instead of in AI-written code.

FAQ

Does Claude Code read DESIGN.md automatically?

Not on its own. Claude Code always loads CLAUDE.md. To include DESIGN.md, add the line @DESIGN.md to your CLAUDE.md, and its contents load with it.

Should I put hex values in CLAUDE.md?

Only if there's no token file the AI can read. It's better to keep the values in your CSS or Tailwind theme and have the rules point there. Then there's one place to change a color, and the rules can't go out of date.

Is .cursorrules still supported?

Cursor still reads it, but it's the older format. New projects should use .cursor/rules/ with .mdc files, or an AGENTS.md in the project root.

Will this make the AI design better-looking pages?

It makes them consistent, which is most of what makes a page look finished. It won't give the AI taste. If your tokens are well chosen, everything built from them will look like it belongs together. If they're not, you'll get a consistent version of a weak design, so it's worth getting the palette, fonts and spacing right first.

All posts