An AGENTS.md file is a Markdown file at the root of your repository that coding agents read before every turn. Put three things in it: commands the agent cannot guess from `package.json`, rules it has already broken in your repo, and one-line pointers to existing packages and docs. Keep the root file under 120 lines.

In my workflow, the agent writes almost all the code, runs the queries, and reads the logs. My job is providing the environment and credentials, looking at the screen on a real phone to judge how an interaction feels, and approving anything that leaves my machine. When a round goes wrong, I don't just patch the code in front of me; I update the instruction file or add a gate script so the next session cannot repeat the mistake.

For months I did that by appending another paragraph to `AGENTS.md` after every bad session. By the time the file passed 300 lines, agents were skimming the middle, rebuilding components we already had, and forgetting constraints halfway through long tasks. Here is what went wrong in my sessions, how human and agent split the work, and the 120-line router format that fixed it.

## Four failures that broke my old file

### 1. The agent claimed a shared package did not exist

While reviewing two apps in the same workspace, I noticed they had different six-digit verification-code inputs. When I asked an agent to add email verification to a third app, it checked the local app folder, decided no OTP component existed, and started building another one from scratch.

My first reply in chat was: "Shouldn't this be a shared component every app uses?" We already had a shared UI package one directory over, along with a shared icon generator and a device runner. I had documented all three inside an on-demand skill file. The agent never loaded the skill. Because nothing in the root instruction file mentioned that shared UI lived in `packages/ui`, the agent assumed the local app directory was the whole world.

### 2. The four-minute screenshot loop and the 60-screen re-shoot

Two things made me type three exclamation marks in chat that week. First, my phone was sitting on my desk plugged into my Mac over USB, and the agent still spent four minutes launching a headless capture, cropping PNGs, and inspecting its own screenshots before letting me see a two-pixel spacing tweak. Second, when I asked it to update our visual archive after changing five screens on one app, it started re-shooting all 60+ screens across the entire suite.

I stopped the run and told it: push the code via hot reload to the screen I have open on the phone, let me look at it directly, and when you update the visual archive, shoot only the screens that changed.

The same week, the agent kept adding `border-left: 3px solid` accent bars to callout cards and blockquotes. I had a prose rule against left side bars sitting around line 260 of my instruction file, and the agent ignored it almost every time it touched CSS.

### 3. Unapproved outward actions

One afternoon an agent read our ad funnel numbers, saw a campaign cross a cost threshold, and paused the ad set by itself. Another session drafted customer replies and tried to send the emails immediately instead of leaving them as drafts. Both agents thought they were being helpful because earlier prompts had said "fix what you find." They had no clear boundary between local work (which they should do without asking) and outward actions (which must wait for a human).

### 4. Compaction amnesia on long tasks

When a multi-package refactor runs past an hour, or when I hand an unfinished feature to a fresh conversation before going to sleep, chat history stops being reliable. Once a long session hit its context limit and compacted the conversation, the summary kept the high-level goal and dropped the ordered constraints, including "leave changes uncommitted in the working tree" and the list of files not to touch. Ten minutes later, the agent skipped two checks and tried to commit the tree.

## Why the agent ignored what I wrote

[AGENTS.md](https://agents.md/) is plain Markdown read by Codex, Claude Code (which falls back to AGENTS.md when no CLAUDE.md exists, per the [Claude Code changelog](https://code.claude.com/docs/en/changelog)), Aider, Jules, opencode, Cursor, Zed, and VS Code.

Three mechanics explain the failures above:

1. **The file loads on every turn, and attention drops in the middle.** Every line in AGENTS.md is billed on every request for the life of the session. When you pad it with architecture tours and polite advice, the hard rules drown in prose.
2. **Passive pointers beat on-demand tools.** An agent only loads a skill if it realizes it needs one. If it doesn't know your repo has a shared UI package or icon tool, it won't search for the skill that explains it.
3. **Agents follow concrete rules and ignore descriptions.** Two studies from early 2026 measured this directly.

An [arXiv study in February 2026](https://arxiv.org/abs/2602.11988) evaluated context files on SWE-bench tasks and real repositories. Adding a context file did not improve task success overall and increased inference cost by more than 20% on average. Agents followed explicit instructions in the files, such as running a specific tool, while repository overviews ("this monorepo contains three packages...") did nothing for pass rates.

Vercel ran the complementary experiment on Next.js 16 APIs and [compared an on-demand docs skill against a compressed index in AGENTS.md](https://vercel.com/blog/agents-md-outperforms-skills-in-our-agent-evals). In 56% of runs, the agent never invoked the skill at all and scored 53%, the exact same score as having no docs. When Vercel embedded an 8 KB index of doc file paths directly inside AGENTS.md, pass rates hit 100% across build, lint, and test.

That matched what I saw in my own workspace. When a capability only lived in a skill, the agent forgot to open it. When I put a one-line pointer in AGENTS.md, the agent found the shared package every time.

## The fix: turn AGENTS.md into a 120-line router

I deleted the prose overview from my root AGENTS.md, set a hard ceiling of 120 lines, and split the file into four parts that match how the agent and I actually divide the work.

### 1. Numbered red-line rules at the top, with dates

The rules that protect my time and prevent unapproved outward actions go in the first 15 lines. Each rule gets a number so I can cite "Rule 0" in chat, and a date so I know when it was added:

```markdown
## Rules (highest priority)

- Rule 0 (UI tuning, 2026-09-15): change the code, hot-reload to the open device or browser, and let the owner check. Run no tests, screenshots, or headless captures unless asked. Visual archive updates are incremental only (re-shoot changed screens, never the full set).
- Rule 0b (outward gate, 2026-09-15): do local reads, edits, and checks without asking. Keep changes uncommitted and never deploy, push, send email, or mutate ad/billing accounts without explicit owner approval for that exact action.
- Rule 1 (code comments, 2026-09-01): English only, short, only when the code cannot state the reason.
- Rule 2 (no side bars, 2026-09-29): no left border or inset side rule on any card, quote, note, or row. Gate: `python3 scripts/check-side-bars.py`
```

Putting Rule 0 and Rule 0b at the top ended both the four-minute screenshot loops and the surprise ad-account mutations.

The dates (`2026-09-15`) cost four tokens each and solve the opposite problem too: rules that calcify. Twice this week an agent refused a change I asked for by quoting an old rule back at me. One was a local job-concurrency limit from `(2026-10-15)` that was throttling parallel builds I now wanted to run at full speed. The other was a rule from `(2026-10-27)` saying "every delete button must use a pale red background, and only confirmation dialogs use solid red." An earlier agent had written that rule into a design doc during a cleanup pass, and now the current agent was enforcing it like law. Seeing the date and source told me immediately that both rules were stale, and I told the agent to delete them on the spot.

### 2. A one-line capability and task router

Instead of explaining how authentication, billing, or shared UI works inside AGENTS.md, I keep one line per domain that names the trigger and points to the package or doc that owns it:

```markdown
## Routes

- Shared UI & icons: use `@acme/ui` (`packages/ui/README.md`) and `packages/icons` (`icongen`); never build a per-app button, modal, or OTP input.
- Local mobile debug: `scripts/dev-loop <app> ios|android|reload|status`; do not run raw `flutter run`.
- Touching billing or webhooks: read `docs/operations/billing.md` first.
- Database schema changes: read `docs/architecture/migrations.md`; never edit an applied migration.
- Long or handed-off task (>30 min): write the brief and boundaries to `.work/active/<task>/BRIEF.md` before starting; re-read it after context compaction.
```

That first route cured the duplicate-component problem. Because the line sits in passive context on every turn, the agent knows `@acme/ui` and `icongen` exist before it writes a line of code, and it reads `packages/ui/README.md` only when the task touches UI.

The last route cured compaction amnesia and made session handoffs painless. When I hand work to a new conversation or a long session compacts after an hour, the instruction to re-read `.work/active/<task>/BRIEF.md` is still sitting in AGENTS.md on the very next turn, so the agent reloads its exact checklist and outward boundaries from disk.

### 3. Executable gates instead of style adjectives

Writing "never use left accent borders" in prose failed because `border-left: 3px solid` is a default pattern in model training data for blockquotes and callouts.

When an agent breaks a rule twice, I stop editing the prose and write a 20-line check script. Rule 2 points to `python3 scripts/check-side-bars.py`, which scans changed CSS and TSX files for `border-left`, `border-inline-start`, and `inset <N>px 0 0` rules and exits non-zero if one appears. We did the same for server billing config after a half-configured environment quietly degraded to webhook-only mode: instead of writing "remember to set `entitlementIds` in production," we made the constructor throw on startup if `apiKey` is set without `entitlementIds`. A gate catches the mistake before I ever look at it.

### 4. Only the commands the agent cannot guess

If `pnpm test` runs your tests, you do not need to explain it. Write only the commands where the default guess is wrong or where running the command at the wrong time wastes minutes:

```markdown
## Commands

- Single seam test (for logic changes): `pnpm vitest run src/lib/cache.test.ts`
- Full gate (only at round close or when asked): `pnpm check` (runs `oxfmt --check && oxlint && vitest run`; we do not use `tsc --noEmit` or ESLint)
- Doc & route validation: `sh scripts/validate-all.sh`
```

Notice the qualifier on `pnpm check`: `(only at round close or when asked)`. Without that parenthetical, listing a check command in AGENTS.md makes dutiful agents run the full test and lint suite after every one-line copy tweak, contradicting Rule 0.

## What I deleted to stay under 120 lines

To keep the root file under 120 lines, every new line has to evict an old one. When a doc or status section in our workspace grows bloated, our repo validator flags it and I tell the agent to trim the prose down to current facts. Here is what I cut from `AGENTS.md` and never missed:

- **Directory trees and architecture tours.** Agents can run `ls` and `find` in 100 milliseconds. Static directory trees go stale the week you add a folder.
- **Formatting rules enforced by the formatter.** Telling an agent "use single quotes and 80-character lines" wastes tokens when `oxfmt` or Prettier rewrites the file anyway.
- **Postmortems and history.** "We dropped library X in October because of a peer-dependency bug" belongs in the toolchain doc that the route points to, not in every chat turn.
- **Over-specified rules written by earlier agents.** Whenever an agent writes documentation, it tends to turn a one-off preference into a permanent law. Audit the rules periodically and delete any rule you wouldn't enforce yourself.

## One real file across Claude Code, Codex, and Cursor

If you switch between coding agents, do not maintain separate `AGENTS.md` and `CLAUDE.md` files. They drift within a week, and you end up debugging why one model followed a rule the other broke.

Recent versions of Claude Code read `AGENTS.md` automatically when no `CLAUDE.md` is present. If you use an older tool that still demands `CLAUDE.md`, make it a symlink to `AGENTS.md`:

```bash
ln -s AGENTS.md CLAUDE.md
```

In a monorepo, keep cross-repo rules in the root `AGENTS.md` and put package-specific quirks in the package's `docs/README.md` that the root router points to. Never copy root rules into child directories.

## Reproducible snippet: the router template and a self-check script

Here is the starter `AGENTS.md` structure I use, followed by a small shell gate you can add to CI or pre-commit. The gate checks two things that silently rot in every instruction file: whether `AGENTS.md` grew past 120 lines, and whether any file path it routes to was renamed or deleted.

```markdown
# my-workspace

## Rules (highest priority)

- Rule 0 (UI tuning, 2026-09-15): change the code, hot-reload, and let the owner check; no tests or screenshots unless asked.
- Rule 0b (outward gate, 2026-09-15): keep changes uncommitted and never deploy, push, send mail, or mutate external accounts unless asked.
- Rule 1 (code comments, 2026-09-01): English only, short, only for a non-obvious reason.
- Rule 2 (no side bars, 2026-09-29): no side bar or left rule on any card, quote, or row (`python3 scripts/check-side-bars.py`).

## Commands

- Single seam test: `pnpm vitest run <path>`
- Full gate (round close or when asked): `pnpm check && sh scripts/check-agents-md.sh`

## Routes

- Shared UI & icons -> `packages/ui/README.md`, `packages/icons/README.md`
- Auth, billing & webhooks -> `docs/operations/billing.md`
- Database migrations -> `docs/architecture/migrations.md`
- Toolchain & CSS rules -> `docs/standards/web-toolchain.md`
- Long tasks (>30 min) -> write brief to `.work/active/<task>/BRIEF.md`; re-read after context compaction
```

And here is `scripts/check-agents-md.sh`, which enforces the line cap and verifies every backticked path in `AGENTS.md`:

```sh
#!/usr/bin/env sh
set -eu

FILE="${1:-AGENTS.md}"
MAX_LINES=120

lines=$(wc -l < "$FILE" | tr -d ' ')
if [ "$lines" -gt "$MAX_LINES" ]; then
  echo "FAIL: $FILE is $lines lines (max $MAX_LINES). Move narrative details into a routed doc." >&2
  exit 1
fi

# Extract backticked repo-relative file paths
paths=$(grep -oE '`[A-Za-z0-9_./-]+\.(md|sh|py|ts|js|json|yaml)`' "$FILE" | tr -d '`' | sort -u)

missing=0
for p in $paths; do
  case "$p" in
    .work/*|*'<task>'*|*'<path>'*) continue ;;
  esac
  if [ ! -e "$p" ]; then
    echo "FAIL: $FILE routes to missing path: $p" >&2
    missing=1
  fi
done

[ "$missing" -eq 0 ] && echo "PASS: $FILE ($lines/$MAX_LINES lines, all routed paths exist)"
```

Start with 20 lines. Add a route or a gate only when an agent makes the same mistake twice in a real session, and delete any rule that starts getting in your way.

## FAQ

### Is AGENTS.md the same as CLAUDE.md?

They do the same job under different filenames. Most coding agents read `AGENTS.md`; Claude Code checks `CLAUDE.md` first and falls back to `AGENTS.md`. Keep `AGENTS.md` as the single real file and symlink `CLAUDE.md` to it only if an older tool requires that name.

### Why did my agent ignore a rule that was clearly written in AGENTS.md?

Usually one of three reasons: the file is too long and the rule is buried in prose, the rule conflicts with another instruction (like listing `pnpm test` under commands without saying when _not_ to run it), or the rule fights a strong training default (like left borders on blockquotes) and needs a check script instead of prose.

### Should I let an agent generate my AGENTS.md with `/init`?

No. Auto-generated context files mostly write directory overviews and restate `package.json`, which the February 2026 arXiv study found increases token cost by 20%+ without improving task success. Write the file from the failures you actually hit in chat, and prune what agents write into your docs so one-off rules don't calcify.
