[FEATURE] Allow hooks (and/or skills) to set the chat session title
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
Today, the only way to title a chat session is for the user to manually invoke /rename from the input box. This makes consistent, automated naming impossible, even though chat names are the primary mechanism for finding past sessions via /resume.
I do many PR reviews per week (often several per day across multiple repos), and I want each review session named consistently so I can come back to a specific review later. The naming pattern itself is mechanical, e.g. PR review: <repo>#<pr-number> (<author>), but I have to remember to type /rename every single time at the start of the session, and after months of trying I still forget more often than not. After a busy week the session list is full of auto-generated topic titles that I can't tell apart.
The same applies to non-review sessions: a one-line title summarizing what the session was about would make /resume actually useful for retrospection. Claude already produces good end-of-turn summaries so there's no reason a title can't be derived automatically.
This is an event-triggered automation (when a session reaches a meaningful state, set its title), which is exactly what hooks are for. But hooks today have no mechanism to do it.
Proposed Solution
Add a way for hook output to set the session name. The cleanest shape is a new field on hookSpecificOutput:
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"setSessionName": "PR review: repo-name#1001 (author)"
}
}
Honored on UserPromptSubmit, Stop, and PostToolUse (so the title can be set/refined as the session takes shape, e.g. after the first gh pr view call reveals the author). Idempotent: setting the same name is a no-op; setting a different name replaces it (matching /rename behavior).
A user prompt hook (the LLM-evaluated kind) is a particularly good fit here:
{
"hooks": {
"UserPromptSubmit": [{
"hooks": [{
"type": "prompt",
"prompt": "If this is the first prompt of a PR review session, output JSON {\"hookSpecificOutput\":{\"hookEventName\":\"UserPromptSubmit\",\"setSessionName\":\"PR review: <repo>#<num> (<author>)\"}}. Otherwise output {}. User prompt: $ARGUMENTS"
}]
}]
}
}
That gives users full control over naming policy without baking any heuristics into Claude Code itself.
Alternative Solutions
I tried each of these before filing:
- Memory / preferences telling Claude to rename proactively. Doesn't work. Claude can't invoke slash commands; they're user-input-only and not exposed as tools. Even with a system-reminder injected via
additionalContext, there is no tool Claude can call to set the title.
- Hook that writes directly to
~/.claude/projects/<hash>/<session-id>.json. This file has a"name"field, but writing to it from a hook is undocumented, races with the running session, and could break on any Claude Code update. But this is a hack so I wouldn't go with it.
- A
claude rename <session-id> <title>CLI command. Doesn't exist today. Would also work as a solution if added (a hook could shell out to it).
- Manual
/rename(the status quo). I forget very often.
Priority
Medium - Would be very helpful
Feature Category
Configuration and settings
Use Case Example
A typical PR review session today:
- User pastes a request: "Please review https://github.com/organization/repo-name/pull/1001"*
- Claude calls
gh pr view 1001 --json author,titleto fetch metadata - Claude reviews the PR, writes a pending review on GitHub
- Session ends with an auto-generated topic title like "Reviewing CI flaky-test fixes"
Two days later the user wants to recall what they decided about that specific PR. They run /resume, scroll through 40 sessions with similar-sounding auto-titles, and can't find it.
With this feature:
- Same request as above.
- The user's
UserPromptSubmithook (a prompt hook) detects the GitHub PR URL and emitssetSessionName: "PR review: repo-name#1001 (author)". (Author can be backfilled via aPostToolUsehook on thegh pr viewcall if not in the URL.) - The session is immediately findable via
/resume— searching forrepo-name#1001orauthorjumps straight to it.
Same approach generalizes: a Stop hook could derive a one-line summary from the conversation and set it as the title for any session, not just reviews.
Additional Context
Investigation notes (in case it saves you time):
- I went through every documented hook output field:
systemMessage,decision,continue,stopReason,suppressOutput,hookSpecificOutput.{permissionDecision, additionalContext, updatedInput}. None of them control session metadata. - I checked whether
/renameis exposed as a tool or skill (it isn't). Slash commands appear to be parsed only from user-typed input. - The
update-configskill and the settings JSON schema confirm there's nosessionName-related field anywhere in settings or hook outputs. - Session JSON files at
~/.claude/projects/<hash>/<session-id>.jsondo contain a"name"field, which suggests the underlying data model already supports programmatic naming (it's just not surfaced as an API).
Implementation note: option 2 from "Proposed Solution" (exposing /rename as a tool to Claude) is more flexible but pushes title-quality decisions into the model's tool-use loop, which is wasteful for what is essentially a deterministic operation. Option 1 (hook-driven) keeps it deterministic and user-controlled, that's why I'd lead with it.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗