#!/bin/bash # Cleanup merged Claude Code background-session worktrees. # # `claude agents` / `claude --bg` создают `.claude/worktrees/agent-*` для # каждой background session. После merge PR worktree остаётся locked # и не удаляется автоматически — за неделю накапливаются десятки. # # Скрипт сравнивает branch каждого worktree с `forgejo/main`; если branch # полностью в main (merged) — удаляет worktree с `--force` (worktree # заперт супервизором). Затем `git worktree prune` чистит references. # # Запускать вручную или через cron (weekly recommended): # 0 9 * * MON cd /path/to/gendesign && ./scripts/cleanup-merged-worktrees.sh # # Safe: # - Не трогает unmerged branches (in-progress work, PR ещё не merged) # - Не трогает worktree.lock с твоими running sessions (force нужен только # потому что Claude Code ставит lock автоматически) # - Логи action — каждый удалённый branch выводится отдельной строкой # # Reference: https://code.claude.com/docs/en/worktrees#clean-up-worktrees set -e REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$REPO_ROOT" echo "Fetching forgejo/main..." git fetch forgejo main --quiet BEFORE=$(git worktree list | wc -l) SIZE_BEFORE=$(du -sh .claude/worktrees/ 2>/dev/null | awk '{print $1}') echo "Scanning $((BEFORE - 1)) worktrees (skip main)..." REMOVED=0 KEPT=0 # Parse `git worktree list --porcelain` into "path branch" pairs. git worktree list --porcelain | awk '/^worktree/{w=$2} /^branch/{b=$2} /^$/{print w" "b}' | \ while read path branch; do # Skip main worktree (no branch field) and detached HEADs. [ -z "$branch" ] && continue short="${branch#refs/heads/}" # Don't touch the worktree we're standing in. if [ "$path" = "$REPO_ROOT" ]; then continue fi if git merge-base --is-ancestor "$short" forgejo/main 2>/dev/null; then if git worktree remove --force "$path" 2>/dev/null; then echo " removed: $short" REMOVED=$((REMOVED + 1)) else echo " failed: $short ($path)" fi else KEPT=$((KEPT + 1)) fi done git worktree prune AFTER=$(git worktree list | wc -l) SIZE_AFTER=$(du -sh .claude/worktrees/ 2>/dev/null | awk '{print $1}') echo "" echo "Before: $((BEFORE - 1)) worktrees, $SIZE_BEFORE" echo "After: $((AFTER - 1)) worktrees, $SIZE_AFTER"