Skip to main content
Run commands, read their output, and check exit codes without SSH. Execution uses a dedicated host-to-guest channel, so it works even with networking disabled.

Run the image default workload

Sandbox creation is boot-only: configuring an image, ENTRYPOINT, or CMD does not execute that workload. Use the default-workload methods when you want the SDK to resolve the effective OCI ENTRYPOINT + CMD and run it. A configured CMD override replaces the image CMD while preserving the effective entrypoint. If neither field supplies an executable, these methods return the typed NoDefaultCommand error instead of falling back to a shell.
The default workload also supports streaming and interactive execution:
Consume the stream as shown in Streaming output. Literal command execution and terminal attachment continue to ignore ENTRYPOINT and CMD.

Execute a command

Run a command and wait for it to complete. You get back the exit code, stdout, and stderr.

Background jobs

Use a background job for a command that should keep running after you disconnect. The local sandbox must already be running. Starting the job returns an ID you can use to check its progress or reconnect.
Stopping the sandbox stops its jobs. Restarting never reruns them. Finish active jobs before taking a full snapshot or forking; pause and resume remain supported. Job IDs belong to one sandbox and are separate from process IDs. Without --job, logs, inspect, and wait refer to the sandbox itself. All commands also support the msb sandbox ... form.
--no-stdin sends EOF and disables automatic terminal allocation. Otherwise, input stays open for a later attachment. --tty forces a terminal; --no-tty uses pipes. Detached launch never reads your terminal’s input and cannot be combined with --stream.
One attachment can write at a time; others can use --read-only. Detaching or reaching local input EOF leaves guest input open. An abrupt disconnect releases input ownership within 30 seconds. Terminal output combines stdout and stderr as output; pipes keep them separate.
Job metadata and captured output remain available after disconnect or sandbox shutdown. After a runtime restart, a job without a confirmed exit is marked lost.
  • Up to 32 active jobs and 256 retained histories per sandbox.
  • Two 512 KiB output segments per job. Reading pruned output reports a cursor-gap error.
  • After 65,536 job admissions, restart the sandbox to launch more.
Use --limit N and --cursor ID to page through jobs. jobs, inspect, and wait accept --format json. Logs retain their usual tail, time, source, and format options.If output storage fails, capture stops permanently for that job. Previously saved output stays readable, and the process and live attachments continue. Inspect the job for the cutoff. If metadata storage also fails, its diagnostic stays in memory until a later update can save it.
Execution timeouts still apply after you disconnect. Older runtimes and unsupported backends reject job launch before dispatch. SDK job errors expose stable codes. If launch confirmation is lost, the error includes a job ID; inspect it before retrying to avoid starting the command twice.While paused, you can inspect or wait for jobs, but waiting does not resume them. Signals take effect after resume. Full input buffers do not block signals or deadlines. Input bytes and EOF remain ordered; a signal may interrupt queued input. Inspect reports signal-delivery failures.Ctrl-] remains available while input is blocked, with up to 1 MiB of buffered lookahead. Detaching waits up to two seconds for earlier input to be accepted. Overflow discards further input but keeps the attachment open until you detach, reach local EOF, or the job finishes.input_not_flushed means some input was dropped or could not be confirmed. Do not resend it automatically: the job may already have received it. Detaching restores your terminal without stopping the job or closing its input.A graceful sandbox stop interrupts queued command input while preserving filesystem ordering. If stop times out, it reports failure without forcing termination.

Execution options

These options apply to a single execution and don’t change the sandbox’s defaults.

Shell commands

Run a command through the sandbox’s configured shell (defaults to /bin/sh). Useful for pipelines, redirects, and other shell syntax that exec doesn’t interpret.

Stream output

Ruby currently collects command output with exec and shell. It does not expose streaming handles, interactive attach, or session IDs.
For long-running processes or large output, streaming gives you stdout, stderr, and exit events as they happen instead of buffering everything until the command finishes.
With the local runtime’s dedicated signal channel, kill() and other signals return execution_closed immediately if the execution ended or its start was rejected. Successful delivery does not confirm process exit; wait for completion. A timeout reports whether the signal was queued and may still be delivered.

Interactive attach

Bridges your terminal directly to a process inside the sandbox for a fully interactive PTY session. Useful for debugging, running REPLs, or anything that expects a real terminal.
Press Ctrl+] (or your configured detach keys) to detach from the session without stopping the process. The process keeps running inside the VM and you can reattach later via its session ID.

Write stdin

TypeScript, Rust, Python, and Ruby can pass input bytes with the command. Ruby does not expose a streaming stdin writer; Go uses a pipe to supply input and collect the result.
Streaming handles can also accept stdin. Enable stdin_pipe and write bytes to it. Combined with tty: true, this lets you drive interactive processes programmatically.

Output and stdin buffering

Each command has a 1 MiB output buffer, shared by stdout and stderr. When it fills, the guest stops reading the command’s output; once the guest pipe buffers also fill, the command’s writes block (or return EAGAIN for nonblocking writers) until you consume output. Nothing is dropped, and other threads in the guest keep running. Read output while the command runs; waiting for a completion marker before reading can leave the command blocked. Collecting complete output uses memory proportional to its size. To let a command finish without a reader, redirect its output to a file. This applies to SDK, CLI, and SSH execution. Stdin has a 64 KiB allowance per command. Writes wait for capacity and send straight from your buffer; cancelling a write can leave an already-delivered prefix. When a command both reads input and writes output, send and read concurrently so neither side blocks the other.

Session IDs

Each streaming exec creates a session ID that you can use to correlate stream events and persisted log entries.

Reference

For exact execution APIs, see TypeScript, Rust, Python, Go, or Ruby. For command-line execution, see msb run and msb exec.