From 1bd80048545726f574cec7fa45f8c9a945eb111a Mon Sep 17 00:00:00 2001 From: Sheldon Finlay Date: Thu, 2 Apr 2026 08:17:15 -0400 Subject: [PATCH] fix: scope Stop hook to agent-loop tmux session only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Stop hook (kill -INT $PPID) was written to the project's settings.local.json, causing ANY Claude Code session in the same project to kill its parent shell on exit — not just the loop's sessions. Now the hook checks tmux session name before firing: only CC sessions inside the "agent-loop" tmux session trigger the kill. Other CC sessions in the same project are unaffected. --- lib/hooks.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/hooks.sh b/lib/hooks.sh index 95400c3..a39f637 100644 --- a/lib/hooks.sh +++ b/lib/hooks.sh @@ -7,9 +7,17 @@ # # Without this hook, claude would exit to an interactive prompt instead of # returning control to the loop script. +# +# IMPORTANT: The hook is scoped to only fire inside the agent-loop tmux session. +# Without this guard, ANY Claude Code session opened in the same project directory +# would pick up the hook and kill its own parent shell on exit. SETTINGS_FILE="${PROJECT_ROOT}/.claude/settings.local.json" +# The hook command checks we're inside the agent-loop tmux session before killing. +# This prevents the hook from affecting other CC sessions open in the same project. +HOOK_COMMAND='tmux display-message -p "#{session_name}" 2>/dev/null | grep -q "^agent-loop$" && kill -INT $PPID || true' + install_hooks() { if [ ! -f "$SETTINGS_FILE" ]; then mkdir -p "$(dirname "$SETTINGS_FILE")" @@ -17,14 +25,16 @@ install_hooks() { fi if command -v jq &>/dev/null; then - jq '.hooks.Stop = [{"matcher": "", "hooks": [{"type": "command", "command": "kill -INT $PPID || true"}]}]' \ + jq --arg cmd "$HOOK_COMMAND" \ + '.hooks.Stop = [{"matcher": "", "hooks": [{"type": "command", "command": $cmd}]}]' \ "$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" && mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE" else - LOOP_SETTINGS="$SETTINGS_FILE" python3 -c " + LOOP_HOOK_CMD="$HOOK_COMMAND" LOOP_SETTINGS="$SETTINGS_FILE" python3 -c " import json, os p = os.environ['LOOP_SETTINGS'] +cmd = os.environ['LOOP_HOOK_CMD'] s = json.load(open(p)) if os.path.exists(p) else {} -s.setdefault('hooks', {})['Stop'] = [{'matcher': '', 'hooks': [{'type': 'command', 'command': 'kill -INT \$PPID || true'}]}] +s.setdefault('hooks', {})['Stop'] = [{'matcher': '', 'hooks': [{'type': 'command', 'command': cmd}]}] json.dump(s, open(p, 'w'), indent=2) " fi