Skip to content

Instantly share code, notes, and snippets.

@amiller68
Created November 3, 2025 16:39
Show Gist options
  • Select an option

  • Save amiller68/606333fb8a8a37f6785419df45e7b173 to your computer and use it in GitHub Desktop.

Select an option

Save amiller68/606333fb8a8a37f6785419df45e7b173 to your computer and use it in GitHub Desktop.
Claude Code Worktree Setup
#!/bin/bash
# Git Worktree Setup Script for Multiple Claude Code Instances
# This script helps create separate git worktrees for working with multiple
# instances of Claude Code on any git repository
set -e
# Default repository directory (can be overridden with --repo flag)
# TODO: replace this with the on system path to the repo you are managing
# worktrees for!
DEFAULT_REPO_DIR="~/path/to/repo"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
print_usage() {
echo "Usage: $0 [--repo <path>] <command> [worktree-name] [branch-name]"
echo ""
echo "Options:"
echo " --repo <path> - Path to the git repository (default: $DEFAULT_REPO_DIR)"
echo ""
echo "Commands:"
echo " create <name> [branch] - Create a new worktree (branch defaults to new branch from origin/main)"
echo " list - List all worktrees"
echo " remove <name> - Remove a worktree"
echo " open <name> - Change to worktree directory"
echo " cleanup - Remove all worktrees"
echo ""
echo "Examples:"
echo " $0 create feature-branch"
echo " $0 --repo ~/my-project create feature-branch"
echo " $0 --repo ~/my-project create hotfix origin/hotfix-123"
echo " $0 --repo ~/my-project open feature-branch"
echo " $0 --repo ~/my-project remove feature-branch"
}
check_git_repo() {
if [ ! -d "$REPO_DIR/.git" ]; then
echo -e "${RED}Error: $REPO_DIR is not a git repository${NC}"
exit 1
fi
}
create_worktree() {
local name="$1"
local branch="${2:-$name}"
local worktree_path="$WORKTREES_BASE_DIR/$name"
if [ -z "$name" ]; then
echo -e "${RED}Error: Worktree name is required${NC}"
print_usage
exit 1
fi
if [ -d "$worktree_path" ]; then
echo -e "${RED}Error: Worktree '$name' already exists at $worktree_path${NC}"
exit 1
fi
echo -e "${BLUE}Creating worktree '$name' from branch '$branch'...${NC}"
# Create the base directory if it doesn't exist
mkdir -p "$WORKTREES_BASE_DIR"
# Change to repository directory and create worktree
cd "$REPO_DIR"
# If using default branch name (same as worktree), check if branch exists
if [ "$branch" = "$name" ]; then
# Check if branch exists locally or remotely
if git show-ref --verify --quiet "refs/heads/$name" || git show-ref --verify --quiet "refs/remotes/origin/$name"; then
echo -e "${YELLOW}Using existing branch '$name'${NC}"
git worktree add "$worktree_path" "$name"
else
echo -e "${YELLOW}Creating new branch '$name' from origin/main${NC}"
git worktree add -b "$name" "$worktree_path" origin/main
fi
else
git worktree add "$worktree_path" "$branch"
fi
echo -e "${GREEN}Worktree created successfully!${NC}"
echo -e "${YELLOW}Path: $worktree_path${NC}"
echo -e "${YELLOW}To use with Claude Code:${NC}"
echo " cd $worktree_path"
echo " claude"
}
list_worktrees() {
echo -e "${BLUE}Git worktrees:${NC}"
cd "$REPO_DIR"
git worktree list
echo ""
echo -e "${BLUE}Available worktree directories:${NC}"
if [ -d "$WORKTREES_BASE_DIR" ]; then
ls -la "$WORKTREES_BASE_DIR"
else
echo "No worktrees directory found"
fi
}
remove_worktree() {
local name="$1"
local worktree_path="$WORKTREES_BASE_DIR/$name"
if [ -z "$name" ]; then
echo -e "${RED}Error: Worktree name is required${NC}"
print_usage
exit 1
fi
if [ ! -d "$worktree_path" ]; then
echo -e "${RED}Error: Worktree '$name' does not exist${NC}"
exit 1
fi
echo -e "${YELLOW}Removing worktree '$name'...${NC}"
cd "$REPO_DIR"
git worktree remove "$worktree_path"
echo -e "${GREEN}Worktree removed successfully!${NC}"
}
open_worktree() {
local name="$1"
local worktree_path="$WORKTREES_BASE_DIR/$name"
if [ -z "$name" ]; then
echo -e "${RED}Error: Worktree name is required${NC}"
print_usage
exit 1
fi
if [ ! -d "$worktree_path" ]; then
echo -e "${RED}Error: Worktree '$name' does not exist${NC}"
exit 1
fi
echo -e "${BLUE}Opening worktree '$name'...${NC}"
cd "$worktree_path" && exec claude
}
cleanup_worktrees() {
echo -e "${YELLOW}Cleaning up all worktrees...${NC}"
if [ -d "$WORKTREES_BASE_DIR" ]; then
cd "$REPO_DIR"
# Remove all worktrees
for worktree_dir in "$WORKTREES_BASE_DIR"/*; do
if [ -d "$worktree_dir" ]; then
local name=$(basename "$worktree_dir")
echo "Removing worktree: $name"
git worktree remove "$worktree_dir" 2>/dev/null || true
fi
done
# Remove the base directory
rm -rf "$WORKTREES_BASE_DIR"
fi
echo -e "${GREEN}Cleanup complete!${NC}"
}
# Parse arguments
REPO_DIR="$DEFAULT_REPO_DIR"
# Check for --repo flag
if [ "$1" = "--repo" ]; then
if [ -z "$2" ]; then
echo -e "${RED}Error: --repo flag requires a path argument${NC}"
print_usage
exit 1
fi
REPO_DIR="$2"
shift 2
fi
# Expand tilde in paths
REPO_DIR="${REPO_DIR/#\~/$HOME}"
# Capture the current working directory for worktrees location
# This ensures worktrees are created where the script is called, not in the repo
ORIGINAL_PWD="$(pwd)"
WORKTREES_BASE_DIR="$ORIGINAL_PWD/worktrees"
# Main script logic
check_git_repo
case "$1" in
create)
create_worktree "$2" "$3"
;;
list)
list_worktrees
;;
remove)
remove_worktree "$2"
;;
open)
open_worktree "$2"
;;
cleanup)
cleanup_worktrees
;;
*)
print_usage
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment