Feature request: SessionEnd hook that fires once at actual session close
Problem
The Stop hook fires after every agent turn, not just when the session actually ends (/exit, Ctrl+C). This makes it impossible to reliably run cleanup/save tasks at session end.
Current behavior: Stop fires after every assistant response. A blocking Stop hook creates a loop (block → Claude processes → Stop fires again). A non-blocking Stop hook can't trigger Claude to do work.
Desired behavior: A SessionEnd hook that fires exactly once when the user ends the session, with enough time for Claude to do final work (e.g., 30-120 seconds).
Use case
I built a Claude Code plugin that extracts relational signals from the conversation at session end (analyzing communication style, updating a memory vector). This requires Claude to analyze the conversation — it's an LLM task, not a simple script.
With the current Stop event, I can't reliably trigger this:
- Blocking command hook: Fires every turn, creates loops
- Prompt hook:
JSON validation failederror on Stop events - Marker file workaround: Fires mid-session at turn N, not at session end. Signals from later turns are lost.
A SessionEnd hook with prompt or block support would solve this completely.
Proposed solution
A new hook event (or modification of Stop):
- Fires once when the session is actually ending
- Supports
prompttype (inject instructions for Claude to follow before close) - Or supports
commandtype withblockdecision (Claude processes the block reason, then session closes) - Timeout: configurable, default ~120 seconds
Workaround attempted
Wrote a Stop command hook with a marker file: blocks once at turn N, writes marker, approves on subsequent turns. This works but:
- Fires mid-session (disruptive)
- Only captures signals up to turn N, losing the rest
- Not a real "session end" trigger
Environment
- Claude Code on Windows 11
- Plugin uses
SessionStart(command, works perfectly) andStop(broken for this use case)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗