acpmux: Claude Code's /context breakdown and MCP reconnect
Adopted and rebased (2026-10-25). The lane that opened this died on cmux16; hb-acpmux adopted it. The branch is now one squashed commit on feat-cmux-next plus a rustfmt-only commit. #24303 had already landed the web side (the AcpmuxContextBreakdown type, contextBreakdownOf, and the session-start test it reads), so that part is dropped here. What stays is the daemon side that produces contextBreakdown and _acpmux/mcp/reconnect. The daemon's output matches the type #24303 reads: categories[{id?, name, tokens, kind}], memoryFiles, mcpTools, optional skills, totalTokens and maxTokens. Base had changed some of the same code, so four conflicts were resolved by hand:
hub/permissions.rskeeps base'sgoal_write/mark_clearedand saves ongoal_write || breakdown_changed.hub/views.rskeepsgoalbesidecontextBreakdown.server/requests.rs: initialize lists base's extensions plusMUX_MCP_RECONNECT.docs/acpmux-schema.json: base's SessionDetail plus thecontextBreakdowntext.
The earlier "SDK schema drift checker" red was the stale merge. At this head, test_check_sdk_schema.py and check-sdk-schema.py both pass, and bun run acpmux-protocol:check is clean.
Tests at this head (fleet, cmux-ci test)
cargo fmt --checkis clean andcargo clippy -p acpmux --all-targets -D warningspasses. The first run caught three rustfmt lines; commit 7ed6a0d fixes them.cargo test -p cmux-agent-pane-policypasses (Swift and TypeScript parity included).cargo test -p acpmux: all of the PR's tests pass (claude_stdio::context_usage_tests,hub_integrationcontext_window and claude_failover,local_app_trust_gate). Three tests fail, and each fails the same way on base 337d37c:daemon_chat_openfails its open-read budget (5.3 MB against a 4 MB budget).session_pool::pooled_sessions_end_with_the_daemon_and_after_a_crashfails 3 of 3 runs on base and on head.harness_login::codex_bridge_statusis flaky: it passed 3 of 3 on rerun at both base and head.
- Webviews:
agent-pane-session-start.test.tspasses 4 of 4, andbun run typecheckfinds no errors.
Review
A fresh Codex (gpt-6-astra, xhigh) reviewed this head and said SHIP. It checked:
- that the four earlier review rounds' fixes survived the rebase (the trust gate, cleanup when a reconnect times out, breakdown persistence, the failover clear, the generation guard against a retired agent);
- the conflict resolutions;
- that the breakdown shape matches what #24303 reads.
Stop conditions: no new timer or observer. The reconnect request has a 30 s bound (RECONNECT_TIMEOUT), and its pending entry is removed when that bound runs out.
The agent pane's Inspector needs Claude Code's /context breakdown for its Context card and a way to reconnect a failed MCP server. acpmux now supplies both for Claude Code chats.
Context breakdown. When a turn ends (its result), acpmux sends Claude Code get_context_usage with detail: "summary". That mode uses the last response's usage, so it makes no token-count API calls. The request goes out after the turn's answer, so the turn never waits on it. acpmux trims the reply and keeps it on the session. _acpmux/info and attach return it as contextBreakdown. It also goes out as a session_info_update with _meta.acpmux.contextBreakdown, so an attached pane gets it live. The shape:
{"categories": [{"id": "system_prompt", "name": "System prompt", "tokens": 3000, "kind": "used"}],
"memoryFiles": [{"path": "/repo/CLAUDE.md", "type": "Project", "tokens": 120}],
"mcpTools": [{"name": "mcp__cmux__a", "serverName": "cmux", "tokens": 40}],
"skills": [{"name": "pdf", "tokens": 30}],
"totalTokens": 3900, "maxTokens": 200000}
idappears only when Claude Code gives one.kindisused,free,bufferordeferred.skillsappears only when skills take context.- Each list holds at most the 50 largest rows.
- Grid rows and colors are dropped. The raw reply is not logged; only the trimmed update is.
When Claude Code refuses the request (older CLIs answer "not supported"), the field stays null.
MCP reconnect. The new _acpmux/mcp/reconnect {sessionId, server} sends Claude Code's mcp_reconnect (serverName) to the chat's running process.
- It answers
{}on success, or with Claude Code's own error. - On success, the server's row reads
connectedinmcpServers. Watchers getsession_changedkindtools. - It never starts a process. A chat without a running Claude Code is refused, because its servers connect when it starts.
- Other harnesses are refused with
data.reason: mcp.unsupported. - Remote browsers are refused with
tools.remote, the same rule asset_tools, because reconnecting restarts the server's configured command. - New capability:
mcp-reconnect-v1. - Also updated: the docs schema, the protocol IR and the generated web method list.
Web pane. The contextBreakdown type and its reading in direct.ts already landed with the Context card in #24303, so this PR no longer carries them. It adds direct.ts reconnectMcp(server) and clears the breakdown on a failover record. cmux-agent-pane-policy and AcpmuxPaneMethods.swift list _acpmux/mcp/reconnect as a session-scoped request, so the app's pane relay forwards it.
Observed / Not run
- Observed:
scripts/web-lint.shpassed andscripts/cmux-next/prepush-gate.pyreported no new violations. Claude Code 2.1.307's own control schema shows theget_context_usagereply shape and themcp_reconnectrequest it parses. - Not run locally: cargo, per the no-local-build rule. The acpmux Rust tests (new:
claude_stdio/context_usage_tests.rsand three tests intests/hub_integration/context_window.rs) run on the fleet against this head and in PR CI. - Not run: a live Claude Code session through the pane.
No capture: acpmux protocol change, no UI
Changelog
none
Agent session: big-red
🤖 Generated with Claude Code