Skip to content

cmux NEXT composer: Return steers a running turn, ⌘Return queues - #22741

Merged
teamleaderleo merged 5 commits into
feat-cmux-nextfrom
cmux/steer-default
Oct 21, 2026
Merged

teamleaderleo merged 5 commits into
feat-cmux-nextfrom
cmux/steer-default

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Leo asked for steer by default, as in Claude Code desktop. The installed nightly still said "↵ to queue, ⌘↵ to steer", and Return queued behind the running turn.

What changes (agent pane composer, webviews only)

  • For an agent that steers (summary.steering, which is every claude-stdio chat), Return while a turn runs steers: the prompt goes into the running turn, and the agent reads it when its current step ends. Nothing is cancelled. This works in the chat composer, the Quick Composer, and with only attachments staged.
  • ⌘Return queues the prompt for after the turn.
  • Placeholder while a turn runs: "↵ steer · ⌘↵ queue". The Quick Composer (its ⌘Return opens the window) and an attachments-only prompt say "Steer this turn…".
  • Tooltips: the Send button, which queues mid-turn, now names ⌘Return (composer.queueLaterTooltip). The steer control now names Return.
  • Agents that can't steer keep their current keys: Return queues, ⌘Return stops the turn and sends.
  • Strings: composer.placeholderSteer is reworded, and composer.placeholderSteerQuick and composer.queueLaterTooltip are new. All are translated into the catalog's 21 locales (state needs_review, like the strings next to them).

Coordinated: composer-polish (#22667) leaves the running-turn placeholder and keys to this PR. Its agentPane.sendWhileRunning setting will rebase onto the returnSteers boolean here. prompt-queue-edit (#22736) is fixing the acpmux side, so every claude-stdio session reports steering=true after a daemon restart. Until that lands, an adopted chat whose steering is false keeps the old keys. Follow-up from this lane: the pending-steer marker, plus a "Send now" button that interrupts.

Tests

  • bun test test/composer-queued-placeholder.test.tsx. Commit 1 (f7c32b7) is red on base: Return sent steer: false, ⌘Return sent steer: true, and the placeholder read "↵ to queue, ⌘↵ to steer". Commit 2 makes it green: 9 pass. It also covers non-steering agents keeping Return to queue and ⌘Return to interrupt.

Behavior changes to dogfood

  • Option-Return used to add a line through WebKit's default. Now it sends or steers like Return. Shift-Return still adds a line.
  • Dictation's "new line" / "new paragraph" voice commands probably arrive as insertParagraph / insertLineBreak, so they would send the half-dictated prompt. If dogfood shows that, narrow the beforeinput catch to a Return right after a keyCode 229 keydown.

Observed / Not run

  • Ran: the bun test above (9 pass), vp fmt and oxlint on the changed files.
  • Independent review subagent: PASS (read-only).
  • CI on 3e60472: the only red is cmux-next guards / defaults-snapshot, which is red the same way on feat-cmux-next runs (39529089308, 39528884211).
  • Not run locally: the full bun run check (type check, layer checks) and the browser lanes. Leo's Mac is at load ~30, and git in the shared checkout is wedged, so I committed from a fresh clone without the pre-push hook. CI's web lint and react-apps-check cover them.
  • Not dogfooded in a build yet.

Changelog

  • Changed: In agent chats, Return while the agent is working now steers the running turn (it reads your message when its current step ends); ⌘Return queues the message for after the turn.

🤖 Generated with Claude Code

Agent session: cosmic-gray


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Makes steering the default while an agent's turn runs, matching Claude Code desktop. Return sends the prompt into the running turn (the agent reads it when its current step ends, nothing is cancelled), and ⌘Return queues the prompt for after the turn.

  • Works in the chat composer, the Quick Composer, and with only attachments staged.
  • Nothing sent stops a turn anymore: agents that can't steer queue on both keys and have no Interrupt control.
  • Placeholder while a turn runs is "↵ steer · ⌘↵ queue" ("Steer this turn…" in the Quick Composer), and the Send button's tooltip names ⌘Return for queueing.
  • New and reworded strings are translated into the catalog's 21 locales.
  • Return never adds a line, even when an input method or Dictation passes it on as keyCode 229: the paragraph input sends or steers instead, and Shift-Return is unchanged.

Written for commit 3e60472. Summary will update on new commits.

View guided diff Turn on auto-fix

teamleaderleo and others added 2 commits October 20, 2026 18:42
…n queues

Red on base: the composer queues on Return and steers on ⌘Return, and the
placeholder says "↵ to queue, ⌘↵ to steer".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bc7-bd7c-70a2-b2fa-5da6fc16b908&host=cosmic-gray
Leo: steer on by default, as in Claude Code desktop. For an agent that steers
(every claude-stdio chat), Return mid-turn goes into the running turn: the agent
reads it when its current step ends, and nothing is cancelled. ⌘Return queues it
for after the turn. The Quick Composer and an attachments-only prompt steer on
Return too. The placeholder says "↵ steer · ⌘↵ queue" ("Steer this turn…" in
the Quick Composer), the Send button's tooltip names ⌘Return for queueing, and the
steer control's names Return. Agents that cannot steer keep Return queueing and
⌘Return interrupting. 21 locales.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bc7-bd7c-70a2-b2fa-5da6fc16b908&host=cosmic-gray
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 3e60472: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr22741 -f ref=cmux/steer-default -f platform=macos -f backend_mode=local

Probably yours: composer-turn-cycle.test.ts, composer-turn-cycle.test.ts fails here but not on main's latest full suite. Seen on other PRs too (likely flaky): composer-row-rhythm.test.ts, composer-row-rhythm.test.ts, agent-pane-background-tasks.test.ts. This PR merged before its CI finished: fix forward on main.

CI failed on 3e60472ea8 (run 39529534286 attempt 1): 2 code, 2 unknown.

Job Verdict Why
web / react-apps-check (4) code a web test failed
web / react-apps-check (2) code a web test failed
web / react-apps-check (1) unknown no known signature; failed step: Fail on the gate checks
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • seen on other PRs composer-row-rhythm.test.ts at 760 px (light): one gap in a group, one between groups, Send at the edge: failed (job)
  • seen on other PRs composer-row-rhythm.test.ts at 760 px (dark): one gap in a group, one between groups, Send at the edge: failed (job)
  • seen on other PRs agent-pane-background-tasks.test.ts clicking a background task's end opens its terminal beside the chat: failed (job)
  • new in this PR composer-turn-cycle.test.ts at 420 px typing while the turn runs moves neither the mic nor Send: failed (job)
  • new in this PR composer-turn-cycle.test.ts at 720 px typing while the turn runs moves neither the mic nor Send: failed (job)
Matched log lines
web / react-apps-check (4): (fail) at 760 px (light): one gap in a group, one between groups, Send at the edge [31924.60ms]
web / react-apps-check (2): (fail) clicking a background task's end opens its terminal beside the chat [932.48ms]

Not re-run automatically: web / react-apps-check (4), web / react-apps-check (2), web / react-apps-check (1), web / react-apps-check are not machine failures.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: web / Web status; base red: the same failure on the base ff8d849; does not block
red: web / react-apps-check; base red: the same failure on the base ff8d849; does not block
red: web / react-apps-check (1); base red: the same failure on the base ff8d849; does not block
red: web / react-apps-check (2); NEW: green on the base ff8d849; do not merge until green; see lane-rules
red: web / react-apps-check (4); NEW: green on the base ff8d849; do not merge until green; see lane-rules

Tour of 3e60472ea8 (run): no media. The tour did not run: only webview code changed (8 path(s)), which the gallery advisory run checks in Linux Chromium on the pull request (its artifact holds any captures); add the media-tour-mac label to tour it on a Mac.

teamleaderleo and others added 3 commits October 20, 2026 18:46
Leo: no Stop & send anywhere. Exactly Claude Code desktop's two keys: Return
steers (read at the next step, no cancel), ⌘Return queues. Only Stop and Esc
stop a turn.

- A steer no longer carries _meta.acpmux.interrupt, so a chat whose steering
  reads false (an adopted session) queues it instead of cancelling the turn.
- An agent that cannot steer queues on Return and ⌘Return, shows no Interrupt
  control, and its placeholder says "Queue a follow-up".
- ⌘Return queues an attachments-only prompt too, so it gets the full hint.
- The interrupt strings go from the catalog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bc7-bd7c-70a2-b2fa-5da6fc16b908&host=cosmic-gray
…nds, never adds a line

Red: Leo's dictated prompt got a new line on Return (agent working, three
queued). The 229 Return reaches no key handler and WebKit inserts the paragraph.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bc7-bd7c-70a2-b2fa-5da6fc16b908&host=cosmic-gray
…od passes it on

Leo (d5829ff): a dictated prompt, the agent working, three queued; Return
inserted a new line instead of sending. macOS Dictation and IMEs hand the
Return that ends their text over as keyCode 229, which every key handler
(the composer's, ProseMirror's) leaves to the input method, and WebKit then
inserts the paragraph. MarkdownField now takes that paragraph input
(onReturnInput) instead of inserting it, and the composer runs Return on it:
send or steer, or pick the open menu's command. Shift-Return's line comes
from the keymap and is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bc7-bd7c-70a2-b2fa-5da6fc16b908&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-k9j8t created for this PR by the cmux coordinator.

@teamleaderleo
teamleaderleo marked this pull request as ready for review October 21, 2026 01:56
@teamleaderleo
teamleaderleo merged commit 184c4e5 into feat-cmux-next Oct 21, 2026
@teamleaderleo
teamleaderleo deleted the cmux/steer-default branch October 21, 2026 01:56
@blacksmith-sh

blacksmith-sh Bot commented Oct 21, 2026

Copy link
Copy Markdown

Found 2 test failures on Blacksmith runners:

Failures

Test View Logs
test/agent-pane-background-tasks.test.ts/agent-pane-background-tasks.test View Logs
test/agent-pane-background-tasks.test.ts/agent-pane-background-tasks.test View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…e again (react-apps-check red)

react-apps-check is red on every feat-cmux-next push since #22741 and #22667
landed together, and since #22636:

- #22741 draws the ↵ steer control only for an agent that reports acpmux
  `steering`; the composer-row and turn-cycle gallery fixtures never set it, so
  composer-row-rhythm and composer-turn-cycle wait 30 s for .acpmux-steer-now
  and time the file out. Both fixtures are Claude Code chats, which steer.
- With ↵ drawn in #22667's plain footer, Stop follows it and both add an
  inset: steer→Stop 16 px against Stop→mic 10 px. ↵ drops its trailing inset
  when Stop follows it, so the three draw one gap apart.
- #22636 removed the Background task note's "Show output" tooltip
  (tooltip-rules); the test still read it. The click test stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c2c-330d-7e83-8d27-d0125af4e8a9&host=huge-blue
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…e again (react-apps-check red) (#22833)

react-apps-check is red on every feat-cmux-next push since #22741 and #22667
landed together, and since #22636:

- #22741 draws the ↵ steer control only for an agent that reports acpmux
  `steering`; the composer-row and turn-cycle gallery fixtures never set it, so
  composer-row-rhythm and composer-turn-cycle wait 30 s for .acpmux-steer-now
  and time the file out. Both fixtures are Claude Code chats, which steer.
- With ↵ drawn in #22667's plain footer, Stop follows it and both add an
  inset: steer→Stop 16 px against Stop→mic 10 px. ↵ drops its trailing inset
  when Stop follows it, so the three draw one gap apart.
- #22636 removed the Background task note's "Show output" tooltip
  (tooltip-rules); the test still read it. The click test stays.


Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c2c-330d-7e83-8d27-d0125af4e8a9&host=huge-blue

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Shipped in:

@github-actions

Copy link
Copy Markdown
Contributor

Shipped in:

teamleaderleo added a commit that referenced this pull request Oct 22, 2026
… never adds a line

macOS Dictation, like an input method, passes Return on as keyCode 229 with
key "Enter". The composer leaves every 229 key to the input method, so
ProseMirror's keymap read it as Enter and split the paragraph; the keydown was
prevented, so the paragraph input #22741 turns into Return never came. The
field now keeps that key from the keymap: the Return that commits a
composition stays the input method's, and any later one is Return.

Leo-ask: ask-810c88dec0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray
teamleaderleo added a commit that referenced this pull request Oct 23, 2026
…24090)

* test(composer): Return after Dictation sends, never adds a line (red)

Leo-ask: ask-810c88dec0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray

* test(composer): each Return test is its own chat

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray

* test(composer): a passed-on Return adds no line

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray

* fix(composer): a Return Dictation or an input method passes on sends, never adds a line

macOS Dictation, like an input method, passes Return on as keyCode 229 with
key "Enter". The composer leaves every 229 key to the input method, so
ProseMirror's keymap read it as Enter and split the paragraph; the keydown was
prevented, so the paragraph input #22741 turns into Return never came. The
field now keeps that key from the keymap: the Return that commits a
composition stays the input method's, and any later one is Return.

Leo-ask: ask-810c88dec0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray

* fix(composer): one passed-on Return sends once, keydown or paragraph

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray

* test(composer): Shift-Return right after an IME commit Return sends nothing (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray

* fix(composer): the IME commit Return goes to ProseMirror, which clears its Safari guard

The 229 commit Return just after compositionend was kept from ProseMirror's
keydown, which is what clears its after-composition guard; a quick
Shift-Return then reached the browser and its paragraph input sent the draft.
Let ProseMirror take that key, treat composing.current as composing, and only
take a plain (unmodified) 229 Return.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16027-99fc-73f0-9482-5a4babfe1b0a&host=cosmic-gray

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant