print mode (`claude -p`): eligible subscription requests never reach the engine, while interactive sessions compress normally
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/cli1.3.3,binary_releasebin-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 status→no 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_requestsadvancing does not correspond to lost cache reads. - The
PreToolUseshrink hook works normally in print mode; this is specific to the engine path.
Source: JuliusBrussee/caveman