Quickstart

Install the sandbox client, start OpenSandbox locally, and run your first command in a container.

Install

bun add @alineo-labs/sandbox @alineo-labs/sqlite

@alineo-labs/sqlite is the ledger every command is written to. For a ledger shared by several processes, use @alineo-labs/postgres instead — storage.

Start a local sandbox server

The quickest path runs OpenSandbox in Docker and writes alineo.config.json for you:

bunx alineo-cli init

A server started this way hands out container addresses your host can't reach, so pass useServerProxy: true to the client in the next step.

To run it on the host instead, without Docker, create ~/.sandbox.toml:

~/.sandbox.toml
[server]
host = "127.0.0.1"
port = 8080

[runtime]
type = "docker"
execd_image = "opensandbox/execd:v1.0.22"

[docker]
network_mode = "bridge"

[ingress]
mode = "direct"

[egress]
mode = "dns"

and start it with uvx opensandbox-server. Container addresses are reachable from the host here, so no proxy is needed.

Hello world

hello.ts
import { Sandbox } from "@alineo-labs/sandbox";
import { SQLiteAdapter } from "@alineo-labs/sqlite";

const client = new Sandbox({
  baseUrl: "http://localhost:8080",
  adapter: new SQLiteAdapter("./ledger.db"),
  useServerProxy: true, // with `alineo init`; leave it off for `uvx opensandbox-server`
});

const sb = await client.sandbox({
  image: "ubuntu:22.04",
  resources: { cpu: "500m", memory: "512Mi" },
  name: "hello-world",
});

try {
  await sb.exec('echo "hello world"').pipe(process.stdout);
} finally {
  await sb.close();
}
bun hello.ts
# hello world

resources is required — OpenSandbox rejects a sandbox without it. There is no connect() on the client and no close() on the adapter: it initialises on first use and closes itself when the process exits.

Capture output

Await the ExecHandle directly to get { stdout, stderr, exitCode }:

const sb = await client.sandbox({
  image: "node:22-slim",
  resources: { cpu: "500m", memory: "256Mi" },
});
try {
  const { stdout: nodeVersion } = await sb.exec('node -e "process.stdout.write(process.version)"');
  await sb.exec(`echo "Running on Node ${nodeVersion.trim()}"`).pipe(process.stdout);
} finally {
  await sb.close();
}

Write and read files

const sb = await client.sandbox({
  image: "ubuntu:22.04",
  resources: { cpu: "500m", memory: "256Mi" },
});
try {
  await sb.writeFile("/tmp/hello.txt", "hello from alineo\n");
  const content = await sb.readFile("/tmp/hello.txt");
  console.log(content.trim()); // "hello from alineo"
} finally {
  await sb.close();
}

Next steps