acpmux: Claude Code's task list becomes the turn's ACP plan

TE
2d ago
+337-4

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 with CLAUDE_CODE_ENABLE_TODO_TOOLS=1 unless the profile already sets it.
  • claude_stdio/task_plan.rs (new): keeps the session's task list from TaskCreate / 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 ACP plan update (status pending / in_progress / completed; deleted removes the task; a new subject renames it).
  • claude_stdio/inbound.rs: holds task calls on tool_use and turns their tool_result into 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_stdio 164 pass, --test hub_integration todo_plan 2 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
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 plan update: deleted removes 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.