Skip to content

Instantly share code, notes, and snippets.

@andynu
Last active March 4, 2026 17:33
Show Gist options
  • Select an option

  • Save andynu/294bf3c468fdada439eb8c2eee71c9c4 to your computer and use it in GitHub Desktop.

Select an option

Save andynu/294bf3c468fdada439eb8c2eee71c9c4 to your computer and use it in GitHub Desktop.
tmx-claude & tmx-worktree: Spawn parallel Claude Code sessions in tmux windows and git worktrees

tmx-claude & tmx-worktree

Spawn Claude Code sessions in tmux windows — either in your current repo or in isolated git worktrees. Lets you run multiple Claude agents in parallel without blocking your terminal.

Notes

  • WORKTREE_BASE defaults to ~/work/src/ in tmx-worktree and worktree-clean. Edit the variable at the top of each script to match your layout.
  • tmx-claude --help mentions bd-lite, a lightweight issue tracker I use. You can ignore that or rip it out.

What's included

Script Purpose
tmx-claude Launch Claude Code in a new tmux window with a prompt
tmx-worktree Create a git worktree + branch, then launch Claude in it
worktree-clean Safely remove worktrees with safety checks

Prerequisites

Installation

# Put these somewhere on your PATH (e.g., ~/bin/)
curl -L https://gist.githubusercontent.com/YOUR_GIST_ID/raw/tmx-claude -o ~/bin/tmx-claude
curl -L https://gist.githubusercontent.com/YOUR_GIST_ID/raw/tmx-worktree -o ~/bin/tmx-worktree
curl -L https://gist.githubusercontent.com/YOUR_GIST_ID/raw/worktree-clean -o ~/bin/worktree-clean
chmod +x ~/bin/tmx-claude ~/bin/tmx-worktree ~/bin/worktree-clean

Or just copy the scripts manually into any directory on your $PATH.

Usage

tmx-claude — fire-and-forget Claude sessions

# Launch Claude in a new tmux window, stay in your current window
tmx-claude "Fix the login bug"

# Specify a project directory
tmx-claude -d ~/projects/myapp "Run the test suite and fix failures"

# Use a specific model
tmx-claude -m sonnet "Review this PR"

# Switch to the new window immediately
tmx-claude -a "Help me debug this"

# Custom window name
tmx-claude -n "auth-fix" "Refactor the authentication module"

If you're not inside tmux, it creates a new tmux session and tells you how to attach.

tmx-worktree — isolated feature branches with Claude

# Create worktree + branch, launch Claude in it
tmx-worktree -b feature-auth "Implement OAuth login"

# Specify the source project (if you're not already in it)
tmx-worktree -p ~/projects/myapp -b fix-123 "Fix issue #123"

# Branch from a non-default branch
tmx-worktree -b hotfix -f release-2.0 "Patch the payment flow"

# Attach immediately
tmx-worktree -a -b spike-caching "Prototype Redis caching layer"

Worktrees are created at ~/work/src/<project>-<branch>/. Edit WORKTREE_BASE at the top of the script to change this.

worktree-clean — safe worktree removal

# Remove a specific worktree (with safety checks)
worktree-clean myapp-feature
worktree-clean ~/work/src/myapp-feature

# Also delete the branch
worktree-clean -d myapp-feature

# Clean all worktrees whose branches are merged
worktree-clean --merged

# Preview what --merged would do
worktree-clean --merged -n

# Skip safety checks
worktree-clean -f myapp-feature

Safety checks before removal:

  • Uncommitted changes (blocks)
  • Untracked files (blocks)
  • Unpushed commits (blocks)
  • Unmerged branch (warns but doesn't block)

Workflow example

# You're working on feature A in your main repo.
# A bug report comes in. Spin up an isolated worktree for it:
tmx-worktree -b fix-crash "Fix the crash in payment processing. See issue #42."

# Meanwhile, you also want Claude to review your current work:
tmx-claude "Review the changes in this branch for security issues"

# Both run in separate tmux windows. Switch between them with Ctrl+A n/p
# (or whatever your tmux prefix + window navigation is)

# When the bugfix is done and merged:
worktree-clean -d myapp-fix-crash

# Periodic cleanup of all merged worktrees:
worktree-clean --merged

Customization

  • WORKTREE_BASE in tmx-worktree and worktree-clean: change where worktrees are created (default: ~/work/src/)
  • -m MODEL in tmx-claude: pass a model flag to Claude Code (e.g., sonnet, opus, haiku)

Tips

  • Works great for running multiple Claude agents on different parts of a codebase simultaneously
  • Each tmux window is independent — Claude stays interactive for follow-up questions
  • Worktrees share the same git object store as the main repo, so they're fast to create and space-efficient
  • Use tmux list-windows to see all your active Claude sessions
#!/bin/bash
# tmx-claude - Launch Claude Code in a new tmux window with an initial prompt
#
# Usage:
# tmx-claude "Fix the login bug" # Current directory
# tmx-claude -d ~/work/src/myapp "Run the tests" # Specific directory
# cd ~/work/src/myapp && tmx-claude "Review code" # From that directory
#
# The window stays open for interactive follow-up. You remain in your
# original window to continue working.
set -e
usage() {
cat <<'EOF'
Usage: tmx-claude [-d DIR] [-n NAME] [-m MODEL] [-a] [-w SECS] PROMPT
Launch Claude Code in a new tmux window with an initial prompt.
The new window runs independently—you stay in your current window.
Options:
-d DIR Change to DIR before starting Claude (default: current directory)
-n NAME Window name (default: basename of directory)
-m MODEL Model to use (e.g., sonnet, opus, haiku)
-a Attach/switch to the new window immediately
-w SECS Seconds to wait for Claude to start (default: 2)
-h Show this help
Examples:
tmx-claude "Review the authentication code"
tmx-claude -d ~/work/src/myapp "Fix the login bug"
tmx-claude -m sonnet -d ~/work/src/myapp "Update dependencies"
tmx-claude -n "auth-fix" "Update the auth flow"
Tip: Use with bd workflow:
tmx-claude -d ~/work/src/myapp "bd ready && bd show beads-xxx"
EOF
exit "${1:-0}"
}
# Check dependencies
if ! command -v tmux &>/dev/null; then
echo "Error: tmux is not installed" >&2
exit 1
fi
if ! command -v claude &>/dev/null; then
echo "Error: claude is not installed" >&2
exit 1
fi
# Defaults
DIR=""
WIN_NAME=""
MODEL=""
ATTACH=false
WAIT_SECS=2
# Parse arguments
while getopts "d:n:m:aw:h" opt; do
case $opt in
d) DIR="$OPTARG" ;;
n) WIN_NAME="$OPTARG" ;;
m) MODEL="$OPTARG" ;;
a) ATTACH=true ;;
w) WAIT_SECS="$OPTARG" ;;
h) usage 0 ;;
*) usage 1 ;;
esac
done
shift $((OPTIND-1))
# Remaining args are the prompt
PROMPT="$*"
if [ -z "$PROMPT" ]; then
echo "Error: Prompt is required" >&2
usage 1
fi
# Use provided directory or current directory
DIR="${DIR:-$(pwd)}"
# Resolve to absolute path
DIR="$(cd "$DIR" 2>/dev/null && pwd)" || {
echo "Error: Directory does not exist: $DIR" >&2
exit 1
}
# Generate a window name from the directory if not provided
WIN_NAME="${WIN_NAME:-$(basename "$DIR")}"
# Truncate prompt for display (first 50 chars)
PROMPT_PREVIEW="${PROMPT:0:50}"
[ ${#PROMPT} -gt 50 ] && PROMPT_PREVIEW="${PROMPT_PREVIEW}..."
start_claude_in_window() {
local target="$1"
# Escape the prompt for shell embedding
local escaped_prompt
escaped_prompt=$(printf '%q' "$PROMPT")
# Build claude command with optional model flag
local claude_cmd="claude"
[ -n "$MODEL" ] && claude_cmd="claude --model $MODEL"
# Start claude with the prompt as a positional argument (more reliable than send-keys)
tmux send-keys -t "$target" "$claude_cmd $escaped_prompt" Enter
}
if [ -z "$TMUX" ]; then
# Not in tmux - create a new session (detached)
SESSION="claude-$$"
echo "Creating tmux session '$SESSION' in $DIR"
tmux new-session -d -s "$SESSION" -c "$DIR" -n "$WIN_NAME"
start_claude_in_window "$SESSION"
echo "✓ Started Claude in tmux session '$SESSION'"
echo " Window: $WIN_NAME"
echo " Dir: $DIR"
echo " Prompt: $PROMPT_PREVIEW"
echo ""
echo "Attach with: tmux attach -t $SESSION"
if $ATTACH; then
exec tmux attach -t "$SESSION"
fi
else
# In tmux - create a new window
CURRENT_WINDOW=$(tmux display-message -p '#I')
echo "Creating window '$WIN_NAME' in $DIR"
tmux new-window -n "$WIN_NAME" -c "$DIR"
start_claude_in_window "$WIN_NAME"
if ! $ATTACH; then
# Switch back to original window
tmux select-window -t "$CURRENT_WINDOW"
fi
echo "✓ Started Claude in window '$WIN_NAME'"
echo " Dir: $DIR"
echo " Prompt: $PROMPT_PREVIEW"
fi
#!/bin/bash
# tmx-worktree - Create a git worktree and launch Claude Code in it
#
# Usage:
# tmx-worktree -b feature-login "Implement login feature"
# tmx-worktree -p myapp -b fix-bug "Fix the authentication bug"
# tmx-worktree -b refactor -f develop "Refactor auth module"
#
# Creates a worktree at ~/work/src/<project>-<branch>/ and launches Claude
# in a new tmux window with the given prompt.
set -e
WORKTREE_BASE="$HOME/work/src"
usage() {
cat <<'EOF'
Usage: tmx-worktree [-p PROJECT] -b BRANCH [-f FROM] [-n NAME] [-a] PROMPT
Create a git worktree and launch Claude Code in a new tmux window.
Options:
-p PROJECT Source project directory (default: current directory)
-b BRANCH Branch name to create (required)
-f FROM Base branch to create from (default: auto-detect main/master)
-n NAME Tmux window name (default: project-branch)
-a Attach/switch to the new window immediately
-h Show this help
The worktree is created at ~/work/src/<project>-<branch>/
Examples:
tmx-worktree -b feature-auth "Implement OAuth login"
tmx-worktree -p myapp -b fix-123 "Fix issue #123"
tmx-worktree -b refactor -f develop "Refactor the data layer"
Cleanup:
Use worktree-clean to safely remove finished worktrees
EOF
exit "${1:-0}"
}
die() {
echo "Error: $1" >&2
exit 1
}
# Check dependencies
command -v git &>/dev/null || die "git is not installed"
command -v tmux &>/dev/null || die "tmux is not installed"
command -v claude &>/dev/null || die "claude is not installed"
# Defaults
PROJECT_DIR=""
BRANCH=""
FROM_BRANCH=""
WIN_NAME=""
ATTACH=false
# Parse arguments
while getopts "p:b:f:n:ah" opt; do
case $opt in
p) PROJECT_DIR="$OPTARG" ;;
b) BRANCH="$OPTARG" ;;
f) FROM_BRANCH="$OPTARG" ;;
n) WIN_NAME="$OPTARG" ;;
a) ATTACH=true ;;
h) usage 0 ;;
*) usage 1 ;;
esac
done
shift $((OPTIND-1))
# Remaining args are the prompt
PROMPT="$*"
# Validate required args
[ -z "$BRANCH" ] && die "Branch name is required (-b BRANCH)"
[ -z "$PROMPT" ] && die "Prompt is required"
# Resolve project directory
PROJECT_DIR="${PROJECT_DIR:-$(pwd)}"
PROJECT_DIR="$(cd "$PROJECT_DIR" 2>/dev/null && pwd)" || die "Directory does not exist: $PROJECT_DIR"
# Verify it's a git repository
git -C "$PROJECT_DIR" rev-parse --git-dir &>/dev/null || die "Not a git repository: $PROJECT_DIR"
# Get project name from directory
PROJECT_NAME="$(basename "$PROJECT_DIR")"
# Auto-detect main branch if not specified
if [ -z "$FROM_BRANCH" ]; then
# Try main first, then master
if git -C "$PROJECT_DIR" show-ref --verify --quiet refs/heads/main; then
FROM_BRANCH="main"
elif git -C "$PROJECT_DIR" show-ref --verify --quiet refs/heads/master; then
FROM_BRANCH="master"
else
die "Could not auto-detect main branch. Specify with -f"
fi
fi
# Verify base branch exists
git -C "$PROJECT_DIR" show-ref --verify --quiet "refs/heads/$FROM_BRANCH" || \
die "Base branch does not exist: $FROM_BRANCH"
# Build worktree path
WORKTREE_PATH="$WORKTREE_BASE/${PROJECT_NAME}-${BRANCH}"
# Check if worktree path already exists
if [ -e "$WORKTREE_PATH" ]; then
die "Worktree path already exists: $WORKTREE_PATH
To reuse it: tmx-claude -d '$WORKTREE_PATH' '$PROMPT'
To remove it: worktree-clean '$WORKTREE_PATH'"
fi
# Check if branch already exists
if git -C "$PROJECT_DIR" show-ref --verify --quiet "refs/heads/$BRANCH"; then
die "Branch already exists: $BRANCH
To use existing branch, create worktree manually:
cd $PROJECT_DIR && git worktree add '$WORKTREE_PATH' '$BRANCH'"
fi
# Set window name
WIN_NAME="${WIN_NAME:-${PROJECT_NAME}-${BRANCH}}"
echo "Creating worktree for $PROJECT_NAME..."
echo " Branch: $BRANCH (from $FROM_BRANCH)"
echo " Path: $WORKTREE_PATH"
echo ""
# Fetch latest to ensure we have up-to-date refs
echo "Fetching latest..."
git -C "$PROJECT_DIR" fetch --quiet origin "$FROM_BRANCH" 2>/dev/null || true
# Create the worktree with a new branch
# Use origin/$FROM_BRANCH if available, otherwise local $FROM_BRANCH
if git -C "$PROJECT_DIR" show-ref --verify --quiet "refs/remotes/origin/$FROM_BRANCH"; then
git -C "$PROJECT_DIR" worktree add -b "$BRANCH" "$WORKTREE_PATH" "origin/$FROM_BRANCH"
else
git -C "$PROJECT_DIR" worktree add -b "$BRANCH" "$WORKTREE_PATH" "$FROM_BRANCH"
fi
echo ""
echo "✓ Worktree created at $WORKTREE_PATH"
echo ""
# Now launch Claude in the worktree using tmx-claude's pattern
start_claude_in_window() {
local target="$1"
local escaped_prompt
escaped_prompt=$(printf '%q' "$PROMPT")
tmux send-keys -t "$target" "claude $escaped_prompt" Enter
}
# Truncate prompt for display
PROMPT_PREVIEW="${PROMPT:0:50}"
[ ${#PROMPT} -gt 50 ] && PROMPT_PREVIEW="${PROMPT_PREVIEW}..."
if [ -z "$TMUX" ]; then
# Not in tmux - create a new session
SESSION="worktree-$$"
echo "Creating tmux session '$SESSION'..."
tmux new-session -d -s "$SESSION" -c "$WORKTREE_PATH" -n "$WIN_NAME"
start_claude_in_window "$SESSION"
echo "✓ Started Claude in tmux session '$SESSION'"
echo " Window: $WIN_NAME"
echo " Dir: $WORKTREE_PATH"
echo " Prompt: $PROMPT_PREVIEW"
echo ""
echo "Attach with: tmux attach -t $SESSION"
if $ATTACH; then
exec tmux attach -t "$SESSION"
fi
else
# In tmux - create a new window
CURRENT_WINDOW=$(tmux display-message -p '#I')
echo "Creating window '$WIN_NAME'..."
tmux new-window -n "$WIN_NAME" -c "$WORKTREE_PATH"
start_claude_in_window "$WIN_NAME"
if ! $ATTACH; then
tmux select-window -t "$CURRENT_WINDOW"
fi
echo "✓ Started Claude in window '$WIN_NAME'"
echo " Dir: $WORKTREE_PATH"
echo " Prompt: $PROMPT_PREVIEW"
fi
echo ""
echo "When done, clean up with: worktree-clean $WORKTREE_PATH"
#!/bin/bash
# worktree-clean - Safely remove git worktrees
#
# Usage:
# worktree-clean ~/work/src/myapp-feature
# worktree-clean myapp-feature # Assumes ~/work/src/ prefix
# worktree-clean --merged # Clean all merged worktrees
#
# Safety checks:
# - Uncommitted changes
# - Unpushed commits
# - Unmerged branch (warning, not blocking)
set -e
WORKTREE_BASE="$HOME/work/src"
usage() {
cat <<'EOF'
Usage: worktree-clean [OPTIONS] PATH|NAME
worktree-clean --merged [-n]
Safely remove a git worktree created by tmx-worktree.
Arguments:
PATH Full path to worktree (e.g., ~/work/src/myapp-feature)
NAME Short name, assumes ~/work/src/ prefix (e.g., myapp-feature)
Options:
-f, --force Skip safety checks (uncommitted changes, unpushed commits)
-d, --delete Also delete the branch after removing worktree
-n, --dry-run Show what would be done without doing it
--merged Clean ALL worktrees whose branches are merged to main/master
-h, --help Show this help
Safety Checks:
- Uncommitted changes (blocks unless --force)
- Unpushed commits (blocks unless --force)
- Unmerged branch (warning only, does not block)
Examples:
worktree-clean myapp-feature # Remove specific worktree
worktree-clean -d myapp-feature # Remove worktree and delete branch
worktree-clean --merged # Clean all merged worktrees
worktree-clean --merged -n # Preview merged cleanup
EOF
exit "${1:-0}"
}
die() {
echo "Error: $1" >&2
exit 1
}
warn() {
echo "Warning: $1" >&2
}
info() {
echo "$1"
}
# Check dependencies
command -v git &>/dev/null || die "git is not installed"
# Defaults
FORCE=false
DELETE_BRANCH=false
DRY_RUN=false
CLEAN_MERGED=false
WORKTREE_PATH=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-f|--force) FORCE=true; shift ;;
-d|--delete) DELETE_BRANCH=true; shift ;;
-n|--dry-run) DRY_RUN=true; shift ;;
--merged) CLEAN_MERGED=true; shift ;;
-h|--help) usage 0 ;;
-*) die "Unknown option: $1" ;;
*)
if [ -z "$WORKTREE_PATH" ]; then
WORKTREE_PATH="$1"
else
die "Unexpected argument: $1"
fi
shift
;;
esac
done
# Get the main repo for a worktree
get_main_repo() {
local worktree="$1"
git -C "$worktree" rev-parse --path-format=absolute --git-common-dir 2>/dev/null | sed 's/\.git$//'
}
# Get branch name for a worktree
get_worktree_branch() {
local worktree="$1"
git -C "$worktree" rev-parse --abbrev-ref HEAD 2>/dev/null
}
# Detect main branch for a repo
get_main_branch() {
local repo="$1"
if git -C "$repo" show-ref --verify --quiet refs/heads/main; then
echo "main"
elif git -C "$repo" show-ref --verify --quiet refs/heads/master; then
echo "master"
else
echo ""
fi
}
# Check if branch is merged into main
is_branch_merged() {
local repo="$1"
local branch="$2"
local main_branch="$3"
# Check if branch is ancestor of main (i.e., merged)
git -C "$repo" merge-base --is-ancestor "$branch" "$main_branch" 2>/dev/null
}
# Check for uncommitted changes
has_uncommitted_changes() {
local worktree="$1"
! git -C "$worktree" diff --quiet 2>/dev/null || \
! git -C "$worktree" diff --cached --quiet 2>/dev/null
}
# Check for untracked files
has_untracked_files() {
local worktree="$1"
[ -n "$(git -C "$worktree" ls-files --others --exclude-standard 2>/dev/null)" ]
}
# Check for unpushed commits
has_unpushed_commits() {
local worktree="$1"
local branch
branch=$(get_worktree_branch "$worktree")
# Check if upstream exists
if git -C "$worktree" rev-parse --verify "@{upstream}" &>/dev/null; then
# Has upstream, check for unpushed
[ -n "$(git -C "$worktree" log '@{upstream}..HEAD' --oneline 2>/dev/null)" ]
else
# No upstream - if there are commits not in origin/main, consider unpushed
local main_branch
main_branch=$(get_main_branch "$worktree")
if [ -n "$main_branch" ]; then
local origin_main="origin/$main_branch"
if git -C "$worktree" show-ref --verify --quiet "refs/remotes/$origin_main"; then
[ -n "$(git -C "$worktree" log "$origin_main..HEAD" --oneline 2>/dev/null)" ]
else
# No remote, can't check
return 1
fi
else
return 1
fi
fi
}
# Clean a single worktree
clean_worktree() {
local worktree="$1"
local force="$2"
local delete_branch="$3"
local dry_run="$4"
# Resolve path
if [[ "$worktree" != /* ]]; then
worktree="$WORKTREE_BASE/$worktree"
fi
# Check if path exists
if [ ! -d "$worktree" ]; then
die "Worktree does not exist: $worktree"
fi
# Check if it's a git worktree
if ! git -C "$worktree" rev-parse --is-inside-work-tree &>/dev/null; then
die "Not a git repository: $worktree"
fi
local main_repo
main_repo=$(get_main_repo "$worktree")
# Check if it's actually a worktree (not the main repo)
local git_dir
git_dir=$(git -C "$worktree" rev-parse --git-dir)
if [[ "$git_dir" == ".git" ]]; then
die "This appears to be a main repository, not a worktree: $worktree"
fi
local branch
branch=$(get_worktree_branch "$worktree")
local main_branch
main_branch=$(get_main_branch "$main_repo")
info "Worktree: $worktree"
info "Branch: $branch"
info "Main repo: $main_repo"
echo ""
# Safety checks
local issues=0
if has_uncommitted_changes "$worktree"; then
if $force; then
warn "Uncommitted changes (--force specified, continuing)"
else
echo "✗ Uncommitted changes detected"
issues=$((issues + 1))
fi
else
echo "✓ No uncommitted changes"
fi
if has_untracked_files "$worktree"; then
if $force; then
warn "Untracked files (--force specified, continuing)"
else
echo "✗ Untracked files detected"
issues=$((issues + 1))
fi
else
echo "✓ No untracked files"
fi
if has_unpushed_commits "$worktree"; then
if $force; then
warn "Unpushed commits (--force specified, continuing)"
else
echo "✗ Unpushed commits detected"
issues=$((issues + 1))
fi
else
echo "✓ No unpushed commits"
fi
# Check merge status (warning only)
if [ -n "$main_branch" ] && [ "$branch" != "$main_branch" ]; then
if is_branch_merged "$main_repo" "$branch" "$main_branch"; then
echo "✓ Branch is merged into $main_branch"
else
warn "Branch is NOT merged into $main_branch"
fi
fi
echo ""
# Abort if issues found and not forcing
if [ $issues -gt 0 ] && ! $force; then
die "Safety checks failed. Use --force to override."
fi
# Perform cleanup
if $dry_run; then
echo "[DRY RUN] Would remove worktree: $worktree"
if $delete_branch; then
echo "[DRY RUN] Would delete branch: $branch"
fi
else
info "Removing worktree..."
git -C "$main_repo" worktree remove "$worktree"
echo "✓ Worktree removed"
if $delete_branch; then
info "Deleting branch..."
git -C "$main_repo" branch -D "$branch"
echo "✓ Branch '$branch' deleted"
fi
fi
echo ""
echo "Done!"
}
# Clean all merged worktrees
clean_merged_worktrees() {
local dry_run="$1"
info "Scanning for merged worktrees in $WORKTREE_BASE..."
echo ""
local cleaned=0
local skipped=0
# Find all directories that look like worktrees (contain .git file)
for dir in "$WORKTREE_BASE"/*; do
[ -d "$dir" ] || continue
# Check if it's a git worktree (has .git file, not directory)
if [ -f "$dir/.git" ]; then
local branch
branch=$(get_worktree_branch "$dir")
local main_repo
main_repo=$(get_main_repo "$dir")
local main_branch
main_branch=$(get_main_branch "$main_repo")
if [ -z "$main_branch" ]; then
warn "Skipping $dir: cannot determine main branch"
skipped=$((skipped + 1))
continue
fi
if [ "$branch" = "$main_branch" ]; then
continue # Skip main branch worktrees
fi
if is_branch_merged "$main_repo" "$branch" "$main_branch"; then
# Check for uncommitted/unpushed
if has_uncommitted_changes "$dir" || has_untracked_files "$dir"; then
warn "Skipping $dir: has uncommitted changes"
skipped=$((skipped + 1))
continue
fi
if $dry_run; then
echo "[DRY RUN] Would clean: $dir (branch: $branch)"
else
echo "Cleaning: $dir (branch: $branch)"
git -C "$main_repo" worktree remove "$dir"
git -C "$main_repo" branch -d "$branch" 2>/dev/null || true
fi
cleaned=$((cleaned + 1))
fi
fi
done
echo ""
if $dry_run; then
echo "Would clean $cleaned worktree(s), skipped $skipped"
else
echo "Cleaned $cleaned worktree(s), skipped $skipped"
fi
}
# Main logic
if $CLEAN_MERGED; then
clean_merged_worktrees "$DRY_RUN"
else
[ -z "$WORKTREE_PATH" ] && die "Worktree path is required (or use --merged)"
clean_worktree "$WORKTREE_PATH" "$FORCE" "$DELETE_BRANCH" "$DRY_RUN"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment