TutorialBy John IseghohiAug 12, 20267 min read

AGENTS.md: The One File That Makes AI Write Better Code

60,000+ repos ship an AGENTS.md and ~20 coding agents read it. Here's what to put in it, what to leave out, and why autogenerated ones make your agent worse.

A small brass pocket compass lying on a folded paper sheet on a near-black desk, its needle caught by a narrow mint beam

The Problem You're Actually Having

Your AI agent writes good code and the wrong code. It invents a folder structure you don't use. It picks a test framework you dropped six months ago. It reformats a file you told it not to touch. Tomorrow, in a fresh session, it does all of it again.

That's not a model quality problem. It's a memory problem, and the industry settled on a fix: a plain Markdown file at your repo root called AGENTS.md that any agent reads before it starts working.

It's now in 60,000+ repositories, read by roughly 20 coding-agent tools — Codex, Cursor, GitHub Copilot, Claude Code, Google Jules, Aider, Windsurf, Zed, Amp, Factory, RooCode among them — and stewarded by the Agentic AI Foundation under the Linux Foundation (codersera, agents.md).

For a solo founder shipping with AI, this is the highest-leverage 100 lines in your repo. Ship something worth writing it for — start at startup ideas.

What It Is (And Isn't)

It's a context file, not a config file. No schema, no validation, no required fields, no parser. Just Markdown that gets prepended to the agent's context before it reads your code.

Two consequences follow directly from that, and they're the two things people get wrong:

  1. Every line costs tokens, and those tokens compete with the actual code the agent needs to reason about. Short and specific outperforms exhaustive.
  2. It's written for a model, not a human. Your README is for contributors. AGENTS.md is for an agent that will run commands and edit files — precise, imperative, executable.

The Sections That Actually Earn Their Tokens

1. Commands (the highest-ROI section)

A 2,500-repo analysis found the Commands section produces more benefit than anything else in the file (Atlan). Not tool names — exact commands with flags.

## Commands
 
| Goal | Command |
|------|---------|
| Dev server | `npm run dev` (port 3000) |
| Type check | `npm run typecheck` |
| Unit tests | `npm test -- --run` |
| Single test | `npm test -- path/to/file.test.ts` |
| Production build | `npm run build` |
 
Run `npm run typecheck` before declaring any task done.

The last line matters as much as the table. Agents will run programmatic checks and fix failures before finishing — but generally only if you list them.

2. Boundaries (three tiers)

The framing that works is Always / Ask first / Never:

## Boundaries
 
Always:
- Add a test alongside any new function in `lib/`
- Use the existing `apiClient` for network calls
 
Ask first:
- Adding a dependency
- Changing anything in `convex/schema.ts`
- Editing generated files
 
Never:
- Commit secrets or `.env*` files
- Force-push or amend published commits
- Edit compiled output in `dist/`

Vague prohibitions get ignored. Named paths get respected.

3. Project structure (a map, not an inventory)

Ten lines with purpose annotations, not a tree dump:

## Structure
 
- `app/` — Next.js App Router pages (server components by default)
- `components/` — shared UI; no data fetching here
- `lib/` — pure helpers, unit-tested
- `content/` — MDX bodies; metadata lives in `*/manifest.json`

The value is the second half of each line. "No data fetching here" prevents a category of mistakes that a file listing never would.

4. Code style (snippets, not prose)

Skip anything a linter enforces — that's what the linter is for. Document only what differs from language defaults or what your formatter can't catch:

## Style
 
- Named exports only, except Next.js pages
- Errors: throw typed errors from `lib/errors.ts`, never bare strings
- No `any`. Use `unknown` plus a narrowing check

5. Testing

Framework, where tests live, what "done" means:

## Testing
 
- Vitest. Tests live beside source as `*.test.ts`
- Mock network at the fetch boundary, never mock our own modules
- New behaviour requires a failing test first

The Rules Most People Break

Keep it under 150 lines. Beyond that you're paying tokens on every task and diluting the instructions that matter. If your file has grown past that, split it.

Don't autogenerate it. Empirical research cited by the GitHub Blog found autogenerated AGENTS.md files can hurt agent performance while inflating token cost — in some tested settings, LLM-generated files performed worse than having no file at all. The reason is obvious once stated: a generated file describes what the code already says. It adds tokens without adding information.

The same body of analysis credits developer-written files with roughly a 4% improvement in task success rate and materially fewer agent-generated bugs. Small numbers per task, compounding across every session.

Use nested files in a monorepo. Agents walk up the directory tree from the file they're editing and combine the AGENTS.md files they find, with the nearest one winning on conflicts. Shared rules at the root, package-specific rules in each package. OpenAI's main repo runs 88 of them.

Make it the single source of truth. If you keep a CLAUDE.md or .cursorrules, have them point at AGENTS.md rather than duplicate it. Duplicated instruction files drift within weeks, and then your agent is following whichever stale copy it read first.

Update it in the same PR as the change it documents. This is the process discipline that separates teams getting real leverage from teams with a decorative file. Convention changed? The file changes in the same commit.

The Weekend-Founder Version

You don't need the enterprise treatment. Twenty minutes, five sections:

# Project
 
One-sentence description. Stack: Next.js 16, TypeScript, Convex, Tailwind v4.
 
## Commands
- Dev: `npm run dev`
- Types: `npm run typecheck` (run before finishing any task)
- Tests: `npm test`
 
## Structure
- `app/` — routes; `lib/` — helpers; `content/` — MDX
 
## Style
- Named exports; no `any`; existing components before new ones
 
## Boundaries
Never: commit `.env*`, edit `dist/`, add deps without asking.
Always: run typecheck before saying you're done.
 
## Gotchas
- `NEXT_PUBLIC_*` vars are inlined at build time — changing them needs a rebuild

That last section is the one to grow. Every time your agent gets something wrong twice, the fix is a line in Gotchas — not a longer prompt. That's the loop: a repeated mistake becomes a permanent rule.

This is the same instinct behind Claude Projects for founders and Claude Code skills worth installing first — stop re-explaining your project every session.

Building something that needs this? Pick it from startup ideas.

Where It Pays Off Most

Security-shaped rules. "Never interpolate user input into a query," "always validate request bodies at the boundary" catch exactly the classes of bug AI ships confidently — the ones covered in vibe coding security.

Cost-shaped rules. "Cache model responses," "no LLM calls in loops" enforced in the file beats discovering them on a bill.

Convention-shaped rules. The thousand small decisions — file naming, error shapes, where types live — where consistency matters more than which choice you made.

FAQ

Do I need this if I'm the only developer?

Especially then. Your agent has no memory across sessions, and you have no teammate catching drift. The file is the teammate.

Is there a required format?

None. Plain Markdown, any headings. Agents parse the text you write, and the only real constraint is that it be short and specific.

What if my tool prefers CLAUDE.md?

Most tools that have a proprietary file now fall back to AGENTS.md when their own is missing. Keep one canonical file and have the others reference it — or symlink them.

How do I know if it's working?

Track repeated corrections. If you're telling the agent the same thing more than twice, that instruction belongs in the file. If the file is long and you're still repeating yourself, it's too long to be read carefully.

TL;DR

AGENTS.md is a plain Markdown context file at your repo root that AI coding agents load before working. 60,000+ repos ship one; roughly 20 agent tools read it; the Linux Foundation's Agentic AI Foundation stewards the spec.

Write it yourself — autogenerated files can perform worse than no file. Keep it under 150 lines. Lead with exact commands and flags, then three-tier boundaries, a structure map with purpose annotations, style rules a linter can't enforce, and a growing Gotchas list. Nest per-package files in a monorepo; nearest file wins. Make it the source of truth and update it in the same PR as the change it documents.

Then use the leverage on something real: startup ideas.