A CLI tool for easy Git worktree management.
easy-worktree simplifies git worktree management.
It keeps the root of your git repository as your primary working area (main), while managing other worktrees in a subdirectory (default: .worktrees/).
- Smart Selection: Quickly switch between worktrees with
wt select. "Jump" into a new shell instantly without any special setup. - Auto Setup: Automatically copy files (like
.env) and run hooks to prepare each worktree. - Clear Status:
wt listshows worktree branches, their status (clean/dirty), and associated GitHub PRs in a beautiful table. - Smart Cleanup: Easily batch remove merged branches or old unused worktrees.
- Two-letter shortcuts: Fast execution with shortcuts like
ad,ls,sl,su,st,cl.
easy-worktree requires the following:
- Git: 2.34 or higher recommended.
- GitHub CLI (gh): Required for PR features (
wt list --pr,wt pr add,wt clean --merged). Installation guide.
pip install easy-worktreeOr install the development version:
git clone https://github.com/igtm/easy-worktree.git
cd easy-worktree
pip install -e .wt clone https://github.com/user/repo.gitThis clones the repository and initializes easy-worktree configuration.
For bare repositories, you can also use plain git:
git clone --bare https://github.com/user/repo.git sandbox.git
git --git-dir=sandbox.git worktree add sandbox/main mainOr let wt do it for you:
wt clone --bare https://github.com/user/repo.git sandbox.gitwt clone --bare automatically:
- clones as bare repository (
sandbox.git) - creates base-branch worktree (
sandbox/<default-branch>) - initializes
.wt/in that base-branch worktree
cd my-repo/
wt initInitializes easy-worktree in the current repository. Your main repository stays at the project root.
For bare repositories:
wt --git-dir=/path/to/sandbox.git initIf no non-bare worktree exists yet, wt init will automatically create a base-branch worktree and initialize .wt/ there.
wt add feature-1This creates the following structure:
my-repo/ (main)
.worktrees/
feature-1/ # Your new worktree
.wt/
...
You can also specify a base branch:
wt add feature-1 mainAs with git -C <path>, you can change the current working directory to the specified path before execution:
wt -C /path/to/repo listWhen using a bare repository, pass --git-dir globally:
wt --git-dir=/path/to/sandbox.git add feature-1 mainDeployment rules for bare repositories:
When using a bare repository, worktrees are automatically deployed alongside the base worktree (e.g., inside repo/), not inside the git directory (repo.git/).
Setting worktrees_dir to an empty string ("") will create worktrees directly in the parent directory.
If you want to create a worktree without running the automatic setup (file copy and hooks):
wt add feature-1 --skip-setupYou can also use the alias flag:
wt add feature-1 --no-setupCreate and immediately switch to the new worktree:
wt add feature-1 --select
wt add feature-1 --select npm testwt list
wt list --pr # Show PR information
wt list --sort created --desc
wt list --sort last-commit --asc
wt list --merged
wt list --days 30wt list shows both Created and Last Commit columns.
Default sort is Created descending.
Quickly stash your current changes and move them to a new worktree.
wt stash feature-2wt select feature-1Running wt select will automatically "jump" you into the worktree directory by starting a new subshell.
- Prompt: Shows a
(wt:feature-1)indicator. - Terminal Title: Updates the window title to
wt:feature-1. - Tmux: Updates the tmux window name to
wt:feature-1if running inside tmux.
To return to your original directory, simply type exit or press Ctrl-D.
- Interactive Mode: Running
wt selectwithout arguments opens an interactive picker usingfzf. - Nesting Control: If you are already in a
wtsubshell, it will warn you to avoid confusing nesting.
You can execute a command after switching:
wt select feature-1 npm testSwitch back to your previous selection:
wt select -Fetch a PR and create a worktree for it. (Requires gh CLI)
wt pr add 123 # Fetches PR #123 and creates 'pr@123' worktreewt rm feature-1Removes the worktree and its directory.
Initialize the current worktree by copying required files and running the post-add hook.
wt setupwt diff
wt diff <name>By default, it runs git diff. You can configure it to use lumen (a rich diff viewer):
wt config diff.tool lumen --globalWhen configured, wt diff will run lumen diff --watch in the target worktree.
Manage settings globally or locally:
wt config <key> <value> [--global|--local]
wt config <key> # Get value
wt config # Show current merged configurationFor a more visual experience, check out easy-worktree-tui.
pip install easy-worktree-tui
wttIt provides a side-by-side view of worktrees and their diffs, with interactive add/remove features.
When you switch to a worktree using wt select, the following features are automatically enabled:
- Terminal Title: The window or tab title is updated to
wt:worktree-name. - Tmux: If you are inside tmux, the window name is automatically renamed to
wt:worktree-name.
You can also use the wt current (or cur) command to display the current worktree name in external tools.
Add the following to your .tmux.conf to show the worktree name in your status line:
set -g status-right "#(wt current) | %Y-%m-%d %H:%M"You can customize your prompt using the $WT_SESSION_NAME environment variable.
Zsh (.zshrc):
RPROMPT='${WT_SESSION_NAME:+"(wt:$WT_SESSION_NAME)"} '"$RPROMPT"Bash (.bashrc):
PS1='$(if [ -n "$WT_SESSION_NAME" ]; then echo "($WT_SESSION_NAME) "; fi)'$PS1Enable completion with one line:
# zsh
eval "$(wt completion zsh)"
# bash
eval "$(wt completion bash)"Persist by adding the same line to ~/.zshrc or ~/.bashrc.
Add a custom module to your starship.toml:
[custom.easy_worktree]
command = "wt current"
when = 'test -n "$WT_SESSION_NAME"'
format = "via [$symbol$output]($style) "
symbol = "🌳 "
style = "bold green"Integrate beautiful worktree indicators by adding a custom segment to .p10k.zsh:
- Add
easy_worktreetoPOWERLEVEL9K_LEFT_PROMPT_ELEMENTS. - Define the following function:
function prompt_easy_worktree() {
if [[ -n $WT_SESSION_NAME ]]; then
p10k segment -f 255 -b 28 -i '🌳' -t "wt:$WT_SESSION_NAME"
fi
}wt clean --merged
wt clean --closed # Remove worktrees for closed (unmerged) PRs
wt clean --days 30
wt clean --allDeletion conditions are:
wt clean --all: removes all clean worktrees (except main/base worktree and symlink-targeted worktrees), without confirmation.wt clean --days N: removes clean worktrees whose directory creation age is>= Ndays.wt clean --merged: removes clean worktrees whose branch is merged into default branch, or is found in merged PR heads fromgh pr list --state merged.wt clean --closed: removes clean worktrees whose branch appears in closed PR heads fromgh pr list --state closed.wt clean ... --yes/wt clean ... -y: skips the confirmation prompt.
Notes:
- Worktrees with local changes are never removed by
wt clean. - Main/base worktree is never removed.
- For
--merged, if branch SHA equals default branch SHA and it is not in merged PR heads, removal is skipped as a safeguard. - Confirmation prompt appears unless
--all,--yes, or-yis specified. Createdtime is pinned from metadata under$XDG_CONFIG_HOME/easy-worktree/(not live filesystem ctime).
wt [-C <path>] [--git-dir <path> | --git-dir=<path>] <command> ...
wt add <work_name> [<base_branch>] [--skip-setup|--no-setup] [--select [<command>...]]
wt select [<name>|-] [<command>...]
wt run <name> <command>...
wt rm <work_name> [-f|--force]
wt list [--pr] [--quiet|-q] [--days N] [--merged] [--closed] [--all] [--sort created|last-commit|name|branch] [--asc|--desc]
wt clean [--days N] [--merged] [--closed] [--all] [--yes|-y]
wt setup
wt config [--global|--local] [<key> [<value>]]
wt doctor
wt completion <bash|zsh>easy-worktree uses a 3-tier configuration system. Settings are merged in the following order of precedence (highest to lowest):
- Global (
~/.config/easy-worktree/config.toml): Applies to all repositories. - Local (
.wt/config.local.toml): Overrides settings locally (git-ignored). - Project (
.wt/config.toml): Shared settings for the repository.
You can manage configuration easily with the wt config command:
# Set a value globally
wt config --global worktrees_dir ".my_global_worktrees"
# Set a value for the project
wt config worktrees_dir ".wt-project"
# View all merged configurations
wt configCustomize behavior in your config.toml files:
worktrees_dir = ".worktrees" # Directory where worktrees are created
setup_files = [".env"] # Files to auto-copy during setup
setup_source_dir = "" # Optional. Override setup file source directoryNote:
worktrees_dirsupports the{repo_name}template variable. For example, settingworktrees_dir = ".worktrees-{repo_name}"will create worktrees in.worktrees-easy-worktreefor theeasy-worktreerepository. This is especially useful for global configurations.
setup_source_dir supports relative paths (resolved from repository base) or absolute paths.
When empty, wt auto-detects the source directory:
- normal repository: repository root
- bare repository: default-branch worktree (fallback to first non-bare worktree)
The worktrees_dir setting is respected for bare repositories, but the base path is automatically adjusted to the parent directory of the base worktree instead of inside repo.git/.
You can use the wt doctor command to check your current environment, verify dependencies (Git, gh, fzf, gitui), and inspect which configuration values are actively applied, including warnings if any unknown configuration keys exist.
.wt/is created under a working-tree directory (never inside bare git object directory).- In normal repositories,
.wt/is at repository root. - With
--git-dir=<path>:- if
<path>points to.git,.wt/is in that repository root - if
<path>points to a bare repo (e.g.sandbox.git),.wt/is created in the preferred non-bare worktree (default-branch worktree first, otherwise first available non-bare worktree)
- if
- If no non-bare worktree exists for a bare repo,
wtreports an error and asks you to create one first.
wt currently stores these files in .wt/:
config.tomlconfig.local.toml(optional, ignored)post-addpost-add.local(optional, ignored)last_selection(ignored)
Metadata storage:
- worktree creation metadata is stored under
$XDG_CONFIG_HOME/easy-worktree/(fallback:~/.config/easy-worktree/)
You can define scripts to run automatically after wt add.
Templates are created in .wt/post-add upon initialization.
MIT License
