Allow hooks to set the terminal tab title

Status Fixed / completed
Maintainer reply None cached
Activity 3 comments · opened May 6, 2026 · closed May 6, 2026

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:

  1. 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).

  1. 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.

View original on GitHub ↗

3 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/17951
  2. https://github.com/anthropics/claude-code/issues/37902
  3. https://github.com/anthropics/claude-code/issues/52258

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

tommygents · 5 months ago

Closing as duplicate of #17951, which proposes the same end goal (user-controlled terminal title content) with a substantially more thorough framing — script-based terminalTitle config mirroring the existing statusLine pattern, plus 24+ reactions and broader use-case coverage including freelancer time-tracking.

The setTerminalTitle hook-output field proposed here is a narrower implementation surface than #17951's script-based config; they could compose, but #17951 is the canonical request. Folding the discussion there.

github-actions[bot] · 3 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.