feat(cli,mcp,sdk,cloud): workspaces default to the cloud; --local/--host for a host; environment-only create
Do not merge yet. Satya asked for a PR to review, not a ship.
The rule
Workspace commands default to the cloud only for accounts that can use cloud workspaces. That's decided by the new cloudWorkspace.available query. Everyone else keeps this machine as the default, exactly as before, so non-cloud flows don't change.
--localor--host <id>always picks a host.- Nothing is guessed from an ID or from where the command runs.
- The CLI caches the availability answer per organization for an hour, in
~/.superset/cloud-availability.json. - An API that can't answer counts as unavailable, whether it's offline or older than this query. Version skew can therefore only fall back to local, never to the cloud.
- The MCP keeps
hostIdrequired for accounts without cloud access.
Verified against production, which lacks the new query: ws list, terminals list --workspace <local id> and ws create --project …, all run without --local, took the this-machine path.
What changed
CLI
workspaces list/create/get/open/update/delete,terminals list/read/send/create/closeandagents createfollow the rule above.--cloudis gone.- Host-only flags without a location are refused with a hint, before any API call:
--project,--session,--checkout,--pr,--task,--tagand so on. An oldws create --project …fails loudly instead of starting a billed sandbox. - Accounts without cloud access get the same
--local/--hosthint when the API refuses them. ws updateon a cloud workspace renames it. Tasks and tags stay host-only.- Fast path to a running box. A cloud command reaches host-service through the gate with a ticket, reusing the ticket from the previous call. Tickets are cached in
~/.superset/cloud-workspace-tickets.jsonwith mode 0600 and last 12 hours. If there's no usable ticket, it asks the newcloudWorkspace.hostTicketendpoint for one. That endpoint signs a ticket for the address stored on the workspace row, with no Vercel lookup. The CLI wakes the sandbox only when nothing answers there. A stopped box returns a non-tRPC 502,SANDBOX_NOT_LISTENING, in about 130ms. The MCP tools and the SDK use the same host ticket and wake fallback. The MCP retries a call after a wake only when host-service never answered, so a mutation that reached the box is never repeated. A wake refreshes the stored address. - Timings on a running production sandbox: 2.1s for the first call, 0.4s once the ticket is cached (local is 0.35s), and 0.9s to recover from a stale ticket. Before this change every call took about 3.7s, because the API's wake re-ran the whole open sequence.
- No box needed for details.
ws getandws openread the API row and never touch the sandbox. - Reads no longer extend a sandbox's session. A cloud box that only CLI reads touch now stops at its session limit.
- Automations keep defaulting to this machine, as on main.
--localis accepted as an explicit spelling of that default. - Machine-only commands are unchanged:
projects,agents list,browser,hosts,start/stop/status,settings.
MCP
workspaces_list/create/update/delete,terminals_*andagents_createtreat a missinghostIdas the cloud.cloud_workspaces_list/create/deleteare folded into the workspace tools and removed.
Environment-only creation
cloudWorkspace.createno longer takesrepositoryIds, and an environment without repositories is refused. That includes "Default", which is the base you build environments from.- The desktop create screen drops the repository picker and offers only environments that have repositories.
SDK (cloud-only)
workspaces.list/retrieve/create/update/deletework on cloud workspaces.terminals.*andagents.creatego through the workspace's sandbox gate, using a cachedcloudWorkspace.accessticket. The API key and organization header are stripped from requests to the gate.- Hosts, projects, automations,
agents.list, the relay option and host routing are removed. - The SDK docs and README are rewritten.
- Typecheck is clean and tests pass, 3 of 3. Tests used a mocked fetch only, not a live workspace.
Docs and skills
- Public docs are unchanged from main. They describe today's behavior and mention no cloud defaults or flags while cloud workspaces stay flagged.
- AGENTS.md and the Superset skills match main, except for
--localonworkspaces create/list/delete. The released CLI already accepts--localthere, and it behaves the same before and after this change. - The standup sweep lists
--localworkspaces by default, so it never fans out over cloud workspaces. - Follow-up. The SDK package README and
api.mddescribe the cloud-only SDK. They only become public when a new SDK version is published.
Verified
Against production, with a CLI binary built from this branch:
ws listreturns the cloud workspaces, including "Hi".ws list --localreturns this machine's workspaces.terminals list --workspace <Hi>reaches the agent terminal through the gate.terminals readreturns the agent's screen.ws get <Hi>returns the name "Hi", the branch and/workspace.
These refusals behave, each with a hint: ws list --project x, ws create --project … without a location, ws create --environment Default, --environment with --local, terminals list --local on a cloud ID, ws update <cloud> --tag x, and automations create without a host.
In the dev app over CDP, with Cloud selected, the create row reads Cloud › "GitHub as me" › main, with no repository pill. The environment picker lists only environments that have repositories. cloudWorkspace.create on "Default" returns BAD_REQUEST with the new message.
Checks: typecheck is clean for cli, mcp, trpc, shared and desktop, apart from a stale host-service type unrelated to this change. Tests pass: cli 260, mcp 6, shared 1058, trpc 284, desktop create flow 159. check:i18n passes, with the new server message translated in all 16 locales.
Not verified
- Mutating cloud commands.
terminals send/create/closeandagents createweren't run against the live box. They use the same client aslistandread. - The MCP cloud path. Not run live, because the MCP server runs in the API and this branch isn't deployed.
- The stored-address fallback, verified on a dev sandbox. A host ticket plus the gate call took about 350ms, against 500ms for a no-wake access and 1.75s for a wake. After I stopped the box, the stored-address call failed fast with a 502. The wake took 9.7s, and both ticket kinds answered afterwards. The address stayed the same across the resume. I deleted the dev workspace afterwards.
- Rollout order. The CLI, MCP and SDK call
cloudWorkspace.hostTicket, so the API has to deploy before a CLI release. An old API would answer that call with NOT_FOUND. - The new cloud default for
ws create. Not exercised end to end, to avoid starting a sandbox.
Not in this PR
- Automations targeting cloud. Designed, pending decisions on concurrency, cleanup, per-run branches and prompt size.
- The create-flow redesign. Tracked in SUPER-2332.