Skip to main content
BoxLite follows SQLite’s model: embedded in your process as a library, with no daemon and no external service. A Box is an isolated execution environment implemented as a lightweight microVM behind a container-like interface.

Component Overview (Under the Hood)

Inside the host process, BoxLite is a library that descends through the shim — a small sandboxed child process that hosts the virtual machine — and finally reaches the guest agent inside the microVM. From top to bottom there are three regions:

Core component responsibilities


One exec, end to end

This code is the smallest observable unit for understanding the architecture: it walks the full chain host application → runtime → Box handle → execution inside the guest agent, and prints what each layer exposes (Box state, exit code, runtime metrics).
The layer each step maps to is shown in the data-flow diagram in the next section.

Data Flow: How a Command Reaches the Box

Expanding the await box.exec("echo", ...) from the Quick Example, it passes through the chain below. Each step is annotated with the entity it maps to in the source or the API: Initialization sequence (happens once, the first time you use a new Box): Key design points (they affect how you write code):
  • Lazy initialization. Before runtime.create() or entering async with SimpleBox(...), the Box has not actually started. The initialization cost is paid once on the first exec/start, so the first command is slower than later ones.
  • Streaming I/O. The native Rust ExecResult contains only exit_code; stdout/stderr are read as streams, and the Python/Node wrapper layer aggregates them into stdout/stderr strings.
  • A non-zero exit does not raise. exec returns a result carrying exit_code (Python) / exitCode (Node), which you check yourself. A standard exception is raised only when the command does not exist or virtualization is unavailable (see Troubleshooting).

Security Layering: Jailer + Hardware Virtualization

BoxLite’s isolation uses defense in depth: beyond the hardware virtualization (microVM), the jailer also sandboxes the shim process that hosts the VM. BoxLite isolation boundaries: a trusted host process spawns a jailed shim process, which runs the microVM containing the guest agent and untrusted code Most users do not need to configure security options: the defaults favor compatibility. When you need stronger isolation, security options are passed through advanced (there is no top-level security= keyword). AdvancedBoxOptions is exported only under the boxlite.boxlite submodule:
The full threat model is in the repository at src/boxlite/src/jailer/THREAT_MODEL.md.

SDK Layering: From Your Code to the Rust Core

Every language SDK is a thin wrapper over the same Rust core library: Easy-to-miss cross-layer conventions (note these before writing code): Detailed APIs for each high-level Box are on the corresponding feature pages; the full methods of the runtime and the low-level Box are on the SDK reference pages.

Parameters and Returns

This is a conceptual page and takes no parameters. Below is a summary of the methods the architecture walkthrough calls directly, for quick reference (full signatures are on the SDK reference pages).

BoxliteRuntime (runtime handle, Python Boxlite / Node JsBoxlite)

LiteBox (the low-level Box, Python Box / Node JsBox)

Wrappers such as SimpleBox are not subclasses of the low-level Box — each one holds a Box internally. That is why some low-level methods (metrics(), for example) are not available on a wrapper directly.

Metrics fields (real field names, commonly mistyped)


Going deeper

Using BoxLite requires none of what follows. Read one of these when you have a specific question:

Troubleshooting

Startup failure: Could not access KVM / no virtualization

Symptom: entering async with SimpleBox(...) raises RuntimeError. Cause: a Box is a microVM and needs hardware virtualization. The exception can be caught with try/except RuntimeError; the host process does not crash.

exec returned, but the command actually failed

exec does not raise on a non-zero exit code — this is intended behavior:
The same applies in Node: check result.exitCode.

A missing command / image pull failure raises a standard exception, not BoxliteError

A missing command or an image pull failure raises a standard RuntimeError (Python) / bare Error (Node), not BoxliteError. See Error Handling.

Passing a string as the volume’s third element errors

A volume’s third element is the boolean read_only; the strings "ro"/"rw" are CLI-only and raise TypeError here. See Volumes.
Note: only the CLI’s -v host:box:ro uses the ro/rw strings; the SDK API uses a bool. Do not confuse the two.

AdvancedBoxOptions import raises ImportError

AdvancedBoxOptions lives in the boxlite.boxlite submodule, not the top level. See Inject secrets and harden a box. Likewise, security options are passed via BoxOptions(advanced=AdvancedBoxOptions(security=SecurityOptions.maximum())); the top-level BoxOptions has no security= keyword.

Reading Box state raises AttributeError: 'BoxInfo' object has no attribute 'status'

State has two levels: BoxInfo.state is a BoxStateInfo, and you then take its .status (a string):

Mixing up the context-manager types of Boxlite and Box

  • Python Boxlite (the runtime) is a synchronous context manager: with Boxlite.default() as rt:.
  • Python Box/SimpleBox/CodeBox, etc. are async context managers: async with SimpleBox(...) as box:.
Writing the synchronous runtime as async with, or a Box as a synchronous with, triggers a TypeError from the context-manager protocol.