Skip to content

morellodev/arbor

Repository files navigation

🌳 arbor

Test & Lint GitHub Release License: MIT

A CLI for managing git worktrees. It keeps all your worktrees under ~/.arbor/worktrees so you can switch between branches without stashing or losing context.

demo

Why arbor?

Git worktrees are great: multiple branches checked out at once, no stashing, no half-finished commits. The problem is that git worktree add makes you pick a directory every time, and you end up with worktrees scattered everywhere.

Arbor puts them all in one place. arbor add feat/login creates the worktree, and with shell integration it cds you into it too. arbor rm feat/login cleans it up.

Who is this for?

If you review PRs while working on your own feature, juggle hotfixes alongside long-running branches, or run tests in one worktree while coding in another — arbor keeps everything organized.

Install

Homebrew (macOS and Linux)

brew install morellodev/tap/arbor

Pre-built binaries (macOS, Linux, Windows)

Download the latest binary for your platform from the releases page.

From source

git clone https://github.com/morellodev/arbor.git
cd arbor
cargo install --path .

You'll need Rust 1.85+ and Git.

Quick start

# Clone a repo (creates a bare repo + worktree for the default branch)
arbor clone user/my-app

# Create a worktree for a branch
arbor add feat/login

# Switch to an existing worktree
arbor switch main

# See all worktrees
arbor ls

# Check which are dirty or ahead/behind
arbor status

# Done? Remove the worktree and its local branch
arbor rm -d feat/login

Shell integration

Run arbor init and it will show you what to add to your shell config:

arbor init
# ▸ Add the following to ~/.zshrc:
#
#   eval "$(arbor init zsh)"

This sets up two things: a wrapper so arbor add, arbor switch, and arbor clone automatically cd into the worktree, and dynamic tab completions for branch names.

The shell is auto-detected from $SHELL. You can also specify it explicitly:

# ~/.zshrc or ~/.bashrc
eval "$(arbor init zsh)"    # or bash

# Fish: ~/.config/fish/config.fish
arbor init fish | source

Commands

Command Alias Description
arbor add <branch> [--repo <name>] [--no-hooks] Create a worktree. Checks out an existing local branch, tracks a remote branch, or creates a new one. --repo lets you add from any directory. --no-hooks skips post-create hooks.
arbor switch <branch> Switch to an existing worktree. Errors if the worktree doesn't exist.
arbor list [--all] [--json] ls List worktrees for the current repo. --all lists across all repos. --json for machine-readable output.
arbor remove <branch> [-f] [-d] rm Remove a worktree. -f forces removal of dirty worktrees. -d also deletes the local branch.
arbor dir <branch> Print the worktree path for a branch. Accepts both feature/auth and feature-auth.
arbor clone <url> [--no-worktree] [--no-hooks] Clone as a bare repo and create a worktree for the default branch. Supports user/repo shorthand for GitHub. --no-hooks skips post-create hooks.
arbor status [--short] [--all] Show dirty/clean state and ahead/behind counts for all worktrees. --all shows across all repos.
arbor fetch [--all] Fetch from origin in the current bare repo. --all fetches across all repos.
arbor clean [-d] Interactively select and remove unused worktrees. -d also deletes local branches.
arbor prune Remove stale worktree references.
arbor init [shell] Set up shell integration (cd wrapper + completions). Auto-detects shell from $SHELL.

How it works

arbor add feat/login inside a repo called my-app creates a worktree at:

~/.arbor/worktrees/my-app/feat-login

Slashes in branch names become dashes in the directory name.

For a worktree-only workflow, start with arbor clone to set up a bare repo:

arbor clone user/my-app
arbor add feat/login

Configuration

On first run, arbor creates ~/.arbor/config.toml:

repos_dir = "~/.arbor/repos"
worktree_dir = "~/.arbor/worktrees"

Change these to store worktrees and bare repos somewhere else.

Hooks

You can run commands automatically after a worktree is created by adding a .arbor.toml file to your repo root:

[hooks]
post_create = "npm install"

Multiple commands are supported:

[hooks]
post_create = ["npm install", "cp .env.example .env"]

Hooks run inside the new worktree directory with these environment variables available:

Variable Description
ARBOR_WORKTREE Absolute path to the new worktree
ARBOR_BRANCH Branch name
ARBOR_REPO Repository name
ARBOR_EVENT Hook event name (post_create)

Hook output streams to stderr so it doesn't interfere with cd $(arbor add ...) piping. If a hook fails, arbor prints a warning and continues — the worktree is still created.

To skip hooks for a single invocation, pass --no-hooks:

arbor add feat/login --no-hooks

Alternatives

If arbor isn't what you're after, here are some other tools in this space:

arbor git worktree (bare) git-branchless git-town
Worktree management Yes Yes (manual) Yes No
Central worktree directory Yes No (you pick each time) No N/A
Auto-cd into worktree Yes (shell integration) No No No
GitHub shorthand clone Yes (user/repo) No No No
Status across worktrees Yes No Yes No
Stacked diffs / rebase workflows No No Yes Yes
Branch sync with remote No No Yes Yes

arbor is intentionally narrow. It manages worktrees and gets out of your way. If you need stacked diffs or branch sync workflows, git-branchless or git-town are better fits.

License

MIT

About

A friendly CLI for managing git worktrees

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages