pingdotgg / pingdotgg/t3code

[Bug]: Stop still kills the Claude CLI and `--resume`s, so every Stop rewrites the full prompt cache (not covered by #10689)

Open
#10,955 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

accepted bug via-triage
Dominant language
TypeScript
Stars
23k
Forks
5.9k
Avg merge
11h 14m
Merged PRs (30d)
357

Description

Before submitting
  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Closest existing reports: #10600 (closed by #10689, which only fixed the idle-reaper clock and says "Claude cache invalidation after a genuine restart is unchanged"), #7338 (closed, asked for hard evidence), #8997 (the interrupt-instead-of-close fix, closed unmerged). This is the Stop half of #10600 that the triage there listed as still forcing a --resume.

Area

apps/server

Steps to reproduce
  1. Start a Claude Code thread and let it run a few tool calls so the context is a few tens of thousands of tokens.
  2. Press Stop while a tool call is running.
  3. Within the cache lifetime (I waited two minutes) send a follow-up in the same thread.
  4. Open ~/.claude/projects/<project>/<session-id>.jsonl and compare cache_read_input_tokens / cache_creation_input_tokens on the assistant messages before and after the Stop.
Expected behavior

Stop interrupts the in-flight turn and keeps the CLI process, so the follow-up continues with the same prompt prefix and hits the cache. This is what native Claude Code does on Esc: it appends [Request interrupted by user] and the process stays up.

Actual behavior

Stop goes through interruptTurnstopSessionInternalquery.close() in apps/server/src/provider/Layers/ClaudeAdapter.ts (the code comment calls Stop a hard session boundary). The next message --resumes a new process and the whole prompt is re-sent as a cache write.

Per-turn usage from the transcript, deduplicated by message id:

Time Event cache_read cache_creation
14:59:33 last turn before Stop 66,247 1,839
15:01:34 Continue from where you left off. meta + <synthetic> reply 0 0
15:01:44 first turn after follow-up 0 75,181
15:02:01 next turn 75,181 628

One Stop rewrote 75k tokens that were cached two minutes earlier. That single turn cost more than the rest of the six-minute session combined, and it scales with thread length. The idle reaper was not involved (two-minute gap), so #10689 does not touch this path.

An extra trigger beyond the git status one in anthropics/claude-code#78720: with the follow-up message the resumed process received a deferred_tools_delta adding claude.ai connector tools (Gmail) and a mcp_instructions_delta appending Linear / Notion / PostHog instruction blocks. Connectors reconnecting late in the fresh process change the system prompt by themselves, so the miss happens even in an untouched repo.

Impact

Major degradation or frequent failure

Version or commit

0.0.41-nightly.20260909.1439 (includes #10689)

Environment

macOS 27.0.0, T3 Code Nightly desktop. Bundled Claude Code 2.1.266 (entrypoint: sdk-ts). Model claude-fable-5-1. Claude subscription, 1-hour prompt cache.

Logs or stack traces
14:59:33 assistant cache_read=66247 cache_creation=1839
15:01:34 user (isMeta) "Continue from where you left off."
15:01:34 assistant model=<synthetic> "No response requested."
15:01:38 user "fetch latest from gh, ..."
15:01:38 attachment deferred_tools_delta addedNames=[mcp__claude_ai_Gmail__..., ...]
15:01:38 attachment mcp_instructions_delta addedNames=["claude.ai Linear","claude.ai Notion","claude.ai PostHog"]
15:01:44 assistant cache_read=0 cache_creation=75181
15:02:01 assistant cache_read=75181 cache_creation=628

Full transcript lines available on request.

Workaround

Don't press Stop. Disabling cloud connectors in Claude Code settings (disableClaudeAiConnectors: true) removes one source of prompt mutation but not the restart itself.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/server/src/provider/Layers/ClaudeAdapter.ts and trace interruptTurn through stopSessionInternal to query.close(), then inspect how the next message uses --resume. Reproduce the Stop and follow-up sequence with the transcript cache metrics; done means Stop interrupts the turn without closing the CLI process and the follow-up preserves the cached prompt prefix.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.