git-worktree-manager (gw)
gw is a lean git worktree manager. Inspired by mr (myrepos), it uses cwd-based scope discovery — no global registry, no cross-repo flags — so commands do exactly what you expect relative to where you run them. Target resolution is strict and consistent: worktree name → branch name → path.
AI coding-assistant integration is built in: gw new creates a worktree and launches your AI tool of choice in it (use --no-term to skip). Future AI-assisted operations (e.g. --ai on merge / rebase) layer on top of the same worktree primitives.
Single static binary (~1.9MB), ~3ms startup. Supports macOS (ARM64/x86), Linux (ARM64/x86), and Windows (x86_64).
Successor to claude-worktree (Python), rewritten in Rust.
Backward compatible: The
cwcommand is included as an alias. Existingcwworkflows,.cwshare, and.cwconfig.jsonfiles work unchanged.
Install
This installs both gw and cw binaries.
# Homebrew (macOS/Linux)
# cargo-binstall (pre-built binary, no compile)
# Direct download
# https://github.com/DaveDev42/git-worktree-manager/releases/latest
After installing, run gw upgrade at any time to update to the latest version (self-replacing binary). Pass --yes to skip the prompt — required in non-TTY environments (CI, nested processes). Homebrew users should use brew upgrade git-worktree-manager instead.
Quick Start
# Create a worktree (and launch your AI coding assistant in it)
# Just the worktree, no AI tool
# Pass an initial prompt to the AI tool
# Or read the prompt from a file (recommended for multi-line / quoted content)
# List all worktrees (rich human-readable output)
# Resume an AI session in an existing worktree
# Launch AI tool in the current worktree (or a named one)
# Remove a worktree (interactive multi-select, or by name)
# Run a command in every worktree in scope
# Run a command in one specific worktree
Commands
| Command | Description |
|---|---|
gw new <name> |
Create worktree (and launch AI tool, unless --no-term) |
gw resume [target] |
Resume AI session in a worktree |
gw spawn [target] |
Launch AI tool in an existing worktree (default: current) |
gw rm [targets...] |
Remove one or more worktrees (-i interactive, --dry-run, --force) |
gw list |
List all worktrees (rich, human-readable) |
gw ls |
Print all worktrees as TSV (for scripts) |
gw exec <target> -- <cmd> |
Run a command in one specific worktree |
gw run -- <cmd> |
Run a command in every worktree in scope |
gw guard |
Claude Code hook helper: allow or block inbound tool use |
gw doctor |
Run diagnostics (5 health checks) |
gw upgrade |
Check for updates / upgrade |
gw setup-claude |
Install Claude Code skill for worktree task delegation |
gw shell-setup |
Interactive shell integration setup |
Scope and Target Resolution
Scope discovery
gw run, gw list, gw ls, and other scope-wide commands discover worktrees relative to the current working directory: it walks up first to find a .cwconfig.json-rooted scope, falling back to a downward walk from cwd if none is found. There is no global registry and no cross-repo flags.
Target resolution
When a command accepts a [target] argument, resolution is strict and ordered:
- Exact worktree name
- Branch name
- Path
No ambiguity modes, no lookup-mode flags. The first match wins.
gw run and gw exec
gw run executes a command in every worktree in scope. gw exec runs in exactly one.
# Run tests in all worktrees, 4 in parallel
# Only worktrees whose name matches a glob
# Skip the main worktree
# Keep going even if some worktrees fail
# Run in one specific worktree
gw ls emits TSV columns (worktree_id, branch, status, age, repo_root, path) for scripting:
|
Terminal Launchers
The launcher used by gw new / gw spawn / gw resume is configured (not a per-invocation flag). Use --no-term on gw new to skip the AI tool launch entirely.
Set the default for a project in .cwconfig.json:
…or globally in ~/.config/git-worktree-manager/config.json. Per-invocation override is via the CW_LAUNCH_METHOD env var:
CW_LAUNCH_METHOD=iterm-tab
| Launcher | Variants |
|---|---|
| Foreground | foreground (default) |
| Detached | detach |
| iTerm | iterm-window, iterm-tab, iterm-pane-h, iterm-pane-v |
| tmux | tmux, tmux-window, tmux-pane-h, tmux-pane-v |
| Zellij | zellij, zellij-tab, zellij-pane-h, zellij-pane-v |
| WezTerm | wezterm-window, wezterm-tab, wezterm-tab-bg, wezterm-pane-h, wezterm-pane-v |
Claude Code Integration
Install the gw plugin into your Claude Code setup:
The plugin bundles two skills:
delegate— invoked via/gw <task description>. Spawns a new worktree and a Claude Code session inside it with the given task as the initial prompt. One-shot, fire-and-forget.manage— auto-applies when you (or Claude) run worktree management commands. Encodes a worktree-health rulebook and a catalog of recommended Claude Code hooks. When relevant, Claude will suggest installing a hook into your project's.claude/settings.jsonand edit it on your consent — gw itself never modifies any settings file.
Shell Integration
# Interactive setup (recommended)
# bash/zsh — add to your shell rc file
# fish
|
This enables:
gw-cd <target>— navigate to a worktree directory (interactive selector if no args)- Tab completion — worktree names and branch names from the current scope, plus options
Generate shell completions separately with gw --generate-completion <bash|zsh|fish|powershell|elvish>.
Configuration
Config is resolved in layers (later layers override earlier ones): built-in defaults → ~/.config/git-worktree-manager/config.json → repo-local .cwconfig.json. There are no gw config subcommands — edit the JSON files directly.
Also reads legacy ~/.config/claude-worktree/config.json from the Python predecessor.
Example .cwconfig.json:
Hooks
Two lifecycle hooks are available, configured in .cwconfig.json (or the global config):
| Hook | Trigger |
|---|---|
hooks.post_new |
After gw new creates a worktree |
hooks.pre_rm |
Before gw rm removes a worktree |
Hooks run as sh -c <cmd> with the worktree directory as the working directory.
pre_rmnon-zero exit aborts the remove (the worktree stays). This is independent of--force—--forcebypasses busy detection, not user hooks.post_newnon-zero exit surfaces as a non-zerogw newexit code, but the worktree itself remains on disk because the hook runs aftergit worktree add. The AI tool launch is skipped.
There are no gw hook CRUD subcommands — set hooks in the config file directly.
Doctor
gw doctor runs 5 lean health checks: git version, worktree accessibility, uncommitted changes, busy worktrees, and Claude Code integration. Pass --session-start for hook-friendly non-interactive mode (single-line summary, always exits 0).
gw rm Exit Codes
| Code | Meaning |
|---|---|
0 |
Full success, --dry-run, or -i with nothing selected / cancelled at selection UI |
1 |
User cancelled at the confirmation prompt |
2 |
Any target failed or was skipped (not found, busy, or remove error) |
Scripts should handle != 0 or specifically check for 2.
License
BSD-3-Clause