Cloud: copying the Mac's Claude/Codex login to a machine is DEV and dogfood only, card recovery included

Merged
TE
5d ago
+44-18

Leo: "IN THE ACTUAL PRODUCTION APP IT MAY BE AGAINST TOS" (copying the Mac's Claude/Codex login to a user's Cloud machine), and on 2026-11-01: "yes those are important".

What changed

  • CloudStartChat.passesHarnessLogin(isDebugBuild:setting:) is the one switch for every Mac-to-machine login transfer: setting ?? isDebugBuild. The cmux.cloud.passHarnessLogin default wins when set (true on, false off); unset, it is on in a Debug/DEV build and off in release. passesHarnessLoginHere reads it for this process. Before, a Debug build could not turn it off (isDebugBuild || optedIn).
  • AgentTabStore.cloudCredentialTransferIsAvailable now also requires the switch (isSignedIn && passesLogin). That one function feeds:
    • the handshake's cloudCredentialRecoveryAvailable (the webview card's "Transfer" offer),
    • syncCloudCredentialTransferAvailability (the native recovery callback),
    • CloudPresenter.recoverCredentials's guard (Claude setup-token and the Codex broker),
    • the new-workspace wizard's credential setup (CredentialAvailability, Claude and Codex broker).
  • cloud.startChat's pre-first-prompt pass reads the same switch.
  • Tests: the switch's full truth table (CloudStartChatLoginTests) and recovery off when the build does not pass the login (CloudCredentialRecoveryTests).

Production-config DEV build: defaults write com.cmuxterm.app.debug.next cmux.cloud.passHarnessLogin -bool NO ("cmux NEXT DEV"; a tagged DEV build uses its own com.cmuxterm.app.debug.<tag>), then relaunch. defaults delete <bundle id> cmux.cloud.passHarnessLogin returns to the build default. The NEXT nightly (com.cmuxterm.app.nightly.cmux-next) is a release build, so it is off unless set -bool YES.

Risk

Production (release) builds stop offering the Mac transfer from the card, the start-chat pass and the new-workspace setup. With it off, the card falls back to the on-machine sign-in being built in parallel (acpmux + webview card); until that lands, a release build's card shows no transfer button. The wizard then shows its existing "Provider credential setup is unavailable with this Cloud connection." note (follow-up: wording). The switch is read when availability syncs (launch, sign-in/account change), so flipping the default takes effect on relaunch.

Swift stays thin: one pure static function plus its call sites, no new logic. Minimal overlap with #29962 (held), which edits other lines of CloudStartChat+Login.swift.

Agent session: agent session

šŸ¤– Generated with Claude Code