Your metal. Machines on demand.
Linux VMs that manage themselves. Create in seconds, snapshot everything, resume in milliseconds. On your hardware, open source.
curl -fsSL bhatti.sh/install | sudo bash
CORE
Real machines. Zero waste.
01
Real VMs. Not containers.
Every machine runs its own Linux kernel. Separate filesystem, separate network, separate process space. Not a namespace trick — a separate computer.
02
Snapshot everything. Not just files.
When bhatti snapshots a machine, it captures everything: running processes, open file descriptors, TCP connections, in-memory state. Resume picks up exactly where it left off.
03
Idle machines cost nothing.
Idle machines pause their CPUs automatically. Left idle longer, they snapshot to disk and free all memory. Any request wakes them transparently — you never manage this.
SYS.PERFORMANCE // LATENCY
| Operation | p50 | p99 |
|---|---|---|
| Create a machine | 266ms | 291ms |
| Snapshot to disk (1024MB) | 485ms | 807ms |
| Wake on request (cold) | 360ms | 430ms |
| Wake on request (warm) | 3.7ms | 10.2ms |
| Destroy a machine | 87ms | 96ms |
| Run a command | 12ms | 14ms |
| 20 commands in parallel | 32ms | 39ms |
Hetzner AX102, btrfs, bhatti v1.11.0, CLI on the daemon host.
Reproduce: bench/run.sh.
SYS.ARCHITECTURE
How it works
Click any component to explore.
Host Machine
REST / WS API
routes, proxy, NDJSON streaming
Thermal Manager
hot → warm → cold lifecycle
Firecracker Engine
create, exec, snapshot, restore
SQLite + age
state, secrets, users
Binary wire protocol · TCP :1024
daemon ⇌ lohar
hot ⇄ warm ⇄ cold
lohar PID 1
exec / shell
PTY sessions
file ops
port forward
eth0 (kernel ip=)
rootfs.ext4
config.ext4
vol-*.ext4
/var/lib/bhatti/sandboxes/
Host Networking
brbhatti-N bridge
TAP device
iptables NAT
CAPABILITIES
What people use it for
One sandbox per AI agent
The original use case for bhatti. Each agent gets its own Linux VM. Snapshot at any tool call so you can branch from that exact moment if the run goes sideways.
# Each agent gets its own Linux VM
$ bhatti create --name agent --image ai
sandbox/agent created (2 vCPU, 2048 MB)
# Snapshot before a risky tool call
$ bhatti snapshot create agent --name pre
✓ checkpoint "pre" created (2048MB)
# Run goes sideways? Branch from there:
$ bhatti snapshot resume pre --name retry
✓ restored, state intact
# 40 agents on a Pi; idle ones go cold
$ bhatti list | grep agent | wc -l
40 Preview environments per PR, free when idle
One sandbox per pull request. `bhatti publish` gives it a public URL with TLS. Idle previews pause themselves, snapshot to disk after thirty minutes, and wake on the next request in ~50 ms. No rented infrastructure.
# CI spins up a preview from your image
$ bhatti create --name pr-247 --image base
$ bhatti exec pr-247 -- ./deploy.sh
$ bhatti publish pr-247 -p 3000
Published: https://pr-247.bhatti.sh
# Days later — the sandbox is cold
$ bhatti list
NAME STATUS THERMAL URL
pr-247 stopped cold https://...
# Reviewer opens the URL — auto-wake
$ curl -s https://pr-247.bhatti.sh
{"build":"ok"} # wake + serve, ~50ms Anything you can rootfs is yours
OCI pull, Docker import, or save a running sandbox. Whatever you put in a rootfs becomes a Linux VM that snapshots, resumes, and idles for free. Postgres, browser automation, full desktops — it all just works.
# Pull an OCI image as a rootfs
$ bhatti image pull ghcr.io/myorg/devbox
✓ pulled, converted (820MB)
# Or import a local Docker image
$ bhatti image import my-app:latest
✓ imported
# Or save a running sandbox as a base
$ bhatti image save dev --name stack
✓ saved "stack" (1024MB)
# Whichever path — snapshottable real VM
$ bhatti create --name web --image stack
$ bhatti snapshot create web --name ready
✓ checkpoint "ready" created (1024MB) CLI
Every command
Single binary. bhatti serve starts the daemon, everything else talks to its API.
bhatti create <name> [--cpus N] [--memory MB] [--image NAME] [--init CMD] [--env K=V] [--volume V:/mnt] [--secret K] [--file local:guest] [--keep-hot] [--hugepages]
Create a new machine
bhatti destroy <name> [-y]
Destroy a machine (alias: rm)
bhatti edit <name> [--keep-hot] [--allow-cold]
Update machine settings
bhatti list [-o wide]
List your machines (alias: ls)
bhatti inspect <name>
Show machine details (alias: info)
bhatti start <name> [--force]
Resume a stopped machine
bhatti stop <name>
Snapshot and stop a machine
Execution & shells
bhatti exec <name> -- <cmd> [--timeout S] [--detach]
Run a command
bhatti shell <name> [--new]
Interactive terminal (Ctrl+\ to detach)
bhatti ps <name>
List active sessions in a machine
bhatti ports <name>
List listening TCP ports inside a machine
Files & Secrets
bhatti file read <name> <path>
Read a file
bhatti file write <name> <path> < stdin
Write a file (atomic)
bhatti file ls <name> <path>
List a directory
bhatti secret set <key> <value>
Store an encrypted secret
bhatti secret list
List secret names
bhatti secret delete <key>
Delete a secret
Images
bhatti image list
List available images
bhatti image pull <ref> [--name N] [--auth U:T]
Pull an OCI image from a public registry
bhatti image import <docker-ref> | --tar <path> [--name N]
Import from local Docker or a tarball
bhatti image save <sandbox> --name <image>
Save a running machine's rootfs as a reusable image
bhatti image delete <name> [-y]
Delete an image
bhatti image share <image> --user <name>...
Share an image with specific users (server-only)
bhatti image unshare <image> --user <name>...
Revoke image access (server-only)
Snapshots
bhatti snapshot create <sandbox> --name <snap>
Checkpoint a running machine (memory + processes + disk)
bhatti snapshot list
List snapshots
bhatti snapshot resume <snap> [--name <new>]
Resume a snapshot into a new machine
bhatti snapshot delete <snap> [-y]
Delete a snapshot
Networking & Publishing
bhatti publish <name> -p <port> [-a <alias>] [--shell]
Publish a port → https://alias.bhatti.sh
bhatti unpublish <name> -p <port>
Remove a published port
bhatti share <name> [--revoke]
Generate a web shell URL
Volumes
bhatti volume create --name <v> --size <MB>
Create a persistent volume
bhatti volume list
List volumes
bhatti volume delete <name> [-y]
Delete a volume
bhatti volume resize <name> --size <MB>
Resize a volume (grow only)
bhatti volume clone <src> --name <new>
Clone a volume (point-in-time copy)
bhatti volume backup <name>
Back up a volume to S3-compatible storage
bhatti volume backup-list <name>
List backups for a volume
bhatti volume restore <name> --backup-id <id>
Restore a volume from a backup
bhatti volume backup-delete <name> <id> [-y]
Delete a volume backup
Server & admin
bhatti serve
Start the daemon (server-only)
bhatti setup
Configure CLI endpoint + API key
bhatti version
Print version, check for updates
bhatti update [--cli-only] [--tiers <list>]
Update bhatti
bhatti completion <bash|zsh|fish>
Generate a shell completion script
bhatti user create --name <u> [--max-sandboxes N] [--max-cpus N] [--max-memory MB]
Create a user (server-only)
bhatti user list
List users (server-only)
bhatti user rotate-key <name>
Rotate a user's API key (server-only)
bhatti user delete <name> [-y]
Delete a user (server-only)
bhatti admin status
One-shot system overview (server-only)
bhatti admin events [--type T] [--since 24h] [--user U] [--sandbox S]
Query the event log (server-only)
bhatti admin metrics [--since 1h]
Query metrics snapshots (server-only)
DEPLOY.SELF_HOST
Run it on your hardware.
One command. Any Linux machine with KVM. Downloads pre-built binaries, a kernel, and an Ubuntu 24.04 rootfs. No Docker, no containers, no orchestration layer.
Requirements
- Linux (x86_64 or ARM64)
- Hardware virtualization (/dev/kvm)
- Root access for daemon (Firecracker requirement)
Running on: two Raspberry Pi 5s with NVMe HATs at home, a Hetzner AX102 in production.
# Install on any Linux box with KVM
$ curl -fsSL bhatti.sh/install | sudo bash
==> Installing bhatti (server, minimal tier)
✓ Firecracker + jailer
✓ bhatti, lohar, kernel, rootfs
✓ admin API key in ~/.bhatti/config.yaml
✓ bhatti.service started
# Create a sandbox — no setup step needed
$ bhatti create --name dev
sandbox/dev created (1 vCPU, 1024 MB)
$ bhatti exec dev -- uname -a
Linux dev 6.1.155 #1 SMP aarch64 GNU/Linux
# Add a teammate; let them drive it remotely
$ sudo bhatti user create --name alice
bht_alice_abc123...
# Then on their machine:
$ bhatti setup --url https://api:8080 \
--token bht_alice_abc123
✓ authenticated (0 sandboxes) SYS.DOCUMENTATION
Documentation
Quickstart
Install, configure, and run your first sandbox in two minutes
→Self-Hosting
Install the daemon on your own hardware
→CLI Reference
Every command, global flags, environment variables
→API Reference
REST endpoints with curl examples
→Configuration
Server config, layered loading, data dir layout
→Architecture
System design, data flow, concurrency model
→Thermal States
Hot/warm/cold transitions and diff snapshots
→Networking
Per-user bridges, TAP devices, kernel ip=
→Wire Protocol
Binary framing, connection lifecycle, auth
→