acpmux: Claude Code's task list becomes the turn's ACP plan
Leo, watching Claude Code Desktop pin its task list under the running turn: "yo wth i want this kind of feature in cmux-next too".
The agent pane draws the turn's ACP plan as a pinned checklist (#34358). Codex already sends one (turn/plan/updated). Claude Code 2.1 does not: in -p sessions it offers no TodoWrite, and the todo tools appear only with CLAUDE_CODE_ENABLE_TODO_TOOLS=1, as TaskCreate / TaskUpdate (one task per call). So a real Claude chat never produced a plan.
What this changes (acpmux, Rust only):
agent/command.rs: Claude Code harnesses launch withCLAUDE_CODE_ENABLE_TODO_TOOLS=1unless the profile already sets it.claude_stdio/task_plan.rs(new): keeps the session's task list fromTaskCreate/TaskUpdate. A call is applied on its result, not its input, so a create gets Claude's own id, a failed call changes nothing, and results that arrive out of order apply to the call they answer. Each change sends the whole list as one ACPplanupdate (status pending / in_progress / completed;deletedremoves the task; a new subject renames it).claude_stdio/inbound.rs: holds task calls ontool_useand turns theirtool_resultinto the plan update. TodoWrite's existing mapping is unchanged.
Tests:
task_plan_tests.rs: in-order creates and updates, out-of-order results, failed or unknown calls, delete and rename, and which tools are followed.hub_integration/todo_plan.rs: a fake Claude that only uses the task tools when the env var is set; the hub sends three plan events that follow its calls.- Fleet run:
cargo test -p acpmux --lib claude_stdio164 pass,--test hub_integration todo_plan2 pass, clippy clean, rustfmt applied.
Risk: a Claude session now has the four Task tools (deferred, found through ToolSearch). They are Claude Code's own and keep their list in Claude Code's session.
Agent session: agent session
🤖 Generated with Claude Code
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Claude chats in cmux-next now draw the turn's task list as an ACP plan, matching what the agent pane already shows for Codex. acpmux launches Claude Code with CLAUDE_CODE_ENABLE_TODO_TOOLS=1 (a profile's own value wins) so its TaskCreate/TaskUpdate tools appear, and turns on Codex's update_plan tool at spawn unless the profile does.
- The list is kept from each call's result, not its input, so a create gets Claude's own id, a failed call changes nothing, and out-of-order results apply to the call they answer.
- Every change re-sends the whole list as one
planupdate:deletedremoves a task, a new subject renames it, and a subagent's task calls don't join the parent's list. - The existing TodoWrite mapping is unchanged, and the Task tools only appear when Claude Code itself offers them.