Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
A. Inherited environment
- Quit T3. From a terminal inside a Claude Code session (
CLAUDECODE=1,CLAUDE_CODE_ENTRYPOINT=claude-desktop), runopen -a "T3 Code (Beta)". - Start two Claude threads in the same project with the same short prompt.
- Check the transcripts: entrypoint is
claude-desktop, and each new thread writes 16k to 19k tokens of 1-hour cache.
B. MCP servers connecting late (also with a clean launch)
- Have at least one MCP server that connects in a second or more (a claude.ai connector is enough).
- Start three Claude threads with the same prompt.
- Compare the first user message of each transcript: the deferred-tool list differs between threads, and each thread writes about 13k to 17k tokens of cache on its first request.
Expected behavior
A new thread in the same project with the same settings reuses the cached prompt prefix. How T3 was started and how fast MCP servers connect do not change the prompt.
Actual behavior
A. The Agent SDK copies process.env, so the spawned Claude Code runs with the parent session's CLAUDE_CODE_ENTRYPOINT=claude-desktop, CLAUDECODE=1, CLAUDE_EFFORT, session id and messaging socket and token. The SDK only sets sdk-ts when the entrypoint is empty.
B. With Claude Code's default non-blocking MCP connect, which servers are connected at the first request varies, so the tool list in the prompt varies per thread.
Measured on one project, question task, Sonnet 5.5, three new threads each:
| Setup | Entrypoint | Cache written per new thread |
|---|---|---|
| inherited env | claude-desktop | 16k to 19k each |
| env scrubbed | sdk-ts | 24.3k, 17.6k |
env scrubbed + MCP_CONNECTION_NONBLOCKING=false |
sdk-ts | 17.3k (first), then 1.7k, 1.3k |
Startup context was identical in the last three threads (34,504 tokens); wall time did not grow (22 to 25 s).
Impact
Major degradation or frequent failure
Version or commit
T3 Code 0.1.2 (macOS arm64), Claude Code 2.1.310
Environment
macOS 27.0.1, Apple silicon
Logs or stack traces
From two consecutive threads, the first user message differs only in the deferred-tool list: one thread lists the mcp__claude_ai_Claude_Docs__* tools, the next lists mcp__t3-code__* tools that had not connected in the first.
Workaround
Point the Claude instance at a wrapper through providerInstances.<id>.config.binaryPath. The wrapper unsets the host-session variables when it detects them (CLAUDE_CODE_HOST_SESSION_ID or CLAUDE_CODE_DESKTOP_APP_VERSION set), resets CLAUDE_CODE_ENTRYPOINT to sdk-ts, exports MCP_CONNECTION_NONBLOCKING=false, then execs claude.
Suggested fix: build the provider env from an allowlist, or drop CLAUDECODE, CLAUDE_CODE_ENTRYPOINT, CLAUDE_CODE_SESSION_ID, CLAUDE_CODE_HOST_SESSION_ID, CLAUDE_CODE_MESSAGING_*, CLAUDE_EFFORT and the other desktop-host CLAUDE_CODE_* values before spawning. For B, pass MCP_CONNECTION_NONBLOCKING=false (or wait for MCP servers before the first request), since new-thread cache reuse is worth more than a faster first token.
Part B looks related to #5605 (late MCP servers missing from SDK sessions); the cache side of it is what we measured here.
Found in real use, while benchmarking our own agents.
Written with Claude Code (Claude Opus 5.5).
Activity
634634624 commentedon Oct 27, 2026
Measurements
Same machine, same day, Claude Sonnet 5.5 at low effort, Claude Code 2.1.310.
1. Harness benchmark (n=20 per harness)
4 coding and code-reading tasks × 5 rounds, each run a new session or thread, all 60 runs passed a hidden check. Token numbers come from the native Claude Code transcripts.
*Cost proxy: $2 / $10 per MTok input / output, 1-hour cache write 2×, cache read 0.1×. The repeated cache write alone is about $0.071 per run, roughly 85% of the gap between T3 and the CLI.
2. Control without any app
env -i HOME=… PATH=… claude -p "Reply with the single word OK." --model claude-sonnet-5-5 --effort low --output-format json, alternating plain andCLAUDE_CODE_ENTRYPOINT=claude-desktop, warm cache:CLAUDE_CODE_ENTRYPOINT=claude-desktop, 3 repeatsMCP_CONNECTION_NONBLOCKING=false, first, then 2 repeatsSo the inherited entrypoint alone makes every new session write ~16k tokens even with nothing else changed: the
claude-desktopsystem prompt carries a per-session part. The MCP setting changes the prefix once and is then stable; in-pmode both variants are stable, the per-thread drift appeared only in the SDK-driven app sessions.3. Inside T3 after the fix
Question task, three new threads each, T3 pointed at a wrapper (
binaryPath):MCP_CONNECTION_NONBLOCKING=falseStartup context was 34,504 in all three of the last threads; wall time stayed at 22 to 25 s.
4. Environment inheritance
CLAUDECODE=1 CLAUDE_CODE_ENTRYPOINT=claude-desktop BENCHMARK_MARK=x open -a TextEdit(and the same with a small probe app that writes its own environment to a file): all three variables show up in the launched app's environment. That is the path by which an agent-launched app gets the parent session's values.Not measured: OpenBot after a clean launch (only T3 was re-measured with the fix).
t3dotgg commentedon Nov 2, 2026
The large cache cost came from the inherited
claude-desktopentrypoint, fixed in #28410. #29169 stops Claude from inheriting the rest of the launching session. On Claude Code 2.1.316 a late MCP server adds about 200 tokens, so we are not making the first message wait for MCP servers.