Open-source Firecracker microVM orchestrator. Each sandbox is a real Linux VM with its own kernel, filesystem, and process isolation — created in seconds, paused for free, resumed in microseconds.
Built for running AI coding agents in isolated environments. A paused sandbox resumes and executes a command in under 3ms.
bhatti create --name dev --cpus 2 --memory 1024
bhatti exec dev -- npm install
bhatti shell dev # Ctrl+\ to detach
bhatti destroy dev
curl -fsSL bhatti.sh/install | bashOn macOS, installs the CLI (~11MB binary). On Linux, asks whether you want the CLI or a full self-hosted server. Re-running updates an existing installation.
Self-hosting? Same command with sudo — it downloads pre-built binaries, a kernel, and an Ubuntu 24.04 rootfs:
curl -fsSL bhatti.sh/install | sudo bashSee Quickstart for full setup details.
On a Raspberry Pi 5 (ARM64, NVMe):
p50 p95 p99
Exec command: 1.26ms 1.88ms 2.93ms
1KB file read: 433µs 733µs 1.08ms
1KB file write: 754µs 1.17ms 1.82ms
Warm resume + exec: 2.70ms 7.36ms 7.36ms
Cold resume + exec: 40.8ms 42.3ms 42.3ms
10 concurrent execs: 12.8ms 22.3ms 22.3ms
VM boot (create + first exec): 8.0s 8.4s 8.4s
Full snapshot (512MB): 3.3s 3.6s 3.6s
Diff snapshot: 20.7ms 35.9ms 35.9ms
Pause (hot→warm): 450µs 611µs 611µs
Resume (warm→hot): 462µs 565µs 565µs
bhatti (host daemon) lohar (guest agent, PID 1 in each VM)
├─ REST/WS API (:8080) ├─ TCP :1024 (exec, files, sessions)
├─ Per-user auth (API keys, SHA-256) ├─ TCP :1025 (port forwarding)
├─ Firecracker engine ├─ PTY sessions + 64KB scrollback
│ (create, exec, snapshot, diff snap) ├─ Atomic file writes
├─ Thermal manager ├─ Process group kill
│ (hot → warm → cold, auto) ├─ Exec as uid 1000 (not root)
├─ Per-user bridge networks (isolated) └─ Config drive (env, secrets)
├─ SQLite store + age encryption
├─ Rate limiting + exec timeouts
└─ Reverse proxy (HTTP + WebSocket)
Idle sandbox → warm after 30s (vCPUs paused, ~400µs resume) → cold after 30min (snapshotted to disk, memory freed, ~50ms resume). Any API request transparently wakes it.
Each user gets their own API key, sandbox limits, and network:
sudo bhatti user create --name alice --max-sandboxes 5
# → API key: bht_... (shown once)- API scoping — users see only their own sandboxes and secrets
- Network isolation — per-user bridge + /24 subnet, cross-user traffic blocked at L2
- Resource caps — per-user limits on sandbox count, CPUs, and memory
- Rate limiting — per-user token buckets (10 creates/min, 120 execs/min)
- Secrets — encrypted at rest (age), scoped per user
| Quickstart | CLI install + server install, user management |
| Architecture | System design, data flow, concurrency model |
| Wire Protocol | Binary framing, connection lifecycle, auth |
| Guest Agent | PID 1 init, PTY, sessions, process management |
| Thermal Management | Hot/warm/cold, diff snapshots, activity caching |
| Networking | Per-user bridges, iptables isolation, kernel ip= |
| API Reference | REST/WebSocket endpoints |
| CLI Reference | All commands — create, exec, shell, user, setup |
| Testing | 11K lines of tests, zero mocks for VM tests |
| Design Decisions | Why TCP over vsock, why no FC SDK, why PID 1, ... |
- Preview URLs —
bhatti publish dev -p 3000→https://dev-k3m9x2.bhatti.sh, auto-wake from sleep on first request - Multi-tenant — per-user API keys, sandbox scoping, network isolation, rate limiting
- Streaming exec — real-time NDJSON output via
Accept: application/x-ndjson - Server-side file truncation —
offset/limit/max_byteson file reads - Diff snapshots — only dirty pages after the first snapshot (~52ms vs ~4.4s)
- Session-aware exec — TTY sessions survive disconnects, scrollback replayed on reattach
- Atomic file writes — temp + fsync + rename, concurrent readers never see partial content
- Process group kill —
SIGKILLto pgid for piped exec,SIGTERMfor TTY sessions - Guest hardening — exec as uid 1000, config drive unmounted after boot, connection/session limits
- Single binary —
bhatti serve= daemon,bhatti create= CLI,bhatti user= admin
Server: Linux (aarch64 or x86_64) with KVM (/dev/kvm) and root access.
CLI: macOS or Linux. No special requirements.