[FEATURE] Add UserPromptCancel / Stop-on-cancel hook event

Resolved 💬 3 comments Opened Apr 8, 2026 by LinuxIsCool Closed Apr 12, 2026

Problem

When a user cancels a prompt mid-execution (Ctrl+C), Claude Code does not fire the Stop hook event. The session continues (not ended), but any hook-driven state that was set on UserPromptSubmit (e.g. a \"working\" indicator) is permanently stuck until the next Stop fires naturally.

This affects:

  • Status indicator systems (tmux pane indicators, statusline integrations)
  • Any hook-driven state machine that tracks Claude's activity state

The Stop event docs say it fires "when Claude stops responding", but cancellation via Ctrl+C is explicitly NOT handled.

Proposed Solution

Add a new hook event UserPromptCancel (or fire the existing Stop event on cancel):

| Event | Trigger |
|-------|---------|
| UserPromptCancel | User pressed Ctrl+C to cancel the current prompt |
| Stop (extended) | Also fire on cancel, same as normal completion |

The UserPromptCancel approach is preferred — it lets hook scripts distinguish cancellation from natural completion if needed.

Workaround

Implement a reconciliation loop that detects stale "working" states (e.g. working for >10min with no live Claude process) and resets them. This is O(N) polling every 60s rather than an O(1) event. It also has a 60s delay before the indicator clears, which is jarring.

Impact

This is a correctness gap in the hook event model. The hook lifecycle currently has no way to know when a user cancels, making hook-driven state machines unable to maintain accurate state after cancellation. The workaround is brittle and adds unnecessary complexity.

Related

  • PreToolUse fires during Claude's init sequence (loading plugins), causing premature "working" state before any user interaction. A startup guard is needed as a second workaround. A UserPromptStart event (after the prompt is actually ready to receive input) would also help here.

View original on GitHub ↗

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