Worktrees
A Bonsai workspace holds one default worktree for the base branch plus any
number of managed branch worktrees. First-run onboarding lets you keep them
under ./.bonsai/worktrees, under
~/.bonsai/projects/<project>/worktrees, or in the classic project folder
with sibling worktrees. These commands manage that set.
Add a Branch Worktree
bonsai add ma-123-implement-auth
add fetches origin, checks out the remote branch when it exists, or
creates a new branch from the configured base branch. It assigns the
worktree a stable port slot, writes the generated .env.local, creates the
Caddy route snippet, applies shared files and .worktreeinclude copies, and
runs the configured install, setup, and postadd commands.
Create a missing branch from a different base branch for one command:
bonsai add ma-123-implement-auth --base-branch develop
Add a Pull Request Worktree
bonsai add --pr 123
bonsai checkout --pr 123
PR worktrees require the GitHub CLI (gh) to be installed and authenticated.
For same-repository PRs, Bonsai fetches the head branch and prepares a normal,
pushable branch worktree. For fork PRs, Bonsai fetches
pull/<number>/head:bonsai/pr-<number> and labels the resulting worktree as
read-only.
If a PR is closed or merged, Bonsai warns and refuses by default. Pass --force
when you intentionally need to inspect that PR anyway.
Post-Add Actions
Pass explicit flags to open the new working context immediately:
bonsai add ma-123-implement-auth --editor --open --start
--editoropens the new worktree using$VISUAL,$EDITOR, orcode.--openopens the prepared branch's primary local URL.--startruns the configured start command in the foreground.
When multiple flags are passed, Bonsai opens the editor, opens the browser, then starts the app.
Switch with Checkout
bonsai checkout ma-123-implement-auth
checkout changes your shell into the matching worktree and requires
shell integration. The lookup accepts a branch name,
worktree directory, or worktree slug, and resolves a unique fuzzy match when
nothing matches exactly. Run bonsai checkout with no argument to choose from
existing worktrees through fzf or Bonsai's built-in picker. If the worktree
does not exist yet, Bonsai prepares it first, exactly like add (including
--base-branch).
Remove a Worktree
bonsai remove ma-123-implement-auth
Run bonsai remove with no argument to pick an existing branch worktree.
Bonsai refuses to remove a worktree with uncommitted changes unless you pass
--force. If [commands].preremove is configured, it runs before any teardown;
a failure aborts removal unless --force is set. Removal also deletes the
worktree's Caddy route snippet and updates workspace state.
If the worktree has a root-level compose.yaml, compose.yml,
docker-compose.yaml, or docker-compose.yml, Bonsai first runs
docker compose -p <project> down, using .env.local
COMPOSE_PROJECT_NAME when present and the worktree folder name otherwise.
If Compose teardown fails, removal stops before the git worktree is removed.
Move (Rename) a Worktree
bonsai move ma-123-implement-auth ma-123-auth
move renames a managed worktree directory. The lookup accepts a branch
name, worktree directory, or worktree slug. Bonsai uses git worktree move
underneath, updates .bonsai/state.json, and rewrites generated files so
path-dependent template values stay current.
Renaming the default worktree requires --force: because
git worktree move cannot relocate the main working tree, Bonsai moves the
directory and runs git worktree repair to re-point every secondary
worktree.
PR-Aware Cleanup
bonsai cleanup
bonsai cleanup --apply
cleanup checks each managed branch for a merged pull request and removes
the eligible worktrees. It recognizes normal branches and fork PR worktrees
created as bonsai/pr-<number>. It requires the GitHub CLI (gh) to be
installed and authenticated, and is a dry run by default.
Branches with no PR, open PRs, unmerged closed PRs, or uncommitted changes
are skipped; pass --force with --apply to remove eligible dirty
worktrees. Applied cleanup uses the same removal lifecycle as
bonsai remove, including preremove, Caddy snippet cleanup, and Docker
Compose teardown.