cmux NEXT CLI: start, read, nudge and interrupt GUI agent chats; agents screenshot panes and tabs
Closed
AU
6d ago+1206+1206+0123456789012345678901234567890123456789-48-48-01234567890123456789
Fixes #23026. See also #23016 and https://github.com/manaflow-ai/cmux/pull/23085.
Agents, a Chief turn included, can now do from the CLI and MCP what a person does with Cmd-N and typing into the chat: start an ordinary GUI agent chat (harness, model, effort, mode, permissions, folder) in a given or new workspace, then read, prompt, nudge and interrupt it. Nothing moves the person's focus.
What changed
cmux agents chat new[--workspace <ws>|--pane <pane>] [--harness] [--model] [--effort] [--mode] [--policy] [--cwd] [--name] [-- <prompt>], MCPagents_chat_new.- The chat starts in the app's own acpmux. The new read-only control method
agent.acpmuxreports that socket (ControlMethod.agentAcpmuxin CmuxNextControl; AppControl only wires it). So a Chief turn, whose own acpmux is its home's, gets an ordinary chat too, never an a1/a2 subagent the app cannot attach. - The chat carries
CMUX_WORKSPACE_IDof its workspace. - The app shows it without focus: in the given pane, or the workspace's focused pane, through
agent.openSessionTab; or in a new workspace throughagent.openSessionWorkspace. - The first prompt is the chat's own message, as typed.
- The receipt names the chat, tab, pane and workspace.
opened: falsewithopen_errormeans the chat runs but no tab shows it;pendingmeans the app is still opening it.
- The chat starts in the app's own acpmux. The new read-only control method
agents chat state <chat>(MCPagents_chat_state): status, running, pending permissions, queued, harness, model, mode.agents chat interrupt <chat>(MCPagents_chat_interrupt): cancels the running turn.agents chat continue <chat> [text]: a nudge, a send whose text defaults to "Continue.".- Reaching chats in the app's acpmux:
send,read,stateandinterruptfind a chat in the caller's acpmux, else in the app's. The session-scope check is the same either way: the chat must run in a workspace of this cmux session. A send always goes through the daemon: agent-message policy, verified sender, holds and limits. Never the caller's own chat. agent.openSessionTab(base, https://github.com/manaflow-ai/cmux/pull/23492) now answerstab,pane,workspaceandworkspace_key, so a script finds the chat tab it opened.- Fixed:
agents palette openandchat newsent the app their receipt labelagentsas the origin, which the app refuses ("origin must be cli, mcp, script or remote"; part of #23016's usage.invalid). They now sendcli, ormcpfrom MCP. - Docs: a
cmux docsguide, "Start, prompt and drive another agent chat in the app", so agents find these verbs throughcmux_docs;plans/cmux-next/cli-gui-parity.md(the GUI-vs-CLI audit and the remaining gaps);plans/cmux-next/mcp.md.
Defaults I chose (no human decision was available)
- First prompt as the chat's own:
chat new's first prompt has no agent-message provenance, ascmux acp new PROMPTalready allows. Recommendation posted on #13742: https://github.com/manaflow-ai/cmux/issues/13742#issuecomment-6390595526. The alternative there: only a Chief turn's first prompt is the chat's own. - Policy limit:
--policyaccepts ask, approve-reads or deny-all. approve-edits and approve-all stay a person's choice in cmux. With no--mode, acpmux applies the machine's configured default for the harness, ascmux acp newdoes. - A retry starts another chat:
agents_chat_newtakes no idempotency key. - No tab, no chat: when the app cannot make the new workspace, the chat is ended (
_acpmux/kill), since nothing could reach it.
Superseded by the base during the merge
- Agent pane and tab screenshots: base #23983 (browser pages blacked out) replaced this branch's earlier screenshot change.
- Opening a session's chat in a pane: base
agent.openSessionTab(https://github.com/manaflow-ai/cmux/pull/23492) replaced this branch's--pane/--workspacearguments onagent.openSessionWorkspace.
Tests
cmux-tui/crates/cmux-tui/tests/cli/agents_chat_tools.rs(a real daemon and acpmux):an_agent_starts_a_chat_in_a_workspace_and_drives_it_without_the_app: env, harness, the first prompt as the chat's own, state, continue, interrupt,--pane, and the refusals (own chat, out of scope, unknown workspace, both flags,--policy approve-all).a_caller_with_its_own_acpmux_starts_and_drives_a_chat_of_the_apps_acpmux: a Chief-like caller (its own acpmux socket dead, a fake app naming the real one) starts, sends to through the daemon, reads, checks and interrupts a chat.
Packages/macOS/CmuxNext/Tests/CmuxNextAppTests/AgentSessionInUnshownPaneTests.swift(real app services and daemon):agent.openSessionTabin a pane no window shows answers its ids and leaves the window, and in a shown pane keeps the person's selected tab.
Observed / Not run
- Rust, run on the rbx builder after the merge:
cargo test -p cmux-tui --test cli agents_chat: 8/8.--test cli agent_message: 1/1.--lib cli::agent cli::mcp cli::docs cli::app: 219/219.cargo clippy -p cmux-tui --all-targets --no-deps -D warnings: clean.- It reran at the final head with the new
ghostty-nextpointer; the result is in the PR comments.
- Swift, cmux-ci steps:
961d1cc0399b99732114d717at12a01ed: ActionOriginTests, CLISurfaceParityTests and the earlier app test passed.11a078fad0a720e9466382f2at2be0f35: exit 0.- The step at the final head is in the PR comments.
- GUI dogfood: on tagged builds of this branch, in an isolated tagged app launched without focus:
- A real Claude chat, started in a workspace no window showed, answered.
- The window stayed on Home and cmux never became the active app.
chat stateshowed the chat;interruptended a long turn as cancelled;continuestarted a new turn that completed.- Not run: the Chief-flow GUI check after the app-acpmux change. The person's running copy of the tag blocked a second instance; the Rust test above covers that flow.
- Hosted cmux-tui verification: three focused runs timed out while still queued, with no verdict.
publish to R2: on the earlier head it failed with GitHub's API rate limit for attestation (infrastructure).
No capture: no visible UI changes. These are CLI/MCP verbs, a control method and an action's result fields.
Changelog
- Added:
cmux agents chat new|state|interrupt|continuestart and drive ordinary app agent chats from the CLI and MCP (a Chief included) without taking focus.
š¤ Generated with Claude Code