Build your own Claude Code
Context management & compaction·5 min

What fills the window

0 / 1

Every turn you've built so far appends to one array and resends the whole thing — the conversation is the context. That worked because your sessions were short. A real fix is not short: the agent reads a dozen files, runs bash twenty times, spawns a subagent, calls an MCP tool, and every one of those observations stays in the array, resent on every single request. The window is finite. This chapter is about surviving the moment it fills up.

What fills the window

The context window is the model's whole working memory for a session, measured in tokens. Before the user even types, a chunk is already spent on startup content: the system prompt, the tool definitions you registered in Chapter 5, CLAUDE.md and any imported memory, and the descriptions of your loaded skills. Then the session itself accumulates: every user message, every assistant turn (text + reasoning), and — the heaviest by far — every tool result. A single view of a long file or a noisy bash run can be thousands of tokens, and it sits in the array forever, paid for again on every turn.

What the window holds — and how it grows
┌─ startup (re-sent every turn, reloads after compaction) ─────────┐
│  system prompt · tool defs · CLAUDE.md / memory · skill *names*  │
├─ session history (grows without bound until you compact) ────────┤
│  user message            "fix the failing auth test"            │
│  assistant text + thinking                                       │
│  tool_use view(auth.ts)  →  tool_result  (240 lines of file)    │  heavy
│  tool_use bash(npm test) →  tool_result  (full stack trace)     │  heavy
│  tool_use str_replace    →  tool_result  ("edited auth.ts")     │
│  ... ×N turns ...                                                │
└──────────────────────────────────────────────────────────────────┘
                     used / limit  →  cross the threshold  →  compact

You track this as pressure: used / limit. As the session runs, used climbs toward limit. You don't wait for it to hit the wall — once you'd overflow on the next turn, the request fails outright and the session is dead. Instead you set a threshold (Claude Code compacts well before the hard limit) and act when pressure crosses it. The next step uses 75% as the trip wire: at used / limit ≥ 0.75, it's time to compact.

What survives compaction

Compaction replaces the bloated history with a compact summary so the session can keep going. The hard part is not summarizing — it's deciding what is load-bearing. Get it wrong by dropping too much and the agent forgets what it was doing; keep too much and you never relieve the pressure. The policy is not a matter of taste; it follows from one question: after the summary, what does the agent need to pick up exactly where it left off?

The preserve / drop policy
KEEP — the agent can't continue without it
  user-intent     the original goal ("fix the failing auth test")
  edit            diffs already applied — what changed on disk
  error           failures seen — so it doesn't repeat them
  task / open     the open to-do list — what's still unfinished

DROP — reconstructable, or pure noise once acted on
  tool-output     verbatim file dumps & bash stdout (huge, stale)
  reasoning       intermediate thinking between turns
  skill-description  reloads on demand when a skill is invoked

RE-INJECT after the summary
  startup         system prompt, tool defs, CLAUDE.md, skill names
Compaction is lossy, then refilled

Compaction doesn't just delete — it summarizes-then-reloads. The verbose middle collapses into a structured summary, and the startup content (system prompt, tool defs, CLAUDE.md, skill names) is re-injected fresh at the top so the compacted session still knows its tools and rules. The next step builds the classifier that decides each item's fate; the step after writes the transcript so nothing dropped from the window is lost from the record.