Virtualization Backends

macOS Capabilities

apple_container and apple_virt are not drop-in replacements for one another. This page is the authoritative list of what each supports. sandbox_exec confines a single process rather than booting a guest, so most sandbox commands do not apply to it at all.

Capability apple_virt apple_container
Isolation Full VM (Virtualization.framework) Lightweight VM via Apple's container
Platform default No — pass --backend apple_virt Yes
heyvm exec Yes Yes
heyvm sh Yes Yes
heyvm ssh Yes (sshd on :22) No — no SSH server in the guest
heyvm port-forward Yes (SSH tunnel to host 127.0.0.1) No — fails with Sandbox has no SSH port
heyvm create --open-port Ignored with a warning — use the guest IP Yes, at creation time only
Reachable from the host Directly at the guest's NAT IP Only via a port mapped with --open-port
Reachable from another machine Via heyvm share / the P2P proxy Not supported
heyvm snapshot Yes — COW rootfs clone, instant Requires container commit/import, often absent
heyvm checkpoint / restore No — Linux backends only No — explicitly rejected
heyvm fork No — Linux backends only No — Linux backends only
--start-command on create Yes Yes
--start-command on restart Yes Yes
Custom image build heyvm images build --backend apple_virt, or the install/ scripts Apple's container buildheyvm snapshot
Runs in the cloud No — local only No — local only

Choosing a backend

Use apple_virt when you need a reusable custom image, SSH, or to reach a service from anywhere other than the host process that created it. It is the only macOS backend with a working heyvm snapshot.

Use apple_container when you want the fastest possible start for running commands in a throwaway guest, and a single --open-port mapping is enough.

Building a reusable toolchain image

This is the supported macOS path, and it does not involve docker import:

# 1. Start from a base image and provision it
heyvm create --name toolchain-build --backend apple_virt --image alpine-3.21
heyvm exec toolchain-build -- apk add --no-cache ruby nodejs npm postgresql redis

# 2. Bake the result into a reusable image
heyvm snapshot toolchain-build --name my-toolchain

# 3. Use it
heyvm create --name dev-1 --backend apple_virt --image my-toolchain

heyvm snapshot clones the sandbox's rootfs with APFS clonefile and hardlinks the kernel, so snapshots are near-instant and cost almost no disk until written to. Images land in ~/.heyo/images/apple_virt/<name>/.

On apple_container, heyvm snapshot shells out to container commit and falls back to container export + container import. Several container builds ship without the container-import plugin, in which case snapshotting fails with Plugin 'container-import' not found. There is no workaround on that backend — build the image on apple_virt instead.

Reaching a service inside a sandbox

On apple_virt the guest holds a host-routable NAT IP, so no forwarding step is needed. The service must bind 0.0.0.0 (or the guest's eth0) rather than 127.0.0.1:

heyvm get <id>                     # read guest_ip
curl http://<guest-ip>:5000

On apple_container, map the port when you create the sandbox — it cannot be added afterwards:

heyvm create --name api --open-port 18734:5000
curl http://127.0.0.1:18734

heyvm bind prints a public https://<subdomain>.heyo.computer URL for local sandboxes, but the CLI does not currently register that subdomain with the cloud, so requests to it return Endpoint not found. Use --open-port or the guest IP for same-machine access, and heyvm share for off-host access, until this is fixed.

See macOS Backends for what each backend is, and Troubleshooting if a sandbox will not start.