CLAUDE.md vs AGENTS.md: what each is and how to use both

· by

CLAUDE.md vs AGENTS.md comes down to who reads the file. Both are plain Markdown files at the root of a repo that tell an AI coding agent how your project works. CLAUDE.md is Claude Code’s own file. AGENTS.md is a tool-neutral convention that Codex, Cursor and a growing list of other agents read, and recent Claude Code falls back to it when there is no CLAUDE.md. If you use more than one agent, keep the rules in AGENTS.md and point CLAUDE.md at it.

What each file is

Neither is a config format. There is no schema and nothing to validate. Each is instructions written for a model, loaded into its context at the start of a session: build and test commands, code style, things not to touch, how the repo is laid out.

  • CLAUDE.md is Claude Code’s memory file. It reads one from the project, and~/.claude/CLAUDE.md for rules that apply everywhere.
  • AGENTS.md is a shared convention for the same job, so a repo does not need one file per tool. Codex and Cursor read it, and so do other coding agents.

Older Claude Code versions read only CLAUDE.md. Newer ones read AGENTS.md too, but only in one situation, covered below.

Which agents read which

Support changes quickly, so check each tool’s own documentation before relying on this table.

  • Claude Code: CLAUDE.md, and AGENTS.md too (v2.1.277 and later) when there is no CLAUDE.md.
  • Codex: AGENTS.md.
  • Cursor: AGENTS.md, alongside its own rules files.
  • Anything else: look for AGENTS.md first. It is the file most tools converge on.

The practical consequence is that the same instructions often need to be visible under two names.

How to keep both in sync

Do not maintain two copies. Two copies drift, and an agent will follow whichever one it happens to read. Pick one source of truth and make the other point at it. There are two ways.

Option 1: import AGENTS.md from CLAUDE.md

Claude Code supports @path imports inside CLAUDE.md, and the imported file is never loaded twice. Put the real rules in AGENTS.md, and make CLAUDE.md a single line:

# CLAUDE.md
@AGENTS.md

Anything Claude Code needs that other agents do not, such as a note about its own slash commands, goes below the import line. Everything else lives once, in AGENTS.md.

Option 2: symlink

If you would rather have no second file with contents at all:

ln -s AGENTS.md CLAUDE.md
git add CLAUDE.md

Git stores a symlink as a link, so this works on macOS and Linux. On Windows a symlink needs a developer-mode setting or elevated rights, and checkouts can end up with a plain text file holding the path. Claude Code’s edit tools also refuse to write through the link and edit AGENTS.md instead. If anyone on your team uses Windows, the import is the safer choice. It is also the only one that lets CLAUDE.md carry Claude-specific notes.

The gotcha: adding a CLAUDE.md hides AGENTS.md

By default, Claude Code reads AGENTS.md only when it finds no CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md in the working directory or above. If one exists, it reads that and ignores AGENTS.md. So creating even a CLAUDE.local.md in a repo that relies on AGENTS.md silently stops Claude Code from seeing your shared rules. The fix is the import above, or the “Project instructions” setting in /config, which can read both files. The details are in Anthropic’s memory documentation.

What to put in the file

A short file that is true beats a long file that is mostly true. Keep what an agent cannot work out by reading the code:

  • The exact commands to build, test and lint.
  • Conventions the code does not make obvious, and the reason for them.
  • Files and directories that are off limits.
  • Choices you have already made, so the agent does not reopen them.

Leave out anything the agent can read from the source. A sentence stating a rule is stronger with its reason attached: “use integer cents, never floats, because we reconcile against the bank’s CSV” gives the agent something to reason from when a new case turns up.

When a static rules file is enough

For rules that stay put, a plain CLAUDE.md or AGENTS.md is enough, and we have measured that. In our own runs, with up to 100 rules, a plain CLAUDE.md worked about as well as trailstone at delivering them and costs less. Those were small samples that we ran ourselves, so treat them as a reason to check rather than a result to cite. But the direction is clear. If your rules are “use pnpm”, “tests live next to the code” and “never edit generated files”, write them down once and stop there. You do not need another tool.

A file that is committed, reviewed in pull requests and loaded at session start is a good mechanism for anything that holds still.

The one case it does not cover

A rule changes while agents are mid-task, and some of them are not looking at the copy you edited.

An instruction file is read when a session starts. It is a file in a checkout. If you change it on main, an agent working in another git worktree is reading its own checkout of that file, on its own branch. So is an agent in a clone that has not pulled. Nothing tells them the file moved.

Here is the shape of the failure. Two agents are building features in separate worktrees. Halfway through, a teammate commits “timestamps are epoch milliseconds, not ISO strings” on main and updates the rules file. Both agents carry on writing ISO strings. The change is in the repository, and neither agent’s checkout has it.

We tested exactly this, and it matters to say what we found. An interactive Claude Code session did notice a CLAUDE.md edit made in its own checkout, 4 of 4 times. So the problem is not that the model ignores the file. The problem is checkouts that never see the change. In the demo on the trailstone home page, two agents in worktrees are told that timestamps changed on main. With CLAUDE.md, 0 of 3 agents switched. With trailstone, 3 of 3 did. In separate clones, a teammate’s pushed CLAUDE.md edit reached 0 of 3 clones that had not pulled, and trailstone reached 3 of 3. Across separate worktrees and separate clones, trailstone reached 15 of 15 and 9 of 9 running agents. All small samples, all run by us.

Where trailstone fits

trailstone is a decision ledger that lives in your repo, in .trailstone/decisions.yml. A decision names the files it governs. When you reverse one, the reversal is a new entry that supersedes the old, and every running agent is told at its next edit of a governed file, wherever it is checked out. It reads the ledger from main and from origin, not from the copy in the agent’s working tree.

trailstone decide "Timestamps are ISO strings" \
    --why "matches the public API" --scope src/api/

trailstone reverse d_5913723e "Timestamps are epoch ms, not ISO"

It also blocks the push of files last committed before the reversal, until someone re-checks them. That is a check on top of the message, so a file built on the old rule cannot slip through unread.

What it does not do is worth stating as plainly:

  • It flags and blocks. It does not fix code. An agent or a person makes the change.
  • A flag means “built on”, not “broken”. Most flagged files still comply and clear quickly.
  • It only watches the files a decision names, and it does not follow renames.
  • It is not a replacement for CLAUDE.md or AGENTS.md. It writes a short block into AGENTS.md so agents without hooks know to ask, and the two work together.

There is no server, no account and no telemetry. The only network call is a background git fetch of your origin’s default branch, and TRAILSTONE_FETCH=0 turns it off. The README lists exactly what installing it changes.

A simple way to decide

  1. Using one agent, or several that share a checkout? Write CLAUDE.md, and stop.
  2. Using several agents? Write AGENTS.md, and import it from CLAUDE.md with @AGENTS.md.
  3. Running agents in parallel worktrees or on teammates’ clones, where a rule can change mid-task? That is the case a static file cannot reach. npx trailstone demo shows it on a throwaway repo in about ten seconds, and needs Node.js 20.17 or later.