[FEATURE] Terminal window title settings

Open 💬 35 comments Opened Sep 6, 2025 by JPBarringer

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

I have set up zsh to title my terminal windows (alacritty in this case) with the working directory and git branch. This helps me manage multiple windows a lot more easily. ...but it doesn't work in Claude Code because it renames the windows.

There are two problems here: one is that I find the current window naming to be generic and not very useful (for me). Some users may like this, but I would really prefer to have more useful information there.

The other more general problem is lack of any sort of control as to what the window titles are.

Here is a demonstration of a few windows – can you figure out which one is which from the title?

<img width="1171" height="54" alt="Image" src="https://github.com/user-attachments/assets/1dd517ea-0626-4f5e-8f1f-aee7e2ad974a" />

Proposed Solution

I'd like to be able to set the window title, either using a hook or a config item. Ideally I'd be able to recreate my own naming convention of <project directory> [branch] | <running process name>. But this feature request is less about a specific naming convention and more about having the option to change it somehow if the default is not pleasing.

If that is not possible, however, I would love more useful names for the window titles.

Alternative Solutions

I don't have a current workaround because Claude Code takes over the naming for the window title when running. I mostly just have to open various windows with names like "git directory" or "code development" until I find the one I want. This makes parallel development more cumbersome.

Priority

Medium - Would be very helpful

Feature Category

Interactive mode (TUI)

Use Case Example

I open a window and claude -c to continue work on a project. Once that's working on a task, I ctrl-n to open a new window and continue a separate project. (etc. – I have 8 windows open right now.)

Especially when on a smaller laptop screen, I can only actively view 3 or so windows at a time, so I need to check in on other open windows by selecting view all – this is where I get a small unreadable thumbnail and a title. The title names rarely provide enough context to know which window is which, so I maximize each one in turn unitl I find what I'm looking for.

Additional Context

I'm a big fan of Claude Code. I just wish it were a bit more extensible.

View original on GitHub ↗

36 Comments

nitromike502 · 10 months ago

+1
I've been pulling my hair out trying to get CC to set tab titles. It just doesn't work.

haveaguess · 10 months ago
na-ka-na · 9 months ago

No it didn't :(

I tried putting it in both settings.json

  "env": {
    "CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "1"
  }

and running it with

CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 claude

they both still take over the title

mikeri · 9 months ago

Does you terminal not have an option to set a static window title? I start my terminal with a static title before starting Claude as a workaround for this.

I do agree that there should at least be an option to disable dynamic window titles in Claude, and a command to set the window title would also be nice.

mthaak · 9 months ago

For iTerm2 you can prevent applications from changing the window title like so:

<img width="1062" height="300" alt="Image" src="https://github.com/user-attachments/assets/9dda915b-8ec3-4f2b-8f65-e89d61d9c0ea" />

chrisblossom · 9 months ago

This is how I solved it for iTerm2 (might work with other terminals, untested).

~/.zshrc

# If you use oh-my-zsh, stop it from managing titles
export DISABLE_AUTO_TITLE="true"

# Function to set iTerm2 title to current directory name
function set_iterm_title() {
  echo -ne "\033]0;${PWD##*/}\007"
}

# Run before each prompt
autoload -U add-zsh-hook
add-zsh-hook precmd set_iterm_title

Then like @mthaak said, change the Title, but instead uncheck all options, CHECK "Applications in terminal may change the title" and put \(session.jobName) as the Subtitle.

You'll then you'll always have your working directory as the title with the job it is working on below it. Ends up looking like:

<img width="330" height="68" alt="Image" src="https://github.com/user-attachments/assets/f1fe0b0d-2878-44f9-b818-d8913b212e27" />

<img width="1278" height="228" alt="Image" src="https://github.com/user-attachments/assets/163f6668-39b9-47e1-9229-a53c1e0e4919" />

sheriffderek · 8 months ago

I've been trying to figure something out for this too.

If I say: "lets talk about Cats" → "* Cat Discussion"
If I say: "lets talk about Dogs" → "* Dog Discussion"
If I say: "see the problem " → "* = Terminal window titles"
etc.

It's nice it's trying to help. But I can't tell what any of my tabs are for at a glance - and being able to just set it as "Feature name" or "Discussion subject" --- would be very helpful.

I can use a different terminal program that lets me name the tab - but in my case, I'm teaching and creating videos and Hyper is the only terminal that lets me zoom in and out without changing it's window size. (I know that's a very niche dependency)

github-actions[bot] · 7 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

darkwebdev · 7 months ago
JohnAposto83 · 6 months ago

Adding my voice here - this feature becomes critical when using multi-agent frameworks.

I'm using BMAD which runs multiple specialized agents in parallel (PM, Architect, Dev, Infrastructure Sage, etc.). Each agent runs in its own Claude Code session, but all terminals show generic names like claude - infrastructure.

The pain point: When 4-5 agents are running simultaneously, there's no way to identify which terminal contains which agent without clicking into each one.

Ideal solution for agent frameworks:

  • A /title slash command for manual setting
  • OR automatic title from skill/agent name when loaded via the Skill tool
  • OR a programmatic API like claude.setTerminalTitle() for custom commands

I investigated workarounds extensively:

  • Bash escape sequences don't work (subprocess captures them as text)
  • /dev/tty is not available
  • Hooks run in isolated subprocesses with same limitation
  • /rename only affects --resume session name, not terminal tab

Closing my duplicate issue #15802 and adding support here. 👍

ingydotnet · 6 months ago

My experience is that CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 is not honored when using either of these:

  • CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 claude -c
  • CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 claude -r

I'm using Bash with:

$ claude --version
2.0.76 (Claude Code)

This is clearly a [BUG] but decided to add it here for now.

ingydotnet · 6 months ago

Also when starting with CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 claude (which does NOT overwrite the title), using the /resume command and selecting a session does overwrite the title.

petros · 6 months ago

+1 on this feature request.

My specific use case: I use /rename to give sessions meaningful names (e.g., ticket IDs like "CUSTOMER-215"). It would be great if Claude Code used this session name as the terminal window title instead of auto-generating one based on the conversation topic.

This way, my terminal tabs would match what I've named my sessions, making it much easier to navigate between multiple Claude Code sessions.

MrAigri · 6 months ago

+1

prenaux · 6 months ago

+1

CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 doesn't work for me under any scenario... using latest "Claude Code v2.1.4"

Caleb-KS · 6 months ago

I had claude code write me some hook scripts that changed the title based on the current tool being performed or needing permission. You can write to CONOUT$ directly to influence the tab with an OSC sequence.

jasongao · 6 months ago

+1

HandsomeStrife · 5 months ago

Working over multiple projects, I can rename the tabs using Warp but then I lose the 'progress indicator'. Being able to set a project name per tab would be so useful.

mrw1986 · 5 months ago
I had claude code write me some hook scripts that changed the title based on the current tool being performed or needing permission. You can write to CONOUT$ directly to influence the tab with an OSC sequence.

I did the same using Konsole and %w. Now, it shows my current worktree as the tab name and updates dynamically.

h4rk8s · 5 months ago

+1

Caleb-KS · 5 months ago
I had claude code write me some hook scripts that changed the title based on the current tool being performed or needing permission. You can write to CONOUT$ directly to influence the tab with an OSC sequence.

It only partially works since if you do it too much (I suspect, during tool usage hooks), then it messes up the placement of text coloring, which is distracting. So it would be nice if changing the terminal title went through claude so this wouldn't be an issue.

bryce-shashinka · 5 months ago

Title Order / Truncation Issue

Related concern: Even when using shell escape sequences to set a custom title (e.g., echo -ne "\033]0;ProjectName\007"), Claude Code appends the custom title after the session ID, resulting in:

[session-id-guid] - ProjectName

When terminal tabs truncate from the left (macOS Terminal.app default), users see:

...d-guid] - ProjectName

Desired behavior: Custom title should come first, so truncation shows:

ProjectName - [session-i...

This would make the human-readable part visible even on smaller screens with many tabs open.

Additional request: The working indicator (spinner) should also appear after the custom title, not before it, for the same truncation visibility reasons.

Workaround attempted: iTerm2 has better tab handling, but the title order issue persists across terminal emulators since it's determined by what Claude Code writes to the title.

This would be solved by either:

  1. Configurable title template (like #17951 proposes)
  2. Simple option to reverse the order: {custom_title} - {session_id} instead of {session_id} - {custom_title}
bryce-shashinka · 5 months ago

Technical Implementation Proposal

I've created a detailed technical specification for implementing terminal title configuration. Here are three implementation options, ranging from simple to comprehensive:

Option A: Simple Order Reversal (Quickest Fix)

Add a single setting to reverse title order:

{
  "terminalTitle": {
    "order": "custom-first"  // or "session-first" (default)
  }
}

Before: [a1b2c3d4-session-id] - MyProject → truncates to ...session-id] - MyProject
After: MyProject - [a1b2c3d4-session-id] → truncates to MyProject - [a1b2c3d4...

Option B: Template-Based (Recommended)

Allow customizable templates with variables:

{
  "terminalTitle": {
    "template": "${customTitle} - [${sessionId}]",
    "showWorkingIndicator": true,
    "indicatorPosition": "end"
  }
}

Available variables:

  • ${sessionId} - Short session identifier
  • ${customTitle} - User-set title (via escape sequences or /rename)
  • ${workingDir} - Current directory basename
  • ${gitBranch} - Git branch name
  • ${model} - Current model (e.g., "Opus 4.5")
  • ${indicator} - Working status spinner

Example templates:

"${customTitle} | ${gitBranch}"           → "MyProject | feature-auth"
"${workingDir} (${model})"                → "my-app (Opus 4.5)"
"${customTitle} - [${sessionId}]"         → "MyProject - [a1b2c3d4]"

Option C: Script-Based (Maximum Flexibility)

Mirror the existing statusLine pattern:

{
  "terminalTitle": {
    "type": "command",
    "command": "~/.claude/terminal-title.sh"
  }
}

Script receives JSON context and outputs title string. Allows users to parse config files, call APIs, etc.

---

Recommendation: Option B (Template-Based)

Why:

  1. Solves immediate truncation issue
  2. Provides flexibility without requiring scripts
  3. Template syntax is familiar
  4. Can extend to Option C later if needed
  5. Backward compatible (default template preserves current behavior)

Default (no breaking changes):

{
  "terminalTitle": {
    "template": "[${sessionId}] - ${customTitle}"
  }
}

---

Implementation Considerations

Title should update when:

  • Session starts
  • Custom title changes (escape sequences or /rename)
  • Working directory changes
  • Git branch changes (if in template)
  • Working state changes (spinner)

Technical notes:

  • Use OSC 2 escape sequences: \x1b]0;${title}\x07
  • Preserve user-set titles via escape sequences
  • Keep sessionId short (8 chars from UUID)
  • Warn if template exceeds ~80 chars (terminal truncation)

Testing across terminals:

  • macOS Terminal, iTerm2, Alacritty
  • Windows Terminal, Ghostty
  • Verify OSC sequences work consistently

---

Full technical spec with code examples available in this gist: terminal-title-feature-spec.md

This would consolidate several related issues (#17951, #25789, #16353, #25307) into a single comprehensive solution.

wthrower · 4 months ago

Workaround: use statusLine to set the terminal title via /dev/tty

Claude Code's statusLine setting runs a command that receives session context as JSON. The command's stdout becomes the status line, but you can also write an OSC 0 title sequence to /dev/tty without interfering with the status line output.

It works on Linux, macOS, and WSL. It would be possible on Windows, but Claude Code for native Windows seems to have statusLine rendering issues, unrelated to this workaround. There's so much friction on native Windows (rendering issues and reliance on a Unix-like environment). Just use WSL. :)

Presumably a terminalTitle setting would include busy/idle info, but this comes close to the full feature using existing functionality.

Example

Setting CLAUDE_CODE_DISABLE_TERMINAL_TITLE prevents Claude Code from overwriting the terminal title.

~/.claude/settings.json:

{
  "env": {
    "CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "1"
  },
  "statusLine": {
    "type": "command",
    "command": "bash ~/.claude/statusline-command.sh"
  }
}

~/.claude/statusline-command.sh:

#!/usr/bin/env bash
input=$(cat)

cwd=$(echo "$input" | jq -r '.workspace.current_dir // ""')
dirname=$(basename "$cwd")
branch=$(GIT_OPTIONAL_LOCKS=0 git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null)

# Your title here.
title="${dirname}"

# Your status line here.
statusline="${dirname} | ${branch}"

[ -n "$branch" ] && title="${title} | ${branch}"
printf "\033]0;%s\007" "$title" > /dev/tty 2>/dev/null

echo "${statusline}"
hypersw · 4 months ago

Building on @sheriffderek's point about auto-generated titles:

The current auto-generated titles change every turn based on conversation topic, which defeats the purpose - you can't build spatial memory of which tab is which when titles keep shifting.

Two suggestions:

  1. Give the LLM a mechanism to set the title consciously - a tool like SetTerminalTitle or special output format. The AI could proactively set a meaningful, stable title early in the conversation (e.g., "RSRP-502923 ConvexHull fix") rather than a separate summarization pass guessing at it every turn.
  1. Make auto-generated titles stable after initial detection - generate the title once when the topic becomes clear, then keep it stable unless explicitly changed via /rename. Constant regeneration provides no benefit and actively harms navigation.

If the LLM had title-setting capability, users could customize behavior via CLAUDE.md prompting - instructing Claude to use issue IDs, project names, or branch names. This makes title behavior user-configurable without multiple settings flags.

---
Co-authored-by: Claude <noreply@anthropic.com>

Caleb-KS · 4 months ago

I disabled claude's titles and did my own by writing to $CONOUT and I had to pivot to a background watcher task because Claude intercepts $CONOUT from hooks now.

I have found it most useful to show
{current dir leaf} | {current branch leaf} | {current tool if running or permission request}

and then set the title progress (indeterminate or paused according to the state).

It's been difficult to get the status when user has interrupted by ESC (for which no hook is sent). Basically, I have a periodic read of the terminal text to figure out this edge case.

tkz79 · 4 months ago

Adding another voice here. I run 5 concurrent Claude Code sessions (PM, EM1, EM2, Engineer, Sidekick) as part of a multi-agent workflow. Every single tab says "claude code." I manually rename a tab, and the next time any session produces output, it gets overwritten back to the generic title.

This isn't a nice-to-have — it actively breaks multi-agent workflows. I spent time tonight setting tab titles only to watch them get stomped repeatedly.

Two asks, in priority order:

  1. Stop overwriting user-set tab titles. If I renamed it, leave it alone.
  2. Add a --name flag (e.g., claude --name "PM") so sessions can be launched with a persistent title.

This issue is from September 2025. 26 comments. Still open. Please prioritize this.

brianruggieri · 4 months ago

Strong +1 on this. I've built claude-code-pulse as a workaround. It wraps Claude Code and uses hooks to push real-time status into terminal pane titles, but requires CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 to prevent Claude from fighting over the title, and that env var has been broken since at least July 2025 (#4765).

A terminalTitle config option modeled after the existing statusLine pattern (script-based, JSON context passed in) would be the cleanest solution and reuse infrastructure that's already there.

DahnJ · 4 months ago

I managed to solve this for macOS with ITerm2 via osascript + $ITERM_SESSION_ID to target the right session.

First disable Applications in terminal may change the title in Settings -> Profiles -> General

Then add this to your CLAUDE.md

At the start of every conversation, set the iTerm2 session title to a short (2-4 word) 
description of the conversation topic using AppleScript. 
Use `$ITERM_SESSION_ID` (set automatically by iTerm2) to target the correct session 
regardless of which is active:


  osascript -e "
    tell application \"iTerm2\"
      repeat with aWindow in windows
        repeat with aTab in tabs of aWindow
          repeat with aSession in sessions of aTab
            if unique id of aSession is in \"$ITERM_SESSION_ID\" then
              set name of aSession to \"YOUR-TITLE-HERE\"
            end if
          end repeat
        end repeat
      end repeat
    end tell
  "
  ```
simPod · 4 months ago
ymcwebdev · 3 months ago

+1 — Running multiple Claude Code sessions in Apple Terminal, tabs are unreadable because the title is too long and gets truncated with '...' at the start. Would love a setting to customize the title format (e.g., just the folder name).

sheriffderek · 3 months ago
I've been trying to figure something out for this too.

(I've just been using sticky notes haha -- )

yurukusa · 3 months ago

You can set the terminal title via hooks using ANSI escape sequences:

BRANCH=$(git branch --show-current 2>/dev/null || echo "no-git")
DIR=$(basename "$(pwd)")
GIT_ROOT=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "$DIR")
TITLE="CC: $GIT_ROOT ($BRANCH)"
printf '\033]0;%s\007' "$TITLE" >&2
if [ -n "$TMUX" ]; then
    tmux rename-window "$TITLE" 2>/dev/null
fi
exit 0
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
DIR=$(basename "$(pwd)")
BRANCH=$(git branch --show-current 2>/dev/null || echo "")
TITLE="CC: $DIR"
[ -n "$BRANCH" ] && TITLE="$TITLE ($BRANCH)"
[ -n "$TOOL" ] && TITLE="$TITLE — $TOOL"
printf '\033]0;%s\007' "$TITLE" >&2
exit 0
{
  "hooks": {
    "Notification": [{
      "matcher": "start",
      "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/terminal-title.sh" }]
    }],
    "PostToolUse": [{
      "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/title-tracker.sh" }]
    }]
  }
}

The \033]0;...\007 sequence works in: alacritty, iTerm2, kitty, WezTerm, Windows Terminal, GNOME Terminal, Konsole, xterm. For tmux, the tmux rename-window command sets the window name directly.
This gives you full control — you can put whatever you want in the title (project name, branch, last command, session ID, etc.).

ijstokes · 3 months ago

ATM, in the latest version of iterm, I have failed to get terminal window title setting to work from within a Claude Code session. I want my agents to rename the window titles as they work based on pre-defined guidance: which task, which PR, what stage of work. Just not working for me, even as I see the Claude Code does, sometimes, update the iterm window title (based on which terminal session tab is active). I've put 30-60 minutes into figuring this out: reviewing the (many) GH issues reporting this, digging into standard ASCII escape sequences, experimenting from the zsh CLI to see if I can manually trigger it, working with Claude Code to "debug" in partnership what is required for the agent to be able to trigger the window title change. Unfortunately all have failed.

ChrisPachulski · 3 months ago

Two things not yet in this thread:

  1. CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 was broken for a long time but works as of ~v2.1.79. If you tried it before and gave up, try again.
  1. If you're setting titles from hooks and it's not sticking, write to /dev/tty (Unix) or use SetConsoleTitleW via ctypes (Windows), not stdout/stderr. The TUI captures stdout. /dev/tty bypasses it.

Working dispatch for 10 terminals if you want a reference.

toschlog-sony · 15 days ago

I would like a "/title" command to rename the window title. I'm mostly happy with Claude Code setting the title so I don't want to set CLAUDE_CODE_DISABLE_TERMINAL_TITLE, but I'd like to be able to set a title for a specific window and have it stick.