One API, any provider
Use common create, exec, files and destroy calls. Choose provider configuration and check its supported capabilities.
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.
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",
}),
)import { Sandbar } from "sandbar-sdk"
import { boxdAdapter } from "@sandbar-sdk/boxd"
const client = await Sandbar.connect({
adapter: boxdAdapter,
credentials: { apiKey: process.env.BOXD_API_KEY! },
config: { org: process.env.BOXD_ORG!, networkPolicy: "internet" },
})import { Sandbar } from "sandbar-sdk"
import { vercel } from "@sandbar-sdk/vercel"
const client = await Sandbar.connect({
adapter: vercel,
credentials: { token: process.env.VERCEL_TOKEN! },
config: {
teamId: process.env.SANDBAR_VERCEL_TEAM_ID!,
projectId: process.env.SANDBAR_VERCEL_PROJECT_ID!,
},
})
await client.sandboxes.with({}, async (box) => {
const run = await box.exec(["printf", "ready"])
console.log(run.stdoutText())
})
await client.close()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.
$ 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
Use common create, exec, files and destroy calls. Choose provider configuration and check its supported capabilities.
Save references to recover across invocations. Scope sandbox cleanup while keeping snapshots and volumes.
OpenTelemetry traces connect SDK calls, provider operations, errors, and recovery context. Integrates with Sentry and Datadog.
Implement create and destroy to start. Add exec, files and recovery as your provider supports them.
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.
// 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: [] };
},
};