Quickstart
Run your first workflow — install, configure, and run a multi-step pipeline in one await.
Install
npm install @alineo-labs/sandbox @alineo-labs/workflowConfigure
import { Sandbox } from "@alineo-labs/sandbox";
import { SQLiteAdapter } from "@alineo-labs/sqlite";
import { workflow } from "@alineo-labs/workflow";
const client = new Sandbox({
baseUrl: "http://localhost:8080",
adapter: new SQLiteAdapter("./ledger.db"),
});No connect() call needed — the adapter initializes lazily on first use.
Run a workflow
await workflow(client)
.sandbox({ image: "node:22", resources: { cpu: "500m", memory: "512Mi" } }, (sb) => {
sb.exec("node --version");
sb.exec("npm --version");
})
.pipe(process.stdout);No close() call needed either — Sandbox has no such method; the adapter closes itself automatically when the process exits.
The callback receives a SandboxBuilder. All calls inside it queue operations synchronously — nothing runs until .pipe() or .result() is awaited. The sandbox is created, all ops are flushed in order, then the sandbox is closed automatically.
Capture output
Use .result() instead of .pipe() to get the combined stdout and any captured file values:
const { stdout, vars } = await workflow(client)
.sandbox({ image: "node:22", resources: { cpu: "500m", memory: "512Mi" } }, (sb) => {
sb.exec("node --version > /tmp/ver.txt");
sb.readFile("/tmp/ver.txt", "nodeVersion");
})
.result();
console.log(vars.nodeVersion); // "v22.x.x\n"Next steps
- SandboxBuilder operations — the full set of queued ops
- Control flow — retry, when, forEach
- Parallel & sequence — multi-sandbox patterns
Workflow SDK
@alineo-labs/workflow adds a lazy, declarative layer over the Core SDK — describe a pipeline, then run it with one await, with sandbox lifecycles managed for you.
SandboxBuilder
The object passed to every workflow callback — queues operations synchronously, flushes them when the workflow is awaited.