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
| Option | Type | Default | Description |
|---|---|---|---|
strict | boolean | true | Throw CommandError on non-zero exit. Set to false to get the exit code instead. |
cwd | string | — | Working directory inside the sandbox |
env | Record<string, string> | — | Extra environment variables for this exec only |
timeoutMs | number | — | 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 = 255ExecCodeOptions
| Option | Type | Description |
|---|---|---|
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.