🌲 supertree
Run several Claude Code (or any) sessions on one repository at once — each in its own git worktree and branch, fully isolated.
You're deep in a Claude session on feature/login. An urgent bug lands. Instead of stashing, switching branches, and losing your context, you open a second terminal:
supertree new bugfix/crash
…and you're instantly in a separate checkout on a separate branch with your .env and dependencies already in place — while your feature/login session keeps running untouched. Commit and push from each independently. Delete them when you're done.
Why not just git worktree?
git worktree is the engine supertree is built on — it's what lets multiple working directories share one .git object store, each with its own HEAD and index. (Git even refuses to check out the same branch in two worktrees, so two sessions genuinely can't corrupt each other.)
But raw git worktree leaves the whole workflow to you. supertree automates it:
With raw git worktree |
supertree |
| Invent a path & naming scheme every time |
One command; consistent, tidy layout |
Fresh worktree has only tracked files — no .env, node_modules, .venv, caches → not runnable |
Copies/symlinks a configured set of untracked files so it just runs |
Re-run npm/pip install by hand |
post_create hook runs your setup |
cd in and start your tool |
Launches claude (or a shell) in the new worktree |
git worktree list is bare |
Rich list with dirty state & ahead/behind |
| Remember to remove + delete branch + prune, easy to lose work |
rm / clean with safety checks |
How is this different from treehouse?
treehouse manages a pool of fungible worktrees that agents lease and return (detached HEAD, no branch names) — great for fleets of automated agents. supertree is deliberately simpler and branch-centric: one named worktree per branch that you create, work in, push from, and delete. If you think in branches and pull requests, supertree will feel natural.
Install
macOS / Linux
curl -fsSL https://jennwah.github.io/supertree/install.sh | sh
Windows (PowerShell)
irm https://jennwah.github.io/supertree/install.ps1 | iex
Go
go install github.com/jennwah/supertree@latest
Nix
nix run github:jennwah/supertree
Or add it to your flake inputs:
supertree = {
url = "github:jennwah/supertree";
inputs.nixpkgs.follows = "nixpkgs";
};
From source
git clone https://github.com/jennwah/supertree.git
cd supertree
make install
Quickstart
cd your-repo
supertree init # write supertree.toml, detecting env files & setup
supertree new feature/login # create worktree + branch, then launch Claude
# … work, git commit, git push, open your PR …
supertree list # see every session and its status
supertree cd feature/login # print the path (see shell integration below)
supertree rm feature/login # remove the worktree when you're done
supertree clean # sweep worktrees whose branch was merged
Commands
| Command |
What it does |
supertree new <branch> |
Create a worktree for <branch> (creating the branch if needed), bring over files, run post_create, and launch your session. Flags: --base <ref>, --no-launch. |
supertree list (ls) |
List all worktrees with branch, clean/dirty, and ahead/behind. |
supertree cd <branch> |
Print the worktree path (for cd "$(supertree cd <branch>)"). |
supertree enter <branch> |
Open a subshell in the worktree; exit to return. |
supertree rm <branch> |
Remove the worktree. Refuses on uncommitted changes without --force. Flags: -d/--delete-branch, -f/--force. |
supertree clean |
Remove worktrees whose branch is merged into the default branch (dry-run by default). Flags: -f/--force, --fetch, -d/--delete-branch. |
supertree status |
Summary of repo, config, and worktrees. |
supertree init |
Scaffold supertree.toml with settings detected from your project. |
supertree update |
Update to the latest release. |
supertree version |
Print version info. |
Configuration
supertree init writes a supertree.toml to your repo root. User-wide defaults can also live in ~/.config/supertree/config.toml; repo settings win.
# Worktrees are created under this path.
# "~" is your home directory; "{repo}" is this repository's name.
root = "~/.supertree/{repo}"
# Untracked files copied fresh into every new worktree (e.g. env files).
copy = [".env", ".env.local"]
# Paths symlinked into new worktrees instead of installed fresh — fast, but
# shares mutable state across branches. Opt in for large dep/cache dirs.
link = []
[hooks]
post_create = "npm install" # runs in the new worktree after it's created
pre_remove = "" # runs just before a worktree is removed
[launch]
command = "claude" # started by `supertree new`; empty = a shell
Hooks and launched sessions get these environment variables: SUPERTREE_WORKTREE, SUPERTREE_BRANCH, SUPERTREE_REPO, SUPERTREE_MAIN.
copy vs link. copy gives each worktree its own private copy — safest for env files. link symlinks a path so every worktree shares it; fast for big node_modules/.venv, but branches then share mutable state, so supertree init prefers a fresh post_create install by default.
Shell integration (optional)
supertree cd prints only a path, so you can jump into a worktree in one keystroke. Add to your ~/.zshrc / ~/.bashrc:
st() { cd "$(supertree cd "$1")"; }
Then st feature/login drops you straight into that worktree.
How it works
supertree new <branch>:
- Resolves the worktree directory (
root + a filesystem-safe form of the branch name).
- Runs
git worktree add, creating the branch from your default branch (or --base).
- Copies
copy paths and symlinks link paths from your main checkout.
- Runs the
post_create hook in the new worktree.
- Launches
[launch].command there (or prints the path with --no-launch).
Everything else is a thin, well-behaved wrapper over git worktree — no hidden state, no lock files. Delete a worktree directory by hand and supertree recovers via git worktree prune.
Development
make build # -> bin/supertree
make test
make vet
make snapshot # local goreleaser build, no publish
Cut a release by pushing a tag — GitHub Actions runs GoReleaser:
git tag v0.1.0 && git push origin v0.1.0
License
MIT © jennwah