Reading what the agent remembers
In this lesson we read the notes a coding agent keeps for itself and clean them up. The notes belong to the to-do project from earlier lessons, and four of them are planted for you: one is still right, two have gone stale, and one holds a fact the whole team should have. You delete the stale two and move the team fact into a file in the repository, where it is versioned and reviewed like code. On the way you meet the import syntax that pulls such a file into the agent’s instruction file.
Where the notes are kept, what loads when, and the import syntax are Claude Code’s, checked against the vendor’s documentation on the date at the end of the lesson [1]. Other coding agents keep notes under other names and in other places. The review works the same way there.
Where the notes are
Section titled “Where the notes are”Auto-memory is the set of notes an agent writes for itself in one
session and reads again in later ones. Claude Code’s version is called
auto memory, and it is switched on unless you turn it off. The agent
picks what to save: your corrections, your preferences, and facts about
the project that the code doesn’t show. The instruction file, CLAUDE.md
or AGENTS.md, is the other kind of memory, and a person writes that
one. A new session starts with both in its context window. To the model
they are text like your own messages, and Claude Code doesn’t enforce
anything they say [1].
In Claude Code the notes for a project are in
~/.claude/projects/<project>/memory/. The <project> part comes from
the git repository, so two worktrees of one repository, or two of its
subfolders, read and write the same notes. The folder is on your own
machine. A colleague who clones the repository has a folder of their
own, with their own notes [1].
The folder holds an index file, MEMORY.md, with a line for each note,
and next to it one Markdown file per note, which the vendor calls a topic
file. A header at the top of each topic file has a type field that says
what kind of note it is. There are four values: user (who you are and
how you like to work), feedback (a correction you made), project
(work in progress, deadlines and decisions) and reference (a pointer to
a tracker or a dashboard outside the repository) [1].
At launch the session reads the start of the index file and no other file from the folder. The start is the first 200 lines, or fewer when those lines are more than 25KB. A topic file stays on disk until the work calls for it and the agent opens it [1] [2]. So the index line is what every session sees, and a wrong index line is wrong in every session.
The planted notes are in the course repository at
site/examples/customizing-agents/memory-review/notes/. The program
startup.py next to that folder applies the loading rule to them. Its
complete source is in the same folder.
What a session starts with
Section titled “What a session starts with”Run this from site/examples/customizing-agents/memory-review/, and
compare what you see with the output below.
python3 startup.pyloaded at start: MEMORY.md, 4 of 4 lines read when needed: project_done_rewrite.md (project) read when needed: project_item_length.md (project) read when needed: project_tests_touch_data.md (project) read when needed: user_diff_first.md (user)
Output verified in CI from site/examples/customizing-agents/memory-review/startup.py.
The index is short, so all of it loads. Here it is, as every session in the project sees it:
- [Diff first](user_diff_first.md) — show the diff before explaining a change- [done is being rewritten](project_done_rewrite.md) — leave done() alone; the rewrite is on the done-v2 branch- [Tests touch the data](project_tests_touch_data.md) — back up todos.json before a test run and restore it after- [Item length](project_item_length.md) — keep item text at 80 characters or fewer for the phone widgetNow put the notes where an agent reads them. Make a fresh copy of the
fixture directory,
site/examples/coding-with-agents/first-session/fixture-repo/, outside
the course repository, change into it, and give it a first commit, as in
the earlier lessons of this course. Put the copy in a folder with no
CLAUDE.md in it or above it, such as your home folder. The last step of
the lesson needs the agent to read the copy’s AGENTS.md, and a
CLAUDE.md above the copy stops that [1].
git init -q && git add -A && git commit -q -m "fixture"Then copy the planted notes to a folder of their own in your home
folder. Replace <course> with the path of your copy of the course
repository. The same command puts the four notes back if you try the
lesson a second time.
mkdir -p ~/memory-review-notes && cp <course>/site/examples/customizing-agents/memory-review/notes/*.md ~/memory-review-notes/Claude Code’s autoMemoryDirectory setting points auto memory at a
folder you pick, written as a full path or as a path that starts with
~/, and the --settings flag may set it [1]. A key
you pass with --settings as inline JSON counts for that session only,
and Claude Code writes it to no file [3]. So this
command starts the agent in your copy with the planted notes as its
memory, and your own memory folders stay as they are:
claude --settings '{"autoMemoryDirectory": "~/memory-review-notes"}'Type /memory to see the memory files the session knows about. The
list also has an option that opens the auto memory folder
[1]. For this lesson, open ~/memory-review-notes in
your editor yourself and read the four topic files. Then ask the agent
what the notes mean for a task, before it does any work.
Before you change anything: if I ask you to fix the bug in the donecommand, which of your memory notes apply? Quote each one and say whatyou would do because of it.The answer below is illustrative, written for this page and not recorded from a model. Yours differs in wording.
Before you change anything: if I ask you to fix the bug in the done command, which of your memory notes apply? Quote each one and say what you would do because of it.
Three notes apply.
- "Leave done() alone; the rewrite is on the done-v2 branch." I would not change done() on this branch. I would tell you the fix belongs in done-v2 and wait.- "Back up todos.json before a test run and restore it after." Before running the tests I would copy todos.json to todos.json.bak, and copy it back after.- "Show the diff before explaining a change." If you tell me to go ahead anyway, I will show the diff first.The agent says all of this with the same confidence. It can’t see from its window that two of the three facts stopped being true.
Delete what has gone stale
Section titled “Delete what has gone stale”A remembered fact doesn’t warn you when it goes out of date. Long-term notes need updating as the world changes [4], and nothing in the feature does that for you. The index line is in the window at the start of every session, and the model reads it as context like anything else there. A note that was right in June and wrong in September is applied in September as firmly as in June, in every session, until someone edits it. Claude Code’s cleanup of old session transcripts leaves the memory folder alone, so a note doesn’t expire by itself [1].
So check each note against the thing it describes. The two project
notes about done() and the tests make claims the copy can confirm or
contradict. Leave the session open, and run the shell commands from here
on in a second terminal in your copy. The rewrite note names a branch.
git branch --list done-v2The command prints nothing: there is no done-v2 branch, and the rewrite
the note waits for isn’t happening here. The test note says the tests
write todos.json.
grep -c todos.json test_todo.pyIt prints 0. The tests build their items as lists and never open the
file, and AGENTS.md says not to edit todos.json. Both
notes were true once, before plans changed, and both now make the agent
do the wrong thing. One makes it refuse a bug fix, and the other makes it
copy a file the instructions say to leave alone.
Delete both topic files in ~/memory-review-notes:
rm ~/memory-review-notes/project_done_rewrite.md ~/memory-review-notes/project_tests_touch_data.mdThen open ~/memory-review-notes/MEMORY.md in your editor and delete
the two lines that point at those files. The notes are ordinary Markdown
files, and the vendor says you may read and change them by hand
[1]. Remove the index line too, since the index is the
part that loads.
Why does the old note win?
Section titled “Why does the old note win?”A coding agent's auto-memory holds a note that says the done command is being rewritten on a branch called done-v2 and must not be changed. The branch no longer exists. The learner asks the agent to fix a bug in the done command, and the agent refuses and cites the note.
Your agent refuses to fix a bug in done() and quotes a memory note:
“the rewrite is on the done-v2 branch”. That branch was deleted weeks
ago. Why does the agent still follow the note?
Where is the note when the session starts, and what else in that session would tell the model the note is out of date?
Move a team fact into a context file
Section titled “Move a team fact into a context file”The diff note and the item length note are left. “Show the diff before explaining a change” is one person’s working preference, and a personal note is what auto memory is for. “Keep item text at 80 characters or fewer” is different. It is a decision about the product, because the phone widget cuts longer text for everyone. Each person on the team needs it in each session, on each machine. In auto memory it reaches only the agent on this one machine, and nobody reviews it.
Context files are the files a person keeps for the agent to read:
project instructions, design notes, a plan, a glossary. They are in the
repository, so a change to one is a commit that someone can review, and
every clone has the same text. The team fact belongs in one. The fixture
has an AGENTS.md, and neither the copy nor a folder above it has a
CLAUDE.md. In that case Claude Code, from version 2.1.277, reads
AGENTS.md as the project’s instructions [1].
You could add the rule to AGENTS.md directly. For a decision that has a
reason and a date, a notes file of its own keeps AGENTS.md short, and
the import syntax loads it with AGENTS.md.
The import syntax is an @ sign directly in front of a path. A line in
AGENTS.md that ends in @docs/decisions.md puts the whole of
docs/decisions.md into the session’s context at launch, next to
AGENTS.md itself. A path that doesn’t start with / starts from the
folder of the file that contains it. So an @glossary.md inside
docs/decisions.md means docs/glossary.md, whichever folder you
launched the agent from. An imported file may contain imports of its own,
and the session follows those too. Inside backticks the @ does nothing:
`@CHANGELOG.md` names the changelog and loads nothing. An
AGENTS.md that Claude Code reads directly follows the same rules
[1].
Here are those rules as a small program, applied to a sample project in
site/examples/customizing-agents/memory-review/imports/. The complete
file is imports.py in the same folder. The project’s AGENTS.md is:
# Agent instructions for todo
- Python 3, standard library only. No new dependencies.- Run the tests with `python3 -m unittest -q`.- Add a line to `@CHANGELOG.md` for every change a user can see.- Team decisions that the code doesn't show: @docs/decisions.mddocs/decisions.md holds the 80-character rule and the line “The words
used here are defined in @glossary.md”. The project has two glossaries:
glossary.md at the top, an old one, and docs/glossary.md, next to
docs/decisions.md. It also has a CHANGELOG.md at the top.
Which files load?
Section titled “Which files load?”A sample project has AGENTS.md at the top. It mentions @CHANGELOG.md inside a code span and imports @docs/decisions.md as plain text. docs/decisions.md imports @glossary.md. The project has both glossary.md at the top and docs/glossary.md, and a CHANGELOG.md at the top. A script applies the vendor's import rules and prints one line per file the session loads.
What does this print, one line per file the session loads?
for path, parent in load(ROOT / "AGENTS.md"): name = path.relative_to(ROOT).as_posix() if parent is None: print(name) else: print(f"{name}, imported by {parent.relative_to(ROOT).as_posix()}")AGENTS.md docs/decisions.md, imported by AGENTS.md docs/glossary.md, imported by docs/decisions.md
Output verified in CI from site/examples/customizing-agents/memory-review/imports.py.
For each @path, ask whether it is inside backticks, and which folder a relative path starts from.
CHANGELOG.md isn’t loaded, because its @ is inside backticks. That
line only names the file. The glossary that loads is the one in docs/,
because @glossary.md is in docs/decisions.md and resolves from
docs/. Moving text into an imported file doesn’t make the session any
lighter. The imported file enters the window at launch with the rest, so
what you gain is a shorter AGENTS.md to read and review, and the
context used stays the same [1].
Now do the move in your copy. Make the folder with mkdir docs, and
create docs/decisions.md in it:
# Decisions
- Keep item text at 80 characters or fewer. The phone widget that shows the list cuts longer text.Add this line at the end of AGENTS.md, with nothing after the path:
- Team decisions that the code doesn't show: @docs/decisions.mdThen delete ~/memory-review-notes/project_item_length.md and its line
from MEMORY.md, so the fact is in one place. Commit the two repository
files, which is the step that makes the fact reviewed and shared.
git add AGENTS.md docs/decisions.md && git commit -q -m "Record the item length decision"Quit the session and start a new one with the same claude --settings
command. Run /context: its list of memory files shows the instruction
files the session loaded, and AGENTS.md is in it
[1]. The list may leave out docs/decisions.md, so
the real check is a question. Ask the agent the limit on item text and
which file states it. The answer names docs/decisions.md. The notes folder holds
MEMORY.md and user_diff_first.md, plus any note the agent saved this
session. Memory notes and context files keep facts from one session for
the next. The next lesson covers what happens inside one long session
when it is compacted.
Keep, delete or move?
Section titled “Keep, delete or move?”A developer reviews the auto-memory notes a coding agent wrote for a small to-do project. For each note they decide whether it stays in the agent's memory, is deleted, or moves into a context file in the repository that the whole team reads.
Place each memory note where it belongs.
For each note, ask whether it is still true, and whether it is one person's preference or something the whole team needs in every session.
Which checks show a stale note?
Section titled “Which checks show a stale note?”A developer checks the auto-memory notes a coding agent keeps for a to-do project. One note says the done command is being rewritten on a branch called done-v2. Another says the tests write the real todos.json file.
Which two of these results show that a memory note has gone stale?
Which results contradict what a note claims, and which only describe the note itself?
What do you do with the note?
Section titled “What do you do with the note?”A coding agent's auto-memory has an index file that loads at the start of every session and one topic file per note. One note says to run only the fast tests, because the full run needs a staging server that is down. The developer checks and finds the server is up and the full run takes 30 seconds.
A memory note says “run only the fast tests, the full run needs the staging server and it is down”. The server is up again, and the full run takes 30 seconds. What do you do?
Is the claim still true, and which part of the memory folder does every session load?
What do you do with each note?
Section titled “What do you do with each note?”A developer reviews the auto-memory notes of a coding agent in a team repository and decides for each note whether it stays in memory, is deleted, or moves into a context file in the repository.
Match each memory note to what you do with it.
Is the note still true, and does it describe one person or the whole team?
Exercise
In a fresh copy of the fixture with its own first commit, copy the
planted notes to ~/memory-review-notes, start the agent with
claude --settings '{"autoMemoryDirectory": "~/memory-review-notes"}',
and open ~/memory-review-notes in your editor. Check each project note
against the copy, delete the two stale notes and their index lines, move
the item length rule into docs/decisions.md with an import from
AGENTS.md, delete that note too, and commit. The work is about ten
minutes and touches one memory folder and two repository files. Doing it
once by hand shows you what a review of an agent’s memory looks like, and
which facts should never have been left in it.
A good result: the notes folder holds MEMORY.md and
user_diff_first.md, plus any note the agent saved this session, and
MEMORY.md has a line for each of those notes and no other.
git log --oneline shows your commit above fixture. A new session names
docs/decisions.md when you ask where the item length rule comes from.
Reflection: which fact does your agent rely on today that you told it
once and never wrote down anywhere a colleague could read?
Stretch: Run `python3 startup.py` with the memory folder of one of your own projects as its argument, a folder under `~/.claude/projects/` that has a `MEMORY.md`. It only reads the folder. Then read every note the index points to and mark each one keep, delete or move.
Recap
- Auto memory is notes the agent writes for itself. In Claude Code they
are in one folder per repository on your machine, with a
MEMORY.mdindex and one topic file per note, and the feature is on by default [1]. - A session loads the first 200 lines or 25KB of
MEMORY.mdat start, and reads topic files only when it needs them. The index line is what every session sees [1]. - A stale note is applied in every session with the same confidence as a true one, because the model reads it as context. Check each note against what it describes, and delete the file and its index line.
- A fact the whole team needs belongs in a context file in the
repository, where it is versioned and reviewed. An instruction file
loads it with
@path, resolved from the importing file’s folder, and a path in backticks stays text [1].
You can now
- Manages what the agent carries between sessions
References
Section titled “References”- Anthropic. How Claude remembers your project. Claude Code documentation. Reference.
Claude Code memory - Anthropic. Explore the context window. Claude Code documentation. Reference.
Claude Code context window - Anthropic. Settings files and precedence. Claude Code documentation. Reference.
Claude Code settings - Addy Osmani, Ivar Soares Urdalen, Leo Simons. Memory and context: context engineering, memory kinds, memory versus RAG, context rot. Agent Engineer Course. Course.
AEC-05