Skip to content

Cloud: a new chat's machine gets the person's own Claude login before the first prompt (DEV builds) - #29771

Merged
teamleaderleo merged 11 commits into
feat-cmux-nextfrom
cloud-harness-login-first-send
Nov 1, 2026
Merged

teamleaderleo merged 11 commits into
feat-cmux-nextfrom
cloud-harness-login-first-send

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Leo, on a Cloud chat that never replied: "whenever i start a chat it should be able to send me to cloud automatically", "A TOKEN GETS PASSED", "IN THE ACTUAL PRODUCTION APP IT MAY BE AGAINST TOS SO THAT'S WHY IT'S DIFFERENT", "WE ALL HATE SETTING UP ENVIRONMENTS".

The bug

A chat started on a Cloud machine got its prompt but never replied. Read on two production machines (image cmux-devbox 2026-10-28-r1):

  • fs-firstsend-exercise: the persisted model plane held only the OpenAI pair, so there was no CodeRouter origin. The launcher resolved team / team-unknown with no endpoint and no key, and claude -p printed "Not logged in · Please run /login".
  • A fresh machine: it reached CodeRouter, but the team's pooled Claude account answered "OAuth token revoked".
  • The personal-login fallback (Cloud: confirmed owner-only provider credential transfer #26139, fix(cmux-next): recover Cloud agent authentication safely #26148) never ran on either. It runs only as recovery after a failed prompt, and its installer refused every machine whose guest vm-kind is team. That is every machine a person creates on a team with other members, the creator's own included.

What changes (DEV and dogfood builds)

  • cloud.startChat passes the person's own Claude login to the chat's machine before the first prompt (CloudStartChat+Login.swift). It runs alongside the folder copy and is awaited before the chat opens.
    • When cmux already holds this account's claude setup-token login (the Keychain cache from Cloud: confirmed owner-only provider credential transfer #26139), it installs with no prompt.
    • Otherwise one confirm runs setup-token once in a visible local terminal. Every later machine of the account then gets it silently.
    • A machine that already has a login is left alone. A teammate's machine, a cancel or a failure opens the chat anyway, and the turn card still offers recovery.
    • Gated to a Debug build or the explicit cmux.cloud.passHarnessLogin default. Production keeps today's sign-in design (the terms concern above).
  • Who may receive a login: the platform's answer, as for Codex, and an owner guest. CloudCredentialTransfer now checks the caller's attach answer (vmKind == "owner", or a Worker machine's owner link; CloudService.callerOwnsVM) before any credential is read and again before delivery, the rule the Codex broker already uses. The guest must also still be an owner machine (/etc/cmux/vm-kind): on a team guest every member's terminal runs as the same Unix user and could read a personal login. cloud.startChat checks the guest's kind before it asks anything, so a team machine (its creator's included) gets no confirm and no login; it keeps the turn card's recovery. Team machines are follow-up Cloud harness login follow-ups from #29771: rebaked image guard, model-plane clobber, Codex first chat #29774.
  • Launcher (agent-auth.sh), own mode with no CodeRouter origin also drops a stale model-plane pair (a CodeRouter URL with the placeholder key), so an own login is never sent to that endpoint. A user's own endpoint with their own key stays. The image source awaits its rebake (awaiting-rebake.json).
  • Launcher (agent-auth.sh): no CodeRouter origin means own mode (no-team-plane), never an empty team plane. Claude then uses a delivered login or shows its own sign-in.

Codex is unchanged: its login is per machine, through the broker's device login (#26211). The alternative that keeps the token on the Mac, a model relay, is scoped in #29766 and not built.

Risk

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

Fixes Cloud chats that started but never replied: a chat's machine now receives the person's own Claude login before the first prompt, in DEV and dogfood builds only.

Old behavior: the launcher fell back to an empty team plane, leaving Claude "Not logged in" or on a revoked team account, and the personal-login fallback only ran as recovery and refused every machine whose guest vm-kind is team.

  • cloud.startChat installs the person's claude setup-token login before the chat opens, for chats with a project and chats without one. A cached login installs silently; otherwise one confirm runs setup-token once in a visible local terminal, and later machines of the account get it with no prompt. The account is re-checked after the login's wait. Automation may dismiss the confirm but never press Set Up, like the other credential dialogs.
  • cloud.startChat probes the guest's own vm-kind first and skips a team guest before any confirm: teammates share its Unix user, so the transfer would refuse it anyway. Delivery stays limited to owner machines.
  • CloudCredentialTransfer authorizes delivery by the platform's answer to the caller's attach request (vmKind == "owner", or a Worker machine's owner link), as the Codex broker already does, checking before any credential is read and again before delivery.
  • The launcher resolves a machine with no CodeRouter origin to own mode (no-team-plane), so Claude uses a delivered login or shows its own sign-in instead of an empty team plane. Own mode also drops a stale model-plane pair (a base URL with the placeholder key) when there is no origin, so a delivered login never reaches that endpoint.

Production keeps today's sign-in design and Codex is unchanged; this is gated to Debug builds or the explicit cmux.cloud.passHarnessLogin opt-in. The launcher change awaits an image rebake.

Written for commit da28d10. Summary will update on new commits.

View guided diff Turn on auto-fix

… (DEV builds)

Leo: "A TOKEN GETS PASSED". A chat started on a Cloud machine never replied:
the launcher fell back to an empty team plane ("Not logged in"), and the
personal-login transfer ran only as recovery and refused every creator-owned
team machine on its guest vm-kind.

- cloud.startChat installs the person's cached claude setup-token login (one
  confirm the first time) before the chat's first prompt; Debug builds or the
  cmux.cloud.passHarnessLogin opt-in only.
- CloudCredentialTransfer authorizes on the caller's attach answer
  (vmKind == "owner", #28788), as the Codex broker does; the installer no
  longer reads the guest's vm-kind.
- agent-auth.sh: no CodeRouter origin means own mode (no-team-plane).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review da28d10: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr29771 -f ref=cloud-harness-login-first-send -f platform=macos -f backend_mode=local

Seen on other PRs too (likely flaky): vm-machine-hygiene.test.ts also failed on other PRs before this one; check whether it is this PR's before re-running. This PR merged before its CI finished: fix forward on main.

CI failed on da28d1029f (run 41256650989 attempt 1): 1 code.
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped.

Job Verdict Why
web / Web tests (3/4) code a web test failed

Failures:

  • seen on other PRs vm-machine-hygiene.test.ts cmux-machine-hygiene > keeps an artifact directory the repository tracks: failed (job)

A web test can import code this PR changes without being one of its files: python3 scripts/ci/web_test_verdict.py --pr 29771 --file web/tests/vm-machine-hygiene.test.ts checks its import graph (on Linux, in a sandbox) and its failures on other branches.

Matched log lines
web / Web tests (3/4): (fail) cmux-machine-hygiene > keeps an artifact directory the repository tracks [8.99ms]

Not re-run automatically: web / Web tests (3/4) is not a machine failure.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: web / Web status; a job it gathers is red on this change (its line here); do not merge until green; see lane-rules
red: web / Web tests (3/4); no finished base run on 07efced to compare; do not merge until green; see lane-rules

Default changes

This pull request changes 2 defaults at da28d1029f54 (what everyone gets without configuring anything):

  • tunable-source.CmuxNextApp/Cloud/CloudPresenter.swift:firstLoginIdentifier: (none) -> "08cc8c9db9730d3a52652d1495f7f2478b7d11f4b5884fad4d6b658394c75654"
  • tunable-source.CmuxNextApp/Control/DebugDialog.swift:userOnly: "520db8f42a15ed84f881e5706b276e137c46462d12e3c80e3fdea6f57729825f" -> "46d93efd6999f06afdaa4e3826eaa690d51efdbfb4b71933ebfc078ececff199"

Needs a review. It passes with an independent review receipt on this commit: a comment or review whose first line is Review (<reviewer>): SHIP at da28d1029f5456ee8d3f82177236aaa652186f08, from a member, not a self-review (the newest verdict naming the head decides; a later BLOCK beats an earlier SHIP), or with an approving review on this commit from @lawrencecchen or @austinywang (the call owners in .github/defaults-call-owners.json, never the author). A receipt posted as a review re-runs this check; after a plain comment, re-run it. The needs a call label alone does not pass, and a new push needs a new receipt.

Merge receipt: merged as 115359799cc5 with these defaults changed, WITHOUT a SHIP receipt or an approving call owner review on its head.

Regenerate the snapshot with python3 scripts/ci/defaults_guard.py snapshot.

Shipped in:

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
…ance is the DEV first chat's only

Review (gpt-6.1-sol, BLOCK at 1c5016b): teammates on a team machine run as the
same Unix user, so the production recovery path keeps requiring an owner guest.
Only cloud.startChat's DEV/opt-in login passes creatorTeamMachine. The account
is checked again after the login's wait.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
@cursor

cursor Bot commented Oct 31, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

…required

Two reviews (gpt-6.1-sol at 1c5016b, gpt-6-astra at 1e2624f) block a personal
token on a team guest, where teammates share the Unix user. That allowance moves
to its own held PR for Leo's security call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
…ss-login-first-send

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudStartChat.swift
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Awareness note from an agent lane that does not own this PR; it is not a review or a request to take the PR over.


Awareness from the Cloud E2E verifier: #29771 fixes the missing Claude login path, but its runHome path still opens with cwd: nil. On a fresh no-project chat this can hit app.folder_needed or inherit a machine workspace before the first prompt, as tracked by #29143. Please keep #29143/#29624 as a required follow-up for the exact fresh-chat state used by the E2E capture. The helper should be tested together with an explicit machine-folder fix before claiming CLOUD_OK.

…r origin

A machine that persisted only the OpenAI pair has a CodeRouter URL and no
CMUX_CODEROUTER_URL. In no-team-plane own mode, a base URL paired with the
placeholder key is the model plane's and is dropped, so an own login never
reaches that endpoint. A user's own endpoint with their own key stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
@teamleaderleo teamleaderleo removed the risk:high Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026
The transfer's preflight refuses a guest whose /etc/cmux/vm-kind is not
owner (teammates share its Unix user), so a creator's team machine could
only end in that refusal after the first-login confirm. Probe the guest's
kind first and skip there; team machines are cmux#29774.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol xhigh, router-review): BLOCK at e014d05

BLOCK at e014d05

Visual verdict: no images; Leo tries the build

  1. [P1] [blocking] Automation can approve credential-transfer consent. CloudPresenter.swift:192 uses firstLoginIdentifier, which is absent from DebugDialog.userOnly. In Debug builds, debug.dialog can therefore press setUp, satisfying consent for installing and caching the year-long Claude login. Existing credential dialogs prohibit this. Add the identifier to the protected set and verify automated approval is rejected.

  2. [P2] [follow-up] Copy failures wait for the login dialog to close. CloudStartChat.swift:108 starts login as an async let. If copying throws while confirmation is pending, scope exit cancels and awaits that child, but CmuxDialogCenter.present ignores cancellation. The failure remains hidden until someone answers the unrelated dialog. Dismiss the confirmation when its task is cancelled.

  3. [P2] [follow-up] First-login dialog lacks visual evidence. CloudPresenter.swift:186 adds a confirmation dialog without screenshots.

Validation: 26 launcher cases passed through a Node/Babel adapter; shell syntax checks passed. Swift compilation was unavailable.

Follow-ups:

@teamleaderleo teamleaderleo removed the risk:high Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026
Automation (debug.dialog) may dismiss it, never press Set Up: the confirm
caches and installs a year-long Claude login, as the other credential
dialogs already guard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="web/tests/vm-devbox-agent-auth.test.ts">

<violation number="1" location="web/tests/vm-devbox-agent-auth.test.ts:681">
P2: This setup never exercises the persisted-only model-plane fallback described by the test, so the regression can remain broken while this test passes. Remove both OpenAI variables from `env` so `agent-config.sh` must source `m.modelPlane` before the launch.</violation>
</file>

<file name="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Handlers/CloudHandlers+Account.swift">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Handlers/CloudHandlers+Account.swift:168">
P2: This wizard path has no DEV or opt-in gate, yet the new `callerOwnsVM` argument adds a platform owner check to production credential transfers. Confirm that is intended, or gate it, since the PR describes production as unchanged.</violation>
</file>

<file name="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudStartChat.swift">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudStartChat.swift:108">
P2: The login task is still running when `run()` throws, and Swift waits for it at scope exit. If the copy fails while the `Set Up Claude` confirm is open, the failure toast and the page's error reply wait for the user to answer it. Await the login only on the success path, or cancel it on the failure paths and make `confirmFirstLogin` dismiss its dialog on cancellation, as `presentCodexDeviceCode` does.</violation>
</file>

<file name="web/services/vms/images/devbox/agent-auth.sh">

<violation number="1" location="web/services/vms/images/devbox/agent-auth.sh:189">
P2: The no-origin test in `cmux_agent_drop_model_plane_env` (`-z "$cmux_aa_origin"`) does not match the https-only test in `cmux_agent_auth_resolve`. A non-https `CMUX_CODEROUTER_URL` puts the launch in own mode as `no-team-plane`, but the placeholder-paired base URL rule never applies, so the model-plane URL can survive into own mode. Gate both on the same https check so the no-origin rule covers every case the resolver treats as no-team-plane.</violation>
</file>

<file name="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudStartChat+Login.swift">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudStartChat+Login.swift:54">
P2: `machineLoginProbe` checks the wrong home on classic `/api/vm` machines, so existing Claude logins are missed and may be unnecessarily replaced. Run the probe with the launcher user’s `HOME=/home/cmux`/`CLAUDE_CONFIG_DIR` (or switch to `cmux`) before calling `cmux_agent_has_own_login`.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

// ("Not logged in"). With no origin there is no team plane to choose.
const m = machine();
const env = bootEnv(m);
for (const name of ["CMUX_CODEROUTER_URL", "ANTHROPIC_BASE_URL", "ANTHROPIC_API_KEY"]) delete env[name];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This setup never exercises the persisted-only model-plane fallback described by the test, so the regression can remain broken while this test passes. Remove both OpenAI variables from env so agent-config.sh must source m.modelPlane before the launch.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At web/tests/vm-devbox-agent-auth.test.ts, line 681:

<comment>This setup never exercises the persisted-only model-plane fallback described by the test, so the regression can remain broken while this test passes. Remove both OpenAI variables from `env` so `agent-config.sh` must source `m.modelPlane` before the launch.</comment>

<file context>
@@ -672,6 +672,47 @@ describe("the default for every agent", () => {
+    // ("Not logged in"). With no origin there is no team plane to choose.
+    const m = machine();
+    const env = bootEnv(m);
+    for (const name of ["CMUX_CODEROUTER_URL", "ANTHROPIC_BASE_URL", "ANTHROPIC_API_KEY"]) delete env[name];
+    const result = await runChild("/bin/bash", ["-c", `. ${m.config}; ${m.launchers.claude} --resume x`], { env });
+    expect(result.status).toBe(0);
</file context>
Suggested change
for (const name of ["CMUX_CODEROUTER_URL", "ANTHROPIC_BASE_URL", "ANTHROPIC_API_KEY"]) delete env[name];
for (const name of ["CMUX_CODEROUTER_URL", "ANTHROPIC_BASE_URL", "ANTHROPIC_API_KEY", "OPENAI_BASE_URL", "OPENAI_API_KEY"]) delete env[name];

try await transfer.run(api: cloud.machineAPI, currentTeamID: { cloud.auth.teamID },
currentUserID: { cloud.auth.user?.id }, confirmed: true)
currentUserID: { cloud.auth.user?.id }, confirmed: true,
callerOwnsVM: { [machineID = session.machineID] in try await cloud.callerOwnsVM(machineID) })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This wizard path has no DEV or opt-in gate, yet the new callerOwnsVM argument adds a platform owner check to production credential transfers. Confirm that is intended, or gate it, since the PR describes production as unchanged.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextApp/Handlers/CloudHandlers+Account.swift, line 168:

<comment>This wizard path has no DEV or opt-in gate, yet the new `callerOwnsVM` argument adds a platform owner check to production credential transfers. Confirm that is intended, or gate it, since the PR describes production as unchanged.</comment>

<file context>
@@ -164,7 +164,8 @@ extension CloudHandlers {
                 try await transfer.run(api: cloud.machineAPI, currentTeamID: { cloud.auth.teamID },
-                                       currentUserID: { cloud.auth.user?.id }, confirmed: true)
+                                       currentUserID: { cloud.auth.user?.id }, confirmed: true,
+                                       callerOwnsVM: { [machineID = session.machineID] in try await cloud.callerOwnsVM(machineID) })
             }
         }
</file context>

try Self.checkAccount(account, now: services.cloud.account, listCurrent: services.cloud.hasLoadedCurrentMachines)
// The chat's harness login (DEV and dogfood builds, +Login): it runs alongside the copy and is
// awaited before the chat opens, so its first prompt starts signed in. It never fails the start.
async let loginPassed = passHarnessLogin(start, machine: machine)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The login task is still running when run() throws, and Swift waits for it at scope exit. If the copy fails while the Set Up Claude confirm is open, the failure toast and the page's error reply wait for the user to answer it. Await the login only on the success path, or cancel it on the failure paths and make confirmFirstLogin dismiss its dialog on cancellation, as presentCodexDeviceCode does.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudStartChat.swift, line 108:

<comment>The login task is still running when `run()` throws, and Swift waits for it at scope exit. If the copy fails while the `Set Up Claude` confirm is open, the failure toast and the page's error reply wait for the user to answer it. Await the login only on the success path, or cancel it on the failure paths and make `confirmFirstLogin` dismiss its dialog on cancellation, as `presentCodexDeviceCode` does.</comment>

<file context>
@@ -103,6 +103,9 @@ struct CloudStartChat {
         try Self.checkAccount(account, now: services.cloud.account, listCurrent: services.cloud.hasLoadedCurrentMachines)
+        // The chat's harness login (DEV and dogfood builds, +Login): it runs alongside the copy and is
+        // awaited before the chat opens, so its first prompt starts signed in. It never fails the start.
+        async let loginPassed = passHarnessLogin(start, machine: machine)
         let size = AgentPaneCloudStart.sizeText(machine.machine.size)
         report(.init(name: "folder", folder: folderName, machine: name, size: size))
</file context>

fi
case "${CMUX_CODEROUTER_URL-}" in
https://*) ;;
*) cmux_agent_auth_mode=own; cmux_agent_auth_reason=no-team-plane; return 0 ;;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The no-origin test in cmux_agent_drop_model_plane_env (-z "$cmux_aa_origin") does not match the https-only test in cmux_agent_auth_resolve. A non-https CMUX_CODEROUTER_URL puts the launch in own mode as no-team-plane, but the placeholder-paired base URL rule never applies, so the model-plane URL can survive into own mode. Gate both on the same https check so the no-origin rule covers every case the resolver treats as no-team-plane.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At web/services/vms/images/devbox/agent-auth.sh, line 189:

<comment>The no-origin test in `cmux_agent_drop_model_plane_env` (`-z "$cmux_aa_origin"`) does not match the https-only test in `cmux_agent_auth_resolve`. A non-https `CMUX_CODEROUTER_URL` puts the launch in own mode as `no-team-plane`, but the placeholder-paired base URL rule never applies, so the model-plane URL can survive into own mode. Gate both on the same https check so the no-origin rule covers every case the resolver treats as no-team-plane.</comment>

<file context>
@@ -180,6 +184,10 @@ cmux_agent_auth_resolve() {
   fi
+  case "${CMUX_CODEROUTER_URL-}" in
+    https://*) ;;
+    *) cmux_agent_auth_mode=own; cmux_agent_auth_reason=no-team-plane; return 0 ;;
+  esac
   if cmux_agent_team_access "$1"; then cmux_aa_rc=0; else cmux_aa_rc=$?; fi
</file context>


/// The probe for a login already on the machine: the image's own detection, with its config
/// sourced as the launcher does. Exits 0 when Claude has its own sign-in there.
static let machineLoginProbe = ". /etc/cmux/agent-config.sh >/dev/null 2>&1; . /etc/cmux/agent-auth.sh && cmux_agent_has_own_login claude"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: machineLoginProbe checks the wrong home on classic /api/vm machines, so existing Claude logins are missed and may be unnecessarily replaced. Run the probe with the launcher user’s HOME=/home/cmux/CLAUDE_CONFIG_DIR (or switch to cmux) before calling cmux_agent_has_own_login.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudStartChat+Login.swift, line 54:

<comment>`machineLoginProbe` checks the wrong home on classic `/api/vm` machines, so existing Claude logins are missed and may be unnecessarily replaced. Run the probe with the launcher user’s `HOME=/home/cmux`/`CLAUDE_CONFIG_DIR` (or switch to `cmux`) before calling `cmux_agent_has_own_login`.</comment>

<file context>
@@ -0,0 +1,93 @@
+
+    /// The probe for a login already on the machine: the image's own detection, with its config
+    /// sourced as the launcher does. Exits 0 when Claude has its own sign-in there.
+    static let machineLoginProbe = ". /etc/cmux/agent-config.sh >/dev/null 2>&1; . /etc/cmux/agent-auth.sh && cmux_agent_has_own_login claude"
+
+    /// Gives the start's machine the person's Claude login when this build passes it. Returns
</file context>
Suggested change
static let machineLoginProbe = ". /etc/cmux/agent-config.sh >/dev/null 2>&1; . /etc/cmux/agent-auth.sh && cmux_agent_has_own_login claude"
static let machineLoginProbe = "HOME=/home/cmux CLAUDE_CONFIG_DIR=/home/cmux/.claude; export HOME CLAUDE_CONFIG_DIR; . /etc/cmux/agent-config.sh >/dev/null 2>&1; . /etc/cmux/agent-auth.sh && cmux_agent_has_own_login claude"

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 15 files

View guided diff | Turn on auto-fix | Re-trigger cubic

@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026
…ss-login-first-send

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextApp/Control/DebugDialog.swift
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at 15f2609

Reviewer: codex gpt-6-astra high, fast tier.

Follow-ups: 2. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at 15f2609

Visual verdict: no images; Leo tries the build

  1. [P1] [follow-up] CloudStartChat.swift:108 starts the login with async let, so a copy failure implicitly cancels and then awaits it. If the login task is waiting on the modal confirmation, cancellation does not dismiss CmuxDialogCenter.present; the chat-start error can remain blocked indefinitely until the user answers the unrelated login dialog.

  2. [P2] [follow-up] CloudStartChat+Login.swift:69 has a race for concurrent first chats. Both starts can observe no cached login and no machine login, queue separate confirmations, and each run claude setup-token; the promised one-time confirmation is not enforced.

Follow-ups:

  • Make login cancellation dismiss its confirmation and avoid awaiting it indefinitely when the folder copy fails.
  • Serialize or coalesce first-login setup per account so concurrent starts share one confirmation and setup-token run.

@teamleaderleo
teamleaderleo merged commit 1153597 into feat-cmux-next Nov 1, 2026
106 of 119 checks passed
@teamleaderleo
teamleaderleo deleted the cloud-harness-login-first-send branch November 1, 2026 00:27
@blacksmith-sh

blacksmith-sh Bot commented Nov 1, 2026

Copy link
Copy Markdown

Found 3 test failures on Blacksmith runners:

Failures

Test View Logs
test_a_picked_signing_label_has_a_rerun_alternative (main.RunsOnFallbackTests.test_
a_picked_signing_label_has_a_rerun_alternative)/
test_a_picked_signing_label_has_a_rerun_alternative (main.RunsOnFallbackTests.test_
a_picked_signing_label_has_a_rerun_alternative)
View Logs
test_the_nightly_is_covered (main.NightlyStepCoverageTests.test_the_nightly_is_cove
red)/
test_the_nightly_is_covered (main.NightlyStepCoverageTests.test_the_nightly_is_cove
red)
View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at da28d10

Reviewer: codex gpt-6-astra high, fast tier.

Follow-ups: 2. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at da28d10

Visual verdict: no images; Leo tries the build

  1. [P1][follow-up] CloudStartChat.swift:108 starts the login as an async let. If copying or the account check fails, Swift cancels and awaits that task. confirmFirstLogin then waits on CmuxDialogCenter.present (CloudPresenter.swift:193), whose continuation is not cancellation-aware, so the start can hang indefinitely until the user answers the login dialog. Make cancellation dismiss the dialog.

Follow-ups:

  • [P1][follow-up] Make the first-login confirmation cancellation-aware.
  • [P2][follow-up] No after screenshots were supplied for visual comparison.

teamleaderleo added a commit that referenced this pull request Nov 2, 2026
…(DEV builds) (#29962)

* Cloud credential transfer: DEV builds pass the login to the creator's team machine

Every machine on a team account has guest kind "team", including one Leo just
made, so #29771's first-chat login and the "Transfer and restart" recovery both
end in "Personal credentials can only be transferred to a Cloud machine you
own." In DEV and dogfood builds (cloud.startChat's existing gate), a team guest
whose creator is the caller (the platform's vmKind == "owner" answer, still
checked before and after the login) may take the login. Production keeps
requiring an owner guest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5

* credential recovery: the restart accepts the creator's team guest under the same DEV allowance

Review (router-review, SHIP at 2997fae, P1 follow-up): the transfer installed on a
team guest but the restart still required an owner guest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — da28d102 Deployed Nov 1, 2026 by teamleaderleo via wait for same-key tree publisher #92281
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:high Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant