Complete API reference for the BoxLite Node.js/TypeScript SDK.
Node.js: 18+ Platforms: macOS (Apple Silicon), Linux (x86_64, ARM64)
- Runtime Management
- Box Handle
- Network Tunnels
- Command Execution
- Box Types
- Error Types
- Metrics
- Type Definitions
- Constants
The main runtime for creating and managing boxes.
import { JsBoxlite } from 'boxlite';
// or use the wrapper classes
import { SimpleBox } from 'boxlite';new JsBoxlite(options: JsOptions)| Method | Signature | Description |
|---|---|---|
withDefaultConfig() |
() => JsBoxlite |
Get runtime with default config (~/.boxlite) |
initDefault() |
(options: JsOptions) => void |
Initialize default runtime with custom options |
| Method | Signature | Description |
|---|---|---|
create() |
(options: JsBoxOptions, name?: string) => Promise<JsBox> |
Create a new box |
listInfo() |
() => Promise<JsBoxInfo[]> |
List all boxes |
getInfo() |
(idOrName: string) => Promise<JsBoxInfo | null> |
Get box info |
get() |
(idOrName: string) => Promise<JsBox | null> |
Get box handle |
metrics() |
() => Promise<JsRuntimeMetrics> |
Get runtime metrics |
remove() |
(idOrName: string, force?: boolean) => Promise<void> |
Remove a box |
close() |
() => void |
Close runtime (no-op) |
// Default runtime
const runtime = JsBoxlite.withDefaultConfig();
// Custom runtime
const runtime = new JsBoxlite({ homeDir: '/custom/path' });
// Create a box
const box = await runtime.create({
image: 'alpine:latest',
cpus: 2,
memoryMib: 512
}, 'my-box');
// List all boxes
const boxes = await runtime.listInfo();
boxes.forEach(info => console.log(`${info.id}: ${info.state.status}`));Runtime configuration options.
| Field | Type | Default | Description |
|---|---|---|---|
homeDir |
string |
~/.boxlite |
Base directory for runtime data |
imageRegistries |
JsImageRegistry[] |
[] |
Registry transport, TLS, search, and auth configuration |
Configuration options for creating a box.
| Field | Type | Default | Description |
|---|---|---|---|
image |
string |
- | OCI image URI |
rootfsPath |
string |
- | Pre-prepared rootfs directory (alternative to image) |
cpus |
number |
1 |
Number of CPU cores |
memoryMib |
number |
512 |
Memory limit in MiB |
diskSizeGb |
number |
- | Persistent disk size in GB |
workingDir |
string |
"/root" |
Working directory inside container |
env |
JsEnvVar[] |
[] |
Environment variables |
volumes |
JsVolumeSpec[] |
[] |
Volume mounts |
network |
NetworkSpec |
{ mode: "enabled" } |
Structured network configuration |
ports |
JsPortSpec[] |
[] |
Local TCP port mappings; omit hostPort for automatic allocation |
secrets |
Secret[] |
[] |
Outbound HTTP(S) secret substitution rules |
advanced |
AdvancedBoxOptions |
{} |
Expert-only options, including capabilities.add and capabilities.drop |
autoRemove |
boolean |
false |
Auto cleanup when stopped |
detach |
boolean |
false |
Survive parent process exit |
Capability policy is intentionally nested with the other expert-only options:
const options = {
image: "alpine:latest",
advanced: {
capabilities: {
add: ["NET_BIND_SERVICE"],
drop: ["NET_RAW"],
},
},
};interface NetworkSpec {
mode: "enabled" | "disabled";
allowNet?: string[];
}Use allowNet only when mode: "enabled". Empty or omitted allowNet means full outbound access. mode: "disabled" removes the guest network interface entirely.
interface JsEnvVar {
key: string;
value: string;
}interface JsVolumeSpec {
hostPath: string; // Path on host
guestPath: string; // Path in container
readOnly?: boolean; // Default: false
}interface JsPortSpec {
hostPort?: number; // None = auto-assign
guestPort: number; // Port inside container
protocol?: string; // "tcp" (UDP is rejected)
hostIp?: string; // Default: "0.0.0.0"
}Port publication is available only with a local runtime. For code that should
work with both local and remote runtimes, use box.network.tunnel(port); each
tunnel handle represents one connection.
OCI EXPOSE declarations do not publish host ports.
interface Secret {
name: string;
value: string;
hosts?: string[];
placeholder?: string; // Default: `<BOXLITE_SECRET:${name}>`
}Handle to a running or stopped box.
| Property | Type | Description |
|---|---|---|
id |
string |
Unique box identifier (ULID) |
name |
string | null |
User-defined name |
network |
JsNetworkHandle |
Box-scoped tunnel operations |
| Method | Signature | Description |
|---|---|---|
info() |
() => Promise<JsBoxInfo> |
Get box metadata |
exec() |
(cmd, args?, env?, tty?) => Promise<JsExecution> |
Execute command |
stop() |
() => Promise<void> |
Stop the box |
metrics() |
() => Promise<JsBoxMetrics> |
Get resource metrics |
Metadata about a box.
| Field | Type | Description |
|---|---|---|
id |
string |
Unique box identifier (ULID) |
name |
string | undefined |
User-defined name |
state |
JsBoxStateInfo |
Runtime state with status, running, and optional pid fields |
createdAt |
string |
Creation timestamp (ISO 8601) |
image |
string |
OCI image reference or rootfs path |
cpus |
number |
Allocated CPU count |
memoryMib |
number |
Allocated memory in MiB |
network |
JsNetworkInfo | null |
Current network configuration and resolved local publications |
interface JsNetworkInfo {
mode: string;
allowNet: string[];
publishedPorts: JsPublishedPort[] | null;
}
interface JsPublishedPort {
guestPort: number;
hostIp: string;
hostPort: number;
protocol: string;
}network === null means network information is unavailable. Within
JsNetworkInfo, publishedPorts === null means the current handle does not know
the lifecycle's publications, [] means there are no active publications, and
a populated array contains concrete active local bindings. JsPortSpec remains
the request type; resolved output uses JsPublishedPort so every reported host
port is concrete.
box.info() always returns a promise. Local metadata reads report
bindings captured when this handle started or reattached the box; REST metadata
reads fetch the current server record. A newly loaded local running box has no
live binding data yet, so box, get, or list info may report
publishedPorts === null until an operation requiring live state reattaches it.
JsBox and SimpleBox expose the same box.network workflow.
| Operation | Signature | Description |
|---|---|---|
| Prepare | await box.network.tunnel(port) |
Return a JsBoxTunnel or BoxTunnel for one TCP connection |
| Inspect | tunnel.endpoint(): string | number |
Return the remote URI or borrowed local file descriptor |
| Connect | await tunnel.connect() |
Consume the tunnel and return its bidirectional connection |
| Read/write | await connection.read(maxBytes), await connection.write(data) |
Exchange bytes with the service |
| Close | await connection.close() |
Close the connection |
Each tunnel handle carries exactly one connection. Call tunnel() again for
each additional or concurrent connection. This differs from ports, which
creates a persistent, local-only host listener that accepts repeated
connections from ordinary host applications.
Handle for a running command.
| Method | Signature | Description |
|---|---|---|
id() |
() => Promise<string> |
Get execution ID |
stdin() |
() => Promise<JsExecStdin> |
Get stdin writer |
stdout() |
() => Promise<JsExecStdout> |
Get stdout reader |
stderr() |
() => Promise<JsExecStderr> |
Get stderr reader |
wait() |
() => Promise<JsExecResult> |
Wait for completion |
kill() |
() => Promise<void> |
Send SIGKILL |
const execution = await box.exec('ls', ['-la', '/']);
// Read stdout
const stdout = await execution.stdout();
while (true) {
const line = await stdout.next();
if (line === null) break;
console.log(line);
}
// Wait for completion
const result = await execution.wait();
console.log(`Exit code: ${result.exitCode}`);Writer for sending input to a running process.
| Method | Signature | Description |
|---|---|---|
write() |
(data: Buffer) => Promise<void> |
Write bytes |
writeString() |
(text: string) => Promise<void> |
Write UTF-8 string |
const stdin = await execution.stdin();
await stdin.writeString('Hello, World!\n');
await stdin.write(Buffer.from([10])); // newlineReaders for streaming output.
| Method | Signature | Description |
|---|---|---|
next() |
() => Promise<string | null> |
Read next line (null = EOF) |
Stream Consumption: Each stream can only be consumed once. After iterating to EOF, subsequent calls return null.
const stdout = await execution.stdout();
while (true) {
const line = await stdout.next();
if (line === null) break;
console.log(line);
}Result of a completed execution.
| Field | Type | Description |
|---|---|---|
exitCode |
number |
Process exit code (0 = success) |
Context manager for basic command execution with automatic cleanup.
import { SimpleBox } from 'boxlite';interface SimpleBoxOptions {
image?: string; // Default: "python:slim"
memoryMib?: number; // Memory in MiB
cpus?: number; // CPU cores
runtime?: JsBoxlite; // Runtime instance
name?: string; // Box name
autoRemove?: boolean; // Default: true
detach?: boolean; // Default: false
workingDir?: string; // Working directory
env?: Record<string, string>; // Environment variables
volumes?: VolumeSpec[]; // Volume mounts
network?: NetworkSpec;
ports?: PortSpec[]; // Port mappings
secrets?: Secret[];
advanced?: {
capabilities?: {
add?: string[]; // Add Linux capabilities
drop?: string[]; // Remove Linux capabilities
};
};
}| Property | Type | Description |
|---|---|---|
id |
string |
Box ID (throws if not started) |
name |
string | undefined |
Box name |
| Method | Signature | Description |
|---|---|---|
getId() |
() => Promise<string> |
Get box ID (async) |
getInfo() |
() => Promise<JsBoxInfo> |
Get box info (async) |
exec() |
(cmd, ...args) => Promise<ExecResult> |
Execute and wait (variadic) |
exec() |
(cmd, args[], env?, options?) => Promise<ExecResult> |
Execute with options (array form) |
stop() |
() => Promise<void> |
Stop the box |
[Symbol.asyncDispose]() |
() => Promise<void> |
Async disposal |
// With async disposal (TypeScript 5.2+)
await using box = new SimpleBox({ image: 'alpine:latest' });
const result = await box.exec('echo', 'Hello!');
console.log(result.stdout);
// Manual cleanup
const box = new SimpleBox({ image: 'alpine:latest' });
try {
const result = await box.exec('ls', '-la');
console.log(result.stdout);
// Per-command options (array form)
const pwd = await box.exec('pwd', [], undefined, { cwd: '/tmp' });
const who = await box.exec('whoami', [], undefined, { user: 'nobody' });
const timed = await box.exec('sleep', ['60'], undefined, { timeoutSecs: 5 });
} finally {
await box.stop();
}The options parameter accepts { cwd?: string; user?: string; timeoutSecs?: number }.
Python code execution sandbox.
import { CodeBox } from 'boxlite';interface CodeBoxOptions extends SimpleBoxOptions {
image?: string; // Default: "python:slim"
}| Method | Signature | Description |
|---|---|---|
run() |
(code: string) => Promise<string> |
Execute Python code |
runScript() |
(scriptPath: string) => Promise<string> |
Run script file |
installPackage() |
(pkg: string) => Promise<string> |
pip install |
installPackages() |
(...pkgs: string[]) => Promise<string> |
Install multiple |
const codebox = new CodeBox({ memoryMib: 1024 });
try {
await codebox.installPackage('requests');
const result = await codebox.run(`
import requests
print(requests.get('https://api.github.com/zen').text)
`);
console.log(result);
} finally {
await codebox.stop();
}Browser automation with Chrome DevTools Protocol.
import { BrowserBox, BrowserType } from 'boxlite';interface BrowserBoxOptions {
browser?: BrowserType; // "chromium" | "firefox" | "webkit"
memoryMib?: number; // Default: 2048
cpus?: number; // Default: 2
}| Browser | Port | Image |
|---|---|---|
chromium |
9222 | mcr.microsoft.com/playwright:v1.47.2-jammy |
firefox |
9223 | browserless/firefox:latest |
webkit |
9224 | browserless/webkit:latest |
| Method | Signature | Description |
|---|---|---|
start() |
(timeout?: number) => Promise<void> |
Start browser |
endpoint() |
() => string |
Get CDP endpoint URL |
import puppeteer from 'puppeteer-core';
const browser = new BrowserBox({ browser: 'chromium' });
try {
await browser.start();
const endpoint = browser.endpoint(); // "http://localhost:9222"
const instance = await puppeteer.connect({ browserURL: endpoint });
const page = await instance.newPage();
await page.goto('https://example.com');
console.log(await page.title());
} finally {
await browser.stop();
}Desktop automation with full GUI environment.
import { ComputerBox } from 'boxlite';interface ComputerBoxOptions {
cpus?: number; // Default: 2
memoryMib?: number; // Default: 2048
guiHttpPort?: number; // Default: 3000
guiHttpsPort?: number; // Default: 3001
}| Method | Signature | Description |
|---|---|---|
mouseMove() |
(x: number, y: number) => Promise<void> |
Move cursor |
leftClick() |
() => Promise<void> |
Left click |
rightClick() |
() => Promise<void> |
Right click |
middleClick() |
() => Promise<void> |
Middle click |
doubleClick() |
() => Promise<void> |
Double click |
tripleClick() |
() => Promise<void> |
Triple click |
leftClickDrag() |
(startX, startY, endX, endY) => Promise<void> |
Drag |
cursorPosition() |
() => Promise<[number, number]> |
Get cursor pos |
| Method | Signature | Description |
|---|---|---|
type() |
(text: string) => Promise<void> |
Type text |
key() |
(keySequence: string) => Promise<void> |
Press key(s) |
| Key | Syntax |
|---|---|
| Enter | Return |
| Tab | Tab |
| Escape | Escape |
| Backspace | BackSpace |
| Delete | Delete |
| Space | space |
| Arrow keys | Up, Down, Left, Right |
| Function keys | F1, F2, ... F12 |
| Page keys | Page_Up, Page_Down, Home, End |
| Modifiers | ctrl, alt, shift, super |
| Combinations | ctrl+c, ctrl+shift+s, alt+Tab |
Examples:
await desktop.key('Return'); // Press Enter
await desktop.key('ctrl+c'); // Copy
await desktop.key('ctrl+shift+s'); // Save As
await desktop.key('alt+Tab'); // Switch window
await desktop.key('ctrl+a Delete'); // Select all and delete| Method | Signature | Description |
|---|---|---|
waitUntilReady() |
(timeout?: number) => Promise<void> |
Wait for desktop |
screenshot() |
() => Promise<Screenshot> |
Capture screen |
scroll() |
(x, y, direction, amount?) => Promise<void> |
Scroll |
getScreenSize() |
() => Promise<[number, number]> |
Get dimensions |
interface Screenshot {
data: string; // Base64-encoded PNG
width: number; // 1024 (default)
height: number; // 768 (default)
format: 'png';
}| Direction | Description |
|---|---|
"up" |
Scroll up |
"down" |
Scroll down |
"left" |
Scroll left |
"right" |
Scroll right |
const desktop = new ComputerBox({ cpus: 4, memoryMib: 4096 });
try {
await desktop.waitUntilReady(60);
// Take screenshot
const screenshot = await desktop.screenshot();
console.log(`${screenshot.width}x${screenshot.height}`);
// GUI interaction
await desktop.mouseMove(100, 200);
await desktop.leftClick();
await desktop.type('Hello, World!');
await desktop.key('Return');
// Access via browser: http://localhost:3000
} finally {
await desktop.stop();
}Interactive terminal sessions with PTY support.
import { InteractiveBox } from 'boxlite';interface InteractiveBoxOptions extends SimpleBoxOptions {
shell?: string; // Default: "/bin/sh"
tty?: boolean; // undefined = auto-detect
}| Value | Behavior |
|---|---|
undefined |
Auto-detect from stdin |
true |
Force TTY with I/O forwarding |
false |
No I/O forwarding |
| Method | Signature | Description |
|---|---|---|
start() |
() => Promise<void> |
Start PTY session |
wait() |
() => Promise<void> |
Wait for shell exit |
const box = new InteractiveBox({
image: 'alpine:latest',
shell: '/bin/sh',
tty: true
});
try {
await box.start();
await box.wait(); // Blocks until shell exits
} finally {
await box.stop();
}import { BoxliteError, ExecError, TimeoutError, ParseError } from 'boxlite';BoxliteError (base)
├── ExecError # Command failed
├── TimeoutError # Operation timeout
└── ParseError # Output parsing failed
Base error class for all BoxLite errors.
try {
await box.exec('invalid-command');
} catch (err) {
if (err instanceof BoxliteError) {
console.error('BoxLite error:', err.message);
}
}Command execution failed (non-zero exit code).
| Property | Type | Description |
|---|---|---|
command |
string |
Failed command |
exitCode |
number |
Non-zero exit code |
stderr |
string |
Standard error output |
try {
await box.exec('false');
} catch (err) {
if (err instanceof ExecError) {
console.error(`Command: ${err.command}`);
console.error(`Exit code: ${err.exitCode}`);
console.error(`Stderr: ${err.stderr}`);
}
}Operation exceeded time limit.
try {
await desktop.waitUntilReady(5);
} catch (err) {
if (err instanceof TimeoutError) {
console.error('Desktop did not become ready');
}
}Failed to parse command output.
try {
const pos = await desktop.cursorPosition();
} catch (err) {
if (err instanceof ParseError) {
console.error('Failed to parse cursor position');
}
}Runtime-wide metrics.
| Field | Type | Description |
|---|---|---|
boxesCreatedTotal |
number |
Total boxes created |
boxesFailedTotal |
number |
Boxes that failed during creation |
numRunningBoxes |
number |
Currently running boxes |
totalCommandsExecuted |
number |
Total commands executed |
totalExecErrors |
number |
Total execution errors |
const metrics = await runtime.metrics();
console.log(`Boxes created: ${metrics.boxesCreatedTotal}`);
console.log(`Running: ${metrics.numRunningBoxes}`);Per-box resource metrics.
| Field | Type | Description |
|---|---|---|
commandsExecutedTotal |
number |
Commands executed on this box |
execErrorsTotal |
number |
Execution errors on this box |
bytesSentTotal |
number |
Bytes sent via stdin |
bytesReceivedTotal |
number |
Bytes received via stdout/stderr |
| Field | Type | Description |
|---|---|---|
cpuPercent |
number | undefined |
CPU usage (0.0-100.0) |
memoryBytes |
number | undefined |
Memory usage in bytes |
networkBytesSent |
number | undefined |
Network bytes sent |
networkBytesReceived |
number | undefined |
Network bytes received |
networkTcpConnections |
number | undefined |
Current TCP connections |
networkTcpErrors |
number | undefined |
Total TCP errors |
| Field | Type | Description |
|---|---|---|
totalCreateDurationMs |
number | undefined |
Total create time |
guestBootDurationMs |
number | undefined |
Guest agent ready time |
stageFilesystemSetupMs |
number | undefined |
Directory setup time |
stageImagePrepareMs |
number | undefined |
Image pull/prepare time |
stageGuestRootfsMs |
number | undefined |
Rootfs bootstrap time |
stageBoxConfigMs |
number | undefined |
Configuration build time |
stageBoxSpawnMs |
number | undefined |
Subprocess spawn time |
stageContainerInitMs |
number | undefined |
Container init time |
const metrics = await box.metrics();
console.log(`CPU: ${metrics.cpuPercent}%`);
console.log(`Memory: ${(metrics.memoryBytes || 0) / (1024 * 1024)} MB`);
console.log(`Boot time: ${metrics.guestBootDurationMs}ms`);Result from SimpleBox.exec().
interface ExecResult {
exitCode: number;
stdout: string;
stderr: string;
}Screenshot capture result.
interface Screenshot {
data: string; // Base64-encoded PNG
width: number;
height: number;
format: 'png';
}Supported browser types.
type BrowserType = 'chromium' | 'firefox' | 'webkit';Default values used by BoxLite.
| Constant | Value | Description |
|---|---|---|
DEFAULT_CPUS |
1 |
Default CPU cores |
DEFAULT_MEMORY_MIB |
512 |
Default memory in MiB |
| Constant | Value | Description |
|---|---|---|
COMPUTERBOX_CPUS |
2 |
Default CPUs |
COMPUTERBOX_MEMORY_MIB |
2048 |
Default memory |
COMPUTERBOX_DISPLAY_WIDTH |
1024 |
Screen width |
COMPUTERBOX_DISPLAY_HEIGHT |
768 |
Screen height |
COMPUTERBOX_GUI_HTTP_PORT |
3000 |
HTTP GUI port |
COMPUTERBOX_GUI_HTTPS_PORT |
3001 |
HTTPS GUI port |
DESKTOP_READY_TIMEOUT |
60 |
Ready timeout (seconds) |
| Constant | Value | Description |
|---|---|---|
BROWSERBOX_PORT_CHROMIUM |
9222 |
Chromium CDP port |
BROWSERBOX_PORT_FIREFOX |
9223 |
Firefox CDP port |
BROWSERBOX_PORT_WEBKIT |
9224 |
WebKit CDP port |
- Node.js SDK README - Quick start and examples
- Getting Started Guide - Installation
- Configuration Reference - BoxOptions details
- Error Codes - Error handling