Make Cursor follow your design system
To make Cursor follow your design system, add a project rule at .cursor/rules/<name>.mdc that lists your tokens and hard rules, with globs matching your UI files and alwaysApply: false, so the rule is attached whenever a component or stylesheet is in context. Keep the full reference in a DESIGN.md at the repo root. Then check the result: an MCP server lets Cursor's agent query tokens and lint snippets, and a CI lint catches what it misses.
How Cursor rules work
Project rules live in .cursor/rules as .mdc files and are committed with the code. Three front matter fields decide when a rule is used (Cursor rules docs):
| Rule type | Front matter | When it applies |
|---|---|---|
| Always Apply | alwaysApply: true |
Every request; globs and description are ignored |
| Apply Intelligently | alwaysApply: false, description, no globs |
When the agent judges it relevant from the description |
| Apply to Specific Files | alwaysApply: false, globs |
When a file matching a pattern is in context |
| Apply Manually | alwaysApply: false, no description or globs |
When you @-mention it |
Two details from the same page catch people out. A plain .md file in .cursor/rules is ignored, because it has no front matter. And rules apply to the agent in chat, not to Cursor Tab.
The manual way
1. Write DESIGN.md
DESIGN.md is Google's open format for a design system: YAML front matter with token values, then prose on how to apply them. See What is DESIGN.md?. The rule is a working summary of it.
2. Create the rule
Create .cursor/rules/acme-design-system.mdc. For a design system, "Apply to Specific Files" is a good fit: it attaches to UI files and stays out of the way for back-end work. Separate multiple globs with commas.
---
description: Acme design system tokens and rules. Apply when writing or editing UI, styles or components.
globs: **/*.tsx, **/*.jsx, **/*.vue, **/*.svelte, **/*.astro, **/*.html, **/*.css, **/*.scss
alwaysApply: false
---
# Acme design system
If the project has a `DESIGN.md`, it is the full reference; this rule is the working summary.
## Tokens
### Colors
- `background` #ffffff
- `text` #1f2933
- `primary` #2f5bea
- `on-primary` #ffffff
### Spacing (4px grid)
`xs` 4px · `sm` 8px · `md` 16px · `lg` 24px
## Constraints
- MUST use only the colours above. No new hex, rgb or hsl values, and no Tailwind palette defaults (`blue-500`, `gray-100`).
- MUST keep every margin, padding and gap a multiple of 4px, preferring the spacing tokens.
- MUST NOT hard-code a value when a token exists; reference the CSS variable or theme key.
- If a requirement cannot be met with existing tokens, ask before adding a token.
- End your reply with a short **Tokens used** list and a **Deviations** list (empty if none).
Cursor's docs recommend keeping each rule under 500 lines. A token list and a handful of MUST rules fit easily; leave the long prose in DESIGN.md.
3. Optional: AGENTS.md
Cursor also reads AGENTS.md in the project root and subdirectories. A short "Design system" section there that points at DESIGN.md reaches Cursor and any other agent that reads the file.
GitHub Copilot instructions
Copilot reads path-specific instructions from NAME.instructions.md files in or below .github/instructions. The applyTo front matter takes glob patterns separated by commas (GitHub docs). Use the same body as the Cursor rule:
---
applyTo: "**/*.tsx,**/*.jsx,**/*.vue,**/*.svelte,**/*.astro,**/*.html,**/*.css,**/*.scss"
---
# Acme design system
## Tokens
...
Where it applies depends on the surface. On GitHub.com, path-specific instructions are used by Copilot cloud agent and Copilot code review. In VS Code they are attached when the agent creates or modifies a file that matches applyTo (VS Code docs). For instructions that apply to the whole repository, use .github/copilot-instructions.md.
The fast way with Designrail
Designrail reads the rendered styles of a live site and writes all of these files from one token set.
From the CLI: in your repository, run:
pnpm dlx designrail scan https://www.example.com --site --install
--site crawls up to 10 same-origin pages plus a 390px mobile pass. --install writes:
DESIGN.md.cursor/rules/<name>-design-system.mdcwith the front matter shown above.github/instructions/<name>-design-system.instructions.mdwith the matchingapplyTo.claude/skills/<name>-design-system/SKILL.mdfor Claude Code- a marked section in
AGENTS.md, leaving the rest of the file untouched design-system/:tokens.css,tailwind-theme.css(Tailwind v4),shadcn-theme.css,tokens.json(DTCG) andpalette.svg
The name is the site name in lowercase, so Acme gives acme-design-system.mdc. The rule body is the same as the generated Claude Code skill, without its front matter. See the CLI docs for every flag.
From the extension (Chrome or Edge): open the Designrail side panel on the site; it scans the page. Choose Add to project… and pick your repository folder. The Cursor rule, Copilot instructions, AGENTS.md section and token files are part of Pro; the free plan writes DESIGN.md and the Claude Code skill.
Keeping it in sync
MCP server. designrail mcp gives Cursor's agent live access to DESIGN.md. Add it to .cursor/mcp.json:
{
"mcpServers": {
"design-system": { "command": "pnpm", "args": ["dlx", "designrail", "mcp"] }
}
}
It provides get_tokens (all tokens, or one of colors, typography, spacing, rounded, components), get_component (one spec with hover, focus and disabled states), check_snippet (lints code for raw colours, default Tailwind palette classes, off-grid spacing and unknown fonts) and check_url (renders a page such as http://localhost:3000 and scores it). The resource design://DESIGN.md serves the whole file. The server rereads ./DESIGN.md on every call. Details are in the MCP docs.
CI. designrail lint-code src --max-warnings 0 fails on raw colour literals, classes such as bg-blue-500, off-grid values such as p-[13px], and unknown fonts; --format github prints annotations. The GitHub Action runs it on every pull request and can score a preview deploy with fail-under. In sync mode it rescans your live site on a schedule and opens a pull request when the design changes, so the rule does not drift from production.
Troubleshooting
The rule is never applied. Check the extension is .mdc and the front matter starts the file. With globs set and alwaysApply: false, the rule attaches only when a matching file is in context. If you ask for a new page from an empty chat, add an existing component to the context or set alwaysApply: true.
Some style files are missed. The generated globs cover .tsx, .jsx, .vue, .svelte, .astro, .html, .css and .scss. If your styles live in .ts, .js, .less or .sass files, add those patterns to globs and applyTo.
Tab completions use off-palette colours. Rules do not affect Cursor Tab. Lean on lint-code in CI for those edits.
Copilot ignores the instructions in VS Code. Path-specific instructions attach when the agent creates or modifies a matching file. For local sessions, check that chat.includeApplyingInstructions is enabled.
The agent still hard-codes values. A rule is guidance. Ask the agent to run check_snippet before finishing, and keep the CI lint as the backstop.
FAQ
Should the design system rule use alwaysApply: true?
Usually not. With globs and alwaysApply: false it attaches to UI files only, which keeps back-end requests free of token lists; switch to true if you often start UI work without a UI file in context.
Why is my .md rule in .cursor/rules ignored?
Cursor's rules system ignores plain .md files there because they have no front matter. Rename the file to .mdc and start it with a description, globs and alwaysApply block.
Can I use one file for Cursor, Copilot and Claude Code?
Not one file, because each tool reads its own location and front matter. Generate all of them from one DESIGN.md, which designrail scan --install does; for Claude Code see Make Claude Code follow your design system.
Will rescanning overwrite my own rules?
It overwrites only the Designrail files: the <name>-design-system.mdc rule, the instructions file, DESIGN.md and the token files. Other rules in .cursor/rules are not touched, and in AGENTS.md only the marked block is replaced.
How is this different from other tools?
Designrail extracts tokens from the rendered site rather than from a design file, and then checks builds against them. See the comparison.