Repository navigation
Chief: your own turns never ask; approvals are opt-in, Stop ends the turn, and an approval is a card - #22640
Merged
Conversation
…how a card (red) The owner's own turns (a cmux chief CLI message, a turn that reads Home, by default a paired phone) must run without approvals; in a gated turn the Chief's own tools never wait, a stop ends the turn, a denied request is not asked again, a newer message leaves a pending approval alone, and the approval is a readable card. Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=e8f63fd9-94e8-4878-bcd4-704659aba1f2&host=cosmic-gray
…nce and ask with a card Every Chief turn waited for approvals since 10-20: the host reads the Home view on every turn and e68aa1b gated every such turn, so a `cmux chief -p` message from the same Mac (user_local over the owner socket, local origin) asked for each effect, Chief's own tell and send included, and remote.autoApprove could not lift it. The text blamed a paired device. - Home view and paired-device gates are opt-in settings, default off: home.ask ("Ask before acting on what Home shows") and remote.ask ("Ask before acting on requests from other devices"); remote.autoApprove true still wins. Another participant's turn always asks. - The Chief's own tools (send, reply, react, stop, sleep, profile, spawn, tell/control without a prompt) never wait; tell/control with a prompt to an approve-all subagent still asks in a gated turn. - chief.stop cancels the session even while a call waits for its approval and denies every later request of the turn at once. A request denied once is denied again without a new card; three repeats stop the turn. - A newer message no longer denies a pending approval. - The approval is a question card: "Allow Chief to run `rm -rf target`?", the reason and pretty-printed arguments, Allow once and Deny, answered by question.answer (owner only) or allow/deny text; two plain lines when the owner refuses the part. Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=e8f63fd9-94e8-4878-bcd4-704659aba1f2&host=cosmic-gray
Contributor
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
web and size checks: green |
This comment has been minimized.
This comment has been minimized.
Collaborator
Author
|
Bead |
…nt controls; side cards answer Review fixes for the approval gates: - In a turn that asks, send with attachments, profile writes or undo, and control actions other than status, interrupt without a message and answer deny ask, unless they target an ask-policy subagent. - A card answered in a side conversation settles its approval there; a card answers only in the conversation it was posted in. - Another participant's answer closes the card, so the owner gets a fresh one. - A turn stopped for repeating a denied request posts one line saying so. - No gate can be loosened while a turn asks. - The card's line marks line breaks and cuts, its code span survives backticks, and the text form carries the arguments. Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=e8f63fd9-94e8-4878-bcd4-704659aba1f2&host=cosmic-gray
Collaborator
Author
|
|
austinywang
added a commit
that referenced
this pull request
Oct 21, 2026
#22640 made the owner's turns never ask, the Chief's own tools never wait, Stop end a waiting turn, and the approval a question card. On its code this keeps only what it does not cover: - An answer acpmux refuses (an allow without the person's proof: a chat reply, a card answered on another device) keeps the approval with a fresh card and says why; one acpmux no longer holds is settled, and a chat answer moves on to the next approval. - A refused auto-allow of the Chief's own tool in an ask turn asks the person with a card instead of leaving the turn waiting. - The Mac Home card (Allow / Deny, answered as the person) renders #22640's card as is: same item and option ids. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
Shipped in:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Since 10-20, every Chief turn waits for approval before each local effect. That includes the owner's own
cmux chief -pon the same Mac and Chief's owntellandsend. Four problems stack on top of that:remote.autoApprovedoesn't lift the gate.cmux chief stopdoesn't end a turn whose tool call is waiting.The CLI was not the cause.
cmux chief -psends asuser_localover the owner socket, which is local origin. The cause is e68aa1b: it gates every turn that reads the Home view, and the host reads Home on every turn (host.rsalways setshome_view). The bubble blamed "a paired device" only because that text is hard-coded. a4bbe5d had also made asking the default for paired devices.What changes
Gates are opt-in. Two new per-Chief settings, both off by default:
remote.ask("Ask before acting on requests from other devices")home.ask("Ask before acting on what Home shows")With both off, the owner's turns from this Mac, from the CLI and from their paired phone run like local turns.
remote.autoApprove: truestill wins overremote.ask. A turn where another participant wrote always asks, which covers the shared-Chief case. The host refuses to loosen a gate during remote-origin work.Chief's own tools never wait. That covers
send,reply,react,stop,sleep,profileandspawn. A child spawned in a gated turn still gets the ask floor.tellandcontrolalso run without asking when they carry no prompt. In a gated turn, atell, or acontrolthat carries a message or an answer, still asks unless the target subagent runs withaskitself. That way a gated turn can't pass a command through an approve-all subagent.Stop means stop.
chief.stopcancels the session even while a tool call is waiting for approval (Interrupt::request_hard). Every later request in that turn is denied at once. If the model repeats a request that was already denied, it is denied again without a new card; after three repeats the turn is stopped. A newer message no longer denies a pending approval.A readable approval card. The approval is now a conversation
questionpart. It shows "Allow Chief to run `rm -rf target`?", a reason line ("Started from Leo's iPhone: …"), the arguments pretty-printed as a monospace preview, and Allow once / Deny buttons. The owner answers withquestion.answer(only the owner's answer counts) or by typingallowordeny. If the owner refuses the part, the same two lines go out as plain text. No JSON appears in the chat.Who added the gate
Lawrence added the paired-device gate on 2026-10-05 (0654733, default ask). He made auto-approve the default on 10-06 (8f1b5b9: "i dont want stuff to require my approval"). On 10-20 his security hardening made asking the default again (a4bbe5d) and gated every turn that reads Home (e68aa1b), because terminal titles, screens and URLs are text an attacker can write. All three went straight to
feat-cmux-next; none came through a PR.Takes back a4bbe5d and e68aa1b (both pushed directly on 10-20): together they put an approval in front of every effect of every owner turn, Chief's own messages included. Leo decided on 10-20 that the owner's own devices run like the Mac by default. Both protections stay available as opt-in settings.
Security analysis (risk:high)
home.askoff, text in the Home block reaches every turn and runs with the owner's policy, as it did before 10-20.home.askon restores the 10-20 behavior.remote.askon puts approvals back.send,replyandreactpost only to the conversation that asked.sendcan attach local files, but in a non-owner turn the participant already reads that conversation (residual risk).spawnget the ask floor.tellandcontrolwith a prompt still ask for approve-all targets.Tests
Command:
cmux-ci run --class isolated --script scripts/ci/cmux-tui-rust-check.sh --arg optchat-chief --ref <sha>(optchat-chief tests, then clippy -D warnings, then fmt).Red commit d5e3840 (new tests only, on base): 8 of the 10 new
approval_gatestests fail. The two guard tests (home.askon,remote.autoApprovewins) already pass on base.The base also fails four existing tests:
crash::a_pending_turn_and_its_items_survive_a_restart_in_the_databasedaemon_workspaces::a_subagent_workspace_is_located_by_its_public_id_and_sessionturn_seal_binding::a_subagent_cannot_reach_owner_controls_on_the_shared_socketremote_policy::a_non_owner_turn_asks_and_only_the_owner_may_approve_itHead 30b89d3:
approval_gates(10) andremote_policy(9) pass.What
tests/approval_gates.rschecks:home.askturns the Home gate on. By default a paired-device turn runs like a local one.remote.askgates a device turn, andremote.autoApprovewins over it. The gate can't be loosened during remote work.tellto an approve-all subagent still asks.question.answerallows the call.tests/remote_policy.rsnow runs withremote.askon, and its default-case test is flipped.Observed / Not run
questionpart as its prompt plus "1. Allow once / 2. Deny" text.MessagesLabHome/Cmux/HomeMapping.swiftfalls back to text, andAgentQuestionCardViewisn't wired to the custom-row seam yet. The Claude-desktop-style card with buttons, the ⌘↵ hint and the answered receipt is a follow-up UI PR. This PR only emits the data that card needs.--chief-homeon a nightly build. Leo's Chief stays stopped.backend/) keep their own policy, and the shared corpusremote_auto_approvecases are unchanged.Changelog
cmux chiefCLI, Home, your paired phone). Asking on requests from other devices or on Home text is now opt-in, Stop ends a turn that is waiting on an approval, and an approval shows as a short card instead of raw JSON.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Chief turns no longer wait for approval unless you opt in: your own turns from the CLI, from Home, and from your paired phone run like local turns by default, with
remote.askandhome.askoff.chief.stopnow ends a turn even while a tool call waits, a denied request isn't asked twice, and approvals appear as a card with Allow once / Deny instead of raw JSON.Key changes
remote.askgates paired-device turns,home.askgates turns that read Home text;remote.autoApprovestill wins, and another participant's turn always asks.sendwithout attachments,reply,react,stop,sleep,profilereads,spawn, andtell/controlwithout a prompt) never wait; in a gated turn,sendwith attachments,profilewrites, andtell/controlwith a prompt still ask unless the target subagent runs withaskitself.chief.stopcancels the session even while a tool call waits, and a request denied once is denied again without a new card; three repeats stop the turn with one line saying so.questioncard with a reason line, pretty-printed arguments, and Allow once / Deny; only the owner's answer counts, a newer message never answers a pending card, and a card answered in a side conversation settles the approval posted there.Written for commit 27a018c. Summary will update on new commits.