cmux NEXT: Use an API key on a chat whose Claude Code or Codex is not signed in

Merged
TE
5d ago
+130-14

Leo-ask: ask-f74602af08

Leo, 2026-10-26: "if user picks a model they don't have api key, we offer them to add credits or add their own api key"

#27058 shipped the Add Credits half, on the cmux model router's plan and credit refusals. The add their own API key half waited on key plumbing (manaflow-ai/cmuxterm-hq#5411): a key the app saved never reached a built-in harness. #30188 has since given acpmux _acpmux/agent_login/api_key. It saves a key where the agent's own CLI reads it (Claude's settings.json env.ANTHROPIC_API_KEY, or codex login --with-api-key with the key on stdin) and restarts the chat on it. Until now only Cloud chats offered it, through the Cloud sign-in card.

With this PR, a chat on this Mac whose built-in claude or codex fails a turn because it isn't signed in offers Use an API key after Sign in again, as an outlined button. It uses the same key field as the Cloud card: a password input, then Save. Send again resends the failed prompt, and only on the person's click.

  • cloudAgentLogin.ts: the shared builder is now agentLogin. cloudAgentLogin covers Cloud chats, as before. The new localApiKeyLogin covers chats on this Mac, and only the built-in claude and codex harnesses. Routes (claude-cr, claude-sr) set their own key and endpoint, so a saved key would never reach them and they get no key field.
  • TurnRows.tsx: a sign-in failure with no Cloud card renders <CloudSignIn keyOnly> after Sign in again.
  • No Rust or Swift changes. The host already allows _acpmux/agent_login/api_key on a click (AcpmuxPaneMethods.swift), and every acpmux advertises agent_login.

Once this lands, cmuxterm-hq#5411's key half is covered for local Claude Code and Codex chats. Two things stay open there: a router BYOK path, and Gemini.

Tests

bun test test/cloud-signin-card.test.tsx test/access-offer.test.tsx test/signed-out-rail.test.tsx: 30 pass. New tests cover:

  • the gating: built-in claude/codex only, never a route, a Cloud chat, a disconnected chat or an acpmux without agent_login;
  • a local signed-out card reading [Sign in again, Use an API key, …], with Save calling agent_login/api_key and Send again resending under a gesture ticket;
  • no key field on a failure that isn't a sign-in.

Observed / Not run

  • Ran: the bun tests above and scripts/web-lint.sh (fmt passed; the type-aware lint and the type check are left to CI on this host).
  • Not run: a DEV build. The card is unchanged CloudSignIn UI, and the gallery covers its states.

Changelog

  • Added: a chat whose Claude Code or Codex isn't signed in offers Use an API key next to Sign in again.

Agent session: agent session

šŸ¤– 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

Lets a chat on this Mac whose built-in Claude Code or Codex isn't signed in offer Use an API key next to Sign in again. Previously only Cloud chats offered API key sign-in; this extends it to local built-in agents through the existing _acpmux/agent_login/api_key path, saving the key where the agent's own CLI reads it and restarting the chat on it.

  • The key field matches the Cloud card's (password input, Save, then Send again resends the failed prompt on click).
  • Routes (claude-cr, claude-sr) and Cloud chats get no key field: routes set their own key and endpoint, and a Cloud chat has its own card.