Field notes for Claude Code users
Why Claude Code compaction drops your decisions
A long Claude Code session does not forget evenly. Compaction is a summary, and a summary keeps what the code looks like now while quietly dropping the decisions that got it there. This is about why decisions are the first thing to go, why you never see it happen, and what actually keeps them alive.
Direct answer (verified 2026-05-17)
Yes, compaction can drop earlier decisions. When a session nears the context limit, Claude Code summarizes the conversation. Anthropic’s own docs say the summary keeps “your requests and key code snippets” but that “detailed instructions from early in the conversation may be lost.” Design decisions, rejected alternatives, and constraints are exactly that kind of early instruction. The loss is silent: nothing errors, the agent just re-derives a decision from the current code and often lands somewhere different.
Compaction does not forget evenly
The mechanics are documented. As a session fills the context window, Claude Code “manages context automatically as you approach the limit. It clears older tool outputs first, then summarizes the conversation if needed.” The summary is lossy by design: it has to be, or it would not free any room. Most guides stop there, at “summaries are lossy.” That is true and it is not the interesting part.
The interesting part is that the loss is not random. A summarizer is answering one implicit question: what does the next turn need to know? The most obvious answer is the current state of the code, so it keeps state. A decision is not state. A decision is a constraint on future actions: use Postgres, not SQLite. The auth module is frozen, do not touch it. We tried the websocket approach and abandoned it. To a summarizer scanning for “what is happening now,” those read as old conversation about something already settled, and settled conversation is what a summary compresses hardest.
Why a decision is dropped before a file path
Sort everything in a long session into two piles and the pattern is obvious. One pile is re-derivable: if the summary forgets it, the agent can recover it by reading the filesystem. The other pile exists only in the conversation. Compaction can only actually destroy the second pile.
Survives compaction either way
- Current file contents (re-readable from disk anyway)
- The latest request you typed
- Recent tool output, the active error being worked
- Key code snippets, per Anthropic's own docs
Exists only in the conversation
- Why one approach was chosen over another
- Alternatives you considered and rejected
- Constraints stated once: "do not refactor the auth module"
- The reasoning chain behind a structural choice
- Agreements like "we will do that part in a follow-up"
Anything in the left column survives whether the summary keeps it or not, because the code itself is the backup. Anything in the right column is single-copy: the conversation is the only place it ever lived. So compaction’s blast radius lands precisely on the highest-value, least-redundant content in the session. The decisions are not collateral damage. They are the target the summary is least equipped to protect.
Anatomy of a dropped decision
Turn 12, you decide
The loss is silent, and that is the dangerous part
There is an asymmetry between the two piles that matters more than the piles themselves. When compaction drops a file path, the failure is loud. The agent calls a tool, the path is wrong, you get a file-not-found error, and you notice in the same turn. The loss announces itself.
When compaction drops a decision, nothing happens. There is no error to fire. The agent simply re-derives a choice from the code in front of it, and the new choice is plausible. It compiles. Tests may even pass, because a contradictory decision is not a syntax error, it is a divergence. You find out three commits later, when two parts of the codebase quietly disagree about how retries work, or when a constraint you stated once gets violated and no one flags it. The model is not being careless. It is doing exactly what the summary told it the situation was.
This is why “the agent re-did work it already finished” and “the agent made an edit that conflicts with an earlier one” are the same bug wearing two coats. Both are a dropped decision. Your code is safe through a compaction. The agent’s awareness of why your code is shaped the way it is, is not.
Compaction begets compaction
A dropped decision is rarely a one-time event, because the recovery behavior feeds the problem. After the first compaction the agent notices it is missing context, so it re-reads files and re-runs commands to rebuild a picture of the current state. That recovery work is bulky, and it lands right back in the window. The window refills faster than it did the first time, the next boundary comes sooner, and now the summarizer is compacting a window that already contains a summary.
The compaction cascade
First compaction
Summary keeps current state, drops the why
Agent re-reads files
It reloads code to recover what the summary lost
Window refills faster
Bulky re-reads and re-run output land back in context
Next compaction, sooner
Now it summarizes a summary, decisions flatten again
Each pass compresses the survivors harder. A decision that made it through the first boundary at low resolution gets flattened again on the second, and by the third pass the agent is reasoning from a summary of a summary of a summary. The decisions that were already thin do not survive that.
What actually keeps a decision alive
The fix follows directly from the two piles. A decision you cannot afford to lose does not belong in the conversation. The conversation is volatile working memory. Move the decision into a file the moment you make it, and it joins the re-derivable pile that compaction cannot touch.
- Standing rules go in CLAUDE.md. The docs are blunt about this: “Put persistent rules in CLAUDE.md rather than relying on conversation history.” Conventions, frozen modules, the libraries you have committed to, anything that should hold for the whole project.
- Steer the summary with Compact Instructions. A section titled
Compact Instructionsin CLAUDE.md tells the summarizer what to keep on every compaction. Or run/compactwith a focus when you see the wall coming. - Session-specific calls go in a plan or decisions file. For choices that only matter for this task, a short
DECISIONS.mdor the plan file works: chose A over B because C. Files get re-read on demand and survive every compaction, every fork, and every restart.
The catch is honest and worth stating: this only protects decisions you remember to write down. The dangerous ones are made in passing, in a single sentence, mid-debugging, and those are exactly the ones that never get filed. For the full set of levers, including what /compact with a focus does and why there is no off switch, see controlling Claude Code context compaction.
The durable layer: keep the transcript, not a summary of it
Start with the honest limit. Nothing that runs Claude Code can delete the compaction boundary. The Claude Code SDK owns when compaction fires, so a wrapper cannot switch it off, and Fazm does not pretend otherwise. A single unbroken window will still compact when it hits the ceiling.
What a wrapper can change is what the conversation is stored as between windows. Claude Code already writes every message, tool use, and result to a plaintext JSONL transcript under ~/.claude/projects/. That file is the verbatim record. Every decision you ever typed is in it, uncompacted. Compaction only summarizes what the model sees in a live window. It never edits the JSONL on disk.
Fazm, an open-source native macOS app that runs Claude Code through the Agent Client Protocol, treats that transcript as the source of truth. The clearest place to see it is what happens when a chat’s working directory changes, because the Claude SDK addresses transcripts by an encoded-cwd directory. A naive host would fall back to replaying a capped summary of recent turns. Fazm does not. The function migrateJsonlForCwdChange in acp-bridge/src/index.ts (line 2506) physically relocates the transcript file into the new workspace’s project directory so session/resume finds the full record. The comment on that function states the intent in one line:
// acp-bridge/src/index.ts, line 2493 // Carry a Claude SDK transcript across a workspace (cwd) // change so the session can be resumed with its FULL // history instead of a capped priorContext summary.
That is not marketing language, it is a code comment explaining why the function exists. The move is logged so you can watch it happen:
The same principle runs through the rest of the app. Forking a chat is one click, and the branch carries the full prior transcript, not a paragraph about it. The compact_boundary event the terminal hides is surfaced in the UI, so you can fork before the wall instead of discovering it after. Sessions are persistent: a Mac restart reopens the window from the same verbatim transcript. None of this stops a window from eventually compacting. What it does is make sure a compaction is never the only copy of your decisions. The conversation always exists on disk in full, and resume and fork rebuild from it.
Tired of re-explaining decisions Claude Code already forgot
Fazm wraps Claude Code via the Agent Client Protocol in a native macOS app. Show me how you run long sessions and I will walk through where decisions get dropped today and what changes when the transcript is the source of truth.
Frequently asked questions
Does Claude Code compaction actually delete my decisions?
It deletes them from the live context window, not from disk. When a session nears the context limit, Claude Code summarizes the conversation so the model can keep going. The original messages, including every decision you typed, stay in the plaintext JSONL transcript Claude Code writes under ~/.claude/projects/. So a decision is lost in the sense that the model can no longer see it, while still being recoverable if a tool reads the transcript. Compaction edits what the model sees, never the file on disk.
Why does compaction drop decisions before file paths?
Because file contents are re-derivable and decisions are not. The agent can re-read a file at any time, so even if the summary forgets a path the information still exists on disk. A decision exists only in the conversation. Once the summary flattens it, there is no second copy in the live window. Summarizers also bias toward current state over past reasoning: a decision reads as settled, old conversation about something already done, which is exactly the kind of text a summary compresses hardest.
How do I know a decision got dropped?
Usually you do not, until something downstream contradicts it. A dropped file path fails loudly: the agent calls a tool, the path is wrong, you see a file-not-found error and notice. A dropped decision produces no error at all. The agent re-derives a choice from the current code, lands somewhere plausible, and the work compiles. You find out commits later when two parts of the codebase disagree, or you never find out. Run /context to watch the window fill, and if your host surfaces the compact_boundary event, treat it as a prompt to check what the summary kept.
Is there a setting to stop compaction from losing decisions?
There is no off switch for compaction itself. You can steer what the summary keeps by adding a Compact Instructions section to CLAUDE.md, or by running /compact with a focus like /compact focus on the database decisions. The more reliable fix is structural: do not rely on the conversation to hold a decision. Write it into a file the moment you make it. Files are re-read on demand and survive every compaction. The full set of compaction controls is covered in our guide on controlling Claude Code context compaction.
What is the compact_boundary event?
It is a system event the Claude Code SDK fires the instant it decides to compact. It carries a trigger field (auto when the SDK decided, manual when you ran /compact) and a pre_tokens count of how much context was live at that moment. The terminal computes all of this and then shows you only the finished summary. The raw event is discarded by the UI. A host built on the Agent Client Protocol can forward the event instead, so you see the boundary coming while you can still act on it.
Does Claude Code's auto-compact summary include my most recent work?
Not always reliably. A reported bug, GitHub issue #14176, described the instant auto-compact summary failing to update to reflect the most recent messages, so recent turns appeared lost when continuing in a new session. The issue was closed as not planned. The practical takeaway: treat the compaction summary as an approximation of the conversation, not a faithful record of it, and do not assume a decision survived just because it was recent.
Does running Claude Code through a wrapper like Fazm change the model or compaction?
No to the model. A host that runs Claude Code through the Agent Client Protocol uses the same agent loop, the same Claude Pro or Max plan, the same tools and prompts. It also cannot remove the compaction boundary, because the SDK owns when compaction fires. What a wrapper changes is durability around the event: whether the verbatim transcript is the source of truth, whether forking carries the full history instead of a summary, and whether sessions survive a restart. The model on the other end of the socket is unchanged.
Related field notes
How to control Claude Code context compaction
You cannot switch compaction off. You can control what the summary keeps, when it happens, and where the conversation continues. The full control panel.
Claude Code auto-compacting token waste
The summary is cheap. The expensive part is the re-establishment work after the boundary fires, retyping facts the model just forgot.
Claude Code context in long sessions
A long session loses context four different ways. Only one is a prompt problem. What survives each, verified against the docs.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.