Skip to main content
Untrusted code, agent-generated scripts, and third-party tools all run in a disposable sandbox with a hardware-virtualization boundary — stronger than a container, and far quicker to start than building a VM yourself.

Prerequisites

  • The @boxlite-ai/boxlite Node package and a machine with hardware virtualization — see Installation.
If the platform does not meet the virtualization requirement, the Box fails to start but the process does not crash; see Troubleshooting below.

Installation

Make sure your package.json is an ESM project (the SDK is published as ESM only):

Quick Example

Create hello.mjs (or a .js file in a "type": "module" project); it is runnable as-is:
Run:
What happens:
  1. On the first run, BoxLite pulls the alpine:latest OCI image (later runs hit the local cache).
  2. The Box is lazily created and starts a microVM on the first exec().
  3. The command runs inside the VM, collecting stdout/stderr/exit code.
  4. stop() stops the VM and cleans up (autoRemove defaults to true).

TypeScript 5.2+: await using for automatic cleanup

SimpleBox implements Symbol.asyncDispose, so it calls stop() automatically when leaving scope — no try/finally needed:

Common execution variants

Parameters and Returns

new SimpleBox(options) common fields

SimpleBoxOptions (the full field list is in the SDK type definitions; the table below covers the most common):

box.exec(...) overloads

The timeout parameter in the wrapper-layer SimpleBox.exec is called timeoutSecs (inside the options object).

ExecResult (the return value of exec)

box.info() return value (JsBoxInfo, a synchronous method)

The correct path to the state string is box.info().state.status (the outer field is state, the inner field is status). info() is synchronous; do not await it. The async version is getInfo().

Troubleshooting

Cannot find package 'boxlite' / module not found

The package name has a scope. Both install and import must use @boxlite-ai/boxlite:

Cannot use import statement outside a module / require is not defined

The SDK is published as ESM only. Add "type": "module" to package.json, or rename the file to .mjs, and use import rather than require.

A command failed but no exception was raised

exec does not raise on a non-zero exit code; it only places the code into ExecResult.exitCode. Always check it explicitly:

A missing command / startup failure raises a bare Error

When a command is not found inside the Box, or the underlying start fails, the error raised may be a standard Error (instanceof BoxliteError === false), with a message like internal error: spawn_failed: .... Do not assume the exception is always an ExecError/BoxliteError:

Image pull failure (network problem)

The first run needs network access to pull the image. On a network error or an unreachable registry, an error is raised. Catch and retry, or pull ahead of time:

No hardware virtualization → the Box cannot start

  • Linux: confirm /dev/kvm exists and the current user is in the kvm group (ls -l /dev/kvm).
  • macOS Intel: not supported.
  • WSL2: enable KVM inside WSL.
  • macOS ARM64: uses Hypervisor.framework by default, no extra configuration needed.
When the start fails, an exception is raised but the Node process does not crash; place it in try/catch to handle it cleanly.

The volume readOnly was passed as a string

In the SDK layer, the volume read-only marker is a boolean, not the CLI’s "ro"/"rw" string:

Next Steps

  • Run the bundled SDK examples in the repository: examples/node/simplebox.js (basic execution), codebox.js (code execution sandbox), browserbox.js, computerbox.js, and interactivebox.js.
  • To run a Python/JS snippet and get its output directly, see CodeBox (fixed language image, run(code) in one step).
  • Other languages: see the Python quickstart, the Rust quickstart, and the Go quickstart.