[FEATURE] Terminal Title Configuration (Script-Based, like statusLine)
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 sets terminal titles based on the current task or just "Claude Code" - but there's no way to include:
- Directory - which folder you're working in
- Repository - which repo this session belongs to
- Branch - often contains ticket numbers (e.g.,
ACME-1234-fix-auth) - PR number - when reviewing or working on a pull request
- Original terminal name - what you had before Claude Code took over
- Custom information - client codes, project phases, billing identifiers
This breaks automatic time tracking. Tools like RescueTime, Timing, Toggl, and ActivityWatch categorize work by window title. When every Claude Code tab just shows "Claude Code" or a task snippet, there's no way to distinguish which client or project you're working in.
For freelancers and consultants billing multiple clients, this means:
- Manual time entry instead of automatic tracking
- Inaccurate billing when you forget to log project switches
- No audit trail for disputed invoices
Community tools don't solve this. Existing solutions (bluzername/claude-code-terminal-title, arorajatin/claude-code-terminal-title) auto-generate titles with fixed formats - no user control over what context appears.
Proposed Solution
Add terminalTitle to settings.json, working exactly like the existing statusLine:
{
"terminalTitle": {
"type": "command",
"command": "~/.claude/terminal-title.sh"
}
}
Claude Code passes JSON context to the script (same pattern as statusLine), script outputs the desired title:
#!/bin/bash
input=$(cat)
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
PARENT=$(basename "$(dirname "$DIR")")
PROJECT=$(basename "$DIR")
BRANCH=$(git -C "$DIR" branch --show-current 2>/dev/null)
echo "${PARENT}/${PROJECT} [${BRANCH}]"
# → "acme/api [ACME-1234-auth-fix]"
Context Object - The JSON passed to the script could include:
{
"workspace": {
"current_dir": "/Users/dev/clients/acme/api",
"git_branch": "ACME-1234-auth-fix",
"git_root": "/Users/dev/clients/acme"
},
"model": {
"name": "claude-opus-4-5-20251101",
"display_name": "Opus 4.5"
},
"session": {
"id": "a1b2c3",
"task": "Fixing authentication bug",
"original_terminal_title": "dev-server"
}
}
Why Script-Based (Not Templates):
- Consistency - mirrors
statusLineexactly, no new syntax to learn - Flexibility - parse branch names, read project config files, call APIs, include PR numbers
- Power users - the people who care about this are comfortable with scripts
- Simpler to implement - reuse the existing
statusLineinfrastructure
Bonus: A /title slash command for ad-hoc overrides would be nice:
/title "🔍 [ACME] Debugging auth - 2hr estimate"
Alternative Solutions
Attempted workarounds:
CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1- Documented but non-functional (#4765, open since July 2025)
- Community tools - bluzername/claude-code-terminal-title and arorajatin/claude-code-terminal-title auto-generate titles but offer no template/script-based customization
- Terminal escape sequences - Don't work due to subprocess architecture (no TTY passthrough)
Related issues this would consolidate:
- #4765 -
CLAUDE_CODE_DISABLE_TERMINAL_TITLEbroken (open since July 2025) - #7229 - Terminal window title settings (open)
- #15802 - Set terminal title from session (closed as duplicate)
- #16572, #3396, #15082, #15084 - Various related issues
Priority
High - Significant impact on productivity
Feature Category
Configuration and settings
Use Case Example
Freelancer with multiple clients:
- I'm a freelancer working on projects for 3 clients: Acme Corp, Globex, and Initech
- I use Timing.app for automatic time tracking - it categorizes work by window title
- Currently, all my Claude Code sessions show as "Claude Code" or task snippets
- At end of week, I can't tell how many hours went to each client
- I manually reconstruct time from memory, often inaccurately
With this feature:
- I create
~/.claude/terminal-title.sh:
#!/bin/bash
input=$(cat)
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
CLIENT=$(basename "$(dirname "$DIR")")
PROJECT=$(basename "$DIR")
echo "[$CLIENT] $PROJECT"
- My terminal titles now show:
[acme] api,[globex] frontend,[initech] backend - Timing.app automatically categorizes hours per client
- Invoicing is accurate, auditable, and takes 5 minutes instead of an hour
Additional Context
Technical note: This mirrors the existing statusLine configuration pattern exactly - same JSON context object, same script-based approach. Implementation could likely reuse much of that infrastructure.
Why this matters for Anthropic: Professional/freelancer adoption depends on workflow integration. Time tracking is table stakes for anyone billing hourly. This is low-effort (pattern exists), high-impact for market expansion.
25 Comments
+1 for this feature - hitting this pain point daily with Warp terminal.
The problem in action: Here's my Window menu showing two different Quarkus-based project folders, both running Claude Code. Completely indistinguishable 😅 :
<img width="308" height="361" alt="Image" src="https://github.com/user-attachments/assets/6f51ea56-3a32-4922-ad33-2dcb491a5952" />
I have to click through each window to find the right one.
Suggestion to enhance your proposal: Pass Claude Code's generated title to the script as a variable (e.g., "claude_title" in the JSON context). This enables a hybrid approach instead of forcing users to choose between 100% custom or 100% CC-generated:
echo "[MyProject] ${CLAUDE_TITLE} [Client-ABC]"Users could then:
Interim solutions that would help:
Workaround I'm using: I manually set the tab's title every single time (despite if I could, I would use just the current folder name etc.).
+1 I would be happy if just the new configurable "session name" was the title of the terminal.
Related: https://github.com/anthropics/claude-code/issues/3161
+1 for Warp terminal tab title support.
Specifically, it would be helpful if Claude Code could set the Warp tab title - even just propagating the session name from
/renamewould be a significant improvement. Currently when working across multiple projects, all tabs look identical which makes context-switching painful.The script-based approach proposed here would be ideal for customization, but even a simple "emit the session name to terminal title" would solve the immediate pain point.
This is one of the things that slows me down a lot.
We could also add "placeholders" to the terminal title where Claude can substitute things in, as well.
+1 to at least add the current working directory that claude was launched from. i have multiple running in different panes on different projects and you can't tell them apart
+1 for me I would like to set a static name for the session e.g. "mow the lawn" and retain the animated status indicator.
+1 when working across multiple terminals, I need to cycle through each terminals to reach the one of internest.
We built this to solve the tab/title/organization challenge: https://github.com/flexmark-intl/aiterm/ - personally, I feel WAY MORE productive using it than I ever was running so many different osx terminal windows each with tabs in them. Its a new project, but we use it internally every day!
The new /rename feature fixed this for me
I can confirm that.
+1 — I use a tab color system in my dotfiles where each project gets a color palette (set via TABCOLOR_PRESET in .envrc + direnv). Work tabs get a bright color + emoji title (🐳 Docker), and Claude tabs inherit the same palette darkened 75% via a SessionStart hook.
The color pairing works great — I can instantly see which Claude tab belongs to which project. But Claude overwrites the tab title with its own status (* Claude Code (gopls)), so the 🤖 Docker title I set in the hook gets lost immediately.
A terminalTitle config (script-based, like statusLine) would let me keep the project context visible. Something like:
{
"terminalTitle": {
"type": "command",
"command": "bash ~/.claude/session-tab-title.sh"
}
}
This is helpful for windows users with the limitations that Linux/Mac doesn't have.
If I could just call /rename automatically through a hook... It would be a great addition removing manual work.
It seems like Claude knows how to automatically rename terminal titles based on context when starting executing plans from plan mode. That's at least my experience, consistently.
So the functionality seems to be there.
We just decided to build our own terminal - gives you best of both worlds, your own title + term title - not to mention a swarm of other productivity features when you are working with lots of tabs and agents across projects.
TIP: Name your tab like this:
YourFeature %title
And you get claude's title whenever he decides to set it AND a consistent reminder of what you are doing in that tab that never changes.
https://flexmark-intl.github.io/aiterm/
I ran into this same issue, running several Claude sessions at once in iTerm. I found myself losing track of which pane was doing what. Now that Claude Code added more hook events recently, I was able to put together claude-code-pulse (ccp). It wraps the CLI and keeps titles updated in realtime.
For myself, I wanted: branch, PR number, and a live status (like when an agent is idle, or when user input was required). It's 'ccp' instead of 'claude' at launch, so not the native solution this issue is asking for, but it has worked for me.
I even added an ai title option to generate a couple word summary of the most recent prompt, to make it even easier to remember what's going on at a glance.
Yes please. /rename doesn't work because it's manual and resets whenever you clear the conversation to start a new session. then you have to manually rename. We all have different workflows so a programatic way (like /statusline) where we can choose how the title gets set/updates via hooks would be incredible. Thanks :)
for me /rename doesn't set the tab title in PowerShell 7 running in Windows Terminal.
it's also not programmatically call able from hook scripts as far as I know
After using /rename a bit and encountering the challenges others have laid
out on this issue like it clearing between sessions and it not being a
template or scriptable, I too.am finding that while /rename improved the
situation around terminal titles and Claude code, there's still a need for
a "status line" style of support
---
Chad Furman, Lead SWE
518-227-0716 (c)
@.***
On Wed, Mar 11, 2026, 23:13 Ben Newman @.***> wrote:
I absolutly agree.
Workaround: LLM-summarized terminal titles via statusLine hook
Sharing a working implementation and gotchas for anyone trying to set terminal tab titles using the
statusLinecommand hook +claude -pfor LLM summarization.The approach
The
statusLineconfig runs a shell script on every render. The script:claude -p --model haikuto generate a 3-5 word titleBugs encountered (and fixes)
1.
Error: Reached max turns (1)— file paths and@mentions trigger tool useEven with
--tools "", the CLI still loads MCP servers and plugins from global/project settings. If the user message contains@file_refor/path/to/file, the model tries to use file-reading tools, exhausts--max-turns 1, and returns the error string.Fix: Add
--strict-mcp-config --mcp-config '{"mcpServers":{}}'to completely isolate the summarization call from all MCP/plugin tools. Also strip@and file paths from the input with sed.2. Chatty/invalid LLM responses get cached permanently
Haiku sometimes returns full sentences like "I'm ready to generate terminal tab titles..." instead of a title. This happens when the first "user" message in the transcript is a
<local-command-caveat>system tag (from/resume) rather than a real user prompt.Fix: Skip transcript lines starting with
<when extracting the user message, and validate the LLM output before caching:Feature request
The core issue is that
--tools ""doesn't fully disable tools when MCP servers and plugins are configured globally. It would help if:--tools ""also suppressed MCP/plugin tools in--printmode, or--no-toolsthat means "truly zero tools"This would make
claude -pmuch more reliable for simple text-in/text-out scripting use cases like title generation, commit message drafting, etc.Adding my use case: I don't need AI-generated summaries in the title at all. I just want to identify which tab is which by git branch name (or repo name when on
main).It would be great if the terminal title had a simple mode selector, e.g.:
Related issues: #34223, #26063, #32600, #34889
The day has come
https://code.claude.com/docs/en/changelog#2-1-81
It's doing exactly what I was looking for and needed. Recommend everyone upgrading ASAP 👍
Adding a concrete data point for this — I went down this exact road building a plugin (jfgreco/tabtag) that sets a per-project tab name plus live status (
● / ✓ / ⚠) via theterminalSequencehook output, re-asserting on every lifecycle event (SessionStart / UserPromptSubmit / PostToolUse / Stop) to try to "stay the last writer."It doesn't hold on 2.1.195. The title paints correctly, but the moment the session settles (goes idle after a turn), Claude Code re-writes its own auto-generated summary and wins.
terminalSequenceonly occupies the title in the brief window before Claude's own write, so it "blips then reverts." There's no hook that fires after that write, and — per the terminal-config, settings.json, and env-var docs — no way to disable it.The only thing that reliably works is launching with
--name, because that changes what Claude writes instead of fighting it — but it's launch-only (can't track branch / PR / cwd mid-session) and precludes any live status.A statusLine-style title template rendered by Claude Code itself (so it owns the write) would solve this cleanly — same reason statusLine works where manual prompt hacks don't. The plugin's hook/state machine is all there (source) if it's a useful reference for what people are reaching for. +1
+1, with a use case beyond directory/branch/PR templating: organizing multiple concurrent Claude Code sessions.
I run several sessions at once in a planner/executor pattern (one planning session dispatching work plans to 2-3 execution sessions in the same repo). Since all sessions share one working directory, the auto-generated titles are near-identical and I can't tell the windows apart. I tried setting the title from inside a session with a plain OSC 0 escape (
printf '\033]0;Session 3 - Execution Session\007'), but Claude Code overwrites it with the auto-generated summary on the next turn.A script-based
terminalTitlesetting likestatusLinewould solve this — even a simpler staticterminalTitle: "string"per session (or honoring/renamein the tab title, per #74094) would be enough to label windows by role.