Skip to content

Run sandboxes

A sandbox is a single isolated world: a root filesystem, a process to run, and a network policy, created for one purpose and addressed by id for its whole life. This guide covers standalone sandboxes — the ones you create directly, without a service definition. New to the model? Start with the agent sandbox quickstart.

All examples assume a configured client:

import { Nimbus } from "@nimbus/nimbus";
const nimbus = new Nimbus({
endpoint: "http://localhost:8080",
tenantId: "demo",
token: process.env.NIMBUS_TOKEN,
});

Endpoint and credential discovery (environment variables, the local credential file) is covered in the SDK resources reference.

const sandbox = await nimbus.sandboxes.create({
profile: "worker", // or "desktop"
spec: {
owner: { kind: "standalone", displayName: "batch-job" },
backend: "container", // or "krun"
root: {
kind: "oci_image",
source: { kind: "reference", reference: "docker.io/library/python:3.12-slim" },
},
process: { argv: ["python", "job.py"] },
},
labels: { purpose: "batch" },
});
const running = await nimbus.sandboxes.get({ id: sandbox.metadata.id });
console.log(running.status.lifecycleState, running.status.endpoints);
await nimbus.sandboxes.stop({ id: sandbox.metadata.id });

The spec answers two separate questions:

  • What root material runs? Either a prepared root filesystem or OCI image material — and image material is obtained either by reference (a registry image, as above) or by build (a Dockerfile and context). A build is a way to obtain an image, not a different kind of sandbox.
  • Who owns it? owner.kind: "standalone" means you created it directly, with an optional display name. Sandboxes launched as a service’s backend instead carry { kind: "service", serviceName } owner metadata — see Manage services. Creating a standalone sandbox never implicitly registers a service name.

backend selects the isolation mechanism, not the resource semantics — the same spec, id, lifecycle, and session rules apply either way:

  • "container" — OCI container isolation, driven through crun. This is the process-capable default that runs workloads today.
  • "krun" — libkrun-based microVM isolation. It currently fails closed for process execution until its network egress enforcement reaches parity with the container backend.

Both run on Linux hosts with deny-by-default outbound network access; on macOS and WSL2, nimbus machine provides the hosting Linux VM. See current capabilities.

Labels are the filtering handle for throwaway resources:

const batch = await nimbus.sandboxes.list({
labelKey: "purpose",
labelValue: "batch",
});

There is deliberately no resolve-sandbox-by-name API — a sandbox id is a receipt, not a dependency contract. If other code needs to find the workload by name, promote it to a service.

Sandbox responses redact launch inputs: process.argv and process.environment come back as { redacted: true, valueCount: n } rather than their values. Don’t round-trip secrets through sandbox reads — what you launched with is not readable back.