Examples
Working boxer.toml files for Next.js, Vite, Python, Go, monorepos, devcontainers and other backends, and a Go program that embeds boxer.
The repository's examples/ directory
has one for each common setup:
| example | kind | shows |
|---|---|---|
nextjs | config | a Next.js dev server per worktree, [urls], allowedDevOrigins, tasks |
nextjs-devcontainer | config | the same from devcontainer.json plus a short boxer.toml, with users, port labels and variables |
vite | runnable | Vite with --strictPort, a name per worktree |
python-fastapi | runnable | uv, with a tool in image_setup and the project in setup |
go-api | runnable | a Go service, tasks for test and vet |
monorepo | config | two services in one sandbox, named ports, JUnit-reporting tasks |
host-prep | config | installing on the host with [prep], and when not to |
docker-backend | config | the same project on docker or podman, and what that gives up |
go-embed | program | pkg/boxer running one command in several worktrees at once |
| kind | what it is |
|---|---|
| runnable | a project you can run as is |
| config | a boxer.toml to drop into an existing project |
| program | a Go program that uses boxer as a library |
Every boxer.toml there except monorepo's has been run on a real sandbox.
Run an example
A runnable example must be its own git repository, because boxer keys a sandbox to a worktree:
cp -R examples/go-api /tmp/go-api && cd /tmp/go-api
git init -q && git add -A && git commit -qm init
boxer up && curl -sk "$(boxer url)"The snippets below are trimmed. The files have comments and more tasks. Each directory's
README.md lists its gotchas.
Next.js
image = "mirror.gcr.io/library/node:24-alpine"
setup = ["npm ci --no-audit --no-fund"]
start = ["npx next dev --webpack -p 3000 -H 0.0.0.0"]
ready = "node -e \"fetch('http://127.0.0.1:3000/').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))\""
ready_timeout = "240s"
[network]
allow_hosts = ["registry.npmjs.org"]
ports = ["auto:3000"]
[urls]
enabled = true
[tasks.test]
cmd = "npm test"
description = "the unit tests"// next.config.ts
const nextConfig = { allowedDevOrigins: ["127.0.0.1", "localhost", "*.localhost"] };
export default nextConfig;Run boxer up, then boxer url. A second worktree gets a second server at
https://<branch>.<repo>.localhost:1355, with its own node_modules and .next.
Python with uv
image = "mirror.gcr.io/library/python:3.12-slim"
image_setup = ["pip install --no-cache-dir uv"] # a tool: once, kept in the pack
setup = ["uv sync"] # the project: once per worktree, into .venv
start = ["uv run uvicorn main:app --host 0.0.0.0 --port 8000"]
ready = "python -c \"import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/').status == 200 else 1)\""
ready_timeout = "120s"
[network]
allow_hosts = ["pypi.org", "files.pythonhosted.org"]
ports = ["auto:8000"]
[urls]
enabled = true- uv goes in
image_setupbecause installing it changes the image. It runs once and is cached for every worktree. - The project's dependencies go in
setupbecause they land in this worktree's.venv.
See Install dependencies.
Go
image = "mirror.gcr.io/library/golang:1.24-alpine"
start = ["go run ."]
ready = "wget -q -O /dev/null http://127.0.0.1:8080/"
ready_timeout = "120s"
[network]
ports = ["auto:8080"]
[urls]
enabled = true
[tasks.test]
cmd = "go test ./..."
description = "the Go tests"With module dependencies, add go mod download to setup and "proxy.golang.org" and
"sum.golang.org" to allow_hosts. Go keeps modules outside the worktree, where a recreated
sandbox loses them, so point its caches into the worktree and ignore that directory in git:
[env]
GOMODCACHE = "/workspace/.cache/gomod"
GOCACHE = "/workspace/.cache/gobuild"
GOFLAGS = "-modcacherw"From a devcontainer
boxer reads .devcontainer/devcontainer.json first. Add a short boxer.toml beside it for what
devcontainer has no key for. The main one is the allowlist, because boxer's default network reaches
only the image registry:
[network]
allow_hosts = ["registry.npmjs.org"]
[urls]
enabled = trueEmbedding boxer in Go
go-embed uses pkg/boxer to open a sandbox per worktree. It runs one shell line in all of them
at once and prints each exit code. Run it from a boxer checkout:
go run ./examples/go-embed -- 'npm test' ~/code/app-wt1 ~/code/app-wt2Each directory must be a git worktree. Each reads its own boxer.toml.
Building on boxer and the Go reference
cover the API.
Rules every example follows
- The server binds
0.0.0.0. A forwarded port arrives on the guest's interface. A server on127.0.0.1never sees it. - Ports are
auto:. A fixed host port makes the second worktree fail to start. readyprobes the server.boxer upreturns when the server answers.- The allowlist names only the package registry. boxer allows the image registry itself. A failed install names any host that is missing.