Repository navigation
Description
Summary
When a large Claude thread is resumed after its prompt cache has expired, the Compact path (/compact before send, or "Resume with less context") can cache-write the whole old history while summarizing it. The next turn then caches the new, smaller context. The old history is about to be dropped, so in this case most of that write buys nothing: one measured cold compaction spent about half its cost writing history that was discarded.
T3 can address this on its own side. In the usual cold case it already starts a fresh Claude CLI process for that compaction turn, and it already passes an env per query. The proposal is narrow: for an explicitly cold compaction only, open that one compaction process with prompt caching disabled, then reopen normally for the next productive turn. Warm compaction and normal turns would keep caching.
This is a cost/performance report with a proposed direction. It's distinct from the warm-window timing work (#13988 → Ideas #18011, Ideas #14233, draft #16855) and from compact-on-send defaults (#17467, Ideas #17170). Those decide when compaction happens; this is about how much the cold compaction itself costs. If maintainers would rather track this as an Ideas discussion, that's fine.
Evidence
Measured cold compaction (Opus 5.5, Claude Code via T3, Oct 9, about 112 min idle, so past the 1h cache):
| Request | input | cache read | cache write (all 1h) | output |
|---|---|---|---|---|
| Previous turn (warm) | 2 | 447,034 | 608 | – |
/compact summarizer |
2 | 11,573 | 364,934 | 4,314 |
| Next productive turn | 2 | 11,573 | 36,190 | 677 |
| Following turn | 2 | 47,763 | 2,068 | 547 |
The compaction boundary reported ~448k tokens before and ~10.9k after. The summarizer request was matched to the compaction boundary by timing (completion within 15 ms, duration ~42.6 s vs ~42.8 s), the same session, and the following turn's usage. No request ID is persisted in the transcript, so this is a strong timing/sequence match, not an explicit ID join.
At published API rates (Opus 5.5: input $4, 1h write $8, cache read $0.20, output $20 per MTok), that compaction costs about $3.01. With the same token counts:
- Old history at ordinary input, keeping the shared
11.6k warm prefix: **$1.55** (saves ~$1.46, ~49%). - Fully uncached (what disabling caching for the whole request does): ~$1.59 (saves ~$1.42, ~47%).
These are arithmetic estimates, not a paired live experiment. Removing cache markers could change the request in other ways. The replacement-context write on the next turn (36k) is unaffected.
Runtime behavior (Claude Code 2.1.296, Agent SDK 0.3.276, read from the shipped minified runtime):
- Default compaction runs a cache-sharing fork with
skipCacheWrite: true. That only moves the tail cache breakpoint back one message. Earlier history keeps its ordinary ephemeralcache_controlmarker. It is not a read-only-cache mode, so with an expired cache the old prefix is written again.- In a synthetic warm Haiku 5.5 test,
/compactstill wrote ~2.2k tokens on top of ~26–27k cached reads. That's cheap when warm; the problem is cold history.
- In a synthetic warm Haiku 5.5 test,
- The compaction request doesn't set
enablePromptCachingitself. The request builder falls back to the model-level check, which returns false whenDISABLE_PROMPT_CACHING(orDISABLE_PROMPT_CACHING_<MODEL>) is set in the process env. So a CLI process started with that env should send the compaction with no cache markers. I found this by reading source; I haven't verified it with a live request. CLAUDE_CODE_COLD_COMPACTexists, but CLAUDE_CODE_COLD_COMPACT is unreachable in the local CLI: the auto-window gate returns before it, and an explicit window routes through the reactive path, which never reads it (2.1.270–2.1.272) anthropics/claude-code#95694 reports it is unreachable on the tested local paths, so it isn't a dependable switch.
Why T3 can realistically fix this
Checked at 273835b:
ProviderSessionManager.ts:DEFAULT_IDLE_TIMEOUT_MS = 30 min. Idle Claude sessions are released well before the 70-min resume offer (CLAUDE_RESUME_COMPACTION_MINUTESinContextWindowMeter.logic.ts). So a cold compaction normally already opens a new CLI process withresume.ClaudeAdapterV2.ts:compactThreadisstartTurnwith text/compact.makeClaudeQueryOptionsalready forwardsenv. The live process is reused only whenqueryPolicyKey/selectionKeymatch; otherwise it is replaced, and replacement is refused while background work runs.
A possible shape:
- When T3 starts a compaction it treats as cold (the existing resume-compaction offer / compact-before-send path), open that turn's query with
DISABLE_PROMPT_CACHING=1added to the env and a distinct query-policy key. - The next productive turn uses the normal key, so the process is replaced with normal env and caching resumes. Idle release already requires a new process for the compaction; restoring normal caching afterward requires one additional process start before the productive turn.
- Warm compaction (manual Compact while the cache is live, auto-compact, feat(server): opt in to compaction before PR waits #16855-style pre-wait compaction) is unchanged.
- If the live process is pinned by background work, fall back to today's behavior rather than killing it.
This is not a request to disable caching globally. That would make warm compaction and every normal turn more expensive.
Tradeoff: forks and branches
Transcript-based forks keep working. T3's fork uses the standalone SDK forkSession(sessionId, { upToMessageId }), which copies the transcript. In a synthetic Haiku 5.5 test, forking an already compacted session at its last precompaction assistant message restored the full old history and all earlier thinking blocks (27,758 cached read, 0 write). The native streaming resumeSessionAt path behaves differently and is not what T3 uses. I tested the SDK call, not the UI fork button.
What is lost is only the warm-cache benefit for a branch made from the precompaction history within the cache TTL, on the same account. Per 100k history tokens on Opus 5.5 with a 1h TTL:
- Skipping the write saves $0.40 now.
- The first such branch would then pay a write ($0.80) instead of a read ($0.02).
Break-even is about a 51% chance of such a branch (about 21% with a 5m TTL). Branches made after expiry would not have benefited from the write anyway.
Not verified
- No paired live test of a cold compaction with caching disabled versus default. The env-gate path comes from reading source.
- Behavior may vary by Claude Code version or server-side experiments. [Bug]: "Resume with less context" is offered only after the prompt cache has expired, so it always takes the expensive path #18011 reported ~$0.90 for compacting a cold ~210k Opus thread, which is closer to uncached input than to a 1h write. Measuring the cache-write tokens of a cold compaction on current versions would confirm how common this is.
- Savings are API-equivalent. How cache writes count against Pro/Max usage limits is not public.
- The 70-min offer is a heuristic for "cache is cold". The 1h-vs-5m TTL split isn't tracked (see [Bug]: "Resume with less context" is offered only after the prompt cache has expired, so it always takes the expensive path #18011 triage). A wrong guess on a still-warm thread would turn cheap reads into ordinary input.
- Haiku tests were synthetic, text-only, with no tools. Opus/Sonnet may differ, and I didn't generalize them.
Environment
Claude Code 2.1.295/2.1.296, @anthropic-ai/claude-agent-sdk 0.3.276, T3 main @ 273835b, Windows 11.
Related: #13988 / #18011, #14233, #16855, #17467, #17170, #16829 (PR watch waking cold threads), #17423 (revert across compaction, separate from fork), anthropics/claude-code#95694, #66115, #99624, #70459.
Activity
juliusmarminge commentedon Oct 11, 2026
Note
Grok responding on behalf of Julius.
This is a cost-optimization proposal, not a bug. Converting to Ideas per CONTRIBUTING.md.
On main, the plumbing you point at is real:
makeClaudeQueryOptionsforwardsenvironmentasenv, idle release is 30 minutes (ProviderSessionManager), andcompactThreadis/compactviastartTurn.DISABLE_PROMPT_CACHINGexists in the shipped Claude Code runtime. What is not verified is that opening one cold compaction with that env actually cuts the cache-write cost (no paired live test; your numbers are arithmetic).Distinct from Ideas #18011 (when the cold resume offer fires). Continue the design discussion there or in the converted thread—especially the warm-cache fork tradeoff and the cold heuristic.
Alb11747 commentedon Oct 11, 2026
Moved to an Ideas discussion, per CONTRIBUTING (proposals belong there): #18069. The discussion also corrects one detail here: restoring normal caching after a cold compaction costs one extra CLI process start.