Skip to content

cloud.startChat: one workspace per small Cloud machine - #30020

Merged
teamleaderleo merged 3 commits into
feat-cmux-nextfrom
cloud-one-workspace-per-machine
Nov 1, 2026
Merged

teamleaderleo merged 3 commits into
feat-cmux-nextfrom
cloud-one-workspace-per-machine

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

Leo, 2026-10-31: "and we ofc wanted to have the thing be having snapshots of whatever vms to do the right-sizing... and also austin/lawrence said indeed we wanted 1 workspace per vm for now / i guess they're relatively smol vms / but anyways we ideally also can just hide the machines too and it's just a cloud button"

This PR is the "1 workspace per vm for now" part, in cloud.startChat's pick (Rust, cmux-tui). Spec: leo-workspace design/cloud.md, "One workspace per small machine, snapshots, and a Cloud button".

What changed

  • pick::destination: after the pinned-send check (a retry stays on its first try's machine) and the workspace's own machine check, a workspace with no machine, or a send from no workspace, gets Destination::New. An existing machine is never reused for a new workspace.
  • pick::claim binds a machine to a workspace only when that workspace has none yet and no other workspace of the account has it; plan and pin go through it, so a machine bound to workspace A is never bound to workspace B (a retry of A's send from B still runs on A's machine but does not give it to B).
  • pick() and its ranking (free, marked-for-chats, lane-pool, idle-paused) became dead and are removed, with the Candidate fields only it read (slug, pause_reason, chats; serde ignores them from the App).
  • The ledger still holds many workspaces per machine (Ledger::held_by_another added); the one-per-machine limit is the pick's policy, so sharing can come back there alone. Ledgers written under cloud.startChat: a Mac workspace keeps the Cloud machine it picked; workspaces reuse and share machines #29532 that already share a machine across workspaces keep those bindings (their chats are on it).
  • New machines keep the cloud-chats-N name (plan has only the workspace id, not its name).

Supersedes the reuse/share behaviour of #29532 and #29582 (merged; Leo's earlier "go arbitrarily many"). Austin's open #26078 does per-workspace VMs for Cmd-N in Swift; this is the chat path in Rust and touches none of his files. Not touched: the create request's team/owner targeting, the composer UI, Swift.

Tests

Updated the tests that asserted reuse; added each_workspace_gets_a_new_machine_and_keeps_it (two workspaces get two New, each keeps its machine across sends, paused or before the list loads), a_free_machine_of_mine_is_not_reused_for_a_new_workspace, and a_machine_bound_to_one_workspace_is_not_taken_by_another.

cmux-ci fleet job 8880d5bb9bad24b949423853 (linux-pool), at 57a00e0: cargo test -p cmux-tui --lib start_chat_cli passed 25 of 25, and cargo clippy -p cmux-tui --all-targets -- -D warnings -A clippy::redundant_closure passed. That one lint is allowed because the base fails it at crates/acpmux/src/hub/processes.rs:256, a file this PR does not touch.

Router review at 6b62dda flagged a P1: two first sends from one workspace can race (both plan New, then both pin). Fixed in 57a00e0. pick::claim binds only while the workspace has no machine, so the first pin wins and the later machine keeps only its own send's chat. A test covers this. The orphaned second machine stays the person's, and pausing or deleting it is a follow-up.

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

cloud.startChat now gives each Mac workspace its own small Cloud machine instead of reusing or sharing existing ones.

  • A workspace's first send plans a new cloud-chats machine and keeps it across later sends, even paused or before the list loads; sends from no workspace get a new machine too.
  • Existing machines are never reused, and pick::claim never binds a machine to a second workspace: a retry of workspace A's send runs on A's machine but does not give it to B.
  • A workspace still drops its own machine when it is a fleet VM or failed (cloud.startChat: the machine pick never takes a fleet VM made under the person's account #29959's check is kept), so the next send makes a new one.
  • The reuse-by-ranking logic in pick() is removed as dead; the ledger still allows sharing, so the one-per-machine rule can move back there alone.
  • Ledgers that already share a machine across workspaces keep those bindings.
  • Two first sends of one workspace that race to pin: the first pin wins, and the later machine keeps only its own send's chat.

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

View guided diff Turn on auto-fix

teamleaderleo and others added 2 commits October 31, 2026 19:08
A Mac workspace's first send makes a new machine and keeps it; a send from
no workspace makes a new one too. An existing machine is never reused for a
new workspace, and a machine one workspace has is never bound to another
(pick::claim). The ledger still holds many workspaces per machine; the
limit is the pick's policy. pick() and its free/marked/lane-pool ranking
are removed as dead.

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

Router review at 6b62dda: two first sends of one workspace can both plan New
and race to pin. pick::claim now binds only when the workspace has no machine
yet, so the first pin wins and the later machine keeps only its own send.
Also drops a struct update clippy flagged in the test fixture.

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

cursor Bot commented Nov 1, 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.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, router-review on eb89937..57a00e0): SHIP at 57a00e0

No correctness findings.

Follow-ups: none

(Earlier BLOCK at 6b62dda, racing first sends of one workspace, fixed in 57a00e0.)

…ace's machine

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:normal Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, router-review): SHIP at ded01ee

Follow-ups:

  1. [P1][follow-up] A workspace can lose its machine and then have it reassigned by a retry. Ledger::bind evicts bindings once there are more than 256 workspaces, and workspace_machine drops the binding for a machine that is unavailable. If a kept send from workspace A is then retried from workspace B, claim finds no other owner and binds A's machine to B. Filed as a follow-up issue.

Tests at this head: cmux-ci fleet job ea0aee6536b9acf3611b7bb7, cargo test -p cmux-tui --lib start_chat_cli passed 26/26 and clippy passed.

@teamleaderleo
teamleaderleo merged commit bdc1362 into feat-cmux-next Nov 1, 2026
155 of 166 checks passed
@teamleaderleo
teamleaderleo deleted the cloud-one-workspace-per-machine branch November 1, 2026 03:45
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

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

Review ded01ee: 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=pr30020 -f ref=cloud-one-workspace-per-machine -f platform=macos -f backend_mode=local

red: cmux-next checks (god files, concurrency, crash safety, l10n); base red: the same failure on the base 69ac0cc; does not block

Shipped in:

@blacksmith-sh

blacksmith-sh Bot commented Nov 1, 2026

Copy link
Copy Markdown

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
test_no_runner_picker_returns_a_hosted_mac (main.NoHostedMacInNightlies.test_no_run
ner_picker_returns_a_hosted_mac)/
test_no_runner_picker_returns_a_hosted_mac (main.NoHostedMacInNightlies.test_no_run
ner_picker_returns_a_hosted_mac)
View Logs

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

teamleaderleo added a commit that referenced this pull request Nov 1, 2026
…ines are Machines…

Leo, 2026-10-31: "but anyways we ideally also can just hide the machines too and
it's just a cloud button without as much of the whole subttitling on whatever...
it's just a cloud button", and "austin/lawrence said indeed we wanted 1 workspace
per vm for now".

- The main list is This Mac and Cloud, one line each: no machine rows, no hairline,
  no machine-name subtitle and no search, however many machines there are. A
  machine or saved environment that is the current pick is its one other row,
  checked, so the pick is never hidden.
- Cloud never chooses a machine: with Run as it is the chat's Cloud mode, whose
  cloud.startChat gives the new workspace its own new machine (cmux-tui #30020);
  without it, it opens New Cloud Machine.
- Every machine and New Tab's saved environments moved, not deleted, to
  Machines… on the control's right-click menu: the same rows, states, ⌥⌘ digits
  and search from 8 machines. ⌥⌘1–9 still pick from anywhere in the composer.
- Sandboxed stays Cloud's ⌥ face; the search that named it went with the main
  list's search.
- Tests and gallery states follow: environment-picker (two rows with machines
  connected), environment-picker-machines (new), and the fleet, cloud machines,
  machine colors and saved environments states open Machines….

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-63b9964940c20354b639
teamleaderleo added a commit that referenced this pull request Nov 1, 2026
…ines are Machines… (#28999)

* test(composer): the environment picker is This Mac and Cloud, one line each (red)

Leo, 2026-10-31: "bro this text is so fucking stupid why the fuck IS THERE SO
MUCH BULLSHIT JUST A LITTLE CLOUD ICON OR FUCKING THE SELECTION YOU KNOW
WHATEVER WORKS JUST NOT THE FUCKING EXISTING GAHHH"

The list is This Mac and Cloud, then the other machines only when there are
some; no section headers, no second lines, no setup rows; a search field only
from eight machines; the setup actions on the control's right-click menu and
still in the app; the control shows the current choice.

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

* composer: the environment picker is This Mac and Cloud, as Codex's menu

Leo, 2026-10-31: "bro this text is so fucking stupid why the fuck IS THERE SO
MUCH BULLSHIT JUST A LITTLE CLOUD ICON OR FUCKING THE SELECTION YOU KNOW
WHATEVER WORKS JUST NOT THE FUCKING EXISTING GAHHH"

- The list is This Mac (⌥⌘1) and Cloud (a pick opens New Cloud Machine), then a
  hairline and the person's other machines and saved environments, only when
  there are some. No section headers, no second lines.
- A search field only from 8 machines (ENVIRONMENT_SEARCH_MIN); under it the
  field stays, unseen, for the arrows, Return and Escape, and filters nothing.
- New Cloud Machine…, Open Cloud…, SSH…, Add Machine…, Connect Phone… and the
  New Tab page's Create / Edit environment move to the control's right-click
  menu; they stay in the palette, the File menu, Settings > Devices and the
  Cloud page. No feature or command is deleted.
- The control names the checked row: "This Mac" with the computer icon, or a
  machine's name and kind icon. This Mac's own name is its row's tooltip.
- A started chat keeps its machine and its one move, one line each.
- Gallery: environment-picker-alone (Leo's two rows) and three control looks
  (environment-face-label, picked; -icon; -chip).

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

* test(webviews): base's picker tests follow the two-row environment picker

The first-computer onboarding test finds Add Machine… and New Cloud Machine… on the control's
right-click menu and Cloud in the list; the New Tab first-frame test reads This Mac as "This Mac".

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

* test(webviews): the onboarding test closes the New Tab scene's open list before the right-click

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

* composer: the environment picker is This Mac and Cloud only; the machines are Machines…

Leo, 2026-10-31: "but anyways we ideally also can just hide the machines too and
it's just a cloud button without as much of the whole subttitling on whatever...
it's just a cloud button", and "austin/lawrence said indeed we wanted 1 workspace
per vm for now".

- The main list is This Mac and Cloud, one line each: no machine rows, no hairline,
  no machine-name subtitle and no search, however many machines there are. A
  machine or saved environment that is the current pick is its one other row,
  checked, so the pick is never hidden.
- Cloud never chooses a machine: with Run as it is the chat's Cloud mode, whose
  cloud.startChat gives the new workspace its own new machine (cmux-tui #30020);
  without it, it opens New Cloud Machine.
- Every machine and New Tab's saved environments moved, not deleted, to
  Machines… on the control's right-click menu: the same rows, states, ⌥⌘ digits
  and search from 8 machines. ⌥⌘1–9 still pick from anywhere in the composer.
- Sandboxed stays Cloud's ⌥ face; the search that named it went with the main
  list's search.
- Tests and gallery states follow: environment-picker (two rows with machines
  connected), environment-picker-machines (new), and the fleet, cloud machines,
  machine colors and saved environments states open Machines….

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>
teamleaderleo added a commit that referenced this pull request Nov 1, 2026
…achine

Base's one-workspace-per-machine claim (#30020) never rebinds a workspace
that already has a machine, so a repick moved the send's retry but left the
workspace on the old machine. A send already pinned to the workspace's
machine and pinned elsewhere now moves the workspace too, unless another
workspace holds the pick. The repick test starts from base's first plan
(a new machine the App pins).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
teamleaderleo added a commit that referenced this pull request Nov 1, 2026
… send failed moves it there and sends again (#30002)

* cmux NEXT Cloud: another machine picked for a Cloud chat whose first send has not run moves it there and sends again

Leo, 2026-10-31: he "picked zesty-indigo-lemur in the machine picker, but the chat stayed on
sr2-tunnel-probe".

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

* cmux-tui start-chat: a repick pin moves the workspace to the picked machine

Base's one-workspace-per-machine claim (#30020) never rebinds a workspace
that already has a machine, so a repick moved the send's retry but left the
workspace on the old machine. A send already pinned to the workspace's
machine and pinned elsewhere now moves the workspace too, unless another
workspace holds the pick. The repick test starts from base's first plan
(a new machine the App pins).

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

3 inactive deployments
artifacts — ded01eec Deployed Nov 1, 2026 by teamleaderleo via add the Windows daemon to the tree #93272
sentry-dsyms — ded01eec Deployed Nov 1, 2026 by teamleaderleo via upload cmux-tui dSYMs to Sentry #93272
ci-routing-agent — ded01eec Deployed Nov 1, 2026 by teamleaderleo via cmux-tui tree preflight #93272
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant