Last week I published a piece about handing off a Claude Code session without re-explaining everything. A reader left a comment that stuck with me: "Compaction is the limit that actually bites." He was right, and I'd glossed over it. So this post is the one I should have written first.
If you searched for "claude code compaction" because your session suddenly stopped knowing things it knew an hour ago, here's what's going on, what actually survives, and the small hook I shipped to fix the part that hurt me most.
TL;DR: When a Claude Code session gets long, Claude summarizes the conversation to free space. The summary keeps the gist and drops the details, and the details are usually your decisions. You can't see what got cut. The fix is to keep decisions outside the conversation and put them back after every compaction. ContextForge 0.12.0 does that with a Claude Code hook that runs automatically.
What compaction actually does
Every model has a context window, and a working session fills it fast: file reads, tool output, your back-and-forth. When Claude Code gets close to the limit, it compacts. It writes a summary of everything so far, throws away the original messages, and keeps going with the summary plus whatever hadn't been summarized yet. You can trigger it yourself with /compact, and it also happens on its own when the window fills up.
From the outside it looks harmless. The status line says "Compacted," the conversation continues, and Claude still sounds like it knows what you're doing. That's the trap.
Why you can't tell what you lost
Here's the part my reader nailed. After a compaction you get the summary plus the tail of messages that hadn't been folded in yet. Where that cut lands depends on the exact moment compaction fired. So no two resumes give you the same context, and from inside the session there's no seam to look for. The summary reads as complete.
What actually falls out is predictable, though. Summaries are good at "we're refactoring the retry logic." They're bad at "retry logic goes in the client, not the handler, and we dropped the Redis layer because it added 40ms for nothing." The gist survives. The decisions evaporate. You find out when Claude cheerfully re-adds the caching layer you removed two hours ago.
What survives a compaction
- The gist of the task: kept, as a summary.
- Recent messages (the tail): kept verbatim, but which ones depends on timing.
- Specific decisions and their reasons: usually gone.
- Tool output and file contents you discussed: gone.
- Anything saved outside the conversation: untouched.
That last line is the whole strategy. --resume won't help you here, because it brings back the same compacted transcript. CLAUDE.md helps for the stable stuff, but it goes stale the moment your decisions move faster than you edit the file (I wrote about that in Why Your CLAUDE.md Goes Stale). What you want is the handful of decisions, stored somewhere compaction can't reach, and reloaded the instant the cut happens.
The fix: a hook that runs after every /compact
Claude Code has a hooks system, and one of the events is SessionStart with a compact matcher. Anything a command prints there gets added straight into Claude's context right after the summary. That is exactly the moment we need.
So in ContextForge MCP 0.12.0, init installs this into your project's .claude/settings.json:
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{ "type": "command", "command": "npx -y contextforge-mcp recall" }
]
}
]
}
}
What the hook does after every /compact
recall is a new subcommand. It reads which project this folder is linked to, fetches the 10 most recent memories saved for that project and up to 5 pending tasks, and prints them as plain text. Claude Code appends that text to the context. From Claude's point of view, the decisions were never gone.
Here's what it looks like in the terminal, right after a compaction:
A few things I cared about while building it:
- It can never break your session. No API key, no linked project, no network, or more than eight seconds: it prints nothing and exits cleanly. You'd never know it ran.
-
It's a tool call, not magic. The hook is a shell command. You can run
npx contextforge-mcp recallyourself from the project folder and see exactly what Claude will see. - It's fast. About four seconds, most of it waiting on the network.
Setting it up
New to ContextForge? Install the MCP server the usual way, then run this once in your project:
npx contextforge-mcp init
That writes the memory rules to your CLAUDE.md and, on Claude Code, adds the hook. Nothing else to configure. Full steps are in the docs.
Already using it? Update to 0.12.0 and re-run init in each project. It's idempotent: it only adds what's missing and leaves your existing settings.json and hooks alone.
npx contextforge-mcp --version # should say 0.12.0 or newer
npx contextforge-mcp init # adds the hook, prints "already present" next time
Then test it: run /compact in a session and ask "what context did you just receive?" If Claude quotes a block that starts with "ContextForge: context restored after compaction," you're set.
Where it falls short
I'd rather you know this now than find out later.
- It only brings back what was saved. If nobody saved the decision, there's nothing to restore. The habit that does the real work is asking the agent to save decisions as you go, and "save where we are and what's next" before you close the terminal.
- It still can't tell you what the summary dropped. Nobody can. What it does is make that question matter less.
- Claude Code only. Cursor and Copilot don't have this hook system. The same saved memories are there when you open the project in those tools, but the automatic re-injection is a Claude Code feature.
-
Your project has to be linked. The hook needs a
.contextforgefile in the repo root to know which project's memories to fetch. Ask the agent to "link project" once and you're done.
FAQ
Does compaction happen without me asking?
Yes. Claude Code compacts automatically when the context window fills up, and you can trigger it manually with /compact. Both fire the hook.
Does this replace --resume?
No. --resume reopens a session on the same machine; use it. The hook covers what --resume can't: the decisions that a compaction summarized away. They complement each other.
Can I see what the hook sends?
Run npx contextforge-mcp recall from the project folder. It prints exactly the block Claude receives, or nothing if the project isn't linked or the API key can't be found.
Why did the hook print nothing for me?
The usual causes: an old CONTEXTFORGE_API_KEY exported in your shell that overrides the one in ~/.claude.json, an older global install of contextforge-mcp shadowing npx, or the project isn't linked yet. The docs have a short troubleshooting list.
Compaction isn't a bug. It's the price of long sessions, and the alternative is a session that stops working. The mistake I made for months was treating the transcript as the thing worth keeping. It isn't. The decisions are. Keep those outside the conversation, hand them back at the right moment, and compaction becomes something you stop noticing.
If you want to try it, ContextForge has a free tier and the setup is three commands. And if you're the reader who left that comment: thank you. You were right.

Top comments (0)