wt

module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2026 License: MIT

README

Logo

wt

Git worktree manager with GitHub/GitLab integration.

Why wt

Git worktrees let you work on multiple branches simultaneously without stashing or switching—great for juggling a feature branch and a hotfix, or running multiple AI agent sessions in parallel.

But worktrees can pile up fast. You end up with a dozen directories, can't remember which ones are already merged, and need custom scripts to open your editor, create terminal tabs, or clean up stale checkouts.

wt solves this:

  • Hooks auto-run commands when creating/opening worktrees (open editor, spawn terminal tab)
  • Prune removes merged worktrees and shows PR/MR status so you know what's safe to delete
  • PR checkout opens pull requests in worktrees for easier code review

Install

# Homebrew (macOS/Linux)
brew install --cask raphi011/tap/wt

# Go
go install github.com/raphi011/wt/cmd/wt@latest

Requires git in PATH. For GitHub repos: gh CLI. For GitLab repos: glab CLI.

Quick Start

# Create config (optional but recommended)
wt config init

# Start working on a new feature
wt add -b my-feature

# Review a PR
wt pr open 123

# Clean up merged worktrees
wt prune

Scenarios

Starting a New Feature
# Create worktree with new branch (from origin/main)
wt add -b feature-login

# Create from a different base branch
wt add -b feature-login --base develop

# Fetch latest before creating (ensures up-to-date base)
wt add -b feature-login -f

# Add a note to remember what you're working on
wt add -b feature-login --note "Implementing OAuth flow"

With hooks configured, your editor opens automatically:

# ~/.config/wt/config.toml
[hooks.vscode]
command = "code {path}"
on = ["add"]
Reviewing a Pull Request
# Checkout PR from current repo
wt pr open 123

# Checkout PR from a different repo (searches in worktree_dir)
wt pr open 123 backend-api

# Clone repo you don't have locally and checkout PR
wt pr clone 456 org/new-repo

After review, merge and clean up in one command:

wt pr merge              # Uses squash by default
wt pr merge -s rebase    # Or specify strategy
wt pr merge --keep       # Merge but keep worktree
Cleaning Up
# See what worktrees exist
wt list

# Show detailed status for a specific worktree
wt show -i 3

# Remove merged worktrees (uses cached PR status)
wt prune

# Refresh PR status from GitHub/GitLab first
wt prune -R

# Preview what would be removed
wt prune -n

# Also remove worktrees with 0 commits (stale checkouts)
wt prune -c

# Remove specific worktree by ID
wt prune -i 3

# Force remove even if not merged or dirty
wt prune -i 3 -f
Working Across Multiple Repos

Label your repos for batch operations:

# Add labels to repos
cd ~/Git/backend-api && wt label add backend
cd ~/Git/auth-service && wt label add backend
cd ~/Git/web-app && wt label add frontend

# Create same branch across all backend repos
wt add -b feature-auth -l backend -d ~/Git

# Or target specific repos by name
wt add -b feature-auth -r backend-api -r auth-service -d ~/Git

# Run command across repos
wt exec -l backend -- git status
wt exec -r backend-api -r auth-service -- make test

# List repos and their labels
wt repos
wt repos -l backend
Quick Navigation
# Jump to worktree by ID
cd $(wt cd -i 3)

# Jump to repo by name
cd $(wt cd -r backend-api)

# Jump to main repo (not worktree)
cd $(wt cd -i 3 -p)

# Run command in worktree without switching
wt exec -i 3 -- git status
wt exec -i 3 -- code .
Running Hooks Manually
# Run a hook on current worktree
wt hook vscode

# Run on specific worktree
wt hook vscode -i 3

# Run multiple hooks
wt hook vscode kitty

# Run across repos by label
wt hook build -l backend

# Pass custom variables
wt hook claude --arg prompt="implement feature X"

# Preview command without executing
wt hook vscode -n
Branch Notes
# Set a note (visible in list/prune output)
wt note set "WIP: fixing auth timeout issue"

# Get current note
wt note get

# Clear note
wt note clear

# Set note by worktree ID
wt note set "Ready for review" -i 3
Moving Worktrees / Migrating to wt

Already have worktrees scattered around? Use wt mv to consolidate them:

# Preview what would be moved
wt mv -d ~/Git/worktrees -n

# Move all worktrees from current directory to central location
wt mv -d ~/Git/worktrees

# Move and rename to consistent format
wt mv -d ~/Git/worktrees --format={repo}-{branch}

# Force move even if worktrees have uncommitted changes
wt mv -d ~/Git/worktrees -f

This updates git's worktree tracking automatically—no manual fixup needed.

Configuration

Config file: ~/.config/wt/config.toml

wt config init    # Create default config
wt config show    # Show effective config
wt config hooks   # List configured hooks
Basic Settings
# Directory for new worktrees (must be absolute or start with ~)
worktree_dir = "~/Git/worktrees"

# Where repos live (for -r/-l lookup, defaults to worktree_dir)
repo_dir = "~/Git"

# Folder naming: {repo}, {branch}, {folder}
worktree_format = "{repo}-{branch}"

# Base ref for new branches: "remote" (default) or "local"
base_ref = "remote"

# Default sort order for list: "id", "repo", "branch", "commit"
default_sort = "id"
Hooks
[hooks.vscode]
command = "code {path}"
description = "Open VS Code"
on = ["add", "pr"]  # Auto-run for these commands

[hooks.kitty]
command = "kitty @ launch --type=tab --cwd={path}"
description = "Open new kitty tab"
on = ["add"]

[hooks.cleanup]
command = "echo 'Removed {branch}'"
on = ["prune"]

[hooks.claude]
command = "kitty @ launch --cwd={path} -- claude {prompt:-help me}"
description = "Open Claude with prompt"
# No "on" = only runs via: wt hook claude --arg prompt="..."

Hook triggers: add, pr, prune, merge, all

Placeholders: {path}, {branch}, {repo}, {folder}, {main-repo}, {trigger}, {key}, {key:-default}

Clone Rules

Configure forge detection for wt pr clone:

[clone]
forge = "github"      # Default forge
org = "my-company"    # Default org (allows: wt pr clone 123 repo)

[[clone.rules]]
pattern = "company/*"
forge = "gitlab"
Merge Settings
[merge]
strategy = "squash"  # squash, rebase, or merge
Self-Hosted Instances
[hosts]
"github.mycompany.com" = "github"
"gitlab.internal.corp" = "gitlab"

Integration with gh-dash

wt works great with gh-dash. Add a keybinding to checkout PRs as worktrees:

# ~/.config/gh-dash/config.yml
keybindings:
  prs:
    - key: O
      command: wt pr open {{.PrNumber}} {{.RepoName}}

Press O to checkout PR → hooks auto-open your editor.

Shell Completions

# Fish
wt completion fish > ~/.config/fish/completions/wt.fish

# Bash
wt completion bash > ~/.local/share/bash-completion/completions/wt

# Zsh (add ~/.zfunc to fpath in .zshrc)
wt completion zsh > ~/.zfunc/_wt

Command Reference

Command Description
wt add Add worktree for branch
wt list List worktrees
wt show Show worktree details
wt prune Remove merged worktrees
wt repos List repositories
wt pr open Checkout PR from local repo
wt pr clone Clone repo and checkout PR
wt pr merge Merge PR and clean up
wt exec Run command in worktree
wt cd Print worktree/repo path
wt mv Move worktrees
wt note Manage branch notes
wt label Manage repo labels
wt hook Run configured hook
wt config Manage configuration
wt completion Generate shell completions

Run wt <command> --help for detailed usage.

Development

make build    # Build ./wt binary
make test     # Run tests
make install  # Install to ~/go/bin

Directories

Path Synopsis
cmd
wt command
internal
cmd
Package cmd provides helpers for executing shell commands with proper error handling.
Package cmd provides helpers for executing shell commands with proper error handling.
forge
Package forge provides an abstraction over git hosting services (GitHub, GitLab).
Package forge provides an abstraction over git hosting services (GitHub, GitLab).
git
resolve
Package resolve provides unified target resolution for worktree commands.
Package resolve provides unified target resolution for worktree commands.
ui

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL