Why Claude Code Forgets Between Sessions, and What We Use Instead
By Andrey Boyko
Published Updated
Reviewed against Claude Code docs on
Claude Code starts every session with an empty context window, so anything not written to a file it loads at startup is gone. There are three separate reasons, and the fix differs for each. This guide covers the limits of recall, what Claude Code keeps on its own, and what we run ourselves.
Why does Claude Code forget between sessions?
Because a session is a fresh start by design. The memory docs say it directly: “Each Claude Code session begins with a fresh context window.” Two mechanisms carry knowledge forward: CLAUDE.md files that you write, and auto memory, where Claude writes notes from your corrections and preferences. Both are loaded at the start of every conversation, and the docs add that Claude treats them “as context, not enforced configuration” (checked 2026-10-23, memory docs). A session you do not resume starts without the earlier conversation.
When something seems forgotten, the cause is usually one of three different things, and mixing them up sends you to the wrong fix:
- The note was never loaded. It sits past a size limit, or in a different project folder, or it was never written.
- The note was stored but never found. This is a retrieval problem, and it applies to memory servers that search by meaning.
- The note was loaded and was wrong. This is drift in a file that nobody re-checks.
What does Claude Code itself keep between sessions?
Auto memory keeps a folder of plain markdown files: an index called MEMORY.md plus one topic file per memory. Per the docs (checked 2026-10-23, memory docs), only the head of the index is loaded at startup: “The first 200 lines of MEMORY.md, or the first 25KB, whichever comes first.” Content beyond that threshold is not loaded at session start. Topic files are not loaded at startup either. Claude reads them with its normal file tools when it needs them.
The folder is ~/.claude/projects/<project>/memory/, and <project> comes from the git repository, so all worktrees of one repo share it. It is machine-local, so it does not follow you to another computer. It survives /compact: the context-window page lists auto memory as “Re-injected from disk” after compaction (checked 2026-10-23, context window docs).
We found no statement that a note will be retrieved or applied, nothing on how Claude picks which topic file to open, and no message at load time that tells a session its index was cut. The docs describe only a write-time reminder and an over-limit error, which fire when Claude edits the file. A GitHub issue asks for a load-time signal: #82056, titled “A session cannot determine whether its auto-memory index loaded whole, truncated, or not at all”. As of 2026-10-23 it was open with 74 comments. A second open issue, #91188, with 59 comments, asks for the index size reminder to be configurable. We have not reproduced anything from either issue, and we have not run a session with an oversize index to see the 200-line or 25KB cut ourselves. Treat those as the docs’ claims and other users’ reports, not our measurements.
For scale, our own index for this project is 35 lines and 5,313 bytes (wc, 2026-10-23). That is 21 percent of the 25KB cap and 18 percent of the 200-line cap, so it is nowhere near truncation.
What did our memory server get wrong?
We run a memory server of our own: notes are stored with embeddings and found by similarity search. In our experience it failed in two different ways, on two different dates, and they should not be merged into one story.
2026-06-27: a known-recent entry was filtered out. The complaint was “context lost between sessions”. Our record from that day says writes were healthy and the fault was retrieval: a similarity threshold plus ranking pushed a recent entry below older, higher-scoring ones, and the caller got plausible results with no warning. This is our own diagnosis from one observed case. The record has no count of queries tried and no failure rate, so we publish none. We did not measure how often it happens.
2026-07-26: an audit found two production faults while 172 tests were green. An audit that day found 172 unit tests passing while provenance and trust fields were dropped on nearly every production recall. The tests mocked the database and fed in rows that already had those fields, so they could not see that the real query never selected them. The same audit found the code’s default similarity threshold was 0.7 while the calibrated value was 0.25. Neither fault was visible to the 172 tests; the audit found both. Production worked only because an environment file overrode the default; a new environment would have returned empty results with no error. Fixes shipped on 2026-08-15, including a startup warning when the threshold exceeds 0.4. We cannot say that fix also resolved the June case. They are different faults.
The lesson we took: for “what is open right now”, semantic search is the wrong tool, because it returns the nearest rows to a query and not a true list.
What do we run at the start of every session?
A plain file at the project root. Since 2026-06-27 our rule has been that operational state (open threads, tasks, blockers) lives in a per-project file that is read directly, and that a session starts with that file plus a recall, never recall alone. It is updated in place, so it always describes the present, while the memory server holds history and decisions and the project instruction file holds architecture and facts.
This is what we run. It is not something our course or templates teach. We checked, and the string STATE.md appears zero times in our memory-protocol template, the two session commands, and course modules 01 and 02. Those cover the recall side, including the failure where recall returns nothing because the threshold is above 0.4.
A state file has its own failure, the third reason on the list above. In two of our own state files (2026-07-17 to 2026-08-03):
- A state file holding several live threads was not tracked by git, so it had no backup until we noticed.
- Two file headers claimed freshness dates (“reconciled”, “verified”) that were weeks behind the real edits.
- Three claims in a file were wrong when re-measured: a row count was too low and the leak was still growing, a count of affected pages was off by a factor of two, and a root cause was a different cause. Our rule since then is to re-measure any count or cause about live data before acting on it.
It also grows. One of those files had passed 250 KB by August and was over 400 KB by late October. On 2026-08-12 we recorded “archive closed sections” as a candidate fix. We applied it to the other file (it dropped to a few KB), but not to this one, and this one kept growing.
“Read the state file at session start” is itself an instruction the model has to follow, and our own record from 2026-10-15, based on one review of one setup and with no rate, says duties a model must remember decay within days. A hook that injects the file’s text at session start should be more reliable, since the file arrives whether or not the model remembers to open it. We have not tested this. The docs describe a SessionStart hook that can re-add context after compaction. How hooks work belongs to a separate guide, and we are not claiming here that we run that setup.
How do I choose between the options?
There are three, and each is good at a different thing. The Hacker News thread “Show HN: Stop Claude Code from forgetting everything” (202 points when we read it) shows commenters mostly sceptical of memory add-ons, with many saying a markdown file in the repo covers most needs. That is what the thread says, not a finding of ours.
| Option | Good at | Bad at |
|---|---|---|
| Built-in auto memory (MEMORY.md) | Zero setup. Survives /compact. Plain files you can read and edit. | Only the first 200 lines or 25KB load. No documented signal at load time that the index was cut. Machine-local. |
| Memory server with semantic recall | Finding old decisions by meaning across many projects. | Ranking can hide a recent entry without warning. Needs setup and tests against the real database. Wrong for “what is open now”. |
| Plain file read at session start | Read whole, so nothing is silently skipped. Easy to back up in git. | Grows without bound. Drifts if nobody re-measures. Only works if it is actually read. |
We use the second and third together: recall for history, the file for the present. If you have one small project, the first or third alone may be enough.
How do I check what Claude Code actually loaded?
Per the docs (checked 2026-10-23, memory docs), /memory lists the CLAUDE.md and other memory files and lets you open them, with a toggle for auto memory. /context shows a live breakdown by category, and its memory files list tells you which CLAUDE.md files loaded; a file not on it is not visible to Claude. Then count your index with wc -l and wc -c against the 200-line and 25KB limits.
Next step
If you want the recall side set up, with the protocol and the failure modes above, the AccrueDev course covers it in modules 01 (Memory System Foundations) and 02 (Memory Architecture). If your problem is instructions that load but get ignored, start with how to write a CLAUDE.md.
Frequently asked questions
Why does Claude Code forget everything between sessions?
Each session starts with a fresh context window. Only two things carry over by design: CLAUDE.md files you write and auto memory notes Claude writes. Both load at the start as context, not as enforced configuration. A session you do not resume starts without the earlier conversation.
How much of MEMORY.md does Claude Code load?
Per the docs, the first 200 lines or the first 25KB, whichever comes first. Content beyond that is not loaded at session start. Topic files are read on demand. We have not reproduced the truncation ourselves.
Is a memory server better than a markdown file?
It depends on the job. A plain file is read whole and cannot silently skip an entry, but it grows. A memory server finds old knowledge by meaning, but its ranking can hide a recent entry. We use both, for different jobs.
How do I check what Claude Code loaded?
Run /memory to list the memory files and open them. Run /context to see a live breakdown by category, including which CLAUDE.md and auto memory files loaded. A CLAUDE.md missing from the Memory files list at launch is not visible to Claude.