Getting started
Ten minutes: build Pynox, run a script, watch the sandbox act, write the permissions down, then send one request to the pool.
Requirements
- Linux on x86_64 or ARM64, glibc 2.28+ or musl 1.2+.
- Kernel 6.2 or newer for the sandbox.
--no-sandboxruns anywhere. - Rust (
rust-toolchain.toml) and uv >= 0.13.1 to build.uvdownloads the matching CPython.
macOS
Use a Linux container or VM. Pynox is Linux only for now (ADR 010).
Build
make bundle
bash scripts/install.sh --archive dist/pynox-0.1.0-cp311-linux-gnu-aarch64.tar.gz
export PATH="$HOME/.local/bin:$PATH"
Ask the runtime and the kernel what they support:
{"version": "0.1.0", "python": {"version": "3.11.17"}, "platform": "linux-gnu-aarch64",
"landlock_abi": 7, "sandbox_supported": true, "sandbox_unavailable_reasons": []}
When sandbox_supported is false, the reasons name the missing kernel
interface. Sandboxed runs then refuse to start and point you at
--no-sandbox; they never run unrestricted on their own.
Run a script
Output and exit code are Python's. The script ran in the sandbox, and it could read its own directory and the standard library, nothing else.
Watch the sandbox act
Traceback (most recent call last):
File "/home/you/probe.py", line 1, in <module>
print(open('/etc/hostname').read())
PermissionError: [Errno 13] Permission denied: '/etc/hostname'
pynox: For files, grant the specific path with --allow-read/--allow-write. ...
Grant the path:
Grants are separate for reading and writing. -c grants nothing; -m makes
the current directory readable, as sys.path[0] would:
Write the permissions down
A project states its permissions once, in a pynox.toml where you run:
Pynox reads --config PATH, then $PYNOX_CONFIG, then ./pynox.toml. It
never reads a file beside the script, so a program cannot grant itself more.
Profiles, pool settings and limits live in the same file; see
commands.
Get a JSON result
{"exit": 0, "stdout": "Hello from Pynox!\n", "stderr": "", "error": null, "duration_ms": 9,
"policy": {"allow_read": [], "implicit_read": ["/home/you"], "network": "deny", "...": "..."}}
Failures carry an error with type, message, file, line and hint. This is
the shape the pool returns for every task.
Send one request to the pool
The pool keeps a CPython template warm and forks a fresh, sandboxed child per request. Agents talk to it; so can you, with a line of JSON:
From Python, the pynox package wraps the protocol. Install the wheel for
your environment's CPython version, built from the checkout:
import pynox
print(pynox.run("print(sum(range(10)))").text) # 45
run_python = pynox.tool(allow_write=["out"]) # a function for your agent framework
Without installing, point the package at a local build:
Plain Python
The unrestricted CPython command line, REPL included, with Pynox's optimizations installed.
Next
- Agents: make
pool.runa tool your model can call. - Pool protocol: every field, profiles and limits.
- Monty: Monty's glue-code sandbox plus Pynox.