treehouse
The worktree pool behind every crewmate — acquire, lease, reuse, prune — and why you rarely have to touch it yourself.
Running parallel agents requires worktrees, and managing worktrees efficiently was a pain. Treehouse manages a pool of resuable worktrees so I can grab one with my eyes closed. — @kunchenguid, 2026-03-17
treehouse ("Manage worktrees without managing worktrees") was the first tool in the stack. It keeps a pool of isolated git worktrees, or experimental Jujutsu workspaces, so each agent gets a clean environment instantly. Dependencies and build caches survive between reuses.
use firstmate when you realize you are constantly juggling between multiple sessions... if you use firstmate then firstmate will use treehouse for you and you don't even need to think about it. — @kunchenguid, 2026-06-27
Install#
curl -fsSL https://kunchenguid.github.io/treehouse/install.sh | sh
# or: nix run github:kunchenguid/treehouse · go install github.com/kunchenguid/treehouse@latest
firstmate needs it for the tmux, Herdr, Zellij and cmux backends, but not Orca, which owns its own worktrees.
How acquisition works#
treehouse → find repo root → git fetch origin →
scan pool for a safely reusable worktree (this clone's, idle, unleased, clean,
HEAD merged into the exact reset target; skip if safety/ownership unprovable)
found? yes → reset to latest default branch
no → create new worktree (detached HEAD at latest default branch) & add to pool
→ spawn subshell in worktree (agent works here)
→ exit subshell
→ terminate lingering worktree processes, verify none remain
→ reset worktree & return to pool (ready for next agent)
Design points:
- Detached HEAD by default. Use
-b <branch>to create a branch and--base <branch>to pick a different cut point. - No daemon. State is a locked
treehouse-state.json. - Clone-correct reuse. Two clones of one remote share a pool, but a slot is only reused by the clone that owns it.
- In-use detection by scanning processes and short-lived reservations.
- Durable leases:
treehouse get --leasereserves a slot with no process inside it.treehouse lease <name>protects an existing slot in place. - Safe recovery. A corrupt state file is rebuilt from disk. Recovered slots stay leased until an automatic check proves them idle, unchanged and landed. Untracked files are moved to a backup folder, never deleted.
--forcewas removed. It was replaced by narrow--include-unlanded,--include-in-useand--include-leasedflags ondestroy, because the old flag "overrode every protection at once".
Commands#
| Command | Does |
|---|---|
treehouse / treehouse get |
acquire a worktree and open a subshell |
treehouse get --lease [--json] |
durable lease; prints the path |
treehouse lease <name> |
lease an existing slot in place |
treehouse enter <name> |
subshell into an existing slot, even if in use |
treehouse status [--json] |
pool status |
treehouse return [path\|name] |
release a slot back to the pool |
treehouse prune [--yes] [--prune-orphans] |
remove stale idle slots (dry run by default) |
treehouse destroy <path> [--include-...] |
deliberate, narrowly scoped removal |
treehouse init |
write a default treehouse.toml |
Config#
Precedence: flag > env > repo treehouse.toml > ~/.config/treehouse/config.toml > default.
| Key | Default | Use |
|---|---|---|
max_trees |
16 | pool size |
root |
~/.treehouse |
"." keeps the pool inside the project |
base_branch |
default branch | non-default cut point |
unique_leaf |
off | name slots <repo>-<slot> for tools that key off the directory name |
worktree_path |
— | custom path template, e.g. {repo_parent}/{repo}-{slot} |
vcs |
git | "jj" (experimental) |
apfs_sharing |
— | "fresh" for macOS copy-on-write sharing of large tracked files |
[hooks] |
— | post_create, pre_destroy, user-level only, so an untrusted clone can't run checked-in shell |
In firstmate#
fm-spawn.shtypestreehouse getinto the new task pane and waits up to 60s for the shell to land in an isolated slot. The worker runs inside treehouse's subshell, and the process scan is what marks the slot in use. A per-project lock serialises slot allocation across the machine.fm-teardown.shreturns it, but only after the landed-work proof. It also verifies that no other task record names the same slot, to guard against a reused slot.- The primary checkout and every crewmate worktree are linked worktrees of the same repo. The only valid "tangle" is the primary checkout sitting on a named non-default branch.
- On Herdr,
treehouse getleaves a nested shell under the pane. That is known and handled (see Troubleshooting).
You shouldn't need to run treehouse by hand while firstmate is managing a project. treehouse status is safe to look at.