Concepts

exec & execCode

Run shell commands with exec() and interpreted code with execCode().

exec()

sb.exec(cmd, opts?) runs a shell command inside the container and returns an ExecHandle.

// Await for full result
const { stdout, stderr, exitCode } = await sb.exec("node --version");

// Stream stdout in real time
await sb.exec("npm run build").pipe(process.stdout);

// Iterate chunks
for await (const chunk of sb.exec("npm test").stdout()) {
  process.stdout.write(chunk);
}

Multi-line scripts

Pass a multi-line string to run a bash script:

const script = `
#!/bin/bash
set -euo pipefail
echo "=== system info ==="
uname -a
echo "=== disk usage ==="
df -h /
`.trim();

await sb.exec(script).pipe(process.stdout);

ExecOptions

OptionTypeDefaultDescription
strictbooleantrueThrow CommandError on non-zero exit. Set to false to get the exit code instead.
cwdstring—Working directory inside the sandbox
envRecord<string, string>—Extra environment variables for this exec only
timeoutMsnumber—Abort the command after this many milliseconds

Exec timeout

Use timeoutMs to abort a command that runs too long:

try {
  await sb.exec("npm test", { timeoutMs: 30_000 }); // abort after 30s
} catch (e) {
  if (e instanceof CommandError) {
    console.error("timed out or failed:", e.exitCode);
  }
}

Strict vs non-strict

// strict (default) — throws CommandError on non-zero exit
try {
  await sb.exec("exit 42");
} catch (e) {
  if (e instanceof CommandError) {
    console.error(`exit ${e.exitCode}`); // 42
  }
}

// non-strict — returns exitCode in result
const { exitCode } = await sb.exec("test -f /etc/hostname", { strict: false });
if (exitCode === 0) {
  console.log("file exists");
}

Using captured output in subsequent commands

const { stdout: nodeVersion } = await sb.exec('node -e "process.stdout.write(process.version)"');

await sb.exec(`echo "Building with ${nodeVersion.trim()}"`).pipe(process.stdout);

Template literals with exec output work because the exec is already awaited — there's no ordering issue.

execCode()

sb.execCode(code, opts?) runs code via the sandbox's code interpreter (Python, JS, TypeScript) using the execd /code endpoint. Requires a code-interpreter image.

import { CodeLanguage } from "@alineo-labs/sandbox";

const sb = await client.sandbox({
  image: "opensandbox/code-interpreter",
  resources: { cpu: "500m", memory: "512Mi" },
  // Required for this image — starts the Jupyter kernel service execCode() depends on.
  entrypoint: ["/opt/code-interpreter/code-interpreter.sh"],
});

Stateless execution

Each call without a context runs in an isolated interpreter session:

await sb
  .execCode(
    `
import sys, math
print(f"Python {sys.version.split()[0]}")
print(f"pi = {math.pi:.6f}")
`.trim(),
  )
  .pipe(process.stdout);

Stateful execution

Contexts must be created first via createCodeContext() — you can't hand-roll one. Pass the returned context to make variables persist across calls:

const ctx = await sb.createCodeContext(CodeLanguage.Python);

await sb.execCode(`data = [2**i for i in range(8)]`, { context: ctx });
await sb.execCode(`print(f"sum = {sum(data)}")`, { context: ctx }).pipe(process.stdout);
// sum = 255

ExecCodeOptions

OptionTypeDescription
context{ id: string, language: CodeLanguage }Stateful interpreter session. Variables defined in one call are available in the next.

CodeLanguage

import { CodeLanguage } from "@alineo-labs/sandbox";

CodeLanguage.Python; // "python"
CodeLanguage.JavaScript; // "javascript"
CodeLanguage.TypeScript; // "typescript"

proxy()

await sb.proxy(port: number): Promise<{ url: string; headers: Record<string, string> }>

Returns a proxied URL and auth headers for a port running inside the sandbox. Use this to send HTTP requests to a server started with exec.

await sb.exec("node server.js &");
// wait a moment for the server to be ready
await sb.exec("sleep 1");

const { url, headers } = await sb.proxy(3000);
const res = await fetch(`${url}/health`, { headers });
console.log(await res.text());

The returned url is routable from outside the sandbox. The headers contain the execd auth token required by OpenSandbox's proxy layer — pass them along with every request.

metrics()

await sb.metrics(): Promise<{ cpu: number; memory: number; timestamp: string }>

Returns current CPU and memory usage for the sandbox container.

const { cpu, memory, timestamp } = await sb.metrics();
console.log(`CPU: ${cpu}, Memory: ${memory} at ${timestamp}`);

Useful for monitoring resource consumption during heavy workloads or detecting runaway processes before a timeout fires.