Use it
Command line
Most days you'll use three commands: pybox vm start, pybox exec, pybox vm stop.
Commands#
| Command | What it does |
|---|---|
pybox exec FILE | Runs 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 | status | Runs 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 NAME | Build 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-local | The 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.ExitCodeThe 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:
$ 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| Option | Default | Meaning |
|---|---|---|
--image | stdlib | stdlib, data (numpy, pandas, matplotlib) or one you built. Images |
--timeout | 2 | More than 0, at most 30 seconds |
--input PATH | none | Copy a file or folder in, at /tmp/input/. Repeatable. Files |
--output DIR | none | Bring back what the program writes to /tmp/output/, into a new or empty folder |
--max-output-bytes | 65536 | Bytes kept per stream; the rest is drained and dropped |
--json | off | Print only the full receipt as JSON |
-q, --quiet | off | Print 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.
| Code | Meaning |
|---|---|
0 | The program exited 0 |
1 | The program exited with an error (or its exit couldn't be established). For doctor: not ready to run |
2 | Invalid input (a bad option, an oversized file, a non-empty output folder); for setup, a missing prerequisite or a conflicting file |
124 | A deadline fired |
125 | PyBox itself had a problem, e.g. the VM isn't running. The receipt's last section says what |
130 | You 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.2Its 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.