Created
November 3, 2025 16:39
-
-
Save amiller68/606333fb8a8a37f6785419df45e7b173 to your computer and use it in GitHub Desktop.
Claude Code Worktree Setup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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