sandlot/SPEC.md
2026-02-17 07:57:24 -08:00

3.3 KiB

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. 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 <branch> and destroyed with sandlot rm <branch>.

Tech Stack

Setup

Prerequisites

  • macOS on Apple Silicon
  • Bun installed
  • Git installed
  • container installed and available on PATH

Install

git clone https://github.com/your/sandlot
cd sandlot
bun install
bun link

This makes sandlot available globally.

CLI

sandlot new <branch>

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/<branch>/ (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 <branch>

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 <branch>

Stop a session's VM without destroying it. The worktree and branch remain.

sandlot rm <branch>

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:

{
  "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:

{
  "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/<branch>/ 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.