Getting started
Your first sealed run
Start the box, run one line of Python, and learn to read the receipt it gives back. You'll know how to read every PyBox result after this page.
1. Start the box#
$ pybox vm start
Running and verified.This boots the private VM and checks its settings: no shared folders, no forwarded ports, the pinned image present. If anything is off, PyBox stops the VM again and says why. No other command ever starts the VM for you.
2. Run a program#
Give PyBox a file, or - to send the program on standard input:
$ 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
Box removed and confirmed gone
…In about a third of a second, PyBox builds a fresh box, runs the program, removes the box, and prints what the program printed, then a short receipt. The command's exit code is 0 when the program exited 0. The exit codes tell you at a glance what happened.
The short receipt is a view. Add --json to get the full record it's built from.
3. Read the receipt#
Here's the full record (pybox exec - --json) of a program that printed hello inspection, recorded on 19 October 2026 and trimmed to the parts that matter:
{
"configured": {
"wall_timeout_s": 2.0, "guest_timer_s": 3.0,
"memory_bytes": 134217728, "pids": 32, "cpu_cores": 0.5,
"network": "none", "user": "10000:10000", "readonly_root": true
},
"observed": {
"policy_verified_before_start": true,
"engine_state": { "Status": "exited", "ExitCode": 0, "OOMKilled": false },
"resources": { "status": "COLLECTED", "sample_count": 1, "final_counters_complete": false,
"metrics": { "memory.peak": { "last": 4247552, … }, … } },
"termination": { "mechanism": "TARGET_EXIT_OBSERVED", "engine_lifetime_s": 0.074583 }
},
"capture": {
"stdout": "hello inspection\n", "stderr": "", "output_complete": true,
"provenance": "target byte streams via bounded Docker attach; untrusted content"
},
"cleanup": { "status": "REMOVED", "removed": true },
"unknown": { "final_resource_counters": true, "exact_termination_cause": true,
"absolute_clock_alignment": true }
}Read it top to bottom as four questions:
| Section | The question it answers | In this run |
|---|---|---|
configured | What did PyBox ask for? | 2-second limit, 128 MB, no network, a non-root user, read-only files. |
observed | What did the engine and the kernel actually see? | The settings were verified before starting. The program exited 0 after 0.075 s. Memory peaked around 4 MB. |
capture | What did the program say? | hello inspection. This is the program's own output, so it's labelled untrusted. |
unknown | What can't PyBox be sure of? | The exact final memory count, the exact cause of termination, and whether the clocks line up. |
Why "unknown" is always there. PyBox reads memory and CPU counters while the program runs, but the box can vanish between two readings. So it reports the last value it actually saw and says the final one is unknown, instead of quietly calling the last reading final.
For a field-by-field guide, see The receipt.
4. Try something that misbehaves#
Ask for something the box won't allow and compare the receipts:
$ printf 'import time\ntime.sleep(8)\n' | pybox exec - --timeout 0.5$ printf 'print(open("/etc/hosts").read()[:80])\n' | pybox exec -$ printf 'x = bytearray(300 * 1024 * 1024)\n' | pybox exec -In the first, PyBox stops the program at the deadline: the receipt says stopped by PyBox at the deadline (or cause not established when the clocks can't confirm the order), and the command exits 124. The second reads the box's own /etc/hosts, not your Mac's: your files simply aren't there. In the third, the receipt shows Out of memory: reported by the engine.
Then try the things that make PyBox useful for real work: files in and out, and numpy, pandas and longer runs.
5. Stop the box#
$ pybox vm stopNext, see what actually happens during a run: How it works.