Compaction

What /compact costs, and why a design hands over to implementation through the plan file, not a compacted session.

Decision record, 2026-10-01: after a design session on Fable, should /compact or a fresh session on the persisted plan carry the design into implementation? Sources: Claude Code docs on context window, prompt caching and costs; the repo's cache facts (context/facts/claude.md, Prompt caching); the README's read-gate section; the hook integration probe (git history: docs/hook-integration-investigation.md); the peek event stream of session be7c0d25 (fdesign on Fable, /compact, /model to Opus, /fimplement).

Decision

A fresh session on the plan. Compaction is for one long task that outgrows its window, never for a phase handoff.

Use cases

SituationDo thisWhy
Design approved, implementation nextPersist and commit the plan, end the session. Start a new one on the implementation model with /fimplement <plan file>.The plan is the contract; anything a summary adds is non-binding by construction.
One task, context near the window/compactThe only case where the summary carries state that lives nowhere else: the in-flight unit.
Unattended routine resumed nightly/compact in the prompt, as Routines does.Context grows per run; nobody is there to split sessions.
Model switch plannedSwitch at the session boundary, not after compaction.The summary bills on the compacting model; the switch alone already costs a partial cache rebuild.

What compaction does

EffectDetail
One large request on the session modelSame system prompt, tools and full history, plus a summarization instruction as the final user message; billed like any call over that context. Since CLI 2.1.198 it inherits the session's extended-thinking setting.
Full cache rebuildThe message list is rewritten, so the next call re-writes the whole remaining context at the cache-write rate. Compaction's own request uses a 5-minute cache TTL unless subagentPromptCacheTtl is set.
Harness re-reads after the summaryUp to five recently read or edited files, newest first; one over 5,000 tokens returns as a path reference. Invoked skill bodies are re-injected, capped at 5,000 tokens per skill and 25,000 total; fdesign (~8,000 tokens) loses its tail.
Intermediate reasoning is gonePrior thinking is not preserved. Conclusions survive only where written down: the plan, its AGENT-ONLY columns, ledgers (Thinking).
HooksPreCompact can block. PostCompact receives the summary, can neither block nor inject. A SessionStart after compaction drops the root agent's read-gate records, so every required file is owed again; recorded skill invocations stay.
Invisible to peekNo usage row in the event stream (the compact skill entry shows 0 in, 0 out); the cost shows only in Anthropic usage.

Why it fails as a phase handoff

Measured on session be7c0d25: design on Fable, implementation on Opus.

StepTimeWhat happened
/compact22:08:54 โ†’ 22:10:08Summary written on Fable over the full design context.
Harness re-reads22:10:17 โ†’ 22:10:32Four automatic Reads rejected: three by the path fence, one by the read-gate.
/model, /fimplement22:17:42, 22:17:46The implementation model takes over.
Read-gate re-reads22:17:57 โ†’ 22:19:02global.md, fimplement.md, fdesign.md (614 lines, ~32k tokens), go.md (1,327 lines, ~30k tokens).
Denied commands22:18:02, 22:18:58git status and git diff refused until fdesign.md was re-read.
Plan read22:18:24The whole plan file, 3,327 lines, ~26k tokens.
First edit22:19:51Two minutes after the skill started.

Three costs a fresh session never pays:

CostDetail
The summary is paid twiceOnce to produce it on the design model, then as context on every later call. A fresh session carries the plan instead, which the implementation skill reads in full anyway (fimplement's intake rule).
The gate demands the wrong filesAfter compaction the read-gate owes every injection file the session ever recorded, the design skill's included; a fresh session owes only what the implementation skill declares. The fdesign injection file alone: 32k tokens re-read for a skill the session no longer ran.
The harness re-reads hit the fenceThe automatic Reads target the most recently touched files: in a design session, the plan-mode file under ~/.claude/plans/ and the injection files under ~/.claude/context-required/, both outside the session roots. Denied, they start the model from a rejected-Reads ledger.

The summary did carry one thing that time: an unfinished persistence. The addendum and its Changes entries existed only in the plan-mode file at compaction; the post-compaction run spent four minutes writing them into the repo plan. A precondition of the plan-on-disk route, not an argument for compaction.

The handoff that works

  1. Persist the plan

    fdesign ends with the plan persisted in the plan dir, smine-rules plan-sections green, and the plan committed.

  2. Start a new session

    Choose the implementation model at start and run /fimplement <plan file>. The tool-policy hook applies the plan's frozen rules on the invocation.

  3. Peek only for ambiguity

    /peek on the design session is the fallback for one thing: a Decision or rejection reason that reads ambiguous. Needing it for more is a plan defect; fix the plan.

Same-session chaining without compaction stays acceptable for a short design. Compaction costs the most and delivers the least.

Open measurements