cmux NEXT model picker: every harness its own tab again (claude-sr2 models back), and Claude Code gets full model ids

AU
2d ago
+223-248

Summary

The model picker in cmux NEXT nightly (1.0.0-nightly.4093446036501, built from 6c1a5ab) regressed. This PR fixes two problems.

1. Custom harnesses lost their tab and their models. https://github.com/manaflow-ai/cmux/pull/26969 (merged 2026-10-29, 7f7d931) folded every harness that draws the Claude or Codex mark into one rail tab (canonicalHarnesses). A harness like claude-sr2, which is its own profile with icon = "claude", disappeared from the rail. It became a launch-only row inside Claude Code's tab and showed no models. Claude Code (acp), Claude Code (sr), Codex (work) and the other launch configurations went the same way.

This PR reverts https://github.com/manaflow-ai/cmux/pull/26969: the webview side is equivalent to git revert 7f7d9315343c (its two conflicts are context from later commits). It removes canonicalHarnesses, the variants block and the canonical-harnesses-* gallery states, and restores test/model-menu-started-chat-fork.test.tsx to its pre-#26969 version. The density (https://github.com/manaflow-ai/cmux/pull/27320), search grouping (https://github.com/manaflow-ai/cmux/pull/27303), Provider row (https://github.com/manaflow-ai/cmux/pull/27151), checkmark (https://github.com/manaflow-ai/cmux/pull/27232) and empty-search (https://github.com/manaflow-ai/cmux/pull/26962) fixes stay as they are.

The revert alone still left a launch configuration that is not the running harness (claude-sr2 in a Claude Code chat, Claude (work), Codex (work)) as a launch-only tab with no models, as before #26969. Now, when its own catalog entry has a model that can be picked, it is an ordinary tab that lists those models; picking one starts the chat on that harness, as picking a Codex model does. An entry with no pickable models (none listed, or its probe failed) still launches from its tab. In a started chat every other tab still forks; a launch configuration with models now shows "Fork to …" on its tab like any harness, instead of forking on the tab click.

2. GUI chats failed with "There's an issue with the selected model (opus-5-5)". A chat started with a versioned family name (opus-5-5) failed every turn, while the header still read "Claude Code · Opus 5.5". Claude Code accepts opus or claude-opus-5-5, but it sends opus-5-5 to the API exactly as typed. The session's own log shows [claude-code:unrecognized_model] {"model":"opus-5-5"} followed by a 404 model_not_found. The Claude stdio translator (claude_stdio::model_id) now passes Claude Code the full id at spawn (--model), on session/set_model and on the model config option. It does this only for opus-/sonnet-/haiku- followed by a digit. Aliases, full ids and other providers' names pass through unchanged. This applies the rule live_models::claude::launch_id already uses.

Testing

Remote runs only (rbx; this Mac had no agent-identity for cmux-ci and no Freestyle key):

  • webviews (bun 1.4.4 on rbx, lane picker-restore-27692-web, tree of c329f8d7a4): bun test test/model-menu-started-chat-fork.test.tsx test/model-menu-compact.test.tsx test/model-menu-providers.test.tsx test/signed-out-rail.test.tsx test/composer-footer-harness.test.ts: 82 pass, 1 skip (browser lane), 0 fail. New tests: claude-sr2 keeps its tab and lists its models, mounted on claude-sr2 and on claude (picking its model starts claude-sr2); a named entry with models starts from one of them; one with no models still launches from its tab; a second launch entry of one family lists its own models and starts itself.
  • Rust (rbx, lane picker-restore-27692, 51f9cccd6a): cargo test --locked -p acpmux --lib claude_stdio::tests: 19/19, including versioned_family_names_reach_claude_code_as_full_ids. Later commits touch only webviews.
  • vp fmt --check over webviews: clean.

Changelog

  • Fixed: the model picker shows every harness, including custom ones such as claude-sr2, as its own tab with its models again.
  • Fixed: a chat started with a model like opus-5-5 no longer fails every turn with "There's an issue with the selected model".

🤖 Generated with Claude Code


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


Summary by cubic

Fixes two model-picker regressions in the cmux NEXT nightly: every harness is back to its own rail tab, and versioned model names no longer fail every chat turn.

  • Each harness and launch configuration gets its own tab. A launch configuration (like claude-sr2, Claude (work), Codex (work)) whose catalog entry lists pickable models shows them on its tab, and picking one starts the chat on that harness; one with no models, or whose probe left every model disabled, still launches directly from its tab. Removes the canonicalHarnesses folding and the variants submenu; the density, search, provider, checkmark, and empty-search fixes from later PRs stay intact.
  • The Claude stdio translator now hands Claude Code full model ids (claude-opus-5-5) at spawn, on session/set_model, and on the model config option. Bare aliases (opus), full ids, and other providers' names pass through unchanged.