#1020·caveman

print mode (`claude -p`): eligible subscription requests never reach the engine, while interactive sessions compress normally

Author: asiyerrCreated Sep 9, 2026Updated Sep 17, 2026

What happen

On Claude Code subscription (OAuth), compression works in an interactive session but never engages for print mode (claude -p). Print-mode requests are counted and marked requests_eligible_for_compression, yet compression_tokens_before does not advance at all — the engine is handed nothing.

This is downstream of #908 / #929. That fix landed: subscription requests are eligible now, and recovery_via_mcp is true. The next step is where it stops.

Environment

  • macOS 26.5.1, arm64
  • @caveman-ai/cli 1.3.3, binary_release bin-v1.1.6
  • Claude Code 2.1.266
  • Claude Pro/Max OAuth, no API key — auth_mode_accounting: {"subscription": N} on every request
  • think.mode = compress (default), execute.mcp = auto (default)
  • caveman statusno off-states — everything the layer can do is on

Preflight, all green:

~/.caveman/run/8787.json  {"mode":"compress","owner":"wrap","recovery_via_mcp":true}
~/.caveman/mcp/claude.json {"tool":"caveman_retrieve","command":"~/.caveman/bin/caveman-mcp","args":[]}
claude mcp list           caveman: ~/.caveman/bin/caveman-mcp - ✔ Connected

Interactive session: compression works

Over one long interactive session, lifetime counters moved:

compression_tokens_before   543 → 11741
compression_tokens_after    535 → 10046
compression_tokens_saved      8 →  1695     (~14.4%)

Print mode: zero, five runs

Identical workload each time — read three files totalling ~250KB (~60k tokens) with the Read tool, then summarise one line each, 7–9 turns. Deltas taken by snapshotting caveman stats before and after each run:

run extra flags Δrequests Δeligible Δbefore Δsaved
A --settings ENABLE_TOOL_SEARCH=auto 16 10 0 0
B --settings ENABLE_TOOL_SEARCH=0 12 7 0 0
C --settings ENABLE_TOOL_SEARCH=auto 15 10 0 0
D --settings ENABLE_TOOL_SEARCH=0 16 9 0 0
E none — inherits normal config 18 10 0 0

Run E is the control: no --settings override at all, so the flag is not the variable. ENABLE_TOOL_SEARCH is not the variable either — with it set to 0 the caveman MCP tool schemas are in-band in the request rather than deferred, and the result is unchanged.

Across all five, ~77 requests and ~46 of them eligible produced Δcompression_tokens_before = 0. Meanwhile the same proxy, same config, same machine compressed 11,198 tokens of interactive traffic.

Repro

snapshot() { caveman stats; }
B=$(snapshot)
claude -p 'Read these three files in full: <three large files>. Then reply with
exactly one line per file. Use only the Read tool.' --allowed-tools Read
sleep 6
A=$(snapshot)
jq -n --argjson b "$B" --argjson a "$A" \
  '{requests:($a.requests-$b.requests),
    eligible:($a.requests_eligible_for_compression-$b.requests_eligible_for_compression),
    before:($a.compression_tokens_before-$b.compression_tokens_before),
    saved:($a.compression_tokens_saved-$b.compression_tokens_saved)}'

Deltas matter here — compression_tokens_before is a lifetime counter, so reading it raw after a fresh session shows the same stale number and looks like "no change" in every arm.

Hypothesis, unverified

#929 proves recovery per request from the caveman_retrieve tool carried in the request. I have not confirmed whether a claude -p session presents its MCP tool list to the provider identically to an interactive one. If print mode differs there, the per-request recovery proof would fail while eligibility — computed earlier — still passes, which matches exactly what the counters show.

Not a problem

Two things I checked that turned out fine, in case they save someone else the work:

  • Routing through the proxy costs no prompt-cache hits. Same workload alternated proxy vs direct, provider-reported usage: hit rate 69.8% proxy vs 69.2% direct, cost within $0.001, latency within noise. cache_bust_requests advancing does not correspond to lost cache reads.
  • The PreToolUse shrink hook works normally in print mode; this is specific to the engine path.