Remove Blaxel and the Go cmuxd-remote daemon; move Freestyle to the public platform (0.2.9)
Removes Blaxel as a Cloud VM provider and collapses the two Freestyle arms into one driver on the public platform (api.freestyle.sh, freestyle@0.2.9).
Provider removal
- Delete
drivers/blaxel.ts,images/blaxel/,build-blaxel-image.sh,test-blaxel-vm-poc.ts; drop"blaxel"fromProviderId, the driver registry, the create kill switch, and the image manifest. defaultProviderId()is now"freestyle"(load-dev-env.shfollows).- A migration rebuilds the
vm_providerenum without'blaxel', rewriting surviving rows to'e2b'first. The trailingDROP TYPEis the interlock: a missed column aborts the whole transaction instead of splitting the schema.
Freestyle collapse
freestyleBeta.tsis promoted to the only Freestyle driver. The legacy 0.1.x arm (SSH gateway, cmuxd-remote WebSocket PTY on 7777) is deleted along withPOST /api/vm/:id/ssh-endpoint, theopenSshEndpointworkflow, the deadbakedFreestyleSignedAdminplumbing, andwsLease.ts.- Every guest command pins
linuxUser: "root". The 0.2 API's default changed to "uid 1000, or root if absent" and the devbox image ships such a user, so an unpinned exec would move the daemon, its install, and the model-plane write off the root layout they are baked around. providerImageNotFound()also recognizes snapshot-not-found: Freestyle resolves an image to a snapshot id, so its missing-image answer is a 404 on the snapshot rather than anIMAGE_NOT_FOUNDcode.- The reaper's orphan-volume scan no longer hardcodes a provider. Volumes were Blaxel-only; it asks the registry and reports partial coverage when no driver exposes an inventory.
Go cmuxd-remote removal
The Go daemon had two arms. The cloud arm (serve --ws) is dead as of this PR:
every driver runs the cmux-tui remote daemon and openAttach throws on all of
them. The cmux ssh arm (serve --stdio --persistent) is being retired too —
terminals keep the plain SSH/mosh PTY, and proxy/egress, the reverse CLI relay
and persistent slots move onto tunnels. So the whole tree goes.
- Delete
daemon/remote/(49 files, ~26.9k lines),build_remote_daemon_release_assets.sh,generate_remote_daemon_release_manifest.py,test_remote_daemon_release_assets.sh, andtest_ci_attestation_retry.sh(it guarded only the daemon asset attestation steps). release.yml/nightly.yml: drop the asset build, theCMUXRemoteDaemonManifestJSONInfo.plist injection, provenance attestation and its retry, everycmuxd-remote-*upload,NIGHTLY_REMOTE_DAEMON_VERSION, and the twoSetup Gosteps that pinned to the now-deletedgo.modand would have failed both jobs outright.ci.yml: drop theremote-daemon-testsjob and, with nothing left routing on it, the entiregochange area — its output, both early-exit emissions, and its entries in thelinux-preflight/ci-statusrouting tables. The two "routed job skipped" preflight tests usedremote-daemon-testsas their exemplar and now useweb-typecheck, which routes onweb.tmux-corpus.yml: dropremote-daemon-fuzzand thefuzztimeinput it consumed.terminal-nightly(macOS Swift, unrelated to Go) stays, so the workflow is renamed to match what it actually runs.release_asset_guard.js/prune_nightly_release_assets.py: stop treatingcmuxd-remotebinaries, checksums and manifests as immutable release assets or prunable nightly assets. Consequence:cmuxd-remote-*-<build>assets already published on the nightly release are no longer matched by the pruner and will need a one-time manual sweep.
Still to come, not in this PR: the Swift client stack that drove the binary —
CmuxRemoteDaemon (3.1k lines) and CmuxRemoteWorkspace (9.2k) go entirely, and
CmuxRemoteSession loses ~3.8k but survives (20 app files import it for tmux
control-mode mirroring, which never touched the daemon). That removal is
user-visible: it drops persistent remote PTY sessions, the SOCKS5/HTTP-CONNECT
proxy and egress, and the reverse CLI relay from cmux ssh, along with the
workspace.remote.pty.* socket API and its CLI verbs. Until it lands the app
still references a daemon binary that no longer ships, so cmux ssh bootstrap
will fail — this PR should not merge ahead of that follow-up.
Desktop / VNC
The VNC seam stays for Freestyle desktop support later, but the client stops claiming a desktop that isn't there: the devbox name heuristic matched only because Blaxel's devbox bundled xfce + noVNC, and the shared devbox image is shell-only. cmux vm new now defaults to --base, and the New Machine sheet offers only the kinds limits.imageKinds reports.
⚠️ Pending before deploy
The devbox snapshot sh-fb3dcf7b… was baked against the retired beta-api.freestyle.sh and is marked validationStatus: "unknown", so Freestyle creates fail closed until scripts/build-devbox-freestyle.ts re-bakes it on the public platform and the new id lands in the manifest. The env audit asserts this rather than hiding it.
Live Blaxel machines should be drained before the migration runs — afterwards nothing in the control plane can address them.
Verification
tsc --noEmitclean;bun test tests/vm→ 301 pass / 0 fail.- Migration validated against a real Postgres 17: all migrations apply in order, Blaxel rows rewrite to
e2b, the enum rebuilds without'blaxel', the old type drops (interlock passes), and new'blaxel'inserts are rejected. - Lint unchanged vs
main(same 16 pre-existing errors, 4 fewer warnings). - CI guards after the daemon removal:
test_ci_change_areas.py,release_asset_guard.test.js,test_ci_self_hosted_guard.sh,test_ci_release_sdk_lane.shand the Python syntax guard all pass;ci.yml,release.yml,nightly.ymlandtmux-corpus.ymlall parse. - Not built: the Mac app —
zigis not installed locally and there is no prebuiltGhosttyKit.xcframework, so the tagged Xcode build could not run. Touched Swift files passswiftc -parse, andlint-pbxproj-test-wiring.shis clean, but the Swift changes are unverified by a real compile.
🤖 Generated with Claude Code
https://claude.ai/code/session_01AhaCvb89W567Qugstm8Gdq
Summary by cubic
Removes Blaxel and the legacy Freestyle arm, leaving public Freestyle (api.freestyle.sh, freestyle@0.2.9) as the only Freestyle driver. It also removes cmuxd-remote; existing Blaxel machines must be drained before migration, and Freestyle creation stays fail-closed until its public-platform snapshot is rebuilt.
Cloud VM changes
- Rebuilds
vm_providerwithoutblaxel, rewriting surviving rows toe2b. - Pins Freestyle guest commands to
linuxUser: "root"and maps missing snapshots to 404 image errors. - Removes the legacy SSH gateway, WebSocket PTY, SSH endpoint, and Blaxel image tooling.
- Makes the New Machine sheet offer only backend-reported image kinds;
cmux vm newnow defaults to--base. - Uses provider inventory for orphan-volume cleanup and reports partial coverage when unavailable.
Removal and rollout
- Deletes the Go daemon and its CI, release, nightly fuzz, attestation, and asset-pruning lanes; existing nightly binaries need a one-time manual cleanup.
- The follow-up Swift client removal is required before merge because
cmux sshstill expects a daemon binary that no longer ships. - Rebuild the snapshot with
scripts/build-devbox-freestyle.tsand add its validated id to the manifest before deploying. - TypeScript and VM tests pass; the Mac app was not compiled because
zigandGhosttyKit.xcframeworkwere unavailable.
Summary by CodeRabbit
-
New Features
- Cloud VMs now default to Freestyle, with E2B and Daytona available as alternatives.
- VM creation now selects an available machine type automatically and defaults to shell-only machines.
- Cloud VM connections consistently use the cmux remote transport.
-
Changes
- Desktop VM creation now reports an unavailable-image error when no desktop image is configured.
- Legacy SSH endpoints and remote daemon-based attachment capabilities are no longer available.
- Cloud VM documentation and settings now reflect the updated provider and shell-only experience.