CLAUDE.md is present in context after /compact but no longer followed — an imperative SessionStart hook in the same context is
Summary
After /compact, the model reliably stops following project instructions from CLAUDE.md, even though the CLAUDE.md content is demonstrably present in the post-compaction context as a <system-reminder>. In fresh sessions in the same repository, compliance with the very same rules is reliable. I have observed this repeatedly and reproducibly.
Concrete instance
The project CLAUDE.md contains, among other rules:
Never create a commit the developer did not ask for. Finish the work, let them review it, and commit when they say so. "Commit this" is one commit, not a licence for the session.
Before compaction the model followed this exactly — over a long session it asked every time before committing.
After /compact:
- The root
CLAUDE.mdcontent was injected into the context as a<system-reminder>shortly after the compaction (the model confirmed this when I asked it what it could see). - The same rule was additionally present in the compaction summary the model had written itself ("Never commit without being asked").
- Despite both, the model committed and pushed twice without being asked. My messages had said only "implement it this way" and "please fix this", with no mention of committing. Earlier in the session I had twice said "commit + push", and it extrapolated that into a standing permission — which is exactly what the second rule above forbids.
The interesting contrast
The same project has a user-defined SessionStart hook whose text is imperative and coupled to a trigger, roughly:
"After a compaction the content of loaded skills is gone — the list is not. Before reading or writing an issue here, invoke Skill(<name>) again. Its rules still apply even when they are not currently in context."
That instruction was followed in the same post-compaction session: the model re-invoked the skill before touching the issue tracker.
So within one and the same post-compaction context, an imperative, trigger-coupled hook instruction was honoured while the standing CLAUDE.md policy in the same context was not. That suggests the problem is not that CLAUDE.md is missing.
Hypothesis
This looks like a salience / pragmatic status problem rather than a presence problem:
- In a fresh session
CLAUDE.mdis the frame the task sits inside. After compaction the summary becomes the frame — it is task-oriented ("here is the state, continue") — andCLAUDE.mdarrives as an attachment to some later message. - The summary compresses standing rules into a short trailing note after many sections of task detail, which costs them weight. (In this case the rule survived into the summary and still lost.)
- The "Resume directly — do not acknowledge the summary" instruction removes the natural moment of re-orientation.
- Recent, repeated action patterns visible in the retained history outweigh a policy stated once, statically.
Suggested directions
- Re-inject
CLAUDE.mdafter compaction at the same structural position and priority it has in a fresh session, instead of as a mid-stream<system-reminder>. - In the compaction summary template, place standing rules and constraints first and imperatively, not as a trailing note behind the task detail.
- Consider surfacing project rules as user-level instructions rather than ambient context after a compaction.
Environment
- Claude Code, desktop app (Code tab), Windows 11
- Observed with Claude Opus 4.8 and Claude Opus 5
- Reproduced repeatedly across sessions in the same repository
3 Comments
Added your case to the list of CLAUDE.md non-compliance https://github.com/anthropics/claude-code/issues/13689, consider upvoting it for visibility.
@andilem try this, should work: https://github.com/sloprail/sloprail/tree/main/examples/no-unasked-commit
It moves the CLAUDE.md rule onto the action itself, which is also why your SessionStart hook held.
git commit/git pushis refused unless the agent quotes your latest message, and a judge reads the session to check it asks to commit these exact changes. The old "commit + push" can't be reused after a compact.Your other CLAUDE.md rules can be written the same way. macOS and Linux only for now; on Windows it would need WSL.
This matches what I see in transcripts too. CLAUDE.md shows up after compaction as a system-reminder, so "not loaded" isn't the problem. The rules that slip are the process ones ("ask before X", "do Y first"), while factual context still gets used. Your finding that an imperative SessionStart hook is followed in the same context is the most useful part here. It suggests framing matters more than presence: summary says "continue the task", CLAUDE.md arrives as ambient context, and the task wins. +1 to re-injecting it at the same position it has in a fresh session.