cmux-next: honest Claude Reasoning menu: resolved default, Ultracode switch, no Ultrathink (cx-ervhd)
The Reasoning menu for Claude didn't match what Claude Code does with each choice. On a fresh chat the chip said Low with no row checked, even though Claude was really running its default level. Ultrathink was listed as an effort level, but all it did was prefix every prompt with a keyword. Ultracode was listed as a level too, though it's a separate Claude Code setting (workflow orchestration at Extra High). Muse, a terminal-only harness, also showed up in the model rail. The full audit is cx-ervhd.
After this change:
- Default resolves to a real level. When a session runs Claude's default, the chip names that level (for example "Medium") and the menu checks that row with a small "Default" hint. The level comes from the model's catalog row, which is now found through aliases and variant ids like
claude-opus-5-5[1m]. Picking a level after that sends it as before. The menu no longer falls back to the first row, and a label that couldn't be resolved is never saved to chip memory. That fallback was where "Low" came from; Low was never actually sent. - Ultracode is an On/Off switch in the Reasoning menu. It's shown only when the model offers Extra High. acpmux reports its state as a separate
ultracodeoption and sendsapply_flag_settings {effortLevel: xhigh, ultracode: true}. The pane switches it through the freeeffortoption (ultracodefor On,xhighfor Off), so the app never confirms it with a mode sheet. Picking a plain level turns it off, and a respawn keeps it on. Turning it off leaves the chat on Extra High. - Ultrathink is gone from the effort list, and acpmux no longer rewrites prompts. A saved
ultrathinkpick runs Claude's default level instead. People can still type the keyword themselves. - Fast mode is shown only for models whose catalog row allows it.
- New chats show the level acpmux will start them on before the session reports back. The same hunk is in the New Tab fix #20577; whichever of the two lands second will pick it up in its base merge.
- Terminal harnesses keep
kindthroughnormalizeCatalog, so Muse leaves the rail. Greying out signed-out harnesses needs acpmux auth detection and is tracked separately (cx-ae9eb).
Evidence
-
cmux-tui/crates/acpmux/tests/claude_reasoning.rsruns against fake Claude Code and records the argv and everyapply_flag_settingsit receives. -
webviews/test/claude-reasoning-default.test.tsplays two gallery variants in the browser lane:- the default effort on a
[1m]model id reads "Medium" and is checked with a Default hint, with no Ultrathink row; - a new chat shows "Medium" before its session attaches.
This PR's react-apps-check runs it on the head. I didn't record a separate red run for this file.
- the default effort on a
-
webviews/test/ultracode-rides-effort.test.tsx(jsdom) mounts the real picker and records what it sends. It was red on 14df3d7 (ultracode=on,ultracode=off) and is green on 463b34d (effort=ultracode,effort=xhigh). That commit came from the review subagent: the first version picked acpmux's ownultracodeid, which the Swift transport confirms with a "Switch mode" sheet. -
The crash ratchet and the Rust god-file check pass on the head.
-
Leo (via coordinator): a correctness fix, merge on the gate.
Fast mode now follows the catalog row's fast flag. A live model with probed efforts and no catalog row of its own keeps no Fast row unless fast mode is already on.
Beads for follow-ups: cx-ae9eb (signed-out rail), cx-z3dra (fast-mode cooldown), cx-42wql (Opus 4.7 default effort and the gallery xhigh fixture), cx-ch019 / cx-5n4f5 (Codex service tier and plan mode).
Changelog
- Fixed: The Claude Reasoning menu now shows the real default level instead of "Low", has Ultracode as an On/Off switch, and no longer lists Ultrathink as an effort level.
Tagged DEV builds on macOS 27 (cosmic-gray), each run with an isolated fake home: stub harnesses only (a fake Claude Code listing made-up models, a fake codex that reports "Not logged in", a terminal-only "muse"), no real credentials or chats. The location chip shows the build host's name. Base is feat 8ae8e3b; head is this PR at c144f6d (before its last base merges, which don't touch these surfaces). The pair also differs in base-only ways: base's rail has "Add harness…", and head's composer has the "Trusted this chat's…" chip that squeezes the effort chip to "Medi…".
Light: base | head. Reasoning menu: base lists Ultracode and Ultrathink as levels; head checks "Medium · Default", has an Ultracode On/Off group and no Ultrathink. Model rail: base has Muse; head doesn't.

Dark: base | head.

Clip (light, head): open Reasoning, turn Ultracode On (the chip names Ultracode), then Off (the chat stays on Extra High).

Full quality:
Earlier dark capture with real Claude Opus 5.5 chats (base b35b1c6 above, head 3dc336b below):

🤖 Generated with Claude Code