# Remote Machines: SSH, Loopback & Cloud VM

> The remote-work architecture that combines local SSH workspaces, remote localhost browser routing, image upload planning, Cloud VM attach endpoints, and a provider registry that stays BYOC and BYOK friendly.

- Repository: manaflow-ai/cmux
- GitHub: https://github.com/manaflow-ai/cmux
- Human wiki: https://grok-wiki.com/public/wiki/manaflow-ai-cmux-5a511656cb1a
- Complete Markdown: https://grok-wiki.com/public/wiki/manaflow-ai-cmux-5a511656cb1a/llms-full.txt

## Source Files

- `CLI/CMUXCLI+SSHCommandSupport.swift`
- `Sources/WorkspaceRemoteConfiguration.swift`
- `Sources/RemoteLoopbackRuntimeBridge.swift`
- `Sources/TerminalImageTransfer.swift`
- `Sources/Cloud/VMClient.swift`
- `Sources/Cloud/VMClientSocketCommands.swift`
- `web/services/vms/drivers/index.ts`
- `web/services/vms/workflows.ts`

---

<details>
<summary>Relevant source files</summary>
The following files were used as context for generating this wiki page:
- [CLI/CMUXCLI+SSHCommandSupport.swift](CLI/CMUXCLI+SSHCommandSupport.swift)
- [CLI/cmux.swift](CLI/cmux.swift)
- [Sources/WorkspaceRemoteConfiguration.swift](Sources/WorkspaceRemoteConfiguration.swift)
- [Sources/RemoteLoopbackRuntimeBridge.swift](Sources/RemoteLoopbackRuntimeBridge.swift)
- [Sources/RemoteLoopbackProxyAlias.swift](Sources/RemoteLoopbackProxyAlias.swift)
- [Sources/Panels/BrowserPanel.swift](Sources/Panels/BrowserPanel.swift)
- [Sources/TerminalImageTransfer.swift](Sources/TerminalImageTransfer.swift)
- [Sources/TerminalSSHSessionDetector.swift](Sources/TerminalSSHSessionDetector.swift)
- [Sources/Workspace.swift](Sources/Workspace.swift)
- [Sources/Cloud/VMClient.swift](Sources/Cloud/VMClient.swift)
- [Sources/Cloud/VMClientSocketCommands.swift](Sources/Cloud/VMClientSocketCommands.swift)
- [web/app/api/vm/route.ts](web/app/api/vm/route.ts)
- [web/app/api/vm/[id]/attach-endpoint/route.ts](web/app/api/vm/[id]/attach-endpoint/route.ts)
- [web/app/api/vm/[id]/ssh-endpoint/route.ts](web/app/api/vm/[id]/ssh-endpoint/route.ts)
- [web/services/vms/drivers/index.ts](web/services/vms/drivers/index.ts)
- [web/services/vms/drivers/types.ts](web/services/vms/drivers/types.ts)
- [web/services/vms/providerGateway.ts](web/services/vms/providerGateway.ts)
- [web/services/vms/workflows.ts](web/services/vms/workflows.ts)
</details>

# Remote Machines: SSH, Loopback & Cloud VM

cmux treats remote work as one product surface with several transports underneath: user-managed SSH workspaces, detected SSH terminals, browser panels that can reach remote `localhost`, and Cloud VM sessions that mint short-lived attach endpoints. The strongest architectural choice is that the Mac app keeps using common local primitives such as SSH, `scp`, WebSocket, and JSON-RPC while the web backend owns Cloud VM provider calls, billing, leases, and image resolution.

Evidence note: this run found no `STRATEGY.md` or `docs/solutions/**` files in the checkout. The selected Compound Engineering profile was used only as page-shape guidance; repository code remains the source of truth.

## System Shape

```mermaid
flowchart LR
  subgraph MacClient["Mac app and CLI"]
    CLI["cmux CLI"]
    Workspace["WorkspaceRemoteConfiguration"]
    Browser["BrowserPanel + RemoteLoopbackRuntimeBridge"]
    Drop["TerminalImageTransferPlanner"]
    VMClient["VMClient + socket vm.* commands"]
  end

  subgraph WebControlPlane["Web VM control plane"]
    Routes["/api/vm routes"]
    Workflows["VM workflows"]
    Gateway["VmProviderGateway"]
    Registry["provider registry"]
  end

  subgraph Providers["Cloud VM providers"]
    E2B["E2BProvider"]
    Freestyle["FreestyleProvider"]
  end

  subgraph RemoteMachine["Remote machine"]
    SSHD["sshd / SSH gateway"]
    Cmuxd["cmuxd-remote"]
    Loopback["remote localhost apps"]
  end

  CLI --> VMClient
  VMClient --> Routes
  Routes --> Workflows
  Workflows --> Gateway
  Gateway --> Registry
  Registry --> E2B
  Registry --> Freestyle
  CLI --> Workspace
  Workspace --> SSHD
  Workspace --> Cmuxd
  Browser --> Loopback
  Drop --> SSHD
```

Sources: [Sources/WorkspaceRemoteConfiguration.swift:275-294](), [Sources/Cloud/VMClient.swift:265-269](), [web/services/vms/workflows.ts:50-60](), [web/services/vms/providerGateway.ts:55-75](), [web/services/vms/drivers/index.ts:8-29]()

## Local SSH Workspaces

A remote workspace snapshot stores just enough durable connection state to rebuild an SSH workspace: transport, destination, port, identity file, SSH options, and flags for PTY preservation or Cloud VM daemon bootstrap skipping. Before persistence, cmux strips transient OpenSSH control socket options such as `ControlMaster`, `ControlPath`, and `ControlPersist`, and expands `~` in identity paths so restored workspaces do not inherit stale control sockets. Sources: [Sources/WorkspaceRemoteConfiguration.swift:4-31](), [Sources/WorkspaceRemoteConfiguration.swift:56-64](), [Sources/WorkspaceRemoteConfiguration.swift:460-475]()

`WorkspaceRemoteConfiguration` is the richer runtime form. It includes proxy and relay ports, relay credentials, local socket path, terminal startup command, foreground auth token, optional WebSocket daemon endpoint, and `skipDaemonBootstrap`. The transport key deliberately includes the transport, bootstrap mode (`bootstrap` vs `vm-baked`), destination, port, identity, durable SSH options, local proxy port, WebSocket daemon identity, and required PTY capability marker. This makes cache/reuse decisions sensitive to the parts that change remote behavior, not just the host string. Sources: [Sources/WorkspaceRemoteConfiguration.swift:275-294](), [Sources/WorkspaceRemoteConfiguration.swift:335-361]()

For normal SSH restores, cmux builds a reconnect command. For preserved PTY sessions, it uses `ssh-pty-attach`, but only when daemon bootstrap is not skipped and the SSH options support reusable foreground auth. That path adds OpenSSH control defaults when missing and generates a foreground auth token. Sources: [Sources/WorkspaceRemoteConfiguration.swift:373-414](), [Sources/WorkspaceRemoteConfiguration.swift:179-217]()

The attach script is intentionally defensive: it resolves the bundled CLI, requires `CMUX_SOCKET_PATH` and `CMUX_WORKSPACE_ID`, derives a session id, and retries bridge exits `254` or `255` with environment-controlled limits. Foreground auth performs a short SSH command, then notifies the app through `workspace.remote.foreground_auth_ready`. Sources: [Sources/WorkspaceRemoteConfiguration.swift:97-118](), [Sources/WorkspaceRemoteConfiguration.swift:121-150]()

Small CLI helpers keep SSH command embedding predictable by wrapping shell snippets as `/bin/sh -c ...`, escaping `%` for OpenSSH option values, and joining already self-delimiting shell snippets. Sources: [CLI/CMUXCLI+SSHCommandSupport.swift:3-31]()

## Remote Loopback Browser Routing

cmux uses a stable alias host, `cmux-loopback.localtest.me`, to represent remote loopback addresses inside browser panels. The alias mapper recognizes `localhost`, `127.0.0.1`, `::1`, `0.0.0.0`, and subdomains of `localhost`; it can translate both from alias to loopback and from loopback to alias. Sources: [Sources/RemoteLoopbackProxyAlias.swift:3-24](), [Sources/RemoteLoopbackProxyAlias.swift:26-53]()

Browser panels inject `RemoteLoopbackRuntimeBridge.runtimeBridgeScriptSource` at document start for all frames. The script only activates on the alias host, installs once, and rewrites cleartext `http:` and `ws:` URLs from loopback hosts to the alias. It explicitly avoids rewriting `https:` and `wss:` because TLS certificate and SNI expectations depend on the original hostname. Sources: [Sources/Panels/BrowserPanel.swift:3412-3418](), [Sources/RemoteLoopbackRuntimeBridge.swift:23-35](), [Sources/RemoteLoopbackRuntimeBridge.swift:49-71]()

The runtime bridge patches the browser APIs that developer servers commonly use after page load: `fetch`, `XMLHttpRequest.open`, `WebSocket`, and `EventSource`. Separately, BrowserPanel rewrites typed/navigated `http://localhost...` URLs to the alias and rewrites displayed alias URLs back to loopback-looking URLs for the user. Sources: [Sources/RemoteLoopbackRuntimeBridge.swift:74-126](), [Sources/Panels/BrowserPanel.swift:5003-5027]()

## Image And File Transfer Planning

File drop and paste are planned before execution. `TerminalImageTransferPlanner` can insert text, insert delayed text segments, upload files, or reject a payload. It resolves the target as local, workspace remote, or a detected SSH session based on the owning workspace and terminal TTY. Sources: [Sources/TerminalImageTransfer.swift:15-25](), [Sources/TerminalImageTransfer.swift:159-183](), [Sources/TerminalImageTransfer.swift:484-496]()

The planner is conservative. Local files become shell-escaped paths unless the action is a multi-image drop, where paths are sent as delayed segments. Remote targets upload only regular file URLs; unsupported file URL payloads fall back to inserting local paths instead of pretending an upload happened. Sources: [Sources/TerminalImageTransfer.swift:213-237](), [Sources/TerminalImageTransfer.swift:335-360]()

Execution is dependency-injected: workspace remote upload and detected SSH upload are passed as closures, then successful remote paths are shell-escaped and inserted into the terminal. This separation is worth copying because it makes planning testable without requiring a live SSH server. Sources: [Sources/TerminalImageTransfer.swift:262-309](), [Sources/TerminalImageTransfer.swift:426-440](), [Sources/GhosttyTerminalView.swift:10627-10655]()

Workspace remote uploads use `scp` on a background queue, force `ControlMaster=no`, add `StrictHostKeyChecking=accept-new` if the user did not specify host-key policy, and pass through port, identity file, and SSH options. On failure, already-uploaded paths are cleaned up. Detected SSH sessions use the same basic `scp` approach but preserve detected flags such as IPv4/IPv6, agent forwarding, compression, config file, jump host, control path, and identity file. Sources: [Sources/Workspace.swift:5765-5815](), [Sources/Workspace.swift:7296-7342](), [Sources/TerminalSSHSessionDetector.swift:83-123](), [Sources/TerminalSSHSessionDetector.swift:125-170]()

## Cloud VM Client And Socket Commands

The Swift `VMClient` is the Mac-side HTTP client for `/api/vm/*`. It lists, creates, destroys, opens SSH endpoints, opens attach endpoints, and executes commands. It gets Stack Auth tokens from `AuthManager`, derives the base URL from `AuthEnvironment.vmAPIBaseURL`, and sends the selected team id as `X-Cmux-Team-Id` when present. Sources: [Sources/Cloud/VMClient.swift:265-333](), [Sources/Cloud/VMClient.swift:342-407](), [Sources/Cloud/VMClient.swift:412-452]()

Attach endpoints are polymorphic. An endpoint may be SSH with host, port, username, credential, and optional fingerprint; or WebSocket with URL, headers, token, session id, expiry, and optionally a daemon WebSocket endpoint. The client validates response shape and maps both password and authorized-key credentials. Sources: [Sources/Cloud/VMClient.swift:226-263](), [Sources/Cloud/VMClient.swift:360-390](), [Sources/Cloud/VMClient.swift:513-544]()

The app exposes the same Cloud VM operations to the CLI over socket methods: `vm.list`, `vm.create`, `vm.destroy`, `vm.exec`, `vm.ssh_info`, and `vm.attach_info`. `vm.create` requires an idempotency key at the socket boundary, while `vm.attach_info` accepts `require_daemon`/`requireDaemon` and returns either SSH or WebSocket attach payloads. Sources: [Sources/Cloud/VMClientSocketCommands.swift:9-70](), [Sources/Cloud/VMClientSocketCommands.swift:86-121]()

The CLI uses those socket calls rather than embedding provider APIs. `cmux vm ssh` asks for `vm.attach_info` with `require_daemon: true`; if the endpoint is WebSocket and has a daemon endpoint, it opens a WebSocket workspace, otherwise it falls back to SSH options that mark the workspace as `skipDaemonBootstrap`. For the SSH gateway case, the CLI disables known-host persistence and control socket reuse, uses `PreferredAuthentications=none,password`, and embeds the one-time token in the destination. Sources: [CLI/cmux.swift:7708-7770](), [CLI/cmux.swift:7838-7869]()

## Web API, Workflows, And Provider Registry

The web API is an authenticated control plane. VM creation validates JSON shape, provider override, image override, and team id before resolving the default provider/image and before calling the paid workflow. It forwards an `Idempotency-Key` or `x-cmux-idempotency-key`, capped at 128 characters. Sources: [web/app/api/vm/route.ts:93-180](), [web/app/api/vm/route.ts:181-229](), [web/app/api/vm/route.ts:231-274]()

Attach and SSH endpoint routes are small adapters around workflows. The attach route parses `requireDaemon`/`require_daemon`, calls `openAttachEndpoint`, and returns the provider endpoint. The SSH route documents the boundary: the Mac client receives short-lived SSH details and then dials the VM directly through the existing SSH transport, so Next.js is not in the data plane. Sources: [web/app/api/vm/[id]/attach-endpoint/route.ts:12-40](), [web/app/api/vm/[id]/ssh-endpoint/route.ts:12-23](), [web/app/api/vm/[id]/ssh-endpoint/route.ts:24-46]()

The provider layer is BYOC-friendly in shape, with one caveat: the current `ProviderId` union is `"e2b" | "freestyle"`, so adding a provider is a code change, not runtime plugin discovery. The interface still keeps the rest of the system provider-neutral: create, destroy, status, pause/resume, exec, snapshot/restore, attach, SSH, and credential revocation all sit behind `VMProvider`. Sources: [web/services/vms/drivers/types.ts:1-18](), [web/services/vms/drivers/types.ts:76-104]()

The registry currently installs `E2BProvider` and `FreestyleProvider`, with `CMUX_VM_DEFAULT_PROVIDER` selecting either when configured and Freestyle as the fallback default. `VmProviderGateway` wraps provider calls in Effect errors so workflows depend on the gateway interface rather than concrete SDKs. Sources: [web/services/vms/drivers/index.ts:1-29](), [web/services/vms/providerGateway.ts:17-37](), [web/services/vms/providerGateway.ts:44-75]()

Workflows compose repository, provider gateway, and billing gateway layers. Creation begins with an idempotent repository reservation, reserves create credit, calls the provider, finalizes the running VM, refunds/marks failed on errors, and records usage events. Attach and SSH endpoint workflows revoke existing identities before minting a new endpoint, store endpoint leases, and record attach/SSH usage. Sources: [web/services/vms/workflows.ts:50-81](), [web/services/vms/workflows.ts:82-170](), [web/services/vms/workflows.ts:306-369](), [web/services/vms/workflows.ts:384-428]()

## Cloud VM Bootstrap Modes

`skipDaemonBootstrap` is the key bridge between user-managed SSH remotes and Cloud VM remotes. For normal SSH, cmux probes, uploads, and starts `cmuxd-remote`. For Cloud VM images where `cmuxd-remote` is pre-baked and systemd/socket activated, cmux skips probe/upload/stdio hello and synthesizes a baked daemon hello. Sources: [Sources/WorkspaceRemoteConfiguration.swift:289-294](), [Sources/Workspace.swift:5887-5898]()

When bootstrap is skipped, cmux also skips reverse-relay metadata cleanup and only starts the proxy when a daemon WebSocket endpoint exists. The SSH-only Cloud VM fallback intentionally keeps the shell connected with proxy disabled because provider gateways may not support the ssh-exec or socket-forwarding paths needed by the normal relay. Sources: [Sources/Workspace.swift:5899-5935](), [Sources/Workspace.swift:6901-6915]()

## Product Hooks Worth Exploring

| Hook | Why it matters | Implementation anchor |
| --- | --- | --- |
| Remote `localhost` browser preview | Lets a browser panel use familiar loopback URLs while the runtime redirects page traffic through a remote-safe alias. | [Sources/RemoteLoopbackRuntimeBridge.swift:49-126](), [Sources/Panels/BrowserPanel.swift:5003-5027]() |
| Upload planning before execution | Separates UX decisions from SSH mechanics; easy to test and reuse across paste, drop, workspace remote, and detected SSH. | [Sources/TerminalImageTransfer.swift:198-237](), [Sources/TerminalImageTransfer.swift:262-309]() |
| Cloud VM attach polymorphism | Allows SSH and WebSocket providers to coexist while the CLI consumes one `vm.attach_info` method. | [Sources/Cloud/VMClient.swift:260-263](), [Sources/Cloud/VMClientSocketCommands.swift:86-111]() |
| Provider registry plus gateway | Keeps provider SDKs behind a small contract, which supports BYOC/BYOK-oriented deployment choices without pushing provider details into the Mac client. | [web/services/vms/drivers/types.ts:76-104](), [web/services/vms/providerGateway.ts:55-75]() |
| Idempotent create workflow | Prevents duplicate paid creates and records billing/usage events around provider operations. | [Sources/Cloud/VMClient.swift:303-333](), [web/services/vms/workflows.ts:70-170]() |

## Design Constraints And Failure Modes

- TLS loopback rewriting is intentionally out of scope. `https:` and `wss:` are not rewritten because aliasing would change certificate/SNI expectations. Sources: [Sources/RemoteLoopbackRuntimeBridge.swift:60-64]()
- Cloud VM provider neutrality exists at the workflow/driver boundary, but provider ids are currently compile-time literals. A new provider should implement `VMProvider`, register in `buildRegistry`, and pass through the existing route/workflow validation. Sources: [web/services/vms/drivers/types.ts:4-18](), [web/services/vms/drivers/index.ts:10-29]()
- Cloud VM SSH attach credentials are short-lived endpoint details, not a permanent client-side provider credential store. The workflow stores leases and revokes prior identities before minting replacements. Sources: [web/services/vms/workflows.ts:384-428](), [web/services/vms/workflows.ts:728-754]()
- Remote file upload uses `scp`, so unsupported file payloads fall back to text insertion and upload errors are surfaced rather than hidden. Sources: [Sources/TerminalImageTransfer.swift:231-236](), [Sources/Workspace.swift:7330-7340]()

## Summary

The remote-machine architecture is strongest where it keeps boundaries boring: SSH remains SSH, browser loopback routing is an alias-and-rewrite layer, file transfer is planned before execution, and Cloud VM providers live behind authenticated web workflows plus a driver registry. That makes the system portable across user-owned machines and hosted VM providers while preserving room for BYOC/BYOK deployment choices through provider selection, environment configuration, and server-side credential ownership. Sources: [web/services/vms/drivers/types.ts:76-104](), [web/services/vms/workflows.ts:306-369](), [Sources/WorkspaceRemoteConfiguration.swift:335-356]()
