DEV Community

Rulestack
Rulestack

Posted on

AGENTS.md: how to write the one rules file most coding agents now read

If you've picked up OpenAI Codex, OpenCode, or half a dozen newer coding agents, you've met AGENTS.md: a plain Markdown file at your repo root that tells the agent how your project works. No frontmatter, no schema, no special syntax — which is exactly why most of them are bad. When anything is valid, nothing forces you to write the parts the agent actually uses.

This post covers how the file is resolved, a four-section structure that holds up in practice, and the specific writing mistakes that make agents quietly ignore your rules.

Who reads AGENTS.md (and who doesn't)

AGENTS.md started as the instructions file for OpenAI Codex and has become the closest thing agent tooling has to a shared standard — OpenCode reads it natively, and a growing list of editors and agents either read it directly or accept it as a rules source. The pattern is converging because the content problem is identical everywhere: the agent needs to know what this project is, how to run its checks, and what it must not touch.

Two practical notes before you assume portability:

  • Claude Code does not read AGENTS.md — it reads CLAUDE.md. The structure ports almost 1:1, but the filename matters. If you maintain both, make one the source of truth and reference it from the other instead of maintaining two diverging copies.
  • Cursor's native format is different (.cursor/rules/*.mdc with frontmatter). Same porting story: content transfers, container doesn't.

So: one well-written AGENTS.md is not automatically "write once, run anywhere," but it is the best single artifact to write first, because it's plain Markdown with no tool-specific syntax to strip out later.

Resolution: the nearest file wins

Codex (and tools that follow its convention) resolves AGENTS.md by proximity: when the agent edits a file, it uses the nearest AGENTS.md walking up from that file. This has two useful consequences:

  1. Monorepos don't need one giant file. Put a root AGENTS.md with shared conventions, then drop a focused one in services/api/ and another in web/. The API file wins for API edits; you never write "if you are in the frontend…" conditionals.
  2. Scope is a placement decision, not a prose decision. A rule that only applies to one package belongs in that package's file. Rules written globally but meant locally are a major source of "the agent did something weird in the other half of the repo."

The four sections that earn their tokens

Every effective AGENTS.md I've written or reviewed reduces to four sections. Order matters — it mirrors what the agent needs first:

# AGENTS.md

## Project overview
One paragraph: what this service does, the stack, and the one
architectural fact that explains everything else (e.g. "all state
lives in Postgres; the API layer is stateless").

## Commands
- Test: `pnpm test` (single file: `pnpm test -- path/to.test.ts`)
- Lint: `pnpm lint`
- Build: `pnpm build`
- Never run: `pnpm deploy` (CI-only)

## Code style
- TypeScript strict mode; no `any`. Reason: downstream consumers
  rely on the generated types being exact.
- Errors are returned as values from services, thrown only at the
  HTTP boundary. Reason: services are called from batch jobs where
  a throw kills the whole run.

## Boundaries
- Allowed: `src/`, `test/`
- Ask first: `migrations/` (schema changes need a review)
- Never touch: `vendor/`, generated files matching `*.gen.ts`
Enter fullscreen mode Exit fullscreen mode

Why these four:

  • Project overview is orientation. Without it the agent infers your architecture from whatever files it happens to open, and infers wrong.
  • Commands get run literally. Write the exact invocation, including the single-file variant — an agent that knows how to run one test iterates dramatically faster than one that runs the whole suite every time. The "never run" line is load-bearing.
  • Code style is where most files bloat. Keep only rules a competent contributor would get wrong without being told — that's the actual bar (more below).
  • Boundaries are the highest-value section per token, because a boundary violation is the most expensive class of agent mistake: touching migrations, editing generated code, "fixing" vendored files.

Attach a Reason: to every rule you care about

The single highest-leverage habit: follow each non-obvious rule with a one-line Reason:.

- Use the repository wrapper in `src/db/repo.ts` for all queries.
  Reason: it enforces tenant isolation; raw queries have leaked
  cross-tenant data before.
Enter fullscreen mode Exit fullscreen mode

This isn't documentation politeness. It changes agent behavior in two ways:

  1. Generalization. A bare rule covers the literal case; a reasoned rule covers the neighboring cases. Given the reason above, an agent asked to add a new query path will route it through the wrapper even in a file your rule never mentioned — because it knows why the rule exists.
  2. Resistance to pushback. When you (or a teammate, or the agent's own alternative idea) push against a rule mid-session, a bare rule folds. Agents agree too fast — say "isn't it better to do X?" and an unreasoned rule loses to the most recent message. A Reason: line is what the agent weighs against the suggestion.

If you can't write the reason, that's diagnostic: the rule is either obvious (delete it — style defaults the agent already follows are wasted tokens) or cargo cult (delete it faster).

The mistakes that make agents ignore the file

These come from testing rules files against actual agent behavior, repeatedly:

1. Aspirations instead of instructions. "Write clean, maintainable code with good test coverage" selects no behavior — nothing changes between an agent that read it and one that didn't. Rewrite every aspiration as a checkable instruction: "every new export in src/services/ gets a test file next to it; run pnpm test -- <that file> before finishing."

2. Duplicating what the agent already does. Modern agents already write idiomatic TypeScript, already add null checks, already follow the surrounding style. Rules restating defaults dilute the file — and the agent's attention over it. The test for every line: would a competent contributor get this wrong without being told? If no, cut.

3. Stale commands. The fastest way to teach an agent to distrust your file is a Commands section that doesn't run. Agents try the command, watch it fail, and start improvising. Treat command lines like code: when the script changes, the rules file changes in the same commit.

4. One 400-line file for a 12-package monorepo. Attention over a rules file is finite. Split by proximity (see resolution above) instead of writing longer.

5. Contradicting your own config. If AGENTS.md says "no default exports" and your ESLint config allows them, the agent sees a codebase full of counterexamples and a rules file it can't reconcile. Rules should state things your tooling can't enforce; things it can enforce belong in the tooling (and the agent will read the error output).

Adding it to a repo that already has one

Don't overwrite an existing AGENTS.md — append, then merge in one pass: keep one project overview (yours); where both files define the same section, drop exact duplicates and keep the stricter rule when two conflict; collapse the command lists into a single block with your repo's real commands; keep every Reason: line that survives.

The append-then-merge order matters because it keeps the diff reviewable — you can see exactly what the template added before you commit to it.

Verify the agent actually loaded it

End of setup, one check:

Summarize the rules you loaded from AGENTS.md.

If the summary misses a section, the file has a structural problem (usually: the section is prose instead of bullets, or it's below a wall of text the agent deprioritized). Fix the structure, not the agent.


I maintain Rulestack, a set of ready-to-adapt rules packs for Codex, Claude Code, and Cursor — including an AGENTS.md template pack with ten stack-specific starting points that follow the structure above.

I post short, practical notes on coding-agent configuration on Bluesky — @ai-shop.bsky.social — including a curated "AI Coding Agents" feed if you want this topic in your timeline.

Top comments (0)