Prompt cache: CLAUDE.md context is never shared across sessions because it shares a cache segment with the first user prompt
Version: 2.1.299 (macOS), first-party OAuth.
What happens
The first request of every session puts the injected context (CLAUDE.md + @imports + MEMORY.md, ~44k tokens in our setup) into messages[0] as text blocks, followed by the user's first prompt in the same message. Explicit cache_control breakpoints are only on system[1], system[2] and the last message. A second session can reuse the cached prefix only up to the end of system, or up to the end of messages[0] if that whole message matches. Since the first prompt differs between sessions, the whole context block is written to cache again on every start.
Measured (pairs of sessions, one variable changed, cache_read of the second start):
- same first prompt: 55.7k read of 78.4k
- different first prompt,
messages[0]context blocks byte-identical: 11.9k read (tools + system only) - different first prompt, same rules moved to
--append-system-prompt-file: +15k read (the appended rules), so system-level placement does share
Background sessions have a second blocker: the "# Background Session" section of the system prompt embeds the literal per-job path (jobs/<id>/tmp), so system itself differs per job and nothing after it can be shared. --exclude-dynamic-system-prompt-sections does not change that for --bg.
Suggested fix
- Put a
cache_controlbreakpoint on the last block of the injected context inmessages[0](before the user's prompt). That would be the 4th breakpoint, still within the limit. - In the Background Session section, refer to
$CLAUDE_JOB_DIRinstead of the literal path, or move the path after the context breakpoint. - Same for subagents: their CLAUDE.md context precedes the task prompt in the same message.
Impact: in our setup ~29 main-thread starts a day have a same-cwd start within the 1h TTL and re-write ~44k tokens each instead of reading them, plus subagents.