Allow hooks to set the terminal tab title
Problem
Users running multiple concurrent Claude Code sessions (one per project, for
example) want to visually distinguish their terminal tabs by user-chosen
context — a Johnny Decimal project code, branch name, ticket ID, etc.
Claude Code's built-in title-setting auto-generates a topic summary from
conversation content, which works well much of the time but doesn't surface
context the user has explicitly attached to a session.
The existing CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 env var provides an
escape hatch to disable the built-in title-setting, but no replacement
mechanism. I tried wiring hooks (UserPromptSubmit, Stop, Notification,
SessionStart) that emit OSC 0 escape sequences directly. They fail for two
reasons:
- Hook subprocesses on Windows have no inherited console attached to
the parent terminal pane. \.\CONOUT$ opens succeed but write to a
detached console (verified empirically — writes return ok:true, no
visible effect, no cross-tab interference).
- ESC bytes in assistant output AND hook stdout are stripped by Claude
Code's display layer. This is correct defensive sanitization (otherwise
prompt injection could rewrite terminal state) — but it leaves no path
for a hook to emit OSC.
Proposal
Add a hook output field, e.g. {"setTerminalTitle": "<string>"}, that
Claude Code's privileged renderer translates into an OSC 0 sequence
emitted from the trusted path. Available on hook events where titles
are likely to change: UserPromptSubmit, Stop, Notification, SessionStart.
Example UserPromptSubmit hook output:
{
"additionalContext": "...",
"setTerminalTitle": "[14.10] working: way authoring"
}
The user retains full control over title content via their hook script;
Claude Code provides only the trusted emit path. Could optionally
auto-prepend or suppress when the built-in title-setter is also active,
or simply require CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 as a precondition
to take effect.
Workarounds
Currently no clean path. Out-of-band approaches that work mechanically:
- PowerShell +
AttachConsole(parent_pid)+SetConsoleTitle()— adds
~1-2s startup latency per hook fire.
- Per-pane watcher daemon polling a side-channel file — heavyweight
multi-process architecture for a one-line feature.
Both are excessive for what could be a single hook-output field.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗