zomg CLI, which talks to a server called zomg-api. The server manages the underlying Kubernetes and filesystem state so you work with boxes, not infrastructure.
The user-facing noun for a sandbox is box. The
--fork flag is reserved for one action: clone an existing box’s filesystem into a new box.The mental model
You create a box, run commands in it, and reach it over the web. It behaves like a fresh Linux machine: install packages, edit files, start services. The default image isubuntu:24.04, and anything you write survives across stops and resumes.
Under the hood, a box is a Kubernetes Deployment running a single privileged runner container. When the box starts, the runner sets up a persistent root filesystem, chroots into it, and starts PID 1:
Mount the kernel interfaces
The runner mounts
proc, sysfs, and the host /dev into the box’s filesystem, and bind-mounts /tmp, /run, /etc/resolv.conf, and /etc/hosts./volumes.
Persistent filesystems
Zomg keeps box state on a btrfs mount on the node. The layers build on each other with copy-on-write snapshots:| Layer | Role |
|---|---|
bases | Read-only template subvolumes. A new box starts from a base. |
roots | Writable btrfs snapshots created from a base — your box’s live root. |
checkpoints | Root snapshots you capture and restore. |
volumes, volume-checkpoints, volume-backups | Data-volume state for disks you mount into boxes. |
The zomg-api server
zomg-api is an HTTP server that owns the Kubernetes and btrfs state and serves interactive transports:
- REST routes under
/v1/projects/{project}/boxes/{name}for box lifecycle. - WebSocket exec at
…/exec/wsand console at…/consolefor running commands and attaching an interactive terminal. A non-WebSocketPOST …/execis also available.
Reaching boxes
Each box is published at a stable HTTPS hostname:That exact form applies to the
default project. Boxes in other projects get a project-qualified hostname instead.ZOMG_DOMAIN (required; falls back to localhost only for local dev defaults).
Box-to-box networking
Boxes in the same project reach each other over DNS without publishing anything. Box Services are headless, so a box name resolves directly to the pod and any port is reachable:- Same project: reach another box by its bare
name. - Different project: reach it by
name.project.
Common commands
Once you have a target configured, the everyday workflow is:zomg create:
--base/-b— start from a specific base (default base isbox-base).--fork/-f— clone an existing box’s filesystem instead of a base (cannot combine with--base).--data/-d— mount a data volume asNAME=/path[:ro|:rw].--env/-e,--cpu,--memory,--project/-p.
zomg docs command prints the full “Using zomg” guide in your terminal.
Projects
Boxes live in a project. The CLI resolves the project in this order:--project/-pflagZOMG_PROJECTenvironment variable- The current git repository’s root directory name
default
project:box (canonical) or project.box (shorthand).
Where to next
Quickstart
Install
zomg, deploy an environment, and publish your first box.Boxes
The box lifecycle: create, exec, stop, resume, delete.
Environment
The runtime inside a box: filesystem layout, PID 1, DNS, and injected env vars.
Snapshots and bases
Capture box state as checkpoints and turn it into reusable bases.
Data volumes
Persistent disks you mount into one or more boxes.
Services
Run long-lived services and expose them at a public URL.