diff --git a/bin/gstack-uninstall b/bin/gstack-uninstall index 9f83386d7..e86447330 100755 --- a/bin/gstack-uninstall +++ b/bin/gstack-uninstall @@ -132,6 +132,35 @@ if [ -d "$STATE_DIR/projects" ]; then done < <(find "$STATE_DIR/projects" -name browse.json -path '*/.gstack/*' 2>/dev/null || true) fi +# ─── Remove gstack hooks from Claude Code settings ────────── +# MUST run BEFORE any install-root deletion: SETTINGS_HOOK resolves inside the +# install being removed — in a real global uninstall, running this after +# `rm -rf ~/.claude/skills/gstack` silently no-ops and orphans every hook. +SETTINGS_HOOK="$(dirname "$0")/gstack-settings-hook" +SESSION_UPDATE="$(dirname "$0")/gstack-session-update" +if [ -x "$SETTINGS_HOOK" ]; then + "$SETTINGS_HOOK" remove "$SESSION_UPDATE" 2>/dev/null && REMOVED+=("SessionStart hook") || true + # Cathedral T8 cleanup: also remove plan-tune PreToolUse + PostToolUse hooks. + if "$SETTINGS_HOOK" remove-source --source plan-tune-cathedral 2>/dev/null | grep -q "removed [1-9]"; then + REMOVED+=("plan-tune cathedral hooks") + fi + # AskUserQuestion error-fallback hook (registered by setup; previously never + # torn down). + if "$SETTINGS_HOOK" remove-source --source auq-error-fallback 2>/dev/null | grep -q "removed [1-9]"; then + REMOVED+=("AskUserQuestion error-fallback hook") + fi + # Timeline Stop hook (#2553). + if "$SETTINGS_HOOK" remove-source --source gstack-timeline-stop 2>/dev/null | grep -q "removed [1-9]"; then + REMOVED+=("timeline Stop hook") + fi + # Identity sweep for untagged strays (Claude Code strips _gstack_source + # tags; pre-v1.67 setups baked worktree paths). Removes every gstack-owned + # hook item, live or dead — the binaries they point at are being deleted. + if "$SETTINGS_HOOK" prune-stale --all 2>/dev/null | grep -q "removed [1-9]"; then + REMOVED+=("stray gstack hook entries") + fi +fi + # ─── Remove global Claude skills ──────────────────────────── CLAUDE_SKILLS="$HOME/.claude/skills" @@ -334,21 +363,6 @@ if [ -n "$_GIT_ROOT" ]; then fi fi -# ─── Remove SessionStart hook from Claude Code settings ───── -SETTINGS_HOOK="$(dirname "$0")/gstack-settings-hook" -SESSION_UPDATE="$(dirname "$0")/gstack-session-update" -if [ -x "$SETTINGS_HOOK" ]; then - "$SETTINGS_HOOK" remove "$SESSION_UPDATE" 2>/dev/null && REMOVED+=("SessionStart hook") || true - # Cathedral T8 cleanup: also remove plan-tune PreToolUse + PostToolUse hooks. - if "$SETTINGS_HOOK" remove-source --source plan-tune-cathedral 2>/dev/null | grep -q "removed [1-9]"; then - REMOVED+=("plan-tune cathedral hooks") - fi - # Timeline Stop hook (#2553). - if "$SETTINGS_HOOK" remove-source --source gstack-timeline-stop 2>/dev/null | grep -q "removed [1-9]"; then - REMOVED+=("timeline Stop hook") - fi -fi - # ─── Remove global state ──────────────────────────────────── if [ "$KEEP_STATE" -eq 0 ] && [ -d "$STATE_DIR" ]; then rm -rf "$STATE_DIR"