[FEATURE] Add UserPromptCancel / Stop-on-cancel hook event
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
PreToolUsefires during Claude's init sequence (loading plugins), causing premature "working" state before any user interaction. A startup guard is needed as a second workaround. AUserPromptStartevent (after the prompt is actually ready to receive input) would also help here.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗