SDK
SDK operations cookbook
Current Python and TypeScript SDK calls, secure defaults, target helpers, and CLI fallbacks for common sandbox operations.
Use this page when you want a practical SDK operation and need to know whether to call the SDK today, use the CLI directly, or treat the helper as target API.
The shipped SDK runtime surface is intentionally smaller than the product
target. Current examples use Sandbox.create(...), commands.start(...), the
one-shot sandbox.exec(...), the full files.* API, TTLs, resources, network
declarations, record mode, live mode, and cleanup. Logs, snapshots, and the
lifecycle helpers are parity targets until the language SDK tests prove them.
Several of the CLI fallbacks below (machine proc, machine fs, machine pause, machine resume, machine checkpoint) are hidden advanced verbs: they
work, but they do not appear in mvmctl machine --help.
Operation status
Section titled “Operation status”| Operation | Python today | TypeScript today | Secure fallback today |
|---|---|---|---|
| Create sandbox recording | mvm.Sandbox.create(...) | Sandbox.create(...) | mvmctl build compile or mvmctl run --mode plan |
| Create live sandbox | mvmctl run --mode live ./script.py | mvmctl run --mode live ./script.ts | mvmctl machine run |
| Start command | sandbox.commands.start([...]) | sandbox.commands.start([...]) | mvmctl machine proc start or mvmctl machine exec |
| Capture command result | sandbox.exec(*argv) | sandbox.exec(argv) | CLI command result and receipt paths |
| Write file | sandbox.files.write(path, data) | sandbox.files.write(path, data) | mvmctl machine fs write |
| Read/list/remove file | sandbox.files.read/list/remove(...) | sandbox.files.read/list/remove(...) | mvmctl machine fs read, mvmctl machine fs ls, mvmctl machine fs rm |
| Logs | Target helper | Target helper | mvmctl machine logs |
| Ports | Not claimed | Not claimed | Declare ingress before boot: mvmctl machine run --port HOST:GUEST |
| Pause/resume | Target helper | Target helper | mvmctl machine pause, mvmctl machine resume |
| Checkpoint create/restore | Target helper | Target helper | mvmctl machine checkpoint create --class vm-full, mvmctl machine checkpoint restore |
| Stop cleanup | context manager or kill() | using/Symbol.dispose or kill() | mvmctl machine stop |
Current paths
Section titled “Current paths”import mvm
with mvm.Sandbox.create( "python-3.12", workload_id="agent-tool", ttl="30m", include=["src"], resources=mvm.resources(cpu_cores=1, memory_mb=512, rootfs_size_mb=1024), network=mvm.network(mode="none"),) as sandbox: sandbox.files.write("/app/main.py", "print('hello from mvm')") sandbox.commands.start( ["python", "/app/main.py"], env={"MODE": "dev", "API_KEY": mvm.secret("api-key", type="bearer", hosts=["api.example.com"])}, )Security notes:
- the Python script itself runs on the host in record, plan, and live modes;
- secret references are recorded as references, not copied as raw values;
commands.start(...)starts work and returns a handle; usesandbox.exec(...)when you want the exit code and captured output back;- the context manager records or performs cleanup through
kill().
Run modes:
mvmctl build compile ./sandbox.py --out /tmp/sandbox-irmvmctl run --mode plan ./sandbox.pymvmctl run --mode live ./sandbox.pyimport { Sandbox, network, resources, secret } from "@runmvm/mvm";
using sandbox = Sandbox.create("node-22", { workloadId: "agent-tool", ttl: "30m", include: ["src"], resources: resources({ cpu_cores: 1, memory_mb: 512, rootfs_size_mb: 1024 }), network: network({ mode: "none" }),});
sandbox.files.write("/app/main.js", "console.log('hello from mvm')");sandbox.commands.start(["node", "/app/main.js"], { env: { MODE: "dev", API_KEY: secret("api-key", { type: "bearer", hosts: ["api.example.com"] }), },});Security notes:
- the TypeScript module runs on the host in runtime SDK modes;
usingcalls the SDK cleanup path when the scope exits;- use static declarations instead of runtime scripts for untrusted deployable workload declarations;
- live mode shells through the invoking
mvmctlbinary.
Run modes:
mvmctl build compile ./sandbox.ts --out /tmp/sandbox-irmvmctl run --mode plan ./sandbox.tsmvmctl run --mode live ./sandbox.tsResult capture
Section titled “Result capture”The shipped one-shot is sandbox.exec(...), live mode only. It returns an
ExecResult carrying the exit code and the captured stdout/stderr:
result = sandbox.exec("python", "/app/main.py", timeout=30)print(result.exit_code)print(result.stdout)print(result.stderr)const result = sandbox.exec(["node", "/app/main.js"], { timeout: 30 });console.log(result.exitCode);console.log(result.stdout);console.log(result.stderr);ExecResult carries no run or audit identifier yet. Use the CLI receipt path
(mvmctl run --receipt ...) when automation needs audit correlation.
File reads
Section titled “File reads”The file API is symmetric and shipped in both SDKs. Everything but write is
live mode only; in record mode these raise a mode error rather than guessing:
sandbox.files.write("/work/input.json", b"{}")data = sandbox.files.read("/work/output.json")entries = sandbox.files.list("/work")sandbox.files.remove("/work/output.json")sandbox.files.write("/work/input.json", "{}");const data = sandbox.files.read("/work/output.json");const entries = sandbox.files.list("/work");sandbox.files.remove("/work/output.json");Treat bytes returned from the guest as untrusted and possibly sensitive.
Target logs and ports
Section titled “Target logs and ports”Logs and ports should keep policy visible:
for event in sandbox.logs(follow=True, redact=True): print(event.message)
# Ingress is declared in Sandbox.create(..., network={"ports": [...]})# before the signed plan is admitted.for await (const event of sandbox.logs({ follow: true, redact: true })) { console.log(event.message);}
// Ingress is declared in Sandbox.create(..., { network: { ports: [...] } })// before the signed plan is admitted.Until language helpers are shipped, declare ingress through machine run --port or the manifest. Bind host ports explicitly and avoid wildcard
listeners unless the workflow requires them.
Target lifecycle and snapshots
Section titled “Target lifecycle and snapshots”Lifecycle helpers should expose the same state model as the CLI:
snapshot = sandbox.snapshot(name="after-index")sandbox.pause()sandbox.resume(snapshot=snapshot.id)sandbox.stop()sandbox.destroy()const snapshot = await sandbox.snapshot({ name: "after-index" });await sandbox.pause();await sandbox.resume({ snapshot: snapshot.id });await sandbox.stop();await sandbox.destroy();Until those helpers are shipped, use:
mvmctl machine pause agent-sandboxmvmctl machine resume agent-sandboxmvmctl machine checkpoint create agent-sandbox --class vm-fullmvmctl machine checkpoint restore CHECKPOINT_IDmvmctl machine stop agent-sandboxSnapshots and cold state can contain memory, files, process state, and credentials. Retention and deletion policy should be explicit in automation.