sbx

command module
v0.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2026 License: MIT Imports: 3 Imported by: 0

README

sbx

CI Go Reference Go Report Card release dependencies license

Give every branch, task or AI agent its own real Postgres, Redis or browser — one that costs nothing while idle, and comes back the instant something needs it.

0 B of RAM when idle · wakes in ~191 ms · one static binary, zero dependencies

The connection is the wake-up call — and it never gets refused

Point psql, a connection pool, Playwright or your test runner at a sleeping sandbox and it just connects. sbx catches that first connection and holds it open while the container starts, then hands over the live socket — the client waits a beat and gets a real answer, and never sees a refused port. The client's own socket is the wake signal: no SDK call, no sbx start, no readiness loop in your code. The connection itself is the start command, and it succeeds on the first attempt — on any protocol that speaks TCP.

That last part is the piece a hand-rolled docker start wrapper can't give you. Everything else here is built around it: sandboxes that drop to 0 B when nobody's using them, and come back the moment anyone does.

Who it's for

  • Teams running many branches at once — twenty branch databases on one laptop, and you pay RAM for only the one you're looking at. Switch branches and the rest drop to 0 B. No more everyone sharing one staging database and stepping on each other's migrations.
  • A fleet of AI agents that each need a real database — hand every agent its own Postgres that dies with the task, woken by its clients (psql, a pool, a test runner — none of which can call an SDK) just by connecting. Keeping every agent's stack alive isn't affordable; a shared database is where the flaky, hard-to-reproduce bugs come from.

A real run, recorded by scripts/demo.sh.

Get a database in three commands

sbx serve --idle 5m &                          # once per machine, not per sandbox
sbx create my-branch --template postgres       # ~492 ms once the image is local
eval "$(sbx env my-branch)"                    # DATABASE_HOST/PORT are now set
psql -U app -d app                             # this wakes it — the call blocks, it doesn't refuse

There is no sbx start and no sbx stop. Opening a socket is the whole signal, so psql, a connection pool, Playwright and your test runner all wake it without knowing sbx exists.


What you can do

Everyday

Run twenty branch databases on one laptop so the ones you're not looking at cost 0 B — no RAM, no bill
Point your existing tools at it, unchanged so anything that opens a socket connects — no SDK, no client library to add
Keep one file per repo sandbox.json says what a branch needs, so a teammate's sbx create matches yours → SPEC
Spin one up with nothing on disk --template postgres, browser, nginx, web-stack (Postgres + Redis), or analytics — so you're never blocked writing a spec first

For AI agents

Give every agent its own workspace so one agent's writes can never corrupt another's — --shell json when a script is reading, not you
Add a service mid-task sbx add task cache --image redis:7-alpine — so an agent that finds it needs a cache doesn't stop to edit a spec
Hand each agent its own copy of a seeded database sbx snapshot once, sbx fork as many as you want — so a write in one is invisible to the rest
Park an agent mid-thought and bring it back sbx checkpoint / sbx resume — memory and processes, not just disk
Run one for a single test, gone after sbx with test-db --template postgres -- go test ./... — so it's always torn down, even on failure
Let an agent reach only the APIs you allow egress_allow: ["api.openai.com"] — the box reaches the listed hosts and nothing else, enforced by a filtering proxy; there's no route around it, and its calls out count as activity so it stays awake while it works
Keep a box awake while it works idle: "never" — an agent computing inside sends no traffic through the port, so this stops the idle timer from sleeping it mid-task
Run code written for OpenSandbox, unchanged sbx serve --osb-addr 127.0.0.1:8080 speaks OpenSandbox's lifecycle and execd APIs, so its Go, Python, JS, Kotlin and C# SDKs work against your own machine — commands, streaming, sessions, files, renew, pause, network policy, snapshots, host and named volumes. Proven by running OpenSandbox's own e2e suite, not a feature table → test/osb
Give an agent sandbox tools over MCP claude mcp add sbx -- sbx mcp — create, run, read and write files in a sandbox, the same 19 tools OpenSandbox's MCP server has → AGENTS
Change what a box may reach while it runs sbx egress <box> --deny '*.example.com' --allow 10.0.0.0/8 — domain, wildcard and CIDR rules, applied live without a restart

The OpenSandbox API always requires a key, loopback included: sbx serve --osb-addr generates one into ~/.sbx/osb/key, sbx mcp reads it from there, and the SDKs take it as export OPEN_SANDBOX_API_KEY="$(cat ~/.sbx/osb/key)" - see SECURITY.md for why. A warm pool (--osb-pool IMAGE[=N]) serves only creates with the same image, entrypoint and resourceLimits as its members, which are the SDKs' defaults (tail -f /dev/null, cpu 1, memory 2Gi); anything else goes cold, and the daemon log names the field that differed - see AGENTS.md.

Scale it up

Keep twenty sandboxes polite on one laptop cpu, memory, gpus per service, so one runaway agent can't starve the rest
Build your own image build: instead of image:, cached by content hash — so a second create does no rebuild work
Take the same spec to a cluster --provider kubernetes, so what worked on your laptop is what runs in CI
Give each sandbox its own kernel, even on a Mac --provider firecracker — a Firecracker microVM; directly on Linux with /dev/kvm, through a helper VM sbx runs for you on an M3+ Mac (macOS 15+; colima is the verified driver, lima is not yet run end to end) or Windows 11 (built and unit-tested; not yet run on a Windows host), refused with the fix anywhere else. sbx doctor says which
Deploy anywhere and still drive it from your terminal sbx pack + sbx connect turn a one-port platform back into local ports

See and drive the fleet

Watch every sandbox live sbx ui — cpu and memory against each service's own ceiling, and where it's been
Drive a deployment from your laptop's terminal sbx ui --connect <url> — wake, sleep, limit, remove, tail logs, f to port-forward here
Read it from a script instead of a screen --json on list, doctor, history, env → AGENTS
Know who changed what, and when sbx history records every change and every wake, secrets redacted

The dashboard

sbx ui — the whole fleet, what each service is using against what it's allowed, and where it's been. Every address is a link: cmd- or ctrl-click opens it in iTerm2, WezTerm, Kitty, GNOME Terminal or Windows Terminal.


Speed

Every number below is measured by a script in this repo, on an Apple M4 (16 GB) — → BENCHMARKS.md has the conditions and how to re-run each one.

Idle costs nothing, so twenty sandboxes on one laptop is twenty disks, not twenty running databases:

xychart-beta
    title "Resident memory - MB, lower is better"
    x-axis ["sleeping sandbox", "sbx daemon", "mysql tuned", "clickhouse", "mysql stock"]
    y-axis "megabytes" 0 --> 420
    bar [0, 9.1, 110, 199, 411]

Waking is a fraction of a second, and mostly it's the workload's own startup — a browser is slow because Chrome is slow to start, not because of sbx:

xychart-beta
    title "Wake latency by workload - median ms, lower is better"
    x-axis ["redis", "chrome (warm)", "postgres", "kubernetes", "chrome (cold)"]
    y-axis "milliseconds" 0 --> 4600
    bar [191, 766, 931, 1534, 3744]

Once it's awake, you won't feel it. A query on an already-open connection costs +15 µs — lost in the noise of a real query, which already crosses a VM boundary at 426 µs. Opening a new connection adds +0.1 ms, inside the normal run-to-run spread. A bulk transfer moves at 6.8 GB/s on loopback — an order of magnitude more than a Postgres COPY will ever feed it — so the database stays the bottleneck a query hits, never sbx.


Install

brew install aryanmehrotra/tap/sbx
or curl · go install · other platforms
curl -fsSL https://raw.githubusercontent.com/aryanmehrotra/sbx/main/scripts/install.sh | sh
# or
go install github.com/aryanmehrotra/sbx@latest

One static binary — macOS · Linux · FreeBSD, amd64 · arm64; Windows via WSL2. Then run the daemon once (it owns the ports sbx env hands out); deploy/ has a launchd plist and a systemd unit, both running as you, not root.

sbx doctor       # what this machine can do
sbx selftest     # create, sleep to zero, wake on a socket, data intact — ~9 s
Every command
sbx create / rm make one from sandbox.json or --template, destroy it with its data
sbx env exports for your tooling — posix, fish, powershell, cmd, json
sbx ready wake it and block until it's serving — the CI one-liner
sbx with create, run a command with its env, always remove it — a fixture for a test
sbx wake / sleep park a sandbox now or bring it back on demand
sbx exec [-t] run anything inside it; -t attaches a terminal for a shell or psql
sbx logs [-f] every service on one structured stdout
sbx cp files in and out (: marks the inside path)
sbx add drop in a service the spec never declared
sbx url a public link that wakes it when opened
sbx snapshot / fork save every service's data, then make as many sandboxes from it as you want
sbx checkpoint / resume save memory and processes and bring them back (CRIU, on a Linux podman runtime)
sbx init / validate write the spec · check one without creating anything
sbx prewarm pull the images now, so the first create isn't a download
sbx gc reclaim volumes whose sandbox is gone
sbx doctor what this machine can do
sbx list · sbx ui what exists and what's awake · the same, live, with cpu and memory
sbx history · sbx templates what happened and who did it · the built-in specs
sbx pack · sbx connect package a sandbox for a one-port platform · turn it back into local ports
sbx serve the daemon — owns the ports, does all waking and sleeping; one per machine

Every sandbox command takes --provider docker|kubernetes|firecracker, --namespace, --isolation container|gvisor|kata|firecracker (on kubernetes: the kata-fc RuntimeClass - unit-tested, not yet run on a cluster) and --socket; SBX_PROVIDER_KIND, SBX_NAMESPACE, SBX_ISOLATION set the defaults and DOCKER_HOST is honoured.


Docs

AGENTS.md pointing an agent at sbx — a block to paste, and the non-obvious bits
USE-CASES.md eleven shapes this fits, with the commands
SPEC.md every field of sandbox.json, and a docker-compose mapping
ARCHITECTURE.md the pieces, both data paths, addressing
BENCHMARKS.md every number, and the script that produced it
COMPARISON.md how sbx relates to E2B, Modal, Fly, Neon, zeropod and more
ROADMAP.md what is next, what it costs, and what is ruled out
TROUBLESHOOTING.md what to do about what you're seeing
console/ metrics, health and a read-only API for a running daemon
CONTRIBUTING.md · SECURITY.md how the tests are arranged · the threat model

MIT. Issues and patches welcome.

Documentation

Overview

Command sbx gives every branch, task or agent its own copy of a project's backing services, and charges nothing for the ones nobody is using. The program lives in internal/app; this root file is only the entry point and the one thing that has to be here.

Directories

Path Synopsis
internal
agentbin
Package agentbin finds a linux sbx binary to run inside a sandbox as its agent.
Package agentbin finds a linux sbx binary to run inside a sandbox as its agent.
app
sbx gives every branch, task or agent its own copy of a project's backing services, and charges nothing for the ones nobody is using.
sbx gives every branch, task or agent its own copy of a project's backing services, and charges nothing for the ones nobody is using.
cli
devcontainer
Package devcontainer reads a devcontainer.json and turns it into a service sbx can run.
Package devcontainer reads a devcontainer.json and turns it into a service sbx can run.
execd
Package execd is the daemon that runs inside a sandbox created through the OpenSandbox API.
Package execd is the daemon that runs inside a sandbox created through the OpenSandbox API.
execdctl
Package execdctl is the host's side of execd's control endpoints: seal before a snapshot, re-key after a restore.
Package execdctl is the host's side of execd's control endpoints: seal before a snapshot, re-key after a restore.
fc
Package fc drives Firecracker: its REST API over a unix socket, the firecracker process that serves it, the pinned binary and guest kernel, and the root filesystem a VM boots from.
Package fc drives Firecracker: its REST API over a unix socket, the firecracker process that serves it, the pinned binary and guest kernel, and the root filesystem a VM boots from.
fc/fcfake
Package fcfake is a Firecracker API server that keeps state and never boots anything.
Package fcfake is a Firecracker API server that keeps state and never boots anything.
fc/guestinit
Package guestinit is PID 1 inside a Firecracker VM: `sbx fc-init`.
Package guestinit is PID 1 inside a Firecracker VM: `sbx fc-init`.
fc/hostcap
Package hostcap answers one question before anything microVM-shaped is attempted: on this machine, which way - if any - can a Firecracker VM be run?
Package hostcap answers one question before anything microVM-shaped is attempted: on this machine, which way - if any - can a Firecracker VM be run?
fchost
Package fchost decides where a Firecracker microVM can run from the machine sbx is on, and when that is not this machine, runs one that can.
Package fchost decides where a Firecracker microVM can run from the machine sbx is on, and when that is not this machine, runs one that can.
fcvsock
Package fcvsock dials a port inside a Firecracker microVM from the host.
Package fcvsock dials a port inside a Firecracker microVM from the host.
features
Package features is the gate in front of anything not yet proven.
Package features is the gate in front of anything not yet proven.
history
Package history is the answer to "what happened to this sandbox, and who did it".
Package history is the answer to "what happened to this sandbox, and who did it".
hostinfo
Package hostinfo reports what the machine a person is sitting at has.
Package hostinfo reports what the machine a person is sitting at has.
jupyter
Package jupyter is the code-interpreter engine behind execd's /code routes: it runs code in Jupyter kernels through a Jupyter Server that the sandbox image provides, and turns what the kernel says into execd's server-sent events.
Package jupyter is the code-interpreter engine behind execd's /code routes: it runs code in Jupyter kernels through a Jupyter Server that the sandbox image provides, and turns what the kernel says into execd's server-sent events.
mcp
Package mcp is a Model Context Protocol server over stdio: JSON-RPC 2.0, one message per line, requests in on stdin and answers out on stdout.
Package mcp is a Model Context Protocol server over stdio: JSON-RPC 2.0, one message per line, requests in on stdin and answers out on stdout.
osb
Package osb serves OpenSandbox's lifecycle API from inside `sbx serve`.
Package osb serves OpenSandbox's lifecycle API from inside `sbx serve`.
osbclient
Package osbclient speaks the OpenSandbox HTTP contract: the lifecycle API (`/v1/sandboxes`) and execd, the per-sandbox agent that runs commands and touches files.
Package osbclient speaks the OpenSandbox HTTP contract: the lifecycle API (`/v1/sandboxes`) and execd, the per-sandbox agent that runs commands and touches files.
osbclient/osbtest
Package osbtest is a fake OpenSandbox server - lifecycle API and execd - for tests of anything that speaks the contract.
Package osbtest is a fake OpenSandbox server - lifecycle API and execd - for tests of anything that speaks the contract.
selfstat
Package selfstat reads the resource usage of the container this process is in, from its own cgroup - no container runtime and no socket required.
Package selfstat reads the resource usage of the container this process is in, from its own cgroup - no container runtime and no socket required.
tui
ui
update
Package update answers "is there a newer sbx" without ever making anybody wait for it.
Package update answers "is there a newer sbx" without ever making anybody wait for it.
wsclient
Package wsclient is the client half of RFC 6455, standard library only.
Package wsclient is the client half of RFC 6455, standard library only.
wsclient/wstest
Package wstest is a deliberately literal WebSocket server for tests of clients.
Package wstest is a deliberately literal WebSocket server for tests of clients.
wsserver
Package wsserver is the server half of RFC 6455, standard library only.
Package wsserver is the server half of RFC 6455, standard library only.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL