---
name: merge-cleanup
description: "Merge a worktree branch to main and clean up the worktree, branch, and tmux window. Safe CWD-aware cleanup that avoids the self-deletion loop."
arguments:
  - name: slug
    description: "Branch/worktree slug to merge and clean up (e.g., 'add-auth')"
    required: true
  - name: base
    description: "Target branch to merge into (default: main)"
    required: false
---

# Merge and Cleanup Worktree

Merge a worktree branch into main (or another base), then remove the worktree, branch, and tmux window.

**Note:** Native `--worktree` uses branch name `worktree-<slug>`. Legacy worktrees may use `<slug>` directly. This skill handles both.

## CRITICAL: CWD Determines What You Can Do

The Bash tool validates that your CWD exists BEFORE running any command. If you delete your own worktree directory, ALL subsequent bash commands fail — even `git -C /valid/path`. There is NO recovery.

**Detect where you are running:**

```bash
MAIN_REPO=$(git worktree list | head -1 | awk '{print $1}')
MY_DIR=$(pwd)
```

- If `MY_DIR` is inside a worktree (not `MAIN_REPO`): you are a **worktree session** → do MERGE ONLY (steps 1-4), then STOP
- If `MY_DIR` equals `MAIN_REPO`: you are the **main session** → do FULL cleanup (steps 1-7)

---

## Steps 1-4: MERGE (safe from anywhere)

### 1. Capture paths and resolve branch name

```bash
MAIN_REPO=$(git worktree list | head -1 | awk '{print $1}')
SLUG="<slug>"
BASE="${base:-main}"

# Resolve actual branch name (native --worktree uses worktree-<slug>, legacy uses <slug>)
if git -C "$MAIN_REPO" rev-parse --verify "worktree-$SLUG" &>/dev/null; then
  BRANCH="worktree-$SLUG"
elif git -C "$MAIN_REPO" rev-parse --verify "$SLUG" &>/dev/null; then
  BRANCH="$SLUG"
else
  echo "Branch not found for slug: $SLUG" && exit 1
fi
```

### 2. Find worktree path and check for uncommitted changes

```bash
WORKTREE_DIR=$(git -C "$MAIN_REPO" worktree list --porcelain | awk -v branch="refs/heads/$BRANCH" '$1=="worktree"{wt=$2} $1=="branch" && $2==branch{print wt}')
git -C "$WORKTREE_DIR" status --porcelain 2>/dev/null
```

If uncommitted changes exist, **stop and warn the user**.

### 3. Show what will be merged

```bash
git -C "$MAIN_REPO" log "$BASE..$BRANCH" --oneline
```

### 4. Merge the branch

```bash
git -C "$MAIN_REPO" checkout "$BASE" && git -C "$MAIN_REPO" merge "$BRANCH"
```

If merge conflicts: tell the user, offer to abort with `git -C "$MAIN_REPO" merge --abort`.

---

**If you are a worktree session: STOP HERE.** Tell the user:

> Merged `<slug>` into `<base>`. To clean up, run from your main session:
> `/worktree clean <slug>`

Do NOT proceed to steps 5-7. Do NOT delete your own worktree.

---

## Steps 5-7: CLEANUP (main session only)

Only run these if your CWD is the main repo (not inside a worktree).

### 5. Remove the worktree

```bash
git worktree remove "$WORKTREE_DIR" 2>/dev/null || git worktree prune
```

### 6. Delete the branch

```bash
git branch -d "$BRANCH"
```

Uses `-d` (safe delete). Never `-D`.

### 7. Kill the tmux window

```bash
tmux kill-window -t "cc-$SLUG" 2>/dev/null
```

Report: merged commits, removed worktree, deleted branch, killed window.

## Edge Cases

- **"Path does not exist" errors:** If you see this, your CWD was deleted. The cleanup likely SUCCEEDED. STOP immediately — do not retry.
- **Worktree already deleted:** Use `git worktree prune` from main, then delete branch.
- **Branch not merged to remote:** `-d` will refuse because the branch isn't pushed yet. This is expected — report that the branch will be cleaned up after the user pushes. Do NOT attempt `-D` (force delete) — it is denied by policy.
- **User handles remote ops:** Never push. Merge locally, user pushes when ready.

## Examples

```
# From worktree session (merge only, cleanup deferred):
/merge-cleanup add-auth

# From main session (full merge + cleanup):
/merge-cleanup add-auth
```
