[BUG] Stop hook fires on every response turn, not session exit — breaks interactive workflows

Resolved 💬 3 comments Opened Mar 24, 2026 by aegertAI Closed Mar 28, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

The Stop hook event fires after every agent response completion, not only on session termination. Any script attached
to the Stop hook (interactive dialogs, cleanup tasks, backup routines) interrupts the user mid-workflow on every
response turn.

What Should Happen?

Stop should fire once when the session actually ends — /clear, /stop, window close, or process termination. It should
not fire on every response turn.

Alternatively, the distinction between "response turn completed" and "session ending" should be documented clearly,
with separate events for each.

Current workaround

Migrating to SessionEnd (which does fire only on actual session termination) resolves the issue. However:

  • The Stop event name implies session-level semantics, not turn-level
  • Most users building hooks will expect Stop to mean "session is stopping"
  • The current behavior is undocumented and surprising

Impact

This is a significant barrier for users building agentic workflows with hooks. Any automation attached to Stop —
backups, cleanup, logging, notifications — fires repeatedly during normal conversation. For users running interactive
scripts (macOS dialogs, terminal prompts), it creates a disruptive UX that breaks flow during multi-turn work like code
reviews, brainstorming sessions, and iterative development.

The issue compounds with voice mode and party-style multi-agent patterns where turns are frequent and the user is not
at the keyboard to dismiss dialogs.

Proposed fix

Either:

  1. Change Stop semantics to fire only on session termination (breaking change, but matches user expectation)
  2. Document the distinction clearly and recommend SessionEnd for session-exit hooks in the hooks documentation
  3. Add a reason field to the Stop hook input so scripts can distinguish between turn completion and session exit

Error Messages/Logs

Steps to Reproduce

  1. Add a Stop hook in ~/.claude/settings.json:

"Stop": [{ "hooks": [{ "type": "command", "command": "osascript -e 'display dialog \"Stop fired\"'" }] }]

  1. Start a session, send a message, get a response
  2. The dialog appears immediately after Claude's response — not on session exit
  3. Send another message. Dialog appears again after the next response.
  4. In multi-turn workflows (party mode, Q&A, iterative design), the dialog fires on every single turn.

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.81

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗