Teaching the agent your conventions

An AGENTS.md file open next to a terminal agent session

This is the second post in a series on the AI engineering toolkit. The first one moved you into the terminal. This one teaches the agent about the project you work in, so you stop re-explaining the same things every session.

The short version: write one AGENTS.md at the root of your repository, fill it with the things an agent would otherwise get wrong, keep it short, and commit it. Most agents read that file already. Claude Code is the holdout and wants its own CLAUDE.md, which you can point at the same content. The rest of this post is about what goes in the file and how far you can trust it once it is there.

It keeps forgetting

You correct the same things every session. In a conda project the agent still reaches for npm instead of pip. The indentation comes back at two spaces when the whole repository uses four. None of it sticks, because the next session starts from a clean slate.

Your conventions only ever lived in the chat, and nothing carries them across sessions on its own. An agent reads your code well enough to see what the project does. The conventions you have settled on and the commands you actually run live outside the code, usually in your own head, and the agent has no way to recover them.

You can usually pick a session back up. All three agents let you resume an earlier one, so a closed terminal does not always mean starting over. A session still fills its context window in the end, though, and the next clean start loses the corrections you typed into the last one.

So you write them down once, in an instruction file the agent reads on its own.

One file, most agents

The fix is a plain markdown file the agent loads at the start of every session, before it does any work. The convention most tools have settled on is a file called AGENTS.md at the root of your repository. You write it in ordinary prose and markdown, with no required structure and no schema to learn.

A growing list of agents read it: OpenCode and Codex among the terminal tools, along with Cursor, Copilot, Gemini CLI, Zed, and a couple dozen others. It began as a shared effort across several of the agent makers and is now stewarded by the Agentic AI Foundation under the Linux Foundation, so it is a genuine cross-vendor standard with no single owner. At the time of writing, over sixty thousand public repositories already ship one.

Here is a small but complete example for a Python project:

# AGENTS.md

## Setup

- Create the environment with `conda env create -f environment.yml`, then `conda activate myproject`.
- Install in editable mode with `pip install -e ".[dev]"`.

## Tests

- Run `pytest` from the repository root. It needs the `dev` extras installed.

## Conventions

- Format with `ruff format`, lint with `ruff check`. Both run in CI.
- Public functions take type hints and a one-line docstring.

It carries the exact commands and the handful of conventions an agent would not guess from the code, and nothing about what the project is for, which the README already covers.

The Claude Code exception

Claude Code is the only one of the three that does not read AGENTS.md. It reads its own file, CLAUDE.md, and ignores AGENTS.md entirely.

You have two documented ways to avoid keeping two files in sync. The first is a symlink, which works when you have nothing Claude-specific to add:

ln -s AGENTS.md CLAUDE.md

The second is an import. Claude expands an @-reference when it loads the file, so a one-line CLAUDE.md can pull in everything from AGENTS.md, with room for Claude-only notes underneath:

@AGENTS.md

## Notes for Claude
- Use plan mode for changes under `src/billing/`.

Reach for the import on Windows, where symlinks need administrator rights, or whenever you want those extra Claude-specific lines. The rest read AGENTS.md and leave CLAUDE.md to Claude, so the bridge is there only to keep Claude happy.

What goes in it

The hard part is deciding what belongs in the file. Ask whether an agent would get something wrong without being told. If not, leave it out.

Build and test commands earn their place, because an agent that guesses them wastes a round-trip getting them wrong. So do the conventions that depart from the language defaults and the setup steps a newcomer would never stumble onto. The pip-not-npm rule from earlier is a good example, cheap to write and enough to save the agent from a confident mistake.

Then there are the traps a newcomer learns only by hitting them. An agent will hand-edit a lockfile that should be regenerated by its tool, breaking the build. If the test suite needs a local Postgres running, the file has to say so. Steps that run in a fixed order, like codegen before the build, are easy for an agent to skip. The commit-message format is worth a line too, since it will otherwise invent its own.

The opposite mistake is stuffing the file. A long AGENTS.md that restates the README and narrates the whole directory tree does more harm than good, because the agent reads all of it on every turn and the signal drowns. Write down what an agent would miss, and trust it to read the code for the rest.

The conda project’s own AGENTS.md has a habit worth copying. It points the agent at where the test fixtures live and how to list them from the code. A fixed table would go stale the first time someone renamed a fixture.

Keep it short

There is a mechanical reason to keep the file short, on top of the general case for focus. Codex caps the combined instruction files at 32 KiB and silently truncates whatever runs over. A bloated file dilutes the agent’s attention, and past the cap part of it simply stops loading with no warning at all.

Claude gives a softer version of the same advice, suggesting you aim for under two hundred lines because longer files get followed less reliably. OpenCode’s guidance is the bluntest of the three: when in doubt, leave it out.

Every line in this file is read on every turn, which means it competes for the same context window as your actual conversation. How that window works, and why filling it carelessly backfires, is the subject of the next post. For now, treat space in the file as a budget you spend.

Where the files live

So far this has been about a single file at the repository root. That is the one you commit, and the one your team picks up from version control. Two other locations matter.

A global file holds your personal preferences across every project you touch. OpenCode looks in ~/.config/opencode/AGENTS.md. Codex uses ~/.codex/AGENTS.md, and Claude its usual ~/.claude/CLAUDE.md. What goes here is different in kind from a project file. Because it loads in every repository, it cannot carry anything project-specific, so build commands and local conventions stay in the project file. The global file is for habits that hold whatever you are working on, like always asking for a plan before an edit. None of it is committed, so it stays personal to you.

For personal notes in a single project, only Claude has a purpose-built file: CLAUDE.local.md, which loads alongside CLAUDE.md and is gitignored. Codex’s nearest equivalent is AGENTS.override.md, though it overrides the directory’s AGENTS.md wholesale, so personal notes there would shadow the shared file. OpenCode has no dedicated file at all. With it you get the same effect by hand: add something like AGENTS.local.md to .gitignore, then list it in the instructions array of opencode.jsonc (OpenCode’s configuration file, plain JSON that also allows comments, sitting at the repository root for project settings or in ~/.config/opencode/ for the global ones). Sharing instructions across a team in earnest, and managing them centrally, is a larger topic that I will come back to in a later post.

Once a repository gets large, two more things help. The first is path-scoped rules. Claude lets you split instructions out of the main file into separate markdown files under .claude/rules/, each one a focused set of instructions on a single topic. Add a paths: field to a rule file’s front matter and it activates only when the agent touches files that match, so a rule about API handlers stays out of context until you are working on API code. The main file stays small because most of the rules are dormant most of the time. That conditional loading is particular to Claude. Codex and OpenCode scope instructions by where a file sits in the tree instead, which is the monorepo case that follows.

The second is the monorepo, where different packages want different instructions. All three handle it with nested files, though they load them differently. Codex reads nested AGENTS.md files from the git root down to wherever you are working, stacking them inside that same 32 KiB budget. Claude does the same with nested CLAUDE.md files, loading each one lazily the first time it reads a file in that directory. OpenCode takes another route, where you point its instructions setting at a glob such as packages/*/AGENTS.md in opencode.jsonc and it loads the matches. Airflow is a good real-world example, a root file that maps the repository and leaves the per-package detail to files further down.

Writing and keeping it

You do not have to write the first version by hand. All three ship an /init command (you met OpenCode’s in the first post) that scans the repository and drafts the file from what it finds, the build commands and the structure it can infer. Claude’s writes CLAUDE.md and the other two write AGENTS.md. If a file already exists, it improves that one in place.

Whatever /init produces is AI output like any other, so read it before you trust it. It can record a command slightly wrong or pad the file with things the agent should have left to the code. You can also get an agent to help with that review. Put it in read-only mode first (Claude’s Shift+Tab plan mode, OpenCode’s Tab toggle, Codex’s read-only permission) so it inspects without editing, then have it critique the draft against the repository or even point it to this very article for cues.

The draft is only a starting point. What matters more is keeping it current, and that is a habit you build. When the agent makes the same mistake twice, or a review catches something it should have known about the project, add a line to the file. Over a few weeks the file collects the corrections you used to repeat, and you stop needing to give them.

Does it actually work

A fair question, once you have written all this down: does the agent actually obey it? Usually, though not always. These files are instructions the model reads and tries to follow, with no guarantee of strict compliance, and the vaguer the instruction the looser the adherence. Claude’s documentation is candid about it, noting that CLAUDE.md arrives as a user message after the system prompt and is treated as guidance the model can still override.

A quick way to check is to ask the agent to do something the file forbids and watch what happens. If it refuses, or at least pushes back, the file is loading and being read. If it sails ahead, either the file is somewhere the agent does not look, or the rule is too vague to act on.

When you need a rule enforced no matter what the model decides, that is the job of a hook, a deterministic check it cannot talk its way past. Measuring whether an edit to the file actually improved the agent’s behaviour is what evals are for. Both get their own posts later. For an instruction file, the realistic expectation is a strong nudge that holds most of the time.

Where to look

The best way to get a feel for a good AGENTS.md is to read a few from projects you respect. The conda repository has the fixtures habit mentioned above. Astral’s uv keeps an unusually disciplined one, eighteen lines that say only what an agent would get wrong and not a word more. Airflow shows the monorepo pattern at scale, and PyTorch’s CLAUDE.md is worth reading for the way it warns about a CI trap that would otherwise cost you an afternoon. The agents.md site links a gallery of tens of thousands more if you want to browse.

Conclusions

What to do

Write one AGENTS.md at the root of your repository, put in it the commands and conventions an agent would otherwise get wrong, and keep it short enough that every line earns its place. Commit it so the team shares it. If you use Claude Code, give it a CLAUDE.md that symlinks or imports the same content.

What to expect

The file turns the agent from something you re-teach every morning into something that already knows how your project works. It will not follow the file perfectly, and the way to tighten that up is to keep editing it as the agent surprises you. The next post goes under the hood of the context window this file lives in, which is what decides how much of all this the model can hold at once.