Article

DESIGN.md vs AGENTS.md vs RULES.md: which file does what

A practical map of the context files AI coding agents read, what belongs in each one, and how to stop them from contradicting each other.

4 min read

I opened a repo last month and counted six instruction files. CLAUDE.md, AGENTS.md, .cursorrules, .windsurfrules, a RULES.md, and a docs/conventions.md that nothing read.

Three of them contradicted each other about the test command. Two disagreed on the primary color. Nobody knew which one was current.

This is the mess that shows up around month three of working with AI agents, and it is completely avoidable. Here is the map I use now.

The three jobs, not the three files

Start with the jobs rather than the filenames. There are really only three kinds of standing instruction a coding agent needs.

How the repo works. Install commands, test commands, folder layout, code style, what to never touch. This is engineering context.

What the product looks like. Color tokens, type scale, spacing, radius, component rules. This is design context.

How the agent should behave. Ask before large refactors, never force push, always run tests before reporting done. This is policy.

Every instruction file you have ever seen is trying to hold one, two, or all three of these. The confusion starts when the same job lands in two files.

AGENTS.md: how the repo works

AGENTS.md has become the closest thing to a neutral standard. It is a plain Markdown file at the repository root, and it is read by Codex, Devin, and a growing number of other tools.

What belongs in it:

markdown
# AGENTS.md

## Commands
- Install: `pnpm install`
- Dev: `pnpm dev`
- Test: `pnpm test` (must pass before reporting done)
- Lint: `pnpm lint`

## Layout
- `src/routes` is file-based routing. Do not create `src/pages`.
- `src/components/ui` is generated. Do not hand-edit.

## Style
- TypeScript strict. No `any`.
- Prefer composition over configuration flags.

Short, factual, verifiable. If a line cannot be checked by running something, it probably belongs somewhere else.

DESIGN.md: what the product looks like

Design deserves its own file for three reasons, and they are all practical rather than philosophical.

Different owner. A designer can review a DESIGN.md pull request without reading your test setup.

Different lifecycle. Your build commands change once a year. Your design tokens change when a rebrand lands. Mixing them means every design tweak touches the engineering file.

Different consumers. Figma plugins, browser builders, and design review tools can read a design contract. They have no use for your lint command.

A DESIGN.md holds tokens, scale, geometry, component rules, and the two or three signature moves that make the product recognisable. Nothing about testing, nothing about folder structure.

CLAUDE.md and .cursor/rules: the delivery mechanism

Here is the part that took me longest to internalise.

CLAUDE.md, .cursor/rules/*.mdc, .windsurf/rules/, .github/copilot-instructions.md, .clinerules, and .kiro/steering are not competing standards for the same content. They are delivery mechanisms, each specific to one tool.

The right pattern is to keep them thin and have them point at the real files:

markdown
# CLAUDE.md

@AGENTS.md
@DESIGN.md

Before any UI change, read DESIGN.md and use only its tokens.
Before reporting a task complete, run the test command in AGENTS.md.

Now adding a new tool is a five line file, not a copy of your entire conventions document. And when the design system changes, it changes in one place.

So where does RULES.md fit

Honestly? Usually nowhere.

RULES.md is not a convention that any major tool reads automatically. When I see one, it is normally holding policy that would be better placed in AGENTS.md, or design rules that belong in DESIGN.md.

There is one case where a separate policy file earns its place: when your behavioral rules are long, apply to humans as well as agents, and are genuinely separate from build mechanics. Security review requirements, for example, or release approval steps.

If that is not you, fold the content into AGENTS.md and delete the file. Fewer files that are read beats more files that are ignored.

The decision table

ContentFileRead by
Install, build, test commandsAGENTS.mdCodex, Devin, and via imports everywhere else
Folder conventions, code styleAGENTS.mdsame
Color, type, spacing, radius tokensDESIGN.mdevery tool, via a pointer
Component rules and statesDESIGN.mdsame
Tool-specific setupCLAUDE.md, .cursor/rules, etc.that one tool
Behavioral policyAGENTS.md, or RULES.md if genuinely largevia imports

The contradiction test

Once a quarter, run this. It takes two minutes and it has caught something every time I have done it.

text
Read every instruction file in this repository. List any place where two files
give different or conflicting guidance. Do not fix anything, just list them.

An agent reading all of your context at once is very good at spotting that AGENTS.md says npm test and CLAUDE.md says pnpm test. You will not spot it, because you only ever read one file at a time.

What this means for you

Two real files, thin pointers for each tool. AGENTS.md for how the repo works, DESIGN.md for how the product looks, and one small file per tool that imports both.

That structure has survived every new agent I have added since, which is the actual test. When a new tool ships next quarter, you write five lines and it inherits everything.

If you do not have a DESIGN.md yet, start from a documented system in the library rather than a blank page. Editing something specific is much faster than inventing something generic.