Skip to content

Prompt cache never hits across chained -p --resume calls, even at minimum config #91971

Description

@thebeals

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

Activity

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

    area:corearea:costbugSomething isn't workinghas reproHas detailed reproduction stepsplatform:macosIssue specifically occurs on macOS

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions