Use it

Command line

Most days you'll use three commands: pybox vm start, pybox exec, pybox vm stop.

Commands#

CommandWhat it does
pybox exec FILERuns a Python file (or - for standard input) in a fresh sealed box. Prints the program's output, then a short receipt
pybox setup [--yes] [--with data]Builds the sealed box, and optionally the data image. Shows its plan unless you add --yes. Details
pybox vm start | stop | statusRuns or stops PyBox's private VM. start checks the VM's settings and stops it again if anything is off
pybox image build NAME --lock FILE, image list, image rm NAMEBuild an image with your own pinned packages, list images, remove one. Details
pybox doctor [--json]A read-only health check, with the next step for anything that isn't ready
pybox mcp [--max-timeout S] [--images LIST]Serves the run_python tool to an AI agent. Details
pybox cleanup [--resolve-attempt RUN]Tidies up expired leftover boxes. How it decides
pybox container [--inspect]The original JSON-only interface, kept for scripts written before exec
pybox run FILE --unsafe-localThe unsealed learning runner, on your Mac with your permissions. Only for your own code

pybox exec#

$ pybox exec script.py
$ echo 'print(sum(range(10)))' | pybox exec -
$ pybox exec report.py --image data --timeout 20 --input sales.csv --output results/
$ pybox exec script.py --json | jq .observed.engine_state.ExitCode

The program's output goes to standard output and standard error as usual, so you can pipe it. The receipt goes to standard error, after the program's output:

Recorded 21 October 2026
$ echo 'print(6*7)' | pybox exec -
42

PyBox receipt · run 5319e024 · image stdlib · 0.166 s of 2 s

From the container engine  checked before start, read back after
  Exit code             0 (ended by itself)
  Settings checked      yes, before the program started
  Mac folders shared    none
  Network               none
  Limits                128 MiB · 32 processes · 0.5 CPU · 2 s (+1 s box timer)
  Box                   removed and confirmed gone

From the Linux kernel  sampled while it ran, from outside the box
  Memory peak           2.5 MiB of 128 MiB
  Processes peak        6 of 32
  CPU throttled         0 periods

From the program  untrusted: a program can print or write anything
  Printed               3 bytes on stdout, 0 bytes on stderr

Not known  PyBox says so instead of guessing
                        final counters (the box can vanish between readings) · exact clock alignment
OptionDefaultMeaning
--imagestdlibstdlib, data (numpy, pandas, matplotlib) or one you built. Images
--timeout2More than 0, at most 30 seconds
--input PATHnoneCopy a file or folder in, at /tmp/input/. Repeatable. Files
--output DIRnoneBring back what the program writes to /tmp/output/, into a new or empty folder
--max-output-bytes65536Bytes kept per stream; the rest is drained and dropped
--jsonoffPrint only the full receipt as JSON
-q, --quietoffPrint the program's output only, no receipt

Programs can be up to 65,536 bytes of UTF-8 source. Set NO_COLOR=1 to turn off the receipt's bold headings. Anything in the receipt that came from the program is shown with control characters escaped, and on a terminal the receipt starts by resetting colours, so a program can't disguise it.

Exit codes#

PyBox's own exit code summarizes the run, so scripts can react without parsing JSON. The program's real exit code is always in the receipt.

CodeMeaning
0The program exited 0
1The program exited with an error (or its exit couldn't be established). For doctor: not ready to run
2Invalid input (a bad option, an oversized file, a non-empty output folder); for setup, a missing prerequisite or a conflicting file
124A deadline fired
125PyBox itself had a problem, e.g. the VM isn't running. The receipt's last section says what
130You cancelled with Ctrl-C (the box was still cleaned up)

When several apply, PyBox reports the first of 130, 125, 124.

pybox container#

The original interface reads the program from standard input and prints JSON: the receipt with --inspect, or the full raw result without it. It accepts --timeout (up to 30) and --max-output-bytes, but no images or files. Use pybox exec for new work.

The unsealed learning runner#

pybox run is not sealed. The program runs as you, on your Mac, with access to your files and the network. It exists to teach how process supervision works, and it requires --unsafe-local to remind you. It's never used for MCP or the AI repair loop, and never as a fallback. Use pybox exec for anything you don't fully trust.

$ pybox run examples/slow.py --unsafe-local --timeout 0.2

Its options: --timeout (up to 60 s), --max-output-bytes (up to 1 MiB per stream), and --cpu-soft-limit N, an experimental CPU-time warning signal that is not a hard cap.

Checked against the source on 21 October 2026.

esc