/t · guide · audit playbook

Claude memory audit: 8 checks for the two files Claude reads every turn.

M
Matthew Diakonov
9 min read
Direct answer · verified 2026-05-19

A Claude memory audit walks two files in order. CLAUDE.md (the one you wrote, ships every byte every turn) gets graded against seven finding kinds: bloat, vague terms, aspirational absolutes, conflict, duplicate, missing-why, and cache-busting timestamps. MEMORY.md (the index Claude wrote about you, under ~/.claude/projects/<slug>/memory/) gets one check: lines past 200 silently stop loading. Eight checks, three minutes on a re-run once you know your file. Authoritative reference for the MEMORY.md cap and layout: code.claude.com/docs/en/memory.

Two things make Claude's memory layer audit-shaped rather than measure-shaped. First, it is two files, not one: people who only audit CLAUDE.md are missing the half Claude writes. Second, the per-line failure modes are deterministic enough that a 100-line file finishes the audit in ten minutes by eye. Below is the order we run them in, and what each one is looking for.

The seven CLAUDE.md checks come straight out of the analyzer source (see src/lib/analyzer.ts); the MEMORY.md check is a one-liner you can run with wc -l before the analyzer ships its own MEMORY.md finding kind.

What an audit pass looks like

Before the procedure, the shape of the output. The analyzer emits a per-file line count and the list of flagged lines with the kind code; the MEMORY.md check appends a single cap-overflow line if the index is past 200.

ccmd audit · CLAUDE.md + MEMORY.md

The 8-check procedure

Run them top to bottom. Checks 1 through 7 are CLAUDE.md and use the analyzer's built-in finding kinds. Check 8 is MEMORY.md and is a one-liner.

1

Check 1 · Bloat

Any line over 28 words gets silently down-weighted by the model. The analyzer flags every CLAUDE.md line above that threshold and reports the per-line word count.

Run wc -w on each bullet, or paste the file into the analyzer. Long stack-description sentences are the usual offenders. Split each one into 2-3 shorter directives.
2

Check 2 · Vague terms

Twelve words have no testable meaning: appropriate, appropriately, good, best, proper, properly, carefully, thoughtfully, well, nicely, cleanly, as needed.

Grep for each one. Replace with a concrete rule: a number, a named tool, or a forbidden pattern. "Handle errors appropriately" becomes "Wrap network calls in a try/catch that logs and re-throws."
3

Check 3 · Aspirational absolutes

Always / never / must / in all cases / every time with no escape clause. Real codebases have exceptions, so the model learns to ignore the absolute the first time it hits one.

For each absolute, either add an "unless X" or drop the absolute. "Never commit to main" is fine if your branch protection enforces it; "never use any" needs an escape for third-party types you don't control.
4

Check 4 · Conflict

Two rules that contradict each other (the canonical pair is "never use comments" plus "add comments where helpful"). The model has no resolution path and will guess.

Read the file end-to-end once. Conflicts hide between sections the author wrote at different times. The fix is to pick one or scope each rule to a named context.
5

Check 5 · Duplicate rules

Two lines that say the same thing. Common after merges and after running the file through a different generator. The analyzer reports the line number of the first copy.

Each duplicate is free token savings: delete one copy. On long files duplicates compound, because Claude reads both and the second one teaches it the rule does not actually constrain behavior.
6

Check 6 · Missing why

Any DO NOT / NEVER / don't with no "because" / "reason" / "got burned" / "incident" nearby. The model follows the rule until it hits an edge case, then guesses.

Add a one-line "Why:" with the constraint or the past incident. "Do not import from /old-billing" becomes "Do not import from /old-billing. Reason: deprecated, will be removed in Q3, the new client lives in /billing-v2."
7

Check 7 · Cache-busting timestamps

An ISO date, the word "today", "this session", or "right now" inside the first 20 lines. The prompt cache hashes a prefix, so any volatile token near the top busts the cache for the rest of the session.

This is the single highest-impact finding by dollar value, because cache-busted prefixes pay full price on every turn instead of the cached 1/10th rate. Move the timestamp to the bottom or drop it.
8

Check 8 · MEMORY.md cap overflow

Only the first 200 lines of ~/.claude/projects/<slug>/memory/MEMORY.md load on session start. Lines past that keep getting appended on every save-memory call but Claude never reads them again.

Run wc -l on the file. If it is past 200, you have a silently-truncated tail. Re-prune so the index stays under 150 (a 50-line buffer below the cap). Bodies under the per-topic .md files do not auto-load and do not need pruning.

Before and after on one CLAUDE.md

A small file with most of the seven kinds, and the same file after the audit pass. The post-audit version is shorter, names a real past incident under check 6, and drops the timestamp under check 7.

CLAUDE.md · before

After the audit:

CLAUDE.md · after

Token count drops, the rubric score climbs, and (this is the part most audits skip) the prohibitions now carry the reason that turns them into rules the model treats as load-bearing.

The one-liner for check 8

MEMORY.md is the only check that needs a shell, because the cap is a property of the file on disk, not of the bytes you paste. Three commands; the second one is the only one whose output you read.

check 8 · MEMORY.md cap overflow

1,135 lines. Only the first 200 load, which on this machine is 21,677 characters or roughly 5,420 tokens per turn. The 935 lines below the cut are dead disk weight: Claude cannot see them, but every new save-memory call keeps appending below them. The fix is a manual prune so the index lives under 150 lines (a 50-line buffer below the cap so the next save does not silently drop). The full math, with the dollar number at the Opus 4.7 input rate, lives on the auto memory tokens page.

CLAUDE.md vs MEMORY.md, as audit targets

The two files share a session and a cache prefix, but the audit lens you apply to each is different. Where one is yours to author, the other is yours to prune. Where one drifts because humans add rules and rarely delete, the other drifts because the model appends without your input.

FeatureMEMORY.mdCLAUDE.md
Who wrote ityou, by handClaude, on every save-memory call you let it make
What loads every turnevery byte of the filefirst 200 lines, capped
How it bloatshumans add rules, rarely deletemodel appends entries on its own; tail rots silently below the cap
Audit cadencebefore any non-trivial rewriteevery time you cross the 150-line buffer; quarterly on a healthy machine
Token cost shapefixed per turn, linear with file sizefixed per turn for the first 200 lines, plus per-session follow-reads of body files
Worst failure moderules ignored, behavior drifts from specold context silently dropped, new context grows beneath the cap

The practical upshot: if you only audit one of these you are missing half of the recurring per-turn config cost, and the half you missed is the one that grows on its own.

What we do not check

A few things this audit deliberately leaves out, with reasons.

  • Per-topic memory bodies. The .md files under ~/.claude/projects/<slug>/memory/ do not auto-load. Claude opens them on demand via the [[name]] links in the index. Auditing every body is correct in theory and wrong in practice: most of them are read zero times per session, so the time-to-impact ratio is bad. Prune the index entries that point at unused bodies and the bodies follow.
  • Settings.json hooks and the MCP allowlist. Those are part of the contract Claude reads on session start and they belong in their own audit (see the config audit page). The memory audit stops at the two .md files because they are the ones that bill tokens per turn.
  • Tokenizer-exact counts. We use the chars/4 heuristic the CLI uses for its on-screen estimate. The tokenizer-exact count is a few percent off either direction, which does not change any audit decision.
  • Cache-aware billing. The per-turn token figure is a worst-case ceiling assuming a clean cache. In steady-state usage the cached prefix drops the effective per-turn cost by roughly 10x. The audit is still right; the dollar number is just smaller in practice.

When to run this

Three triggers we use on our own files.

  1. Anytime CLAUDE.md crosses 100 lines. The seven finding kinds compound past that point; the audit is at its sharpest as a regular pass on a file you are still actively editing.
  2. Anytime wc -l on MEMORY.md crosses 150. That is the 50-line buffer below the 200 cap. Past 150, the next save-memory call has a real chance of pushing an old entry below the cut, so it is the moment a prune actually saves a memory rather than tidying one up.
  3. Anytime the model's behavior drifts. If Claude keeps ignoring a rule, that rule is failing one of checks 1, 2, 3, 4, or 6. Run the audit on the rule first, and the file second; usually the rule is what needs the edit, not the model.

Want a second pair of eyes on your CLAUDE.md and MEMORY.md?

Bring both files. We will run the 8 checks together, pick the three cuts with the largest per-turn impact, and rewrite the two rules the model is ignoring most.

Frequently asked questions

What does a Claude memory audit actually cover?

Two files, both of which Claude reads on every turn. CLAUDE.md is the agent-config file you wrote; every byte of it ships in the system prompt every turn. MEMORY.md is the persistent-memory index Claude writes about you (one line per memory, body in a sibling file); only its first 200 lines load. An audit checks CLAUDE.md against seven finding kinds (bloat, vague terms, aspirational absolutes, conflicts, duplicates, missing-why, cache-busting timestamps) and MEMORY.md against the 200-line cap. The seven CLAUDE.md kinds are the ones the ccmd analyzer ships today; the MEMORY.md cap check is the next one on the roadmap.

Where does CLAUDE.md actually live, and where does MEMORY.md live?

CLAUDE.md lives at the repo root (or at ~/.claude/CLAUDE.md for the global one); both load. MEMORY.md lives under ~/.claude/projects/<slugified-absolute-path>/memory/MEMORY.md, where the slug replaces every slash in the absolute path with a dash. For /Users/you/myrepo the path is ~/.claude/projects/-Users-you-myrepo/memory/MEMORY.md. There is also a global memory directory at ~/.claude/projects/-Users-<you>/memory/ that loads on every session, not just inside that repo. Run ls -la on each of those to see the index file plus the per-topic .md bodies.

Why is the order of the checks important?

Cost first, correctness second. Cache-busting timestamps (check 7) and the MEMORY.md cap overflow (check 8) are the two findings that change the dollar number, so they belong at the end where you have a chance to feel the savings. Bloat, vague terms, and aspirational absolutes (checks 1-3) are the ones that change behavior most, so they go first; a file you rewrote before fixing the timestamp will still drift if you skipped them. Conflict, duplicate, and missing-why (checks 4-6) sit in the middle because they require reading the file end-to-end rather than running a regex, and the eye is freshest before the math.

How long does the audit take if I run it by hand?

On a typical 100-line CLAUDE.md, about ten minutes the first time and three minutes on every re-run. The seven CLAUDE.md checks each take under a minute once you have the file open. The MEMORY.md cap check is a single wc -l. The slow part is rewriting the lines you flag, which is not part of the audit itself; the audit only produces the list. Most of the rewrite time goes to the missing-why check, because each prohibition needs a real reason from your own history.

Does the analyzer ship a MEMORY.md check today?

Today the analyzer is purpose-built for the four files Claude or its peers concatenate verbatim into the system prompt: CLAUDE.md, AGENTS.md, .cursorrules, .grokrules. MEMORY.md is shaped differently (one line per memory, plus a directory of bodies Claude follows on demand), so the seven finding kinds map only partially. Shared checks (bloat, cache_bust, duplicate, missing_why) still help because Claude reads MEMORY.md as part of the same system-prompt prefix. The 200-line cap is the memory-specific check we plan to add next; today, you run it by hand with wc -l.

How does this audit differ from a token-cost audit?

A token-cost audit measures the bill: how many tokens fire every turn, at what rate, for how many turns of a session. A memory audit produces the list of lines that should not be on the bill in the first place. Both end at the same place (a slimmer file), but the lens is different. Cost-first work tells you when to do the audit; the audit tells you what to cut. See /t/claude-md-token-cost-audit for the cost-first lens and /t/claude-md-auto-memory-tokens for the MEMORY.md-specific cost math.

What is the global MEMORY.md and should I audit it separately?

Yes. The global directory at ~/.claude/projects/-Users-<you>/memory/ loads on every session no matter which repo you are in. On a long-lived machine it grows the fastest because every save-memory call across every project lands there. Most of the entries below the 200-line cut on a year-old machine are global-memory entries, not project ones. Audit global memory more aggressively: keep only entries that are genuinely cross-project (account identities, default cards, keychain patterns), and demote everything else into the per-project memory directory where it only fires on turns inside that repo.

Can I run the analyzer on a snippet, or does it need the whole file?

Either. The analyzer is a pure function in the browser; nothing leaves your tab, nothing is uploaded. Paste the whole file for the rubric score and the per-line findings, or paste a single section to focus on one check. The 200-line MEMORY.md check is the only one that needs the whole file (you cannot tell whether you are past the cap from a snippet), and that one you run with wc -l rather than in the analyzer.

What is the smallest CLAUDE.md that still passes most of the rubric?

We have seen real CLAUDE.md files in the 30 to 60 line range that pass 9 of the 12 Karpathy rules. The shape: a one-line project description, a stack list (covers rule 9), a plan-before-coding directive (rule 1), one explicit forbidden pattern with a past-incident reason (rules 10, 11), a tests-as-truth line (rule 7), and a concise-output line (rule 8). Short and specific beats long and aspirational. The audit is at its sharpest on files in that size range, because every line still earns its keep.

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.