132 lines
3.2 KiB
Markdown
132 lines
3.2 KiB
Markdown
# sandlot
|
|
|
|
A CLI for branch-based development using git worktrees and Lima VMs. Each branch gets its own worktree and isolated VM.
|
|
|
|
## Concepts
|
|
|
|
**Sandlot** is a thin workflow layer over two things: git worktrees and [Lima](https://github.com/lima-vm/lima). 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
|
|
|
|
- [Bun](https://bun.sh) runtime
|
|
- [Commander](https://github.com/tj/commander.js) for CLI parsing
|
|
- [Lima](https://github.com/lima-vm/lima) for VMs
|
|
|
|
## Setup
|
|
|
|
### Prerequisites
|
|
|
|
- macOS on Apple Silicon
|
|
- [Bun](https://bun.sh) installed
|
|
- Git installed
|
|
- [Lima](https://github.com/lima-vm/lima) installed (`brew install lima`)
|
|
|
|
### Install
|
|
|
|
```bash
|
|
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 a Lima 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:
|
|
|
|
```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": "sandlot-fix-POST",
|
|
"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.
|