You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] Claude forgets everything in CLAUDE.md after compaction #6354
My complex project has a lot of things that need to be known for agentic workers to navigate effectively. All these details are listed in my project's CLAUDE.md located at the root of my project. I noticed that I have to tell it to re-read this every time it compacts, otherwise it starts doing things in "common sense" ways that deviate from the "correct way" that is defined. After re-reading, all problems disappear.
Steps to Reproduce
have a complicated project with specific operational requirements
do a lot of work until compaction
watch claude not follow CLAUDE.md
tell claude to read CLAUDE.md and watch it follow it
Expected Behavior
After compaction, Claude should remember or re-read CLAUDE.md
Actual Behavior
Claude does not remember CLAUDE.md after compaction
Could you try asking Claude to recite what is in CLAUDE.md when compaction happens (you can trigger compaction manually using /compact). In my testing it still have the contents of CLAUDE.md in context but would be great to have a repro of this not happening.
After conversation compaction/summarization, Claude needs to be explicitly reminded to follow CLAUDE.md conventions, otherwise it reverts to generic behavior that doesn't match my established patterns.
Real example from today: Built a smart email archiver system with specific filtering rules, attachment handling, and vault organization patterns all defined in CLAUDE.md. After compaction, continuing work would require manually asking Claude to re-read the context.
Impact: This breaks continuity in long-running projects where CLAUDE.md serves as the single source of truth for project-specific conventions.
+1 for making CLAUDE.md persistent across compaction cycles.
I routinely have this problem as well. It just wiped out a running production project because it carried on making changes after compaction and before I could catch it.
Reacted by Huneau romain, TerrysPOV, Sarah Oloumi and scott378
@claude : just create/enable a post compact hook and this MAJOR issue would be solved. You release features all the time far more useless and complex than this would be to do. Come on guys this is killing us!
I also routinely run long sessions (sometimes for weeks) with hundreds of interactions and dozens of context compactions. After every compact, I have to tell it to re-read the memory files. Please either make this automatic, or add a hook for after compact.
Reacted by Sarah Oloumi, BalÃĄzs Czoma, Andrew Stewart, Ali Zamani, Sebastian Rogala and Aleksandr Vishniakov
Edit: I would likely not recommend the below, due to https://news.ycombinator.com/item?id=46723384
(possibly off-topic, but on the topic of guideline stability): It seems we can, even without CLAUDE.md changes, "poison" the compactor agent itself, transferring style+information (i.e. guidelines) into the summary, and can even give the summarizer tasks. I presume this would be easier if you added lines in CLAUDE.md for the summarizer ('upon a summary request...'). I also assume that this is all within normal expectations since this issue implies guiding auto-compaction is an expected of CLAUDE.md: #7708 (comment)
If you have Claude Code give such a compaction summary to a subagent, that subagent will automatically assume certain guidelines. Seems like the models give extra high priority to 'the summary' over other things. Presumably one could just skip all the ceremony and write their own compaction-summary-like text for any Claude Code agent to pattern match on.
Something possible more useful for auto-compaction: TodoWrite a final item for "read CLAUDE.md post-compaction" (haven't tested though)
I dont know that is the problem to implement this? The lack of this make experience WAY worst, as someone that pay 200USD/MONTH i guess you guys need at least a explanation why dont want to implement, because its IMPOSSIBLE to be hard to implement a hook after compact!
STOP. Your context was just reset.
Step 1: Say "Let me refresh my context first."
Step 2: Call Read tool on CLAUDE.md (visible to user)
DO NOT skip Step 2. DO NOT assume CLAUDE.md is loaded.
Key insight: The instruction must be the first line and include a specific observable action (say a phrase, then visibly read file). Passive context injection doesn't work.
Results:
Trigger
Hook fires?
Content injected?
Claude follows it?
/clear
â
â
â
/compact
â
â
â
The problem with /compact: The compacted conversation summary creates "momentum" that overrides the injected reminder. Claude sees the summary ("user asked about X") and continues that thread, ignoring the hook output.
Suggested fix: The hook output needs higher priority than the compacted summary - perhaps injected AFTER the summary in Claude's context, or treated as a system instruction rather than context.
Reacted by Art Shendrik, Aleksandr Vishniakov, Borys Papevis and MrHarbot
This has been my biggest pain point too â CLAUDE.md instructions forgotten after compaction, and then Claude goes off-script. The root issue is that compaction is lossy compression, and when it's operating on a session full of noise (progress ticks, duplicate system reminders, stale file reads, metadata), the signal-to-noise ratio is terrible and the important stuff gets summarized away.
What helped me was Cozempic. The approach: remove the noise before compaction fires, so when it does compress, it has a much better signal-to-noise ratio and CLAUDE.md instructions are more likely to survive.
pip install cozempic
cozempic init
cozempic init auto-wires a guard daemon that starts on every session and continuously prunes dead weight â progress ticks (often 40-50% of session size), duplicate system-reminder injections, stale file reads that were superseded by later edits, thinking block signatures, metadata bloat. On a typical session I see 15-22% size reduction from pure noise removal.
The result: compaction triggers far less often, and when it does, it has much less junk to wade through. Won't fix the fundamental issue of compaction being lossy, but it significantly reduces how often you hit it and improves the quality when you do.
Would appreciate if you could give it a try and let me know if it helps with the CLAUDE.md retention. If compaction is still dropping your instructions after pruning, I'd like to investigate what's left in the session and see if there are additional strategies to apply.
This thread captures the core problem well â compaction summaries create "momentum" that overrides re-injected instructions.
I've been running mnemon in production to address this â it's a standalone skill binary for persistent agent memory. Rather than fighting the compaction summary, mnemon stores knowledge in a local SQLite graph outside the context window. After compaction, the SessionStart hook re-injects relevant entities via structured recall â not re-reading a monolithic CLAUDE.md, but querying specific facts and decisions relevant to the current work.
The PreCompact hook also extracts critical insights before compression occurs, so knowledge survives the cycle.
mnemon setup auto-detects Claude Code and deploys skill + four lifecycle hooks. Portable â the same binary + skill works across Claude Code, OpenClaw, and any LLM CLI that reads markdown skills.
What helped me was [insert product here]. The approach: remove the noise before compaction fires, so when it does compress, it has a much better signal-to-noise ratio and CLAUDE.md instructions are more likely to survive.
Would be nice if you stop advertising your own projects here, especially without a disclaimer.
Register as PreCompact hook in settings.json. After compaction, the next turn can read ~/.claude/session-handoff.md to recover context about what was happening.
For automatic session end state capture:
I keep seeing the same failure pattern: the agent follows repo-specific rules until compaction, then falls back to generic behavior and starts violating the projectâs actual way of doing things.
For people here, what rule types hurt most when they get dropped? Stack constraints, migration/schema rules, banned commands/patterns, or post-task workflow steps?
This is caused by compaction summarizing CLAUDE.md instructions into prose â the specific rules get diluted or dropped. The compact-summary-collapse strategy in Cozempic v1.4.1 proactively removes stale pre-compaction content (85-95% savings) so compaction operates on a much smaller, cleaner input.
Additionally, the behavioral digest feature extracts your corrections and syncs them to Claude Code's memory system as feedback type memories. These persist on disk and survive compaction natively â Claude re-reads them on every turn.
pip install cozempic && cozempic init
Run cozempic digest show to see what rules have been extracted from your sessions.
This is a known structural limitation â compaction summarizes conversation history but doesn't preserve the full CLAUDE.md context. Two workaround approaches using hooks:
1. Save state before compaction (PreCompact hook)
#!/bin/bash# PreCompact hook â saves session state before compactionset -euo pipefail
INPUT=$(cat)
CHECKPOINT=".claude/pre-compact-checkpoint.md"
mkdir -p .claude
{
echo"# Pre-compaction checkpoint ($(date -Iseconds))"echo""echo"## Current branch"
git rev-parse --abbrev-ref HEAD 2>/dev/null ||echo"not a git repo"echo""echo"## Modified files"
git diff --name-only 2>/dev/null | head -20
echo""echo"## Recent commits"
git log --oneline -5 2>/dev/null
echo""echo"## Critical CLAUDE.md rules"
grep -iE '(ABSOLUTE|MUST NEVER|NEVER|CRITICAL|įĶæĒ)' CLAUDE.md 2>/dev/null | head -20
} >"$CHECKPOINT"echo"ðļ Pre-compact checkpoint saved to $CHECKPOINT">&2exit 0
This extracts lines containing enforcement markers (ABSOLUTE, MUST NEVER, etc.) and prints them to stderr every 20 tool calls. The output appears in Claude's context, acting as a persistent reminder that survives compaction.
Neither approach is perfect â the root fix needs to come from Anthropic preserving CLAUDE.md context across compaction boundaries. But these hooks significantly reduce the "amnesia" effect in long sessions.
The gap has moved since most of this thread was written, so here is where it stands on current builds. PostCompact exists (added in 2.1.76) and its payload carries the full compact_summary. SessionStart with matcher compact is a real injection point that supports additionalContext. InstructionsLoaded fires with load_reason: "compact" when instruction files are re-loaded after a compaction. The rules text surviving is mostly handled now. What still fails is rank. After compaction the summary is the live frame, so anything re-injected reads as background and gets outranked, which matches the earlier hook tests in this thread: the reminder fires on /compact and the model still follows the summary.
Re-injection loses that fight. A denied tool call does not.
So gate instead. After any compaction, the first mutating tool call is refused until the model reads the rules file, and that read clears the gate. The re-anchor stops being optional, and it covers /compact and auto-compaction the same way.
.claude/hard-rules.md, only the rules that actually get violated, one line each:
# Hard rules
Read after every compaction. One line per rule, no prose.
1. Never commit directly to main. Use a branch and open a PR.
2. Never edit anything under vendor/. Patch upstream instead.
3. Run pnpm test --filter changed before every commit.
4. Create a rollback checkpoint before any destructive command.
5. Do not reformat files outside the requested change.
.claude/hooks/post-compact.sh saves the summary that replaced the transcript and arms the gate. PostCompact cannot inject context, so the message goes through SessionStart instead:
#!/usr/bin/env bash# PostCompact hook: save the summary that replaced the transcript, arm the re-anchor gate.set -euo pipefail
cd"${CLAUDE_PROJECT_DIR:-.}"
input=$(cat)
sid=$(printf '%s'"$input"| jq -r '.session_id // "nosession"'| cut -c1-8)
agent=$(printf '%s'"$input"| jq -r '.agent_id // empty')
trigger=$(printf '%s'"$input"| jq -r '.trigger // "unknown"')
stamp=$(date -u +%Y%m%dT%H%M%SZ)
mkdir -p .claude/compact-log
log=".claude/compact-log/${stamp}-${trigger}-${sid}.md"printf'# compaction %s (%s)\n\n%s\n'"$stamp""$trigger""$(printf '%s'"$input"| jq -r '.compact_summary // ""')">"$log"# main conversation only: a teammate compaction should not gate the lead sessionif [ -z"$agent" ];then touch .claude/.reanchor-required;fiprintf'compact audit: %s\n'"$log">&2exit 0
.claude/hooks/session-start-compact.sh tells the model what is blocked and what clears it:
#!/usr/bin/env bash# SessionStart hook (matcher: compact): tell the model the gate is armed and what clears it.set -euo pipefail
cd"${CLAUDE_PROJECT_DIR:-.}"
[ -f .claude/.reanchor-required ] ||exit 0
latest=$(ls -t .claude/compact-log/*.md 2>/dev/null | head -n 1 || true)
ctx="Context was just compacted. Mutating tools are blocked until you read .claude/hard-rules.md with the Read tool. That read clears the gate."if [ -n"$latest" ];then ctx="$ctx The summary that replaced the transcript is saved at $latest.";fi
jq -n --arg c "$ctx"'{hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:$c}}'exit 0
.claude/hooks/reanchor-gate.sh is the enforcement. Only Bash, Edit, Write and NotebookEdit are denied while armed, so the model can still find and read the rules file with its normal tools, and everything unblocks on that read:
#!/usr/bin/env bash# PreToolUse hook (no matcher): block writes after a compaction until the rules file is read.set -euo pipefail
cd"${CLAUDE_PROJECT_DIR:-.}"
marker=.claude/.reanchor-required
[ -f"$marker" ] ||exit 0
input=$(cat)
tool=$(printf '%s'"$input"| jq -r '.tool_name // empty')if [ "$tool"="Read" ];then
file=$(printf '%s'"$input"| jq -r '.tool_input.file_path // empty')case"$file"in*hard-rules.md|*CLAUDE.md) rm -f "$marker";exit 0 ;;
esacficase"$tool"in
Bash|Edit|Write|NotebookEdit)
jq -n '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"Post-compact re-anchor pending: read .claude/hard-rules.md first. That read clears this gate."}}'exit 0 ;;
esacexit 0
.claude/hooks/instructions-loaded.sh records which instruction files actually re-loaded, so the reload question stops being guesswork:
Run /compact, then ask for a small edit. The edit gets denied with "Post-compact re-anchor pending", the model reads .claude/hard-rules.md, and the same edit goes through in that turn.
cat .claude/compact-log/*.md now holds the summary that replaced your transcript, on disk. Diff it against hard-rules.md once. You will see which rules the compactor paraphrased away instead of keeping.
tail .claude/compact-log/reloads.log lists every instruction file that re-loaded and why, so you know what actually comes back on your machine.
The log folder and the marker are local state: add .claude/compact-log/ and .claude/.reanchor-required to .gitignore.
The gate arms only when agent_id is absent, because these events also fire for teammate compactions (#91910). Confirm PostCompact actually fires on your version and platform before trusting the gate (#77832 reports Windows misses). If it does not fire, the gate cannot arm.
For anyone hitting this and looking for a stopgap while this is open: I built a small Claude Code plugin, seatbelt, that re-reads and re-injects CLAUDE.md at the moments it's most likely to have been dropped â SessionStart on compact/resume, and past a token-depth threshold in long sessions. It also gives a systemMessage confirmation each time it fires, so it's not silent.
To be clear about what it isn't: it doesn't fix the underlying compaction behavior (that's this issue), it just re-supplies the context afterward, and I don't have a clean measurement yet of how much that actually improves adherence versus just having the rules re-read again. It's a workaround for the symptom, not a fix for the cause.
tatyree's comment above is the one that should anchor this thread â a production project damaged because, post-compaction, the model kept changing things by "common sense" instead of the documented way. The structural problem is that CLAUDE.md is context, and compaction is a lossy summary of context: anything that lives only in the window gets rewritten at exactly the moment the work is longest and least supervised. We keep durable rules outside the window instead â a local-first memory kernel with an append-only, tamper-evident log, where a rule's exact handle stays retrievable no matter what the compactor kept. No embeddings, no fuzzy recall; you keep handles honest, and that's the trade. It wouldn't have saved everything here, but the conventions would still have been addressable. brew install samvallad33/tap/vestige
(Disclosure: I work on Vestige, the memory kernel just described; free and open-source.)
Activity
github-actions commentedon Aug 22, 2025
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
ðĪ Generated with Claude Code
igorkofman commentedon Aug 22, 2025
Could you try asking Claude to recite what is in CLAUDE.md when compaction happens (you can trigger compaction manually using /compact). In my testing it still have the contents of CLAUDE.md in context but would be great to have a repro of this not happening.
DougJoseph commentedon Sep 12, 2025
I have this problem with every auto-compact. Claude Code forgets what is in Claude.md and I have to tell it to read again.
rogerc66 commentedon Oct 21, 2025
I can confirm this issue is critical for production workflows. I maintain a comprehensive CLAUDE.md with specific instructions for:
After conversation compaction/summarization, Claude needs to be explicitly reminded to follow CLAUDE.md conventions, otherwise it reverts to generic behavior that doesn't match my established patterns.
Real example from today: Built a smart email archiver system with specific filtering rules, attachment handling, and vault organization patterns all defined in CLAUDE.md. After compaction, continuing work would require manually asking Claude to re-read the context.
Impact: This breaks continuity in long-running projects where CLAUDE.md serves as the single source of truth for project-specific conventions.
+1 for making CLAUDE.md persistent across compaction cycles.
tatyree commentedon Nov 24, 2025
I routinely have this problem as well. It just wiped out a running production project because it carried on making changes after compaction and before I could catch it.
TerrysPOV commentedon Dec 20, 2025
@claude : just create/enable a post compact hook and this MAJOR issue would be solved. You release features all the time far more useless and complex than this would be to do. Come on guys this is killing us!
solace-rcampbell commentedon Jan 7, 2026
I also routinely run long sessions (sometimes for weeks) with hundreds of interactions and dozens of context compactions. After every compact, I have to tell it to re-read the memory files. Please either make this automatic, or add a hook for after compact.
wiwa commentedon Jan 28, 2026
Edit: I would likely not recommend the below, due to https://news.ycombinator.com/item?id=46723384
(possibly off-topic, but on the topic of guideline stability): It seems we can, even without CLAUDE.md changes, "poison" the compactor agent itself, transferring style+information (i.e. guidelines) into the summary, and can even give the summarizer tasks. I presume this would be easier if you added lines in CLAUDE.md for the summarizer ('upon a summary request...'). I also assume that this is all within normal expectations since this issue implies guiding auto-compaction is an expected of CLAUDE.md: #7708 (comment)
If you have Claude Code give such a compaction summary to a subagent, that subagent will automatically assume certain guidelines. Seems like the models give extra high priority to 'the summary' over other things. Presumably one could just skip all the ceremony and write their own compaction-summary-like text for any Claude Code agent to pattern match on.
Something possible more useful for auto-compaction: TodoWrite a final item for "read CLAUDE.md post-compaction" (haven't tested though)
asvishnyakov commentedon Jan 29, 2026
HALF A YEAR! And nothing done for that. I'm sorry, this isn't even free, we pay you money for that
tiagogbarbosa commentedon Jan 30, 2026
I dont know that is the problem to implement this? The lack of this make experience WAY worst, as someone that pay 200USD/MONTH i guess you guys need at least a explanation why dont want to implement, because its IMPOSSIBLE to be hard to implement a hook after compact!
SebRogala commentedon Feb 4, 2026
Findings from extensive SessionStart hook experimentation
We tested using the existing
SessionStarthook withcompactmatcher to auto-refresh CLAUDE.md. Here's what we found:Setup that works for
/clear:{ "hooks": { "SessionStart": [{ "matcher": "clear", "hooks": [{ "type": "command", "command": "cat \"$CLAUDE_PROJECT_DIR\"/.claude/session-start-reminder.md; exit 0" }] }] } }With reminder content:
Key insight: The instruction must be the first line and include a specific observable action (say a phrase, then visibly read file). Passive context injection doesn't work.
Results:
/clear/compactThe problem with
/compact: The compacted conversation summary creates "momentum" that overrides the injected reminder. Claude sees the summary ("user asked about X") and continues that thread, ignoring the hook output.Suggested fix: The hook output needs higher priority than the compacted summary - perhaps injected AFTER the summary in Claude's context, or treated as a system instruction rather than context.
junaidtitan commentedon Feb 10, 2026
This has been my biggest pain point too â CLAUDE.md instructions forgotten after compaction, and then Claude goes off-script. The root issue is that compaction is lossy compression, and when it's operating on a session full of noise (progress ticks, duplicate system reminders, stale file reads, metadata), the signal-to-noise ratio is terrible and the important stuff gets summarized away.
What helped me was Cozempic. The approach: remove the noise before compaction fires, so when it does compress, it has a much better signal-to-noise ratio and CLAUDE.md instructions are more likely to survive.
cozempic initauto-wires a guard daemon that starts on every session and continuously prunes dead weight â progress ticks (often 40-50% of session size), duplicate system-reminder injections, stale file reads that were superseded by later edits, thinking block signatures, metadata bloat. On a typical session I see 15-22% size reduction from pure noise removal.The result: compaction triggers far less often, and when it does, it has much less junk to wade through. Won't fix the fundamental issue of compaction being lossy, but it significantly reduces how often you hit it and improves the quality when you do.
Would appreciate if you could give it a try and let me know if it helps with the CLAUDE.md retention. If compaction is still dropping your instructions after pruning, I'd like to investigate what's left in the session and see if there are additional strategies to apply.
Grivn commentedon Feb 21, 2026
This thread captures the core problem well â compaction summaries create "momentum" that overrides re-injected instructions.
I've been running mnemon in production to address this â it's a standalone skill binary for persistent agent memory. Rather than fighting the compaction summary, mnemon stores knowledge in a local SQLite graph outside the context window. After compaction, the
SessionStarthook re-injects relevant entities via structured recall â not re-reading a monolithic CLAUDE.md, but querying specific facts and decisions relevant to the current work.The
PreCompacthook also extracts critical insights before compression occurs, so knowledge survives the cycle.brew install mnemon-dev/tap/mnemon && mnemon setupmnemon setupauto-detects Claude Code and deploys skill + four lifecycle hooks. Portable â the same binary + skill works across Claude Code, OpenClaw, and any LLM CLI that reads markdown skills.bodiam commentedon Feb 24, 2026
Would be nice if you stop advertising your own projects here, especially without a disclaimer.
junaidtitan commentedon Feb 24, 2026
asvishnyakov commentedon Mar 8, 2026
Any update on this?
yurukusa commentedon Mar 24, 2026
A PreCompact hook can save critical state before compaction happens:
Register as PreCompact hook in settings.json. After compaction, the next turn can read
~/.claude/session-handoff.mdto recover context about what was happening.For automatic session end state capture:
Not a complete fix (CLAUDE.md should be re-injected by the system), but preserves the "what was I working on" context.
lipcool8-ship-it commentedon Mar 25, 2026
I keep seeing the same failure pattern: the agent follows repo-specific rules until compaction, then falls back to generic behavior and starts violating the projectâs actual way of doing things.
For people here, what rule types hurt most when they get dropped? Stack constraints, migration/schema rules, banned commands/patterns, or post-task workflow steps?
junaidtitan commentedon Apr 3, 2026
This is caused by compaction summarizing CLAUDE.md instructions into prose â the specific rules get diluted or dropped. The
compact-summary-collapsestrategy in Cozempic v1.4.1 proactively removes stale pre-compaction content (85-95% savings) so compaction operates on a much smaller, cleaner input.Additionally, the behavioral digest feature extracts your corrections and syncs them to Claude Code's memory system as
feedbacktype memories. These persist on disk and survive compaction natively â Claude re-reads them on every turn.pip install cozempic && cozempic initRun
cozempic digest showto see what rules have been extracted from your sessions.yurukusa commentedon Apr 6, 2026
This is a known structural limitation â compaction summarizes conversation history but doesn't preserve the full CLAUDE.md context. Two workaround approaches using hooks:
1. Save state before compaction (PreCompact hook)
Register in
settings.json:{ "hooks": { "PreCompact": [{ "hooks": [{ "type": "command", "command": "bash .claude/hooks/pre-compact-knowledge-save.sh" }] }] } }After compaction, Claude can read
.claude/pre-compact-checkpoint.mdto recover context.2. Periodic CLAUDE.md re-injection (PostToolUse hook)
This extracts lines containing enforcement markers (ABSOLUTE, MUST NEVER, etc.) and prints them to stderr every 20 tool calls. The output appears in Claude's context, acting as a persistent reminder that survives compaction.
Neither approach is perfect â the root fix needs to come from Anthropic preserving CLAUDE.md context across compaction boundaries. But these hooks significantly reduce the "amnesia" effect in long sessions.
feat: v1.6.9 â periodic rule reinforcement via PostToolUse hook
marcindulak commentedon Aug 17, 2026
See #68636 (comment)
John-Rood commentedon Sep 27, 2026
The gap has moved since most of this thread was written, so here is where it stands on current builds.
PostCompactexists (added in 2.1.76) and its payload carries the fullcompact_summary.SessionStartwith matchercompactis a real injection point that supportsadditionalContext.InstructionsLoadedfires withload_reason: "compact"when instruction files are re-loaded after a compaction. The rules text surviving is mostly handled now. What still fails is rank. After compaction the summary is the live frame, so anything re-injected reads as background and gets outranked, which matches the earlier hook tests in this thread: the reminder fires on /compact and the model still follows the summary.Re-injection loses that fight. A denied tool call does not.
So gate instead. After any compaction, the first mutating tool call is refused until the model reads the rules file, and that read clears the gate. The re-anchor stops being optional, and it covers
/compactand auto-compaction the same way..claude/hard-rules.md, only the rules that actually get violated, one line each:.claude/hooks/post-compact.shsaves the summary that replaced the transcript and arms the gate. PostCompact cannot inject context, so the message goes through SessionStart instead:.claude/hooks/session-start-compact.shtells the model what is blocked and what clears it:.claude/hooks/reanchor-gate.shis the enforcement. Only Bash, Edit, Write and NotebookEdit are denied while armed, so the model can still find and read the rules file with its normal tools, and everything unblocks on that read:.claude/hooks/instructions-loaded.shrecords which instruction files actually re-loaded, so the reload question stops being guesswork:Merge into
.claude/settings.json:{ "hooks": { "PostCompact": [ { "hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/post-compact.sh" }] } ], "SessionStart": [ { "matcher": "compact", "hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/session-start-compact.sh" }] } ], "PreToolUse": [ { "hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/reanchor-gate.sh" }] } ], "InstructionsLoaded": [ { "matcher": "compact", "hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/instructions-loaded.sh" }] } ] } }Verify on your build:
chmod +x .claude/hooks/*.sh.jqmust be on PATH./compact, then ask for a small edit. The edit gets denied with "Post-compact re-anchor pending", the model reads.claude/hard-rules.md, and the same edit goes through in that turn.cat .claude/compact-log/*.mdnow holds the summary that replaced your transcript, on disk. Diff it against hard-rules.md once. You will see which rules the compactor paraphrased away instead of keeping.tail .claude/compact-log/reloads.loglists every instruction file that re-loaded and why, so you know what actually comes back on your machine.The log folder and the marker are local state: add
.claude/compact-log/and.claude/.reanchor-requiredto .gitignore.The gate arms only when
agent_idis absent, because these events also fire for teammate compactions (#91910). Confirm PostCompact actually fires on your version and platform before trusting the gate (#77832 reports Windows misses). If it does not fire, the gate cannot arm.dripston commentedon Sep 28, 2026
For anyone hitting this and looking for a stopgap while this is open: I built a small Claude Code plugin, seatbelt, that re-reads and re-injects CLAUDE.md at the moments it's most likely to have been dropped â
SessionStarton compact/resume, and past a token-depth threshold in long sessions. It also gives asystemMessageconfirmation each time it fires, so it's not silent.To be clear about what it isn't: it doesn't fix the underlying compaction behavior (that's this issue), it just re-supplies the context afterward, and I don't have a clean measurement yet of how much that actually improves adherence versus just having the rules re-read again. It's a workaround for the symptom, not a fix for the cause.
samvallad33 commentedon Oct 1, 2026
tatyree's comment above is the one that should anchor this thread â a production project damaged because, post-compaction, the model kept changing things by "common sense" instead of the documented way. The structural problem is that CLAUDE.md is context, and compaction is a lossy summary of context: anything that lives only in the window gets rewritten at exactly the moment the work is longest and least supervised. We keep durable rules outside the window instead â a local-first memory kernel with an append-only, tamper-evident log, where a rule's exact handle stays retrievable no matter what the compactor kept. No embeddings, no fuzzy recall; you keep handles honest, and that's the trade. It wouldn't have saved everything here, but the conventions would still have been addressable.
brew install samvallad33/tap/vestige(Disclosure: I work on Vestige, the memory kernel just described; free and open-source.)