Skip to content

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) #95694

Open

Description

@edubraqd

Summary

CLAUDE_CODE_COLD_COMPACT is in the env allow-list (CLAUDE_CODE_COLD_COMPACT:()=>Je in the 2.1.272 bundle) and its name suggests "compact when the cache is already cold". In the local CLI the flag has no effect on any path:

  • with the default (auto) window, the client-side autocompact check returns false before the flag is consulted;
  • with a window set via CLAUDE_CODE_AUTO_COMPACT_WINDOW or autoCompactWindow, autocompact goes through the reactive path, which also returns before the flag is read;
  • the only branch that reads it (stripNonEssential) is reachable with CLAUDE_CODE_REMOTE or when querySource is undefined.

And where it is read, what it does is not "cold-aware compaction": it makes the summary leaner and disables prompt-cache prefix sharing for the compaction request (Ye = !D && P("tengu_compact_cache_prefix", true)), which is strictly worse in the warm case (the summary request pays 1× input instead of 0.1× cache read). #70459 (jens-f, 2.1.186) already noted the second half; this report adds that on local the flag is dead code, and an A/B confirming it.

Environment

  • Claude Code 2.1.272 (static reading of the bundle) and 2.1.270 (A/B), Windows 11, Opus 5 and Haiku 4.5, subscription login, no gateway
  • Both cc_entrypoint=cli and the desktop app

Where the flag is read (2.1.272 bundle, minified names as they appear)

function wRs(){return a.CLAUDE_CODE_COLD_COMPACT}

// client-side autocompact gate
async function TRs(e,n,r,s,d=0,h){
  if(ree(s))return!1;                 // querySource === "compact"
  if(cG(s))return!1;
  if(C1e(s,n,r))return!1;
  if(!ff())return!1;                  // auto-compact enabled
  if(LU()&&!RX(n,r))return!1;         // <-- local && window source === "auto"  → never past here
  let b=lg(e,zf(n))-d,O=_te(b,n,r);
  return t(`autocompact: tokens=${b} level=${O.level} effectiveWindow=${r2(n,r)}`), O.level==="compact"||O.level==="blocked"
}
function LU(){if(a.CLAUDE_CODE_REMOTE){if(!Dms.isOpen())return!1}return!0}   // true on local
function RX(e,n){return qw(e,n).source!=="auto"}

// autocompact driver
async function*aEt(e,n,r,s,d,h,b){
  ...
  if(!await TRs(e,O,D,s,h,n.agentContext))return{kind:"not_needed"};
  ...
  let Se=Fnt(O,D);                                   // window source
  if(s!==void 0&&Se!=="auto"&&LU()){                 // explicit window on local
    t(`autocompact: routing through reactive (thresholdSource=${Se})`);
    ... return {...routedThroughReactive:!0}          // <-- returns; wRs() below never runs
  }
  let xe={...}, Ae=wRs();                            // <-- the only read of the flag
  ... TZt(e,Le,r,!0,{isAutoCompact:!0,recompactionInfo:xe,stripNonEssential:Ae,...})
}

// inside the compaction itself
let Ye=!D&&P("tengu_compact_cache_prefix",!0)       // D = stripNonEssential → prefix sharing OFF when the flag is on

So on a local session:

window source TRs aEt flag read?
auto (default) returns false at LU()&&!RX — no autocompact: line is ever logged not_needed no
env / settings passes routing through reactive, returns no
remote (CLAUDE_CODE_REMOTE) passes reaches Ae=wRs() yes

A/B (2.1.270)

Forcing a compaction in claude -p with CLAUDE_CODE_AUTO_COMPACT_WINDOW=100000 (minimum accepted; effective ~80k) and a ~22k-token Read, --debug-file on, n = 1 per arm:

arm compaction request input (uncached) cache_read cache_creation
CLAUDE_CODE_COLD_COMPACT unset 25,837 ~57.8k 127–162
CLAUDE_CODE_COLD_COMPACT=1 25,837 ~57.8k 127–162

Token-identical. In both arms the compaction shows up in the debug file as Forked agent [reactive-compact] finished: ... totalUsage: with the same numbers (the session .jsonl does not record the compaction agent's usage at all; only --debug-file has it). A Haiku session with the automatic window at 181k context logged zero autocompact: lines, consistent with the early return in TRs.

Recipe:

CLAUDE_CODE_AUTO_COMPACT_WINDOW=100000 CLAUDE_CODE_COLD_COMPACT=1 \
  claude -p "Read <file of ~22k tokens> then say ok" --debug-file dbg-on.txt --max-turns 3
grep -E "autocompact:|reactive-compact" dbg-on.txt
# repeat without CLAUDE_CODE_COLD_COMPACT → same lines, same totalUsage

Expected

One of:

  1. The flag is internal / remote-only → drop it from the public env allow-list so it does not show up as a lever (it is being tried as one: Auto-compaction: two compounding cost bugs — stale precompute keeps ~200k tokens verbatim, and that prefix is repeatedly cache-created instead of cache-read #70459, and my own settings for a week), or
  2. If "cold compact" is meant to mean schedule the compaction on a request that will miss the cache anyway (gap > TTL, --resume, model switch) — that is the feature that would actually save tokens (Prompt-cache forensics from 30 real sessions: 68% of cache writes come from 36 events (TTL expiry, microcompact, resume) — with paper-backed mitigations #94177 proposal 1; 68% of cache writes in 30 sessions came from 36 such events), and today nothing implements it.

Either way, the reachable effect of the flag (prefix sharing off for the summary request) should not be tied to a name that suggests cache-aware behaviour.

Notes

  • Everything above is inferred from string constants and control flow in claude.exe; the source is not readable, so the minified names may differ between builds. The same gate (local && auto window → return false) and the reactive early return were found in 2.1.270 under other minified names (E_s()), and in 2.1.272 as quoted above.
  • Method, debug files and the jsonl analysis: https://github.com/edubraqd/lastro (report/findings.md §6).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions