Session lifecycle hooks: proactive Claude response on start + pre-exit turns
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Claude Code has no mechanism to let Claude act autonomously at session boundaries: —
neither at the start (before any user input) nor at the end (before the process exits).
Today, Claude only generates output in response to a user turn. This means:
- At session start: useful context injected by
SessionStarthooks (previous session summary, open issues/PRs, collaborator changes, system status) is available in Claude's system context, but Claude cannot surface it until the user types something. The user must manually trigger a response every session and if that trigger is not performed that session will not cover the actual needs of the project during that session, just the human being concerns at that moment based on their, therefore, imprecise memory, not an actually complete information.
- At session end: if the user closes the terminal or runs /exit without first typing a trigger phrase, any configured end-of-session actions (writing a summary, flushing commits, posting a log) never run. The existing
SessionEndhook only triggers shell commands — Claude cannot act. Again, in the same way, we are not fulfilling the main goal of the agent, supporting the human being on their imperfect actions the way they will always have what they need at session start.
Both gaps share the same root cause and block the same class of user-configured, and human being needed automated sessions workflow. We are requesting the two primitives needed to close that loop:
Preparing, before leaving the session, what will be needed right when starting the next session protecting the humans from their interactions.
Proposed Solution
Primitive 1 — Proactive response on session start
A mechanism for Claude to generate and display an assistant turn at session start, before the user types anything, using context already injected by the SessionStart hook.
Suggested implementation: if the SessionStart hook returns an "autoPrompt" field in its JSON response, Claude Code treats that string as a synthetic first user message, processes it, and displays Claude's response immediately.
Example hook response:
{"continue": true, "autoPrompt": "Show the session briefing from context."}
Alternatively: a dedicated hook event SessionStartPrompt whose stdout is treated as the first user message.
Primitive 2 — Pre-exit hook that triggers a Claude turn
A PreSessionEnd hook event that fires when the user requests exit — before termination — and injects a prompt into Claude's context so Claude can execute configured actions before the session closes.
Required behavior:
- Fires on /exit, Ctrl+D, and terminal close (not only one of them).
- Hook receives a JSON payload: session_id, transcript_path, cwd.
- Hook's stdout (or a designated JSON field) is injected as a final prompt that Claude processes normally — Claude's response and tool calls complete before the process exits.
- Optional: non-zero hook return code blocks the exit (analogous to Git's pre-commit hook), with /exit --force as override.
This is explicitly different from the existing advisory SessionEnd hook, which fires after termination begins and cannot trigger a Claude turn.
Alternative Solutions
We have tested every workaround we could find. None achieves the goal.
For session start (Primitive 1):
SessionStarthook stdout → Claude's system context: works, but Claude only acts on it when the user sends a message. The information is there; Claude cannot surface it proactively.- Hook stdout visible in the terminal: was working in v2.1.15 and v2.1.25, regressed in v2.1.27 (see #23524, #24425), partially re-appeared in v2.1.157, regressed again in v2.1.158 (see #64119, still open). Even when it worked, it showed raw text in the terminal — not a Claude response in the conversation UI.
claude --print --continuevia shell alias: re-enters the prior session with high latency and wrong UX (replays prior conversation instead of opening fresh with a briefing).- Writing to /dev/tty from the hook script: produces terminal output before Claude starts, but outside the conversation context — Claude cannot reference or act on it.
expect-based synthetic keypress: fragile, terminal-dependent, requires a separate process.
For session end (Primitive 2):
- Existing
SessionEndhook: fires after termination begins — Claude cannot act. Also unreliable: does not fire on /exit in some versions (#17885, #35892) and is killed before async work completes (#41577). Stophook: fires after each Claude turn during the session, not at exit.- Shell wrapper scripts around the
claudebinary: can run commands after exit but cannot trigger a Claude turn or access final session state cleanly.
Priority
High - Significant impact on productivity
Feature Category
Configuration and settings
Use Case Example
Concrete workflow we are trying to automate (currently requires manual intervention at both ends of every session):
SESSION START:
- SessionStart hook injects: previous session summary, open GitHub issues/PRs, recent changes from collaborators via a shared interface folder.
- With Primitive 1: Claude immediately displays a structured briefing — "Last session: X. Open PRs: Y. Collaborator added endpoint Z." — before the user types anything.
- Without Primitive 1: all that context sits silently in Claude's system prompt. The user must type "show me the briefing" every single session.
SESSION END:
- User runs /exit or closes the terminal.
- With Primitive 2: PreSessionEnd hook fires, injects "Write session summary to .claude/session_summary.md and commit pending changes." Claude executes, the file is written, the commit is made, then the session exits.
- Without Primitive 2: if the user forgets to type "I'm closing the session", no summary is written and the next session starts without continuity context.
The two primitives together close the loop completely: end of session N automatically produces the context that start of session N+1 automatically surfaces — with no user input required at either boundary.
This pattern generalizes to any user-configured session workflow:
- Surface CI/deploy status at start, post session log at end.
- Check for unread collaborator messages at start, flush pending commits at end.
- Load project-specific context at start, archive transcript at end.
Additional Context
Related issues — none covers exactly this request:
| # | Title | Status | Relationship |
|--------|---------------------------------------------------------------|------------------------|--------------|
| #47023 | Expose compact/session lifecycle hooks for memory layers | Open | Closest precedent; focuses on shell hooks, not Claude turns |
| #64119 | Hook stdout shown + suppressOutput:true ignored in 2.1.158 | Open | Symptom of unstable hook output visibility history |
| #12755 | Add blocking pre-exit hook | Closed — bot, inactive | Primitive 2 partial; incorrectly auto-closed as dup of #9293 (different proposals) |
| #9293 | Pre-exit hook (advisory) | Closed — bot, dup | Advisory only; no Claude turn; wrongly marked dup of #2622 |
| #41577 | SessionEnd hooks killed before async completion | Closed — bot, dup | Shows existing SessionEnd unreliable for non-trivial work |
| #17885 | SessionEnd hook doesn't fire on /exit | Closed — bot, dup | Shows existing SessionEnd doesn't cover all exit paths |
| #23524 | SessionStart hook stdout not displayed (regression) | Closed — stale | Primitive 1 partial; raw terminal output, not a Claude response |
Note on #12755: the auto-duplicate bot flagged it as a duplicate of #9293, but the author's comment explains why they are different (advisory vs. blocking).
Neither was ever reviewed by a human. We are not re-filing #12755 — our request goes further (Claude turn, not just shell command).
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗