sand is a single Go binary that provisions disposable development VMs for
coding agents. Choose Claude Code, Codex, OpenCode, and Pi, point your
agents at a repository, and throw the VM away when you're done.
VMs can run on your own machine, on another machine over SSH, or on a Proxmox VE host. You pick per VM, and the board shows every location at once.
For full documentation, visit https://lullabot.github.io/sandbar/latest/
brew install lullabot/sandbar/sandThat's it — no Ansible, no Go toolchain, and no clone of this repository
required. Homebrew also pulls in Lima, which sand
uses to run VMs on your own machine and on remote machines over SSH. A
Proxmox host needs no Lima at all, just a scoped API token.
Open the interactive TUI board:
sandPress n to create a VM, then S on its tile for a shell. Or drive it
headlessly:
sand create
sand shell claudeSee Getting Started for the full walkthrough, or the CLI Reference for every command and flag.
Out of the box, sand runs VMs on the machine you launched it from. Add a
Connection Profile and it runs them somewhere else instead — or as well:
- Local — Lima on your own machine. Always present, nothing to configure.
- Remote SSH — Lima on another machine you can SSH into, so VMs live on a workstation or home server while you work from a laptop.
- Proxmox VE — VMs on a Proxmox host through its REST API, using a least-privilege token scoped to one resource pool.
Every enabled profile is live at the same time: one board, tiles from all of
them side by side. Profiles are managed from the TUI's p screen or by
hand-editing a secret-free, shareable profiles.yaml. See
Where VMs Run
for the model and
Proxmox VE Setup
for the one-time host setup.
Use sand land NAME PATH --review (or the Landing pane, l, then v) to
review uncommitted or unpushed changes in your browser. The review server
runs inside the VM, sends the diff to your browser through a loopback
connection, and saves your comments in the checkout for the agent to read.
See Reviewing changes in a browser.
sand also supports golden templates — named, reusable clone sources you
can snapshot from an existing VM. Once you've set up a VM with project-specific
or team-specific tools and configuration, press t on its tile to save it as a
template, then create new VMs from that template with sand create --template <name>
or via the TUI's Source selector. Every clone starts from your saved setup instead
of rebuilding the shared base, then receives the normal finalize pass. See
Golden Templates
for details.
Building from a checkout, running tests, and how sand embeds and runs
its Ansible provisioner are covered in AGENTS.md and the
Contributing
docs.
go test ./... # fast unit + integration suite (no VM needed)
go test ./... -race # the same, with the race detector (what CI runs)
go test -tags limae2e ./... # real-VM e2e — needs a host with Lima + KVM
go test -tags proxmoxe2e ./... # real-VM e2e on Proxmox — needs a configured PVE hostCoverage. CI's unit job measures coverage over ./internal/... (the
cmd/sand entrypoint glue is excluded) and fails if it drops below a floor
committed in .github/workflows/test.yml (COVERAGE_FLOOR). It's a manual
ratchet — no third-party service; the run uploads an HTML report as a build
artifact. To reproduce the gate locally:
go test ./... -race -covermode=atomic -coverpkg=./internal/... -coverprofile=coverage.out
go tool cover -func=coverage.out | tail -1 # the gated total
go tool cover -html=coverage.out # browse itMutation testing (advisory, core packages) runs weekly in CI and on demand. Locally:
go install github.com/go-gremlins/gremlins/cmd/gremlins@v0.5.0
gremlins unleash --config .gremlins.yaml ./internal/provision/...Ansible role tests. molecule/ holds converge/verify scenarios for the
base and samba roles, run in a systemd-capable Debian container (weekly / on
demand in CI). The other roles are a documented follow-up. Locally, with
molecule + Docker installed: molecule test -s base (samba's idempotence
stage has a known failure — see AGENTS.md).