← All posts

Context

Claude Code context compaction: what gets lost, and how to preserve the knowledge that matters

Compaction is what lets a session outlive its context window. It works by summarizing earlier turns, and summaries keep narrative while dropping detail — which is precisely backwards from what engineering work needs.

Long sessions hit the context window. When they do, the agent doesn't stop — it compacts: earlier turns are summarized into something shorter, freeing room to keep going. Without compaction, every long task would die at the window boundary. It's a genuinely good mechanism.

It also has a specific, predictable failure mode, and it's worth understanding rather than being surprised by.

What summarization keeps and what it drops

Compaction is summarization, and summarization has a consistent bias: it preserves structure and discards specifics. That's the correct behaviour for most text. It's exactly wrong for debugging.

Here's a real shape of loss. Before compaction, the session contains:

[47 turns of investigation]

...ran the failing test 200 times, 6 failures, all between 00:00-05:00
local. Checked parseSettlementDate — it uses new Date(str) on a
timestamp with no offset, so it's parsed as local time, but the
reconciliation window is computed in UTC. Between midnight and 05:00
local (UTC+5) the local date is already tomorrow's UTC date, so the
transaction reconciles against the wrong day. Confirmed by pinning TZ
in the test.

After compaction, the same region often reads:

The user and assistant investigated an intermittent test failure in the
settlement reconciliation code and identified a date-handling issue,
which was subsequently fixed.

Both are accurate. Only one is useful. The second sentence would not let you re-derive the fix, spot the same bug elsewhere, or explain to a future session why the offset handling in that function must not be simplified.

Why this is worse than it looks

Three things compound.

It's silent. There's no marker in the conversation saying “a specific finding was removed here.” The session continues fluently, and the agent behaves confidently, because from its point of view the summary is the history.

It's biased toward recency. The oldest turns are compacted first, and in a debugging session the oldest turns often contain the actual discovery, with everything after it being implementation. The most valuable content is first in the queue to be summarized.

It cascades. A very long session may compact more than once, and a summary of a summary is further from the original. What survives to hour four is a summary of a summary of the thing that mattered.

Why a bigger context window doesn't fix it

It raises the threshold, which genuinely helps — more sessions finish without ever compacting. But it doesn't change the mechanism, and it doesn't help at all with the boundary that comes after: the session still ends. Tomorrow's session starts empty regardless of how large the window is.

The two problems look similar and aren't. Compaction is a within-session loss; session end is a between-session loss. Both are solved by the same thing, which is why it's worth solving once. More on capacity versus persistence.

Four things that actually help

1. Write the finding down when you find it

The single highest-value habit, and the cheapest. The moment a session produces a durable conclusion — a root cause, a constraint, a rejected approach — put it somewhere outside the context. Not at the end of the session, when you might have compacted twice already. At the moment it's understood.

With an MCP memory server connected, that's one tool call the agent makes itself:

upsert_note({
  project: "payments",
  title: "Settlement timestamps have no offset — parse as provider-local, not UTC",
  tags: ["debugging", "constraint", "timezone"],
  body: "Intermittent reconciliation failures for transactions between\n" +
        "00:00-05:00 local. parseSettlementDate() used new Date(str) on a\n" +
        "naive timestamp, so it parsed as local while the reconciliation\n" +
        "window is UTC. Fix: apply the provider offset explicitly.\n" +
        "Repro: pin TZ=Asia/Karachi in the test and run 200 iterations.\n" +
        "src/settlement/parse.js:88 — do not simplify the offset handling."
})

Compaction can now take that region of the conversation freely. The knowledge isn't in the conversation any more.

2. Ask for a checkpoint before a long stretch

If you can see a session is about to get long — a big refactor, a deep investigation — ask the agent to record what it has established so far before it continues. This is cheap insurance and takes one sentence: “before you carry on, save what we've established to project memory.”

3. Start a fresh session for a genuinely new task

Long-running sessions accumulate irrelevant history, which brings compaction on sooner and makes it lossier. If the next task is unrelated, a new session with a search against project memory is usually better context than a compacted session's summary of something else. This inverts the usual instinct, and it's right: retrieval beats retention once you have somewhere to retrieve from.

4. Write a handoff when you stop mid-task

If you're stopping without finishing, the thing to preserve isn't just findings, it's position: what's done, what's half-built, what you were about to do. That's a handoff, and it's the difference between resuming and restarting.

What's worth preserving

Not everything, and being selective is what keeps the store useful. The test: would a competent engineer reading only the resulting code know this?

PreserveDon't
The root cause behind a fixThe fix itself — it's in git
Approaches tried and rejected, with whyThe step-by-step narrative of trying them
A constraint discovered the hard wayAnything the code plainly states
A decision and the alternative it beatGenerated output and logs
How to reproduce something intermittentSpeculation that was never confirmed

The shape of the fix

DiscoveryThe session works something out that took real effort.
Written out immediatelyOne tool call. Now it exists outside the context window.
Compaction runsTakes the conversation. The finding is untouched.
Any later sessionSearches and gets it back verbatim.

Compaction stops being a loss and becomes what it was designed to be: a way to free room in working memory, with nothing important in it.

Related reading

FAQ

What is context compaction?

When a session approaches its context window limit, earlier turns are summarized into something shorter so the session can continue. It's what lets long tasks outlive the window, and it's lossy by construction.

Does compaction delete information?

It replaces it. The original turns are gone from the context and a summary stands in their place. The summary is accurate but far less specific, and specifics are usually what an engineering session was producing.

How do I know compaction has happened?

Often you don't, directly. The tell is behavioural: the agent starts asking about something it established earlier, or contradicts a decision from the same session. By then the detail is already gone, which is why the fix is to write findings out as they happen rather than to detect compaction after the fact.

Can I stop compaction from running?

Not usefully — without it the session would simply hit the wall. The productive move is to make compaction harmless by keeping the important findings somewhere outside the context window.

Make compaction harmless

Write findings to project memory as they happen, and a compaction pass costs you nothing but conversation. Free plan, no card required.

Create free workspace