Start a live container in one call. Pick any Docker image, set resource limits, and get back a Sandbox you hold like any other object.
Run commands and get stdout, stderr, and exit code back. Stream live output to your process, set a working directory, inject environment variables.
Read and write files directly inside the sandbox. Inject source code, pull build artifacts, inspect logs — all from TypeScript with no extra tooling.
Snapshot the container at any point — filesystem, processes, memory. Resume later from the exact same state. Pay for compute only when you need it.
Branch a running container from any checkpoint. Each fork is an independent Sandbox — run parallel test shards, A/B variants, or speculative executions.
Define a named environment once — image, resources, setup script. drej builds it, snapshots it, and restores from that snapshot on every subsequent call.
Chain steps into a durable workflow. Each step is logged to the ledger — on failure, replay from the last successful checkpoint without re-running earlier work.
Every exec is logged to a durable ledger. Query past sessions, inspect exec counts and timing, or delete records — all through a typed API.
const sb = await client.sandbox({
image: "node:22",
resources: {
cpu: "500m",
memory: "256Mi",
},
});
const { stdout } = await sb.exec(
"node index.js",
);
// stream live output
await sb.exec("npm test")
.pipe(process.stdout);
await sb.writeFile("/app/main.py", src);
const logs = await sb.readFile(
"/var/log/app.log",
);
const entries = await sb.listDirectory(
"/app", { depth: 1 },
);
await sb.checkpoint("before-tests");
// restore exact state later
const resumed = await client.resume(
sandboxId,
);
await resumed.exec("npm test");
await sb.checkpoint();
const fork = await sb.fork();
// two independent containers, same state
await Promise.all([
sb.exec("npm test -- --shard=1/2"),
fork.exec("npm test -- --shard=2/2"),
]);
const env = client.environment("ci", {
image: "node:22",
resources: { cpu: "500m", memory: "512Mi" },
setup: async (sb) => {
await sb.exec("npm ci");
},
});
// builds once, restores from snapshot
const sb = await env.sandbox();
await sb.exec("npm test");
await workflow(client)
.sandbox(
{ image: "node:22", resources },
async (sb) => {
await sb.exec("npm ci");
await sb.exec("npm test");
},
)
.result();
const sessions = await client.sandboxes.list({
status: SandboxStatus.Running,
limit: 20,
});
const details = await client.sandboxes.get(
"ci", sandboxId,
);
// { status, execCount, startedAt }