sand is a single Go binary that provisions disposable Claude Code
development VMs on Lima. Spin up an isolated, fully
provisioned VM in seconds, point Claude Code at a repository, and throw the
VM away when you're done.
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 pulls in Lima as a dependency.
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.
By default sand manages VMs on a local Lima. It can also manage a fleet
of VMs spread across your local machine and one or more remote hosts over
SSH, all at once — each host you add is a named Connection Profile,
managed entirely from the TUI's p screen or hand-edited in a secret-free,
shareable profiles.yaml. See
Connection Profiles
for the model. (Earlier, unreleased builds selected a single remote target
via SAND_PROVIDER / SAND_REMOTE_* environment variables; that surface has
been removed in favor of profiles.)
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 + KVMCoverage. 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).