Back to Monty

pydantic-monty-runtime

crates/monty-runtime/README.md

0.0.214.4 KB
Original Source

pydantic-monty-runtime

The monty command-line binary for the Monty sandboxed Python interpreter.

console
$ monty -c "print('hello world')"
hello world

Usage

  • monty — start an interactive REPL
  • monty file.py — run a Python file
  • monty -c "<code>" — run a program passed as a string (like python -c)
  • -i / --interactive — run the file or -c program in a REPL session (like python -i)
  • -t / --type-check — type check (powered by ty) before executing
  • -m / --mount /host/path::/virtual/path[::mode[::write_limit_bytes]] — mount a host directory into the sandbox (ro, rw, or overlay)
  • --max-memory 10MB, --max-duration 0.5, --max-recursion-depth, --gc-interval — sandbox resource limits

Features

  • standalone (default) — the monty <file> / -c / REPL path and its terminal stack (rustyline, anstream, anstyle). Without it the binary serves monty subprocess alone, which is all a pool ever spawns; the flags still parse, but anything other than subprocess is refused.
  • telemetry — see below. Implies standalone, since it only instruments that path.

Observability

Behind the telemetry feature, off by default because its exporter links MBs of TLS that monty subprocess — which never exports — would otherwise carry. Without it, LOGFIRE_TOKEN is ignored.

Built with --features telemetry, standalone CLI runs configure the Rust Logfire SDK when LOGFIRE_TOKEN is set. The SDK also honors standard OpenTelemetry exporter and resource environment variables. The CLI owns the SDK lifecycle and flushes it before exiting.

monty subprocess deliberately ignores telemetry environment configuration: worker processes are instrumented by their parent pool, avoiding duplicate exporters and keeping credentials out of sandbox workers.

Worker mode

monty subprocess runs the binary as a wire-protocol child: framed protobuf requests on stdin, framed events on stdout (see the monty-proto crate). This is how the monty-pool crate — and through it the pydantic-monty and @pydantic/monty packages — runs Monty with crash isolation. It is meant to be driven by a parent process, not by hand.

The binary runs under the monty-alloc global allocator, which provides the session's soft-limit usage and enforces a higher hard ceiling. Crossing the soft limit raises MemoryError at an interpreter checkpoint; crossing the hard limit exits with a dedicated status the parent can classify.

PyPI packaging (pydantic-monty-runtime)

The binary is also packaged for PyPI as pydantic-monty-runtime, the same way uv and ruff package theirs: installing the wheel places the compiled binary in the environment's scripts directory. It exists so that pydantic-monty-client can find a monty binary without any manual setup, and is pulled in automatically by the pydantic-monty metapackage — you normally don't install it directly.

Monty crates

  • monty — the core interpreter: Python parser, bytecode VM, and sandbox.
  • monty-types — the shared boundary data types (values, exceptions, OS calls, resource limits) hosts use without linking the interpreter.
  • monty-fs — host-side filesystem mounts: maps virtual sandbox paths to real host directories.
  • monty-runtime — the monty binary: REPL, file runner, and subprocess worker mode. this crate
  • monty-pool — an elastic pool of crash-isolated monty worker subprocesses.
  • monty-proto — the protobuf wire protocol spoken between pool parents and workers.
  • monty-type-checking — type checking of sandboxed code, powered by ty.
  • monty-typeshed — the trimmed typeshed stubs describing the stdlib subset Monty implements.
  • monty-macros — the proc macros behind monty's argument parsing.