Description
On chained -p --resume calls, prompt caching never accumulates. The static system-prompt/tool-definition prefix caches correctly (cache_read_input_tokens is nonzero and stable), but the per-turn conversation content never gets promoted into reusable cache after being written once — every subsequent call pays the same small fresh-write cost for new turn content instead of cache_read climbing to absorb what was created in the previous call.
To be precise about what's expected vs. not: it's normal for cache_creation_input_tokens to grow a little each call, since each --resume adds a genuinely new turn that didn't exist before. What's not expected is that cache_read_input_tokens stays completely flat forever instead of increasing turn-over-turn — the content written in call N should be readable from cache in call N+1, and it never is.
Reproduction
sid=""
for word in alpha beta gamma; do
if [ -z "$sid" ]; then
out=$(claude -p "Say the word $word" --model sonnet --effort high --output-format json 2>&1)
sid=$(printf '%s' "$out" | grep -oE '"session_id":"[^"]+"' | head -1 | cut -d'"' -f4)
else
out=$(claude -p "Say the word $word" --resume "$sid" --model sonnet --effort high --output-format json 2>&1)
fi
printf '%s' "$out" | grep -oE '"(cache_creation_input_tokens|cache_read_input_tokens)":[0-9]+'
echo "---"
done
Expected
cache_read_input_tokens climbs call-over-call as prior turns' content becomes reusable cache. cache_creation_input_tokens stays small and roughly constant (just the size of each new turn), not compounding.
Actual
cache_read_input_tokens never increases past its initial value, no matter how many resumed calls happen. cache_creation_input_tokens grows by a small but nonzero amount every call — consistent with each turn's own content, but never subsequently readable from cache on the next call.
Isolation work done
Bisected across 9 plugins, 91 skills, 48 remote connectors, 5 local MCP servers, 2 personal UserPromptSubmit hooks, and nested-session env vars (desktop-app child session vs. standalone terminal) — the flat-cache_read signature is identical at every configuration, including bare-minimum (no plugins/skills/MCP/connectors). Only the baseline token count scales with how much is loaded; the qualitative non-accumulation never changes. Also confirmed in a fully standalone Terminal.app session outside any parent Claude Code process, ruling out nested-session artifacts.
Environment
claude --version: 2.1.79 (Claude Code)
- OS: macOS (Darwin)
- Invocation:
claude -p ... --resume <session_id>, one process per call, in a loop
Description
On chained
-p --resumecalls, prompt caching never accumulates. The static system-prompt/tool-definition prefix caches correctly (cache_read_input_tokensis nonzero and stable), but the per-turn conversation content never gets promoted into reusable cache after being written once — every subsequent call pays the same small fresh-write cost for new turn content instead ofcache_readclimbing to absorb what was created in the previous call.To be precise about what's expected vs. not: it's normal for
cache_creation_input_tokensto grow a little each call, since each--resumeadds a genuinely new turn that didn't exist before. What's not expected is thatcache_read_input_tokensstays completely flat forever instead of increasing turn-over-turn — the content written in call N should be readable from cache in call N+1, and it never is.Reproduction
Expected
cache_read_input_tokensclimbs call-over-call as prior turns' content becomes reusable cache.cache_creation_input_tokensstays small and roughly constant (just the size of each new turn), not compounding.Actual
cache_read_input_tokensnever increases past its initial value, no matter how many resumed calls happen.cache_creation_input_tokensgrows by a small but nonzero amount every call — consistent with each turn's own content, but never subsequently readable from cache on the next call.Isolation work done
Bisected across 9 plugins, 91 skills, 48 remote connectors, 5 local MCP servers, 2 personal
UserPromptSubmithooks, and nested-session env vars (desktop-app child session vs. standalone terminal) — the flat-cache_readsignature is identical at every configuration, including bare-minimum (no plugins/skills/MCP/connectors). Only the baseline token count scales with how much is loaded; the qualitative non-accumulation never changes. Also confirmed in a fully standalone Terminal.app session outside any parent Claude Code process, ruling out nested-session artifacts.Environment
claude --version: 2.1.79 (Claude Code)claude -p ... --resume <session_id>, one process per call, in a loop