For each worktree, run the following cleanup:
a. Remove the git worktree from the source repo:
git -C "<worktree-source>" worktree remove "<worktree-path>" --force
If the worktree directory was already deleted or is not registered, run:
git -C "<worktree-source>" worktree prune
b. If the worktree directory still exists after removal (e.g. untracked
files prevented cleanup), delete it:
rm -rf "<worktree-path>"
c. Kill the associated tmux session if one exists. Derive the session name
from the worktree directory basename using the same logic as the
sessionizer — replace :, spaces, and . with _, lowercase, then
capitalise the first letter:
dir_name=$(basename "<worktree-path>")
session_name=$(echo "$dir_name" \
| tr ':. ' '___' | tr '[:upper:]' '[:lower:]')
session_name=$(echo "${session_name:0:1}" \
| tr '[:lower:]' '[:upper:]')${session_name:1}
tmux kill-session -t "$session_name" 2>/dev/null
If no tmux session with that name exists, this is a no-op.
d. Delete Xcode caches keyed to the worktree path. Xcode names each
DerivedData folder <ProjectName>-<hash> where the hash is derived
from the absolute workspace path, so a worktree gets its own folder
distinct from the source repo's. Find and remove every DerivedData
folder whose info.plist references the worktree path:
for derived in "$HOME/Library/Developer/Xcode/DerivedData"/*/; do
info_plist="$derived/info.plist"
[ -f "$info_plist" ] || continue
workspace_path=$(/usr/libexec/PlistBuddy \
-c "Print :WorkspacePath" "$info_plist" 2>/dev/null) || continue
case "$workspace_path" in
"<worktree-path>"|"<worktree-path>"/*)
rm -rf "$derived"
;;
esac
done
Also remove any per-worktree SwiftPM build artifacts and
xcodebuild.nvim caches that live inside the worktree itself —
these go away with rm -rf "<worktree-path>" in step (b), so no
extra command is needed. Never touch the shared
ModuleCache.noindex directory under DerivedData.