Concepts

Two deadlines

One clock is PyBox's own. The other lives inside the box, so a program can't outlive PyBox, even if PyBox itself is killed.

The short version#

ClockDefaultStartsWhen it fires
Mac deadline (primary)2 sJust before the program startsPyBox asks the engine to stop that exact box, checks it stopped, removes it
Box timer (backup)3 sWhen the box's first process startsThe timer kills the program itself, with no help from PyBox

The box timer is always one second longer, so in normal operation PyBox's own deadline acts first and the timer never has to.

Why one clock isn't enough#

PyBox's normal cleanup lives in its own Python process. If that process is force-killed (by you, by the OS, by a crash), its cleanup code never runs. A program left behind could keep running forever.

So the box's very first process isn't Python. It's a tiny timer that starts Python as its child:

What runs inside the box
timeout -s KILL 3 python -I -B -u -

When the timer runs out, it kills Python. It doesn't need PyBox to be alive. In a recorded test, PyBox was force-killed about 0.1 seconds into an 8-second sleep. The program still stopped at 3.03 seconds, and PyBox's own command logs show it never sent a kill.

A second recorded test went further: the program tried to stop or pause the timer by signalling it. The timer still fired, at 3.03 seconds both times.

Choosing the time limit#

The default is 2 seconds. You can lower it, or raise it to at most 30 seconds when a job needs it:

$ pybox exec slow_job.py --timeout 20

The box timer follows: 20 s on the Mac means 21 s in the box. In a recorded test, a program sleeping for 60 s with --timeout 30 was stopped by PyBox at 30.01 s. For AI agents, the server's --max-timeout sets the ceiling. See longer runs. The receipt shows both, as wall_timeout_s and guest_timer_s.

Other bounded waits#

Every step PyBox takes has its own short budget, so no single slow step can hang a run:

StepBudget
Create the box5 s
Start and attachThe run's own deadline (at least 2 s)
Inspect, query, stop2 s each
Remove3 s
All of cleanup together15 s (a single retry, after an interruption mid-cleanup, gets a fresh 15 s)

What the receipt says about it#

The receipt never decides why a program ended from its exit code alone. Exit code 137 means "killed", but not by whom. So PyBox only labels the cause when it has its own evidence:

LabelMeans
TARGET_EXIT_OBSERVEDThe program ended by itself; PyBox didn't stop it
SUPERVISOR_KILL_OBSERVEDPyBox sent a stop, the engine confirmed it, and the timestamps line up
IN_CONTAINER_TIMER_CONSISTENTPyBox sent nothing, and the program ended right when the box timer would. That's consistent with the timer, but not proof
UNKNOWNAnything else. PyBox says so instead of guessing

Limits. Both clocks assume a healthy virtual machine that keeps getting CPU time. If your Mac sleeps or the VM is paused, time inside the box pauses too. These are strong practical limits, not hard real-time guarantees.

Checked against the source on 20 October 2026.

esc