Runtime support
Which images run on which local runtime or in the cloud, what customization each accepts, and how ports reach them.
Which images run on which local runtime or in the cloud, what customization each accepts, and how ports reach them.
This reference describes the Python Sandbox SDK in cua-sandbox 0.9.0, exported
by cua 0.2.0. An accepted image specification or generated Fleet template is
evidence of SDK behavior, not proof that a guest boots on every host or deployment.
The same image reference runs locally (local=True, or cua sb create) and in
the cloud. The resolver picks the variant each backend runs; the guest OS can
still differ in format, backend and available operations between the two.
| Image input | Guest and kind | Local backend | Cloud |
|---|---|---|---|
Image.linux() | ghcr.io/trycua/linux:24.04 rootfs (amd64, arm64) | Docker or Podman; gVisor when the engine has runsc, else runc | gVisor; warm by default |
Image.linux(kind='vm') | ghcr.io/trycua/linux:24.04-disk containerDisk | QEMU (cua runtime setup qemu installs it); raises when QEMU is missing | KubeVirt |
Image.windows() | ghcr.io/trycua/windows:2022-disk containerDisk | Hyper-V on a Windows host that has it, else QEMU | KubeVirt, EFI; warm by default |
Image.windows('11') | Windows 11 VM | Local ISO installation | Rejected |
Image.macos() / Image.macos('15') | ghcr.io/trycua/macos:26 / :15 Lume VM | Lume on Apple silicon | Rejected |
Image.android() | Android 14 | Legacy Android emulator adapter | Rejected |
Image.from_registry(ref) | Any OCI image: rootfs, containerDisk or Lume | Rootfs as a container, containerDisk on QEMU, Lume image on Lume | Rootfs on gVisor, containerDisk on KubeVirt; amd64 only |
Image.from_file(...) | Disk or ISO | QEMU (or Hyper-V) | Rejected |
Not supported locally: macOS containers and macOS images that are not Lume images. The cloud runs amd64 only, so a Linux image must have an amd64 variant. With no container engine the managed runtime VM is not available yet; install Colima or Docker Engine. See Manage local runtimes.
The canonical images are generated from the SDK source:
| Constructor | Canonical image | Variant a backend runs |
|---|---|---|
Image.linux() | ghcr.io/trycua/linux:24.04 | Rootfs for containers; the -disk containerDisk for kind="vm" |
Image.windows() | ghcr.io/trycua/windows:2022 | The -disk containerDisk (VM) |
Image.macos() | ghcr.io/trycua/macos:26 | Lume, local only (Image.macos("15"): ghcr.io/trycua/macos:15) |
The resolver pins them by digest on both sides. Override one with
CUA_IMAGE_LINUX, CUA_IMAGE_WINDOWS or CUA_IMAGE_MACOS.
Cloud templates for image.os_type == 'windows' use Firmware.EFI.
Image.from_registry() defaults to os_type='linux' and does not inspect the
disk, so pass os_type='windows', kind='vm' for a Windows containerDisk.
| Operation | Local | Cloud |
|---|---|---|
Layers: apt_install(), pip_install(), uv_install(), run(), env(), copy() | Container image: built into the local engine before boot, cached by content. VM image: applied after boot through cua-spacesd (else Unsupported) | Remote build on the image as base, cached by content (not available yet) |
Other layers: brew_install(), choco_install(), winget_install(), app_install(), ... | Applied after boot through cua-spacesd (for example Image.linux()); Unsupported on an image without it | Unsupported (a NotImplementedError) |
expose() | Forwarded to a free host port, reported in sb.exposed_ports | Declares the service port-N |
Image.from_registry(ref, secret=...) | Authenticated pull | Registry pull secret for the sandbox and its sidecars |
Sandbox.snapshot() | Not implemented | Not implemented; snapshot-derived images are rejected |
Cloud layers fail with a clear error until Fleet builds images. cua image build and cua image push build and
publish an image both sides can use. See
Build and publish an image.
| Option | Local | Cloud |
|---|---|---|
command= | Container entrypoint, or run by cloud-init in a Linux VM | Template command with processMode: Run (container and VM images) |
env= | Container environment or cloud-init | Template environment with processMode: Run (VM images: single-line values) |
services=, wait_for= | Published loopback ports; probes | Gateway services; probes |
sidecars= | Extra containers sharing the network namespace, reached by name or localhost; needs runtime="runc" where gVisor would run | Container images: extra containers in the gVisor pod. VM images: a companion gVisor pod named in the guest's /etc/hosts |
VM sandboxes with sidecars= | Refused | Supported (companion pod) |
Sidecars are reached by name on every runtime: the sandbox reaches db:6379,
and a sidecar reaches the sandbox at main. With sidecars the service names
main, sidecars and sc are reserved.
Readiness is daemon-agnostic: a sandbox is ready when its backend reports it
running, plus the probes you declare (wait_for= in Python, --wait in the
CLI), and fails fast when the sandbox exits. The computer interfaces use
cua-spacesd on 3211 when the image has it; the SDK reports the env
service only for images that do.
| Service | Template behavior | Guest requirement |
|---|---|---|
env | Published on port 3211 when the image has cua-spacesd | cua-spacesd, for the computer interfaces and sb.spacesd() |
Names in services= | One gateway service per name | Your process listening on that port |
port-N | Added by .expose(N) | The application listening on N |
server | Added by the older server_port= | Your own daemon on that port |
Declaring a service does not install or start it. For an example layout, see the Omarchy recipe.
| Sandbox | Computer interfaces | sb.tunnel.forward() | sb.service(), public_url(), mcp() |
|---|---|---|---|
| Local (container, QEMU, Lume) | spacesd, else QMP or VNC fallback | Loopback TCP listener | Yes; public URLs through the cua daemon |
| Cloud | spacesd through the gateway (gRPC-Web) | Loopback listener (spacesd tunnel, else gateway proxy for a declared service) | Yes; public URLs are signed service URLs |
Direct Sandbox.connect(url=...) | spacesd | spacesd tunnel | No declared services |
| Legacy adapters (Android ADB, OSWorld, Tart, Hyper-V) | Adapter-specific | ADB forwards ports and Android sockets | Adapter-specific |
Cloud service URLs require authentication unless you create a public URL. See Set up cloud credentials and Sandbox interfaces.
The package mappings below are generated from source manifests and image constants. They describe the clients built from this repository, not the versions inside a particular deployed image.
cua-sandbox 0.9.0 source: image constructors, runtime selection, pool
claims, Fleet validation, firmware, and services.cua-image source (canonical.rs): the canonical image references.cua 0.2.0 source: public Python exports.cua-fleet 0.1.17 package mapping: Python bound-claim service requests.@trycua/fleet 0.1.2 package mapping: TypeScript service requests.cua-sandbox[driver] 0.9.0 maps direct Driver use to cua-driver
0.28.2. This client mapping is not the Driver version inside a particular
published or deployment-qualified guest image.Verification covers source and offline contract checks, not provisioned cloud boots, authenticated service requests, or local VM and container boots on every host. Recipe observations, such as the Windows Minecraft workflow, describe their own tested environment.