cmux NEXT composer: Codex keeps its fast-mode bolt left of the mic; Claude's Fast mode stays in the model menu
Merged
TE
15d ago+942+942+012345678901234567890123456789-43-43-01234567890123456789
Leo, on his nightly: "There must be ONE button, "Opus 5.5 Medium", that opens one menu ... Never a separate "Reasoning ⌄" dropdown", and "the lightning (fast mode) symbol: REMOVE it for Claude, where Fast mode lives inside the menu. KEEP it for Codex."
How we got here:
- #20946 (4ba5e791989, 10-15, "reasoning is its own clickable control on New Tab and new chats") brought the separate effort chip back. That is the regression Leo saw.
- #22800 (a3e14d3a9e0, 10-21 00:08) was the partial fix: one model button, Fast mode as a menu row, no effort chip. It also took the bolt (#20964) away from every harness, Codex included.
- Leo's nightly is built from 03960f5 (10-20 23:29), which predates #22800, so it still shows the Reasoning chip and the bolt for Claude.
What this PR changes on top of #22800:
- Codex keeps its bolt in the box, just left of the mic. The chat composer and the New Tab box both draw it, in either footer look. The model button's menu (and the full picker) has no Fast mode row for Codex, because the bolt is its control.
- Claude has no bolt. Fast mode stays the last checkbox row of the model button's menu.
- The bolt is restyled: a plain 16 px outline glyph in muted ink, the soft pill only on hover or keyboard focus, the theme accent (
--agent-accent) when on. Ultrafast no longer fills the glyph and there is no disc. It never drops out of a narrow row (it is Codex's only speed control), the same as the mic. - Codex is detected by
summary.familyor the harness id (/codex/i), so a second Codex profile also gets the bolt. If a Codex chip has no composer to draw the bolt, Fast mode stays in its menu, so the speed is never unreachable. - The bolt's five strings (
composer.speedLabel,composer.speedTooltip,picker.tierStandard|Fast|Ultrafast) are restored from before #22800 in all 21 locales. That is the +660 lines inLocalizable.xcstrings: nothing was regenerated.
Checked on every surface, and nothing else needed changing:
- Chat (Composer.tsx), New Tab (
NewTabComposerChips), and Quick Composer (QuickSurface renders the same Composer). All of them render throughDefaultComposerChips→ComposerPickers→ModelPicker→QuickModelMenu: one button and one menu (harness rail, numbered models, Effort ›, More models ›, Account ›, then Fast mode). On base, nothing rendersEffortPicker. - Home/Chief: the webview Home composer has no model controls. The native Chief settings popover (Lawrence's fe0e57b3e1c, with a Speed row) is a settings form, not a composer, so I left it alone.
Changelog
- Fixed: Codex chats show the fast-mode bolt again, just left of the mic; Claude chats keep Fast mode in the model menu and show no bolt.
Regression test
cd webviews && bun test test/composer-fast-toggle.test.tsx (run on huge-blue)
- Red on base: test file at head with
webviews/srcfrom the merge base 011b0146dfd: 2 fail, 6 pass. The two Codex bolt tests fail because no.acpmux-fastrenders. - Green on head 6aace33e8c9: 8 pass, 0 fail.
- (a) Claude and Codex: no
.acpmux-effortchip, and no button except the model button names the effort. - (b) The bolt renders for a Codex snapshot with a fast option, left of the mic, as an outline glyph, and steps through the tiers. It does not render for Claude.
- (c) Claude's menu ends on the Fast mode row. Codex's menu has none.
Observed / Not run
- Observed, on huge-blue at 6aace33e8c9:
bun test test/composer-fast-toggle.test.tsx test/model-menu-compact.test.tsx test/composer-row-fit.test.ts test/agent-options-menu.test.tsxgave 37 pass, 0 fail. - Observed: gallery frames for
agent-pane.composerreasoning-codex and reasoning-claude, before and after (headless Chromium):- Codex after: an outline bolt just left of the mic, and the reasoning-codex play passes.
- Codex before: no bolt, Fast mode as a menu row.
- Claude: identical before and after (no bolt, Fast mode row checked). The reasoning-claude play reports a failure on both base and head, so that failure is not from this change.
- Not run:
bun run checklocally (cosmic-gray's hook forbids it; the pre-push web lint ran on push and passed), the full webview suite, any Mac build.
No capture: webview-only change; gallery compare https://cmux-lawrences-mac-mini.tail137216.ts.net:18796/compare/composer-look-model-button/?entry=agent-pane.composer (variants reasoning-codex, reasoning-claude)
Agent session: cosmic-gray
🤖 Generated with Claude Code