Skip to content

Writing project instructions the agent reads every session

In this lesson we read two sessions a coding agent ran on the same small repository and find the one mistake it made in both. We fix that mistake once, with one line in the file the agent reads at the start of every session. Then we start a fresh session and check that it follows the line without being told. The last two sections are about keeping a session lean enough that the agent keeps following the file, and about recording a decision where the next session finds it.

The file is the project’s project instructions, AGENTS.md or CLAUDE.md at the root of the repository. How to write one from nothing, and what belongs in it, is the subject of the customizing-agents lesson on AGENTS.md. This lesson starts where that one stops: the file exists, and you are the engineer who runs sessions against it and notices what it fails to say.

The file works because the agent grounds its work in what is in its context, as the retrieval lesson showed for a chat model. A rule in the instructions file is in the context of every session. A correction you typed in an earlier session is not. Where this lesson names a Claude Code feature it says so, and the vendor pages are checked on the date at the end of the lesson.

The fixture is the to-do program from Telling the agent where the task is and where it stops, after its undo change. docs/SPEC.md now specifies two more commands that nobody has built: rename <n> <text> and remove <n>. The repository is in the course repository under site/examples/coding-with-agents/project-instructions/fixture-repo/. Copy that directory to a place of its own and change into it. Then give the copy one commit, so that git status can show what a session changed:

Terminal window
git init -q && git add -A && git commit -qm start

Delete the copy and copy again to reset. Then read the instructions file.

Example · run it

Print the file from inside the copy.

Terminal window
cat AGENTS.md
Output
# Agent instructions for todo

- Python 3, standard library only. No new dependencies.
- Tests use `unittest`. Run them with `python3 -m unittest -q`.
- `docs/SPEC.md` is the specification for the commands. Follow it.
- `legacy/` is the old single-file version, kept for reference. Never edit it
  and never import it.
- Do not edit `todos.json`; the tests use their own lists.

Output verified in CI from site/examples/coding-with-agents/project-instructions/instructions.py.

The file has five rules, and each is a fact the agent can’t read from the code. That is a good file by the measure of the customizing-agents lesson, and it is short.

Most coding agents load this file before your first message. Claude Code loads its instructions files at the start of every session, reads AGENTS.md when the repository has no CLAUDE.md, and in an interactive session prints a line that names the AGENTS.md it loaded [1]. Its /context command shows what is in the context window, so you can confirm the file is there [2]. Other agents have their own file names and their own way to show it. With any agent you can check what it took from the file by asking before the task starts, for example “What does the instructions file say about todos.json?”. An agent that quotes the last rule has most likely read the file, and in Claude Code /context shows it for certain.

An agent can have the file in its context and still do what the file was meant to prevent. The sessions below show how.

The course has the logs of two sessions on fresh copies of the fixture. The first added rename, and the second added remove. Each had a short, scoped brief and the verification command. The logs are in the course repository, in sessions/ next to fixture-repo/, so an agent that works in your copy never reads them. They are illustrative: the author wrote them to show what such sessions look like, and the course runs the program to check every output line in them.

Example · run it

Print the log without its header, from site/examples/coding-with-agents/project-instructions/ in the course repository.

Terminal window
tail -n +4 sessions/session-2.txt
Output
you: Add the remove command that docs/SPEC.md specifies. Done when
     python3 -m unittest -q prints OK.

read AGENTS.md
read docs/SPEC.md
read todo.py
read test_todo.py
edit todo.py: add remove(items, number) after undo, and a remove branch
     in main after the undo branch
write test_remove.py
run python3 -m unittest -q
  OK
run python3 todo.py remove 3
  removed #3: Renew the passport
run python3 todo.py list
  1. [ ] Buy milk
  2. [x] Call the plumber
  3. [ ] Water the plants
  2 open, 1 done

agent: remove is in todo.py, with two tests in test_remove.py. The suite
     passes, and I ran the command against the list to confirm it works.

Output verified in CI from site/examples/coding-with-agents/project-instructions/log.py.

Each session on its own looks fine. The agent read the instructions first and followed the spec, and its tests pass. A mistake that repeats doesn’t show in one session. It shows when you put two next to each other and look for what they have in common. Start with the commands the agent ran against the program.

Example · run it

Run this from site/examples/coding-with-agents/project-instructions/ in the course repository.

Terminal window
grep -H '^run python3 todo.py' sessions/*.txt
Output
sessions/session-1.txt:run python3 todo.py rename 1 "Buy oat milk"
sessions/session-1.txt:run python3 todo.py list
sessions/session-2.txt:run python3 todo.py remove 3
sessions/session-2.txt:run python3 todo.py list

Output verified in CI from site/examples/coding-with-agents/project-instructions/repeated.py.

In both sessions the agent tried the new command once by hand, which is a good habit, and it ran the command with no TODO_FILE. docs/SPEC.md says the program then reads and writes todos.json next to the scripts, the list committed to the repository. git status at the end of each session shows the result. The course replays both sessions on fresh copies and prints it.

Example · run it

The course applies each session’s change to its own copy and runs every command in the log the way the agent ran it. It fails if an output differs from the log. Then it runs this in each copy.

Terminal window
git status --short
Output
session-1.txt
 M todo.py
 M todos.json
?? test_rename.py
session-2.txt
 M todo.py
 M todos.json
?? test_remove.py

Output verified in CI from site/examples/coding-with-agents/project-instructions/replay.py.

todos.json changed in both sessions, and neither report mentions it. Session 1 renamed an item in the committed list, and session 2 deleted one. A reviewer who reads the diff catches it. The next session makes the same mistake again, because nothing it loads says otherwise.

Checkpoint · choice

Both sessions read AGENTS.md, and both left todos.json changed. What went wrong?

A mistake the agent makes in two sessions is a fact about the project that the instructions file doesn’t state yet. What kind of fact belongs there is in the customizing-agents lesson, and this section is about when to add one. Claude Code’s documentation gives a similar trigger for its own instructions file: a mistake the agent has made before, or a correction you already gave in an earlier session [1]. The agent-engineering course says the same about AGENTS.md: start small, and add a line when you see an agent repeat a mistake [3].

A correction in the next brief fixes one session. The line in the file reaches each session after it, including a teammate’s, because the file is in the repository. So the fix goes in the file, and it is one line.

The line needs to be specific enough that you can check the agent against it. The existing rule says what not to do in words the agent read narrowly. The fix names both ways the file changes and says what to do instead. Claude Code’s documentation ties how reliably the agent follows a rule to how exact and short it is [1]. Replace the last line of AGENTS.md with this one:

- Never change `todos.json`, by hand or by running `todo.py`. To try a command, copy the list first: `cp todos.json /tmp/todos.json`, then run `TODO_FILE=/tmp/todos.json python3 todo.py ...`.
Checkpoint · repair

In another project, seed.py fills the database that DATABASE_URL names with sample data, and test.db is a local database for trying things. In two sessions the agent ran seed.py against the shared database to “check the data”, although AGENTS.md has the line below. Rewrite the line so it names the action the agent took and what to run instead.

Commit the line. The next session starts from the committed file.

Terminal window
git commit -qam "docs: say how to try a command without changing todos.json"

Start a fresh session and give it the brief of session 2, word for word. The brief says nothing about todos.json.

Prompt (illustrative, not a recorded transcript)

Add the remove command that docs/SPEC.md specifies. Done when python3 -m unittest -q prints OK.

Response

I read AGENTS.md, docs/SPEC.md, todo.py and test_todo.py.

Added remove(items, number) to todo.py after undo, and a remove branch in main. Added test_remove.py with two tests. python3 -m unittest -q prints OK.

I tried the command on a copy of the list, as AGENTS.md says: cp todos.json /tmp/todos.json, then TODO_FILE=/tmp/todos.json python3 todo.py remove 3, which printed removed #3: Renew the passport. todos.json is unchanged.

Like the logs, this exchange is illustrative, and your agent phrases it differently. Check the repository, because the report is the agent’s account of what it did.

Example · run it

The course commits the new line in its own copy, applies the change of session 2, runs the command the way the new line says, and then runs git status.

Terminal window
cp todos.json /tmp/todos.json
TODO_FILE=/tmp/todos.json python3 todo.py remove 3
git status --short
Output
removed #3: Renew the passport
 M todo.py
?? test_remove.py

Output verified in CI from site/examples/coding-with-agents/project-instructions/fresh.py.

The command still printed the message the spec asks for, and todos.json is gone from the list of changed files. The brief was the same as in session 2. The one thing that changed is a line in the file the agent loads before the brief, and later sessions load that line too.

The instructions file is loaded once, at the start. What comes after it in the session goes into the same context window: the files the agent reads, the command outputs and your corrections. As that window fills, the agent follows earlier instructions less well, and Claude Code’s documentation says so for its own tool [2]. The file you just fixed is in the context, and so are forty tool outputs after it.

Context rot is the drop in how well the agent follows its instructions as the context window fills. Avoiding context rot is keeping the context lean so the agent keeps following its instructions and keeps the goal in view. These habits keep a session lean.

  • One task per session. When rename is done and committed, start a new session for remove. Claude Code has /clear for this, and its documentation advises clearing between unrelated tasks [2].
  • Summaries instead of raw logs. Paste the three lines of a failing test that matter, or ask the agent for a short account of a long log.
  • Point at files by path instead of pasting them. The agent reads a file when it needs it.
  • When the agent ignores a rule it followed an hour ago, or you have corrected the same thing twice, compact or restart. Claude Code compacts the conversation on its own near the limit, and /compact with instructions does it when you choose. Its documentation advises a fresh session with a better prompt after two failed corrections [2].

The instructions file makes a restart cheap. Claude Code reads the root instructions file from disk again after /compact, and an instruction you gave only in the conversation can be lost in the summary [1]. A rule in the file comes back in the next session. A rule you typed in chat does not. Anthropic’s course Claude Code in action has a module on steering long sessions for more on this [4].

Checkpoint · scenario

What do you do?

Record the decision where the agent reads it

Section titled “Record the decision where the agent reads it”

The instructions file also holds the reasons behind the project’s structure, at least where to find them. Suppose the remove session proposed moving the list from todos.json into an SQLite database, and you said no: one JavaScript Object Notation (JSON) file keeps the program to the standard library, and the diff of todos.json shows every change in review. That reason is now in a transcript, and the next session that finds the JSON file slow will propose the database again.

Write the decision down in the repository and point at it from the file. One line in AGENTS.md is enough for the pointer:

- The list stays one JSON file. Read `docs/decisions/` before you change how `store.py` saves it.

The next lesson, Staying the engineer who understands the system, shows the decisions folder and a decision file in full. The part that belongs here is the direction: a decision you want every session to respect goes in a file the session loads or is pointed at, because the transcript of the session where you made it is in nobody’s context.

Checkpoint · choice

Where should the decision and its reasons go?

Exercise

Run the two sessions yourself. Reset the copy of the fixture, start your coding agent in it, and give it the brief of session 1 from sessions/session-1.txt. When it is done, save its report and the output of git status --short. Reset the copy, start a fresh session, and do the same with the brief of session 2. Plan on fifteen minutes.

Put the two reports and the two status lists next to each other and find the one thing that went wrong in both. It may be todos.json, as on this page, or something else your agent does, such as a wrong test command or a file it edits that the task didn’t need. Write the one line that fixes it, specific enough to check. Delete the copy and copy the fixture again. Add or change the one line in its AGENTS.md, commit it with the command above, then start a fresh session with the brief of session 2. Check git status --short again.

A good result: the fresh session’s status no longer shows the mistake, the brief was word for word the one from before, and AGENTS.md is one line different from the original. Delete the copy when you are done. Then answer one question: if your agent made no mistake in both sessions, what did you check to be sure, and what would you add to the file if a third session made one?

Stretch: Do the same in a repository of your own. Read your last two agent sessions side by side, find one thing the agent got wrong in both, and fix it with one line in the instructions file. In the same edit, delete one line the agent gets right without it.

Recap

  1. The project instructions file is loaded at the start of every session, so a rule there reaches every later session, and a correction in the chat reaches one [1].
  2. A mistake that repeats shows when you put two sessions side by side. Fix it once, with one line in the file [3].
  3. Write the line so you can check the agent against it: name the action the agent took and what to do instead.
  4. A long file gets its rules ignored. When you add a line, delete the ones the agent no longer needs [2].
  5. Keep the context lean: one task per session, summaries instead of raw logs, and compact or restart when the agent stops following rules it followed earlier.
  6. Record a decision in the repository and point at it from the instructions file, because the next session never reads the transcript where you made it.

You can now

  • Gives the agent the files, constraints and limits the task needs
  • Keeps their own understanding of the code as the agent produces more of it

  1. Anthropic. How Claude remembers your project. Claude Code documentation. Reference. Claude Code memory
  2. Anthropic. Best practices for Claude Code. Claude Code documentation. Reference. Claude Code best practices
  3. Addy Osmani, Ivar Soares Urdalen, Leo Simons. AGENTS.md: contents, monorepo hierarchies, with a builder widget. Agent Engineer Course. Course. AEC-15
  4. Anthropic. Claude Code in action. Claude Academy. Course. Academy claude-code-in-action