# sandlot A CLI for branch-based development using git worktrees and Apple containers. Each branch gets its own worktree and isolated VM. ## Concepts **Sandlot** is a thin workflow layer over two things: git worktrees and [Apple containers](https://github.com/apple/container). The idea is that spinning up a branch should give you a fully isolated environment — filesystem and runtime — with zero setup. When you're done, use git to merge and `sandlot rm` to clean up. A sandlot **session** is a (worktree, VM) pair tied to a branch. Sessions are created with `sandlot new ` and destroyed with `sandlot rm `. ## Tech Stack - [Bun](https://bun.sh) runtime - [Commander](https://github.com/tj/commander.js) for CLI parsing - [Apple container](https://github.com/apple/container) for VMs ## Setup ### Prerequisites - macOS on Apple Silicon - [Bun](https://bun.sh) installed - Git installed - [container](https://github.com/apple/container) installed and available on PATH ### Install ```bash git clone https://github.com/your/sandlot cd sandlot bun install bun link ``` This makes `sandlot` available globally. ## CLI ### `sandlot new ` Create a new session. This: 1. Checks out the branch if it exists (local or remote), or creates a new branch from current HEAD 2. Creates a git worktree at `.sandlot//` (relative to the repo root) 3. Boots an Apple container VM mapped to that worktree 4. Drops you into the VM shell ``` $ sandlot new fix-POST Creating worktree at .sandlot/fix-POST/ Booting VM... root@fix-POST:~# ``` ### `sandlot list` Show all active sessions. ``` $ sandlot list BRANCH VM STATUS WORKTREE fix-POST running .sandlot/fix-POST/ refactor-auth stopped .sandlot/refactor-auth/ ``` ### `sandlot open ` Re-enter an existing session's VM. If the VM is stopped, boots it first. ``` $ sandlot open fix-POST Booting VM... root@fix-POST:~# ``` ### `sandlot stop ` Stop a session's VM without destroying it. The worktree and branch remain. ### `sandlot rm ` Tear down a session. Stops the VM, removes the worktree, deletes the local branch. Does not touch the remote branch. ## Configuration Optional `sandlot.json` at the repo root: ```json { "vm": { "cpus": 4, "memory": "8GB", "image": "ubuntu:24.04", "mounts": { "/path/to/shared/deps": "/deps" } } } ``` ## State Sandlot tracks sessions in `.sandlot/state.json` at the repo root: ```json { "sessions": { "fix-POST": { "branch": "fix-POST", "worktree": ".sandlot/fix-POST", "vm_id": "container-abc123", "created_at": "2026-02-16T10:30:00Z", "status": "running" } } } ``` `.sandlot/` should be added to `.gitignore`. ## Edge Cases - **Stale VMs**: If a VM crashes, `sandlot open` detects the dead VM and reboots it. - **Multiple repos**: State is per-repo. No global daemon. - **Branch name conflicts**: If `.sandlot//` already exists as a directory but the session state is missing, prompt to clean up or recover. ## Non-Goals - Not a CI/CD tool. No pipelines, no test runners. - Not a replacement for git. All git state lives in the real repo. Sandlot manages worktrees and VMs only. - No multi-user collaboration features. This is a single-developer workflow tool.