Sandbox model
Sandboxis the one durable entity in nexus — everything else is a transient instantiation or an artifact of it.
A running VM, a snapshot, an image — none are first-class entities alongside Sandbox. When the VM dies, the record survives. When you fork, children are new Sandbox records with the same struct and lifecycle.
# Create a sandbox — mints the Sandbox record and boots the VM
nexus create my-app --image nexus-base --label task-id=42
# Filter by label — AND-semantics across multiple --label flags
nexus ps --label task-id=42nexus sandbox create; see CLI sandbox commands for the mapping.The Sandbox struct
| Field | Type | Description |
|---|---|---|
ID | SandboxID | Stable sb- prefixed identifier. Never reused. |
Name | string | Human-readable name within a project. |
Project | string | Namespace for grouping sandboxes. |
Labels | map[string]string | Arbitrary key=value metadata. CLI: --label KEY=VALUE, multiple flags AND-matched on fleet verbs. Nil and empty map are equivalent. |
State | State | Cached lifecycle state. The VMM is authoritative; where a live VM disagrees, the VM wins. |
Envelope | Envelope | Frozen configuration resolved at creation. Never mutated after the record is written. |
InstanceID | string | Identifier of the current running instantiation. Internal; not exposed in external keys. |
RemoveOnExit | bool | The --rm flag, recorded at creation. Durable. |
RemovalMarker | bool | Write-ahead tombstone set before any destructive removal. If the process crashes while this is true, the sandbox is gone. |
StopReason | StopReason | Qualifier on the stopped state. Meaningful only when State == stopped. |
Provenance | *Provenance | Fork lineage. Nil for sandboxes created with create. Frozen at creation. |
SupervisorPID | int | PID of the detached per-sandbox supervisor process. Zero means in-process perimeter. |
BaseRef | string | Full 40-hex SHA of the host repo HEAD at creation time. Empty when no source mount is declared. |
Envelope fields
| Field | Type | Description |
|---|---|---|
ImageDigest | string | Content-addressable digest of the rootfs image. |
AllowedHosts | []string | Hostnames the sandbox may reach through the egress perimeter. |
SSHPublicKey | string | OpenSSH public key injected into /root/.ssh/authorized_keys at boot. Empty = no SSH provisioned. |
Mounts | []MountSpec | Live virtiofs mounts: host path → guest path. Edits inside the sandbox appear on the host immediately. |
StopReason values
| Value | Meaning |
|---|---|
"clean" | Stopped by explicit user command. Safe to restart. |
"memory_lost" | Substrate destroyed (host reboot, VMM kill, power loss). In-progress work was lost. |
Identity
Content-addressing applies to images and snapshots, not sandboxes.
Fan-out exists precisely to create N sandboxes from identical inputs. Content-addressing would collapse them into one, so it is explicitly rejected for Sandbox. A sandbox's identity is its sb- ID.
Project identity is content-addressed (hash of normalized project inputs). Handle format: <project>/<name> — parsed by domain.ParseHandle.
Labels
Labels are arbitrary key=value pairs on a sandbox. The --label KEY=VALUE flag on nexus create and nexus ps is the primary way to attach intent to a sandbox and then select it from a fleet.
# Attach labels at create time
nexus create worker --label task-id=lint --label env=ci
# Select by label
nexus ps --label task-id=lintSource model
The primary source-init answer is a live virtiofs mount: declare one or more host paths to mount into the sandbox via --mount <host-path>:<guest-path>. Edits inside the sandbox appear on the host immediately. This is the target model for agentic workflows where a git worktree directory is the sandbox source.
Shadow disks sit in front of write-heavy directories (node_modules, .next, target, dist) to keep write amplification off the captured workspace. They attach to --workspace, not to --mount: a live virtiofs mount gets no shadow disks. For dependency isolation on a mounted tree, use --mount-named kind=disk.
Fork and snapshot are refused on a live-mounted sandbox (see Snapshots and fork). N-way parallelism uses independent create calls, each with its own worktree.
Fork children are ordinary Sandboxes
A sandbox produced by fork is an ordinary Sandbox — same struct, same lifecycle, same states. Its fork origin is recorded in the Provenance field, not by a separate type or state. See Snapshots and fork.
Host vs. client
The host is the machine running Cloud Hypervisor. The client is any machine that issues nexus commands — usually the same machine, but the seam is kept clean for remote use. The host owns the VMM process; the client speaks to the core library, which speaks to the driver, which drives the VMM.
What is NOT an entity
- VM — the running instantiation is an internal field (
InstanceID), not an entity. - Workspace — the term is retired. nexus has no
Workspacetype; a source tree mounted into a sandbox is a configuration detail onEnvelope, not an entity. - Project (as an entity) — there is no
Projectrecord. Project is a string namespace onSandbox.