Sandbox router for TypeScript

One SDK.
Every sandbox.

A typed API to create, run code in, and tear down sandboxes on Daytona, E2B, boxd, Boat, Runloop and Vercel. Keep application workflows consistent while configuring each provider explicitly.

v0.7.0 on npm · Getting started
run.ts
import { Sandbar, Image } from "sandbar-sdk"
import { daytona } from "@sandbar-sdk/daytona"

const client = await Sandbar.connect(
  daytona({
    apiKey: process.env.DAYTONA_API_KEY!,
    target: "us",
    environment: Image.prepared("daytona-small"),
    networkPolicy: "daytona-default",
  }),
)
await client.sandboxes.with({}, async (box) => {
  const run = await box.exec(["printf", "ready"])
  console.log(run.stdoutText())
})
await client.close()
connecting…
Adapters & support →
  • Daytona
  • E2B
  • boxd (exp)
  • Boat (exp)
  • Runloop (exp)
  • Vercel
  • Modal (exp)
  • + your adapter
@sandbar-sdk/cli

Same sandboxes. Straight from your shell.

sandbar creates, runs in and removes sandboxes on any provider with an adapter. It never prompts, every command has a --json form, and exit codes say what to do next, so your coding agent can drive it as easily as you can.

Install the CLI
Teach your agent to use it
zsh — sandbar
$ export SANDBAR_PROVIDER=e2b E2B_API_KEY=...
$ sandbar create --name web
web
$ sandbar cp ./app.py web:/tmp/app.py
$ sandbar exec web -- python3 /tmp/app.py
hello from e2b
$ sandbar ls
NAME  STATE    PROVIDER  PROFILE  ID            CREATED
web   running  e2b       e2b      i8mq2v0x7cz4  2026-10-19T09:41:07.312Z
$ sandbar rm web
web
exit 0 · sandbox removedvia e2b

Typed workflows. Plain TypeScript.

One API, any provider

Use common create, exec, files and destroy calls. Choose provider configuration and check its supported capabilities.

Plays nice with serverless

Save references to recover across invocations. Scope sandbox cleanup while keeping snapshots and volumes.

Traced end to end

OpenTelemetry traces connect SDK calls, provider operations, errors, and recovery context. Integrates with Sentry and Datadog.

Small adapters

Implement create and destroy to start. Add exec, files and recovery as your provider supports them.

@sandbar-sdk/adapter

Bring your own provider

Wrap any sandbox API with defineAdapter. Declare config and credential schemas, implement the operations your provider supports, and Sandbar handles lifecycle, error mapping and recovery around it.

Writing an adapter →
adapters/acme.ts · excerpt
// Inside your adapter's connect() method:
// Authenticate the client and verify scope first.
return {
  scope,
  supports: { images: ["prepared"], network: ["blocked"] },
  async create(input, ctx) {
    const box = await client.spawn({
      account: account.id,
      imageId: input.image.value,
      region: config.region,
      blockAllEgress: true,
      public: false,
      requestId: ctx.submissionId,
    });
    return {
      id: box.id,
      state: box.ready ? "running" : "unknown",
    };
  },
  async destroy(box) {
    await client.deleteAndWait(box.id, account.id, config.region);
    return { computeStopped: true, retainedResources: [] };
  },
};