Skip to content

Instantly share code, notes, and snippets.

@neilwashere
Last active April 17, 2026 18:24
Show Gist options
  • Select an option

  • Save neilwashere/6aac8215f3397d5edc7d3baf8a3fd9ab to your computer and use it in GitHub Desktop.

Select an option

Save neilwashere/6aac8215f3397d5edc7d3baf8a3fd9ab to your computer and use it in GitHub Desktop.
Git worktree helpers for zsh — quick wt-new/wt-review/wt-cd/wt-rm commands with Claude Code context sharing
# Git Worktree Helpers for Zsh
# Quick shortcuts for working with git worktrees.
# Worktrees are created under ../$repo.worktrees/$branch alongside the main repo.
# Includes optional Claude Code context sharing so sessions in worktrees
# pick up the same project memory as the main repo.
# Usage:
# wt-new <branch> [base] Create a new feature branch in a worktree (defaults to main)
# wt-review <branch> Check out a remote branch in a worktree
# wt-cd <branch> cd into an existing worktree
# wt-ls List all worktrees
# wt-rm <branch-or-path> Remove a worktree (cleans up Claude symlinks too)
# Install: source this file from your .zshrc
# --- Internal helpers ---
# Derives a worktree path: ../$repo.worktrees/$branch
_wt_dir() {
local repo=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)")
local branch="${1#origin/}" # strip remote prefix only
echo "../${repo}.worktrees/${branch//\//-}"
}
# Symlink Claude Code project context (memory, settings) from a worktree back to the main repo
# so claude sessions in the worktree share accumulated knowledge
_wt_link_claude() {
local main_abs=$(git rev-parse --show-toplevel 2>/dev/null)
local wt_abs=$(cd "$1" && pwd)
local claude_base="$HOME/.claude/projects"
local main_claude="${claude_base}/$(echo "$main_abs" | tr '/' '-')"
local wt_claude="${claude_base}/$(echo "$wt_abs" | tr '/' '-')"
if [[ -d "$main_claude" && ! -e "$wt_claude" ]]; then
ln -s "$main_claude" "$wt_claude"
echo "Claude context linked to main repo"
fi
}
# Remove the Claude context symlink for a worktree
_wt_unlink_claude() {
local wt_abs=$(cd "$1" 2>/dev/null && pwd) || return
local claude_base="$HOME/.claude/projects"
local wt_claude="${claude_base}/$(echo "$wt_abs" | tr '/' '-')"
if [[ -L "$wt_claude" ]]; then
rm "$wt_claude"
echo "Claude context symlink removed"
fi
}
# --- Public commands ---
# Open a remote branch in a new worktree for review/work
wt-review() {
if [[ -z "$1" ]]; then
echo "Usage: wt-review <branch> (e.g. wt-review feat/async-travel)"
return 1
fi
git fetch origin
local dir=$(_wt_dir "$1")
git worktree add "$dir" "$1" 2>/dev/null \
|| git worktree add "$dir" -b "$1" "origin/$1"
echo "Worktree ready at $dir"
cd "$dir"
}
# Create a new feature branch in a worktree (with shared Claude context)
wt-new() {
if [[ -z "$1" ]]; then
echo "Usage: wt-new <branch> [base] (e.g. wt-new feat/my-feature main)"
return 1
fi
local base=${2:-main}
git fetch origin "$base" || return 1
local dir=$(_wt_dir "$1")
git worktree add "$dir" -b "$1" "origin/$base"
_wt_link_claude "$dir"
echo "Worktree ready at $dir (based on origin/$base)"
cd "$dir"
}
# List all worktrees
alias wt-ls="git worktree list"
# Remove a worktree (by branch name or path); extra args passed to git worktree remove
wt-rm() {
if [[ -z "$1" ]]; then
echo "Usage: wt-rm <branch-or-path> [-- git-worktree-remove-args...]"
return 1
fi
local target="$1"; shift
# If arg looks like a path, use it directly; otherwise derive from branch name
if [[ "$target" == */* && -d "$target" ]]; then
_wt_unlink_claude "$target"
git worktree remove "$@" "$target"
else
local dir=$(_wt_dir "$target")
_wt_unlink_claude "$dir"
git worktree remove "$@" "$dir"
fi
}
# cd into an existing worktree by branch name
wt-cd() {
if [[ -z "$1" ]]; then
echo "Usage: wt-cd <branch>"
return 1
fi
local dir=$(_wt_dir "$1")
if [[ -d "$dir" ]]; then
cd "$dir"
else
echo "No worktree found at $dir"
echo "Active worktrees:"
git worktree list
return 1
fi
}
# --- Tab completion ---
# wt-review and wt-rm complete on remote branches
_wt_remote_branches() {
compadd ${(f)"$(git branch -r 2>/dev/null | sed 's|origin/||;s/^\[ \*\]\*//' | grep -v HEAD)"}
}
compdef _wt_remote_branches wt-review
compdef _wt_remote_branches wt-rm
# wt-cd completes on existing worktree branches
_wt_existing_worktrees() {
compadd ${(f)"$(git worktree list --porcelain 2>/dev/null | awk '/^branch refs\\/heads\\//{sub("refs/heads/","",$2); print $2}')"}
}
compdef _wt_existing_worktrees wt-cd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment