Mostly yes, with three exceptions that give no warning, and every character you load is paid for on every request. Our counts (version 2.1.300) show that an imported file which exists loads in full, and so does a rules file without a path filter. An import that points at a missing file loads nothing, yet the run ends with exit code 0 and an empty error stream. AGENTS.md sitting beside CLAUDE.md is never read. And an import placed in a path-filtered rules file is pulled in at session start regardless, so moving a heavy import there saves nothing.
Method
For each case we made a new empty folder, put the memory files under test in it and ran one non-interactive request that only asks the model to answer with a single word. We used the JSON output, turned the tools off, let Claude Code read project settings only, and chose the Sonnet alias. The number we report is the sum of the three input counters in the usage block: plain input, cache creation and cache read. That sum is the whole context of the request, so a memory file that was loaded shows up as extra tokens and one that was not loaded does not. Runs went one after another, never in parallel.
The filler was varied English lines. A block of 20 000 characters came to 6 480 tokens, which is the yardstick for "this file was loaded". A first run straight after an automatic update came out at 19 127 tokens once and never again, so we discarded first runs.
The documented side comes from the Claude Code memory page, read the same day. Where it speaks, our counts agree with it. Two rows below cover behaviour the page does not describe at all: the import that points at a missing file, and the import placed inside a filtered rule.
Results
| Case | Tokens | What it shows |
|---|---|---|
| A tiny CLAUDE.md | 10 611 | the baseline for the rest |
| Import of an existing 20 000-character file | 17 093 | the file loads |
| Import pointing at a missing file | 10 617 | nothing loads, no warning, exit code 0 |
| Rule with a path filter, 20 000-character body | 10 611 | body deferred until a match |
| Rule without a path filter, same body | 17 096 | the body loads at start |
| Filtered rule holding just an import | 17 088 | the import loads at start |
| Large AGENTS.md, tiny CLAUDE.md | 10 611 | not read |
The missing import is the quiet one. The line itself adds six tokens and the file adds none. Nothing in the exit code or the error stream tells you that the instructions you believe are active are not there. A typo in a path, or a file that was renamed, produces exactly this.
The scoped rule behaves as documented, until it holds an import. The docs say a filtered rule is read once Claude works on a matching file, and its body did wait. The docs are silent about an import placed in such a rule. It expands at launch: 17 088 tokens, against 17 093 for the same file imported directly. A frequent tip is to move heavy material into the rules folder to lighten the start. With an import in it, that does not work. What helps is to remove the import and leave a short pointer line instead.
Size was not a limit in our runs. A CLAUDE.md of 160 000 characters loaded completely and cost 62 789 tokens, again with exit code 0 and nothing on the error stream. A file of 60 000 characters cost 29 075. English filler came to about 3.25 characters per token in the second case and about 3.07 in the first. An older note of ours said that a file above roughly 150 000 characters is cut; that did not reproduce, and the current documentation says a file up to 4 MiB loads in full. The documentation does describe a startup warning for long files. A one-shot request does not show it, so we did not observe it.
Bulgarian packs fewer characters into a token. We also measured our own always-loaded memory, written mostly in Bulgarian. It came to 82 395 characters, which is 38 994 tokens on every request, about 2.1 characters per token. The English filler gave 3.25. The same text length therefore costs noticeably more tokens. We then moved three rarely needed files out of the always-loaded set and left a short pointer line for each, naming the traps that matter most. The same measurement gave 27 927 tokens, which is 11 067 fewer, a drop of 28 %.
A model does not know what it was given. Earlier we hid a secret word in a memory file and asked fresh sessions about it. Identical setups denied having it in one run and recited it in another. A model's account of its own context is testimony. The usage sum above is a measurement.
Our test of a reviewing skill agrees. We pasted 31 memory setups, 26 with a planted fault and 5 sound, and ran each once per model. Sonnet got every setup right with the claude-code-memory-review skill and 27 of 31 without it. Haiku scored the same, 31 and 27. Bare Sonnet assumed a heavy import in a filtered rule would stay idle until a matching file shows up, in three cases, and it did not mention the one-time approval that a project import reaching outside its folder requires. It handled the other points on its own.
We reported the silent missing import and the import inside a filtered rule to Anthropic as comments on the public tracker, in issues 88813 and 16299.
Checking your own setup
- Start a session in the project and run
/context. The output names the memory files read at launch and gives the cost of each (documentation). - For a scripted check, run the one-word request from the Method section twice, once with the memory file and once without it, and subtract the two usage sums.
- After you add an import, count again. The sum should grow by roughly the size of the imported file; if it grows by only a few tokens, the import resolved to nothing.
- Do not ask the model. It will answer confidently either way.
What we did not measure
- One system and one version. Windows 11 and Claude Code version 2.1.300. Other platforms and later versions may behave differently, and the oversize behaviour has already changed once.
- Non-interactive runs only. The interactive startup warning about long files was never seen, so we cannot say what it shows or when.
- English filler for most cases. The characters-per-token figures for English come from repeated varied lines, not natural text. The Bulgarian ratio comes from a single memory set.
- One run per case. Another run could shift any single count.
- Our own cases for the skill test. We wrote the 31 setups and the scoring, so they reflect what we thought to ask.
- Tokens, not the weekly limit. We counted tokens in the request. How cached tokens count against a subscription allowance we did not measure.
Read this post as Markdown: /blog/claude-code-memory-what-loads.md · Atom feed.
