[BUG] Auto-compaction re-injects the CLAUDE.md/MEMORY.md copy from the last user prompt, not the on-disk file; disk re-read only happens at the next prompt

Status Open
Reported on v2.1.260
Maintainer reply None cached
Activity 2 comments · opened Sep 8, 2026

Summary

After an auto-compaction, the CLAUDE.md / MEMORY.md content re-injected into context is not read from disk. It is the copy captured at the last user prompt. Disk is consulted only when the next user prompt arrives, which is when the "Instruction files were re-read after the conversation was compacted; these differ from their earlier copies" system-reminder appears.

The docs ("Context window" → What survives compaction) say project-root CLAUDE.md and auto memory are "Re-injected from disk". In practice they are re-injected from an in-memory snapshot, so any edit made during a long autonomous turn (many tool calls, no user prompt) that spans an auto-compaction is silently reverted in the model's context until the user types something.

Environment

  • Claude Code 2.1.260 → 2.1.261, macOS (Darwin 25.4), desktop app "Code" tab; model claude-fable-5-1
  • CLAUDE_CODE_AUTO_COMPACT_WINDOW=300000 (project settings), 5 auto-compactions in one session

Evidence (from the session transcript JSONL)

Every compaction writes an attachment record of type: "instructions" next to the compact_boundary; every user prompt after a compaction may write another one with changed: true, reason: "compaction". Hashing the files[].content of each record and matching it against the git history of the project CLAUDE.md gives (all times UTC, same day):

| time | event | project CLAUDE.md injected | on disk at that moment |
|---|---|---|---|
| 20:42 | session start | version A | A |
| 20:55 / 21:11 / 21:29 | auto-compact ×3 (instructions, changed absent) | A | A / B (edited 21:03) / B |
| 21:37 | user prompt (changed:true reason:compaction) | C (= disk) | C |
| 21:55 | auto-compact | C | D (edited 21:44) |
| 22:00 | user prompt (changed:true reason:compaction) | D (= disk) | D |
| 22:49 | auto-compact | D | F (edited 22:09 → E, 22:46 → F) |
| 22:52 | user prompt (changed:true reason:compaction) | F (= disk) | F |

So at 22:49 the compaction re-injected a copy that was 40 minutes and two edits behind disk; the model then kept working on it for the rest of that turn. The same pattern holds for ~/.claude/CLAUDE.md (edited 21:45 and 21:53; the 21:55 compaction still injected the 21:37 copy, 3060 chars; the 22:00 refresh delivered the current 2610-char file) and for the auto-memory MEMORY.md.

Note the refresh mechanism itself works: the changed:true reason:compaction record is correct every time. It just runs at the next user prompt instead of at the compaction.

Steps to reproduce

  1. Start a session; give one long task that will run through an auto-compaction (lower CLAUDE_CODE_AUTO_COMPACT_WINDOW to reach it quickly).
  2. During that turn, have the model append a marker line to the project CLAUDE.md with a tool call.
  3. Let auto-compaction happen inside the same turn.
  4. In the transcript JSONL, compare the instructions attachment written at the compact_boundary with the previous one: same content hash, no marker. The marker first appears in the instructions record with changed: true, reason: "compaction" written at the next user prompt.

Expected

At compaction, re-read CLAUDE.md / rules / MEMORY.md from disk (as documented), or at least run the same "re-read and inject what changed" step that currently runs at the next user prompt.

Workaround

A SessionStart hook with matcher compact that lists instruction files whose mtime is newer than the session start (first timestamp in transcript_path) and tells the model to read them from disk.

Related: #91243 (docs question about which files /compact reloads), #88886 (same snapshot-at-session-start behaviour for subagents).

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗