SessionStart hook sessionTitle is applied, then silently reverted by the background AI titler
Environment
- Claude Code v2.1.220, Linux (Pop!_OS 22.04, kernel 6.18.7)
- TUI (
tui: "fullscreen"), interactive sessions
Summary
A SessionStart hook that returns hookSpecificOutput.sessionTitle works momentarily — the new title appears in the session header — but within seconds the session's background AI titler re-asserts the auto-generated title, and the picker/list reverts to the unprefixed name. The docs describe sessionTitle as "sets or renames the session title" with no caveat that it can be overridden afterwards.
Repro
- Configure a
SessionStarthook (all sources) whose command outputs:
``json`
{"hookSpecificOutput":{"hookEventName":"SessionStart","sessionTitle":"myproject — <existing title>"}}
session_title
(Ours reads the current title from stdin , falling back to the latest "type":"ai-title" record in transcript_path`, and prepends a project prefix.)
- Resume an existing session (or trigger
/compact) in a matching project. - Observe: the prefixed title appears briefly, then the display reverts to the plain AI title. Leaving and re-entering the session shows the old title; the hook's title never survives.
Evidence
Transcript inspection shows the reversion mechanism: after the hook fires, the harness keeps appending fresh {"type":"ai-title",...} + {"type":"agent-name",...} record pairs containing the plain auto-generated title (observed repeatedly at ~30-line intervals during an active session). Latest-wins, so the hook's title loses.
Hook-side logging confirms the hook fires and emits valid JSON on startup/resume/compact sources with correct input (session_title empty unless a user-set name exists; transcript_path valid).
Contrast: /rename persists
A manual /rename in a live session sticks permanently (it writes {"type":"custom-title",...} records and survives restarts). Notably, appending a byte-identical custom-title record to a closed session's transcript does not change the title shown in the picker (even after full restart), suggesting the session list is served from daemon/index state rather than transcript records — so there is also no offline path to rename sessions.
Expected
Either of:
sessionTitlefrom a SessionStart hook is treated like a user-set name (as/renameis) and is not overridden by the AI titler; or- documentation states that hook-set titles are transient and can be reverted.
Use case
Per-project session-title prefixes ("myproject — <topic>") so multi-project session lists are scannable. Related: #80711 (sessionTitle persisted but not shown in TUI badge), #67389 (sessionTitle ignored for clear), #69411 / #71552 / #44786 (feature requests for exactly this kind of programmatic naming).