Blog / claude code
Claude Code forgets rules after compaction: how to keep them
Root CLAUDE.md survives compaction; rules said only in chat, path-scoped rules and nested files don't. Move them, then add one hook that re-reads them.
Claude Code's project-root CLAUDE.md comes back after every compaction: Claude Code re-reads it from disk. What disappears is anything you said only in the conversation, rules scoped to certain paths, and CLAUDE.md files in subfolders. Put the rules that must hold all session long in the root file, keep it short, and add one SessionStart hook with the compact matcher for the few things that change during the day, such as the task in hand.
A long session ends the same way for many people: an hour in, Claude Code compacts, and the agent that was running pnpm test before each commit starts running npm install. It looks as if the rules vanished. Usually they were never in a place that survives.
What survives compaction in Claude Code#
When the context window fills, Claude Code summarizes the conversation so far and carries on from the summary. The Claude Code docs list what happens to each kind of context. The short version:
| Where the instruction lives | After compaction |
|---|---|
Project-root CLAUDE.md and rules without paths: | Re-read from disk |
| Auto memory | Re-read from disk |
| System prompt and output style | Still apply |
| A plan written in plan mode | Re-read from disk |
Rules with paths: frontmatter | Come back only when a matching file is touched again |
CLAUDE.md in a subfolder | Comes back only when Claude works in that folder again |
| Something you typed in the chat | Only what the summary kept |
| Context a hook added earlier | Only what the summary kept |
Output of a SessionStart hook matching compact | Run again and added |
Three rows cause almost every "it forgot my rules" report.
Rules you typed. "From now on use pnpm" lives in the conversation. The summary may keep it, shorten it, or drop it. Anything you want for the rest of the project belongs in a file.
Path-scoped rules. A rule file with paths: frontmatter loads when Claude reads or edits a matching file. That load is part of the conversation, so compaction summarizes it away with everything else. It returns the next time Claude touches a matching file, which may be several steps after it already broke the rule.
Nested CLAUDE.md files. Same story: a CLAUDE.md in packages/api/ loads when Claude works there, and after compaction it waits until Claude goes back.
Fix 1: put lasting rules in the root CLAUDE.md#
Anything the agent must follow all session goes in the project-root CLAUDE.md (or a rule file without paths:). Write rules as commands, one per line:
# Rules
- Use pnpm, never npm or yarn.
- Run `pnpm test` before every commit; never commit with failing tests.
- Never edit files under `migrations/` without asking.
- Branch names: `feat/<short-name>`.Keep it short. The docs suggest staying under about 200 lines per file, because a longer file costs more context and the agent follows it less closely. If two rules contradict each other, the agent may pick either one, so read the file now and then and delete what no longer applies.
If you rely on a path-scoped rule that must never be broken, such as "never hand-edit generated files", drop its paths: line so it loads with the root file instead.
Fix 2: add a hook that re-reads what changes#
Some context changes during the day: the task you are on, the branch, a decision made an hour ago. It doesn't belong in CLAUDE.md, but you want it back after a compaction.
Claude Code runs SessionStart hooks after compaction with the source compact, and adds what the hook prints to the new context. Keep the changing part in one small file and print it, plus recent commits:
mkdir -p .claude
cat > .claude/after-compact.md <<'EOF'
Keep these after every compaction:
- Current task: move checkout to the new payments API.
- Decided today: keep the old webhook until Friday.
EOFThen add the hook to .claude/settings.json in the project:
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{ "type": "command", "command": "cat \"$CLAUDE_PROJECT_DIR/.claude/after-compact.md\"; git log --oneline -5" }
]
}
]
}
}If the file already has a hooks key, add SessionStart next to the events already there rather than replacing it. Type /hooks in Claude Code to check that the hook is listed, then run /compact in a test session and ask the agent what the current task is.
Run the command yourself first, from the project folder, to see exactly what Claude will get:
CLAUDE_PROJECT_DIR="$PWD" sh -c 'cat "$CLAUDE_PROJECT_DIR/.claude/after-compact.md"; git log --oneline -5'Two limits are worth knowing. A hook's text is capped at 10,000 characters; past that Claude Code saves it to a file and shows only the start. And PreCompact and PostCompact hooks can't add context: their messages are discarded, so the reminder must come from SessionStart.
Fix 3: write down where you are before it compacts#
Rules come back with the fixes above. Progress is harder: what was tried, what failed, which file is half done. The summary keeps some of that, in its own words.
The cheapest habit is a short note before the context fills. Run /context now and then to see how full the window is. When it is getting close, ask the agent to write three lines into the task: what is done, what is next, what to avoid. After compaction, it reads its own note instead of guessing from a summary. The same note lets a teammate, or a different agent, continue the work.
You can also compact on your own terms: /compact keep the failing test names and the decision about webhooks tells the summary what matters most.
A checklist before your next long session#
- Lasting rules are in the project-root
CLAUDE.md, as short commands. - No rule you rely on lives only in the chat.
- Must-follow rules have no
paths:frontmatter. - A
SessionStarthook with thecompactmatcher prints the current task and recent commits. - You check
/contexton long sessions and write a progress note before it fills.
Where Joxo fits#
Joxo keeps a team's tasks, decisions and handoff notes outside any one conversation, so a compaction doesn't touch them. In Claude Code sessions, Joxo also says when the context window is filling up and suggests writing a handoff before Claude compacts, so the next step is written down rather than summarized. Setup is on the setup page; the handoff guide shows what a good note holds.
Frequently asked questions#
Does Claude Code keep CLAUDE.md after compaction?#
Yes. The project-root CLAUDE.md and rule files without paths: frontmatter are read again from disk after compaction. CLAUDE.md files in subfolders and path-scoped rules come back only when Claude works with matching files again.
Why does Claude Code ignore instructions after /compact?#
Usually the instruction was given only in the chat, lives in a nested CLAUDE.md, or is a path-scoped rule that hasn't matched a file since. Move it to the root CLAUDE.md, or print it from a SessionStart hook with the compact matcher.
Can a PreCompact hook save context for after compaction?#
Not by adding text: Claude Code discards a PreCompact hook's message. Use it for side effects such as saving a copy of the transcript, and use a SessionStart hook with the compact matcher to put context back.
See also: Set up Claude Code for a team, for sharing one rules file across everyone's agents.