Ghostty tab titles from git repo names
On this page2 sections ▾
When I run Claude Code and GitHub Copilot CLI across several Ghostty tabs, process names such as "claude" and "copilot" don't tell me which project is open. I wanted each tab to show the git repo name, with a short directory path as the fallback outside a repo.
A zsh hook sets the title, and a Ghostty setting stops its shell integration from overwriting it.
If you're using copilot_here (my sandboxed Docker wrapper for GitHub Copilot CLI), this is actually better. It sets custom tab titles that tell you what's going on at a glance. Normal mode shows "🤖 xylem", YOLO mode (auto-approve everything) shows "🤖⚡️ xylem", and if you've got Airlock enabled (the secure network isolation mode that restricts which domains the container can reach) you get "🤖 xylem 🛡️". You can immediately tell which project, which mode, and whether network isolation is active, all from the tab title. But it only applies to the copilot_here panels, not to your Claude Code sessions or regular shells.
#The fix
Two changes: a zsh function that sets the tab title, and a Ghostty config tweak to stop Ghostty from stepping on it.
#The zsh hook
Add this to your .zshrc:
# Update Ghostty tab title to git repo name (or current folder)
set_ghostty_title() {
local dir="$PWD"
while [[ "$dir" != "/" ]]; do
if [[ -d "$dir/.git" ]]; then
echo -ne "\e]0;${dir##*/}\a"
return
fi
dir="${dir:h}"
done
# Not in a git repo — show last 3 path segments
local short_path
short_path=$(echo "$PWD" | awk -F/ '{
n=NF;
if(n>=3) print $(n-2)"/"$(n-1)"/"$n;
else if(n==2) print $(n-1)"/"$n;
else print $n
}')
echo -ne "\e]0;${short_path}\a"
}
autoload -Uz add-zsh-hook
add-zsh-hook chpwd set_ghostty_title
# Also run on shell startup so the first tab gets named
set_ghostty_titleHere's what it does:
chpwdhook: zsh fires this every time youcdto a different directory, so the title updates as you move around- Walk up the tree: starting from
$PWD, it checks each parent directory for a.gitfolder - Repo name: when it finds
.git, it uses that directory's basename as the title (so/Users/gordonbeeming/Developer/github/gordonbeeming/xylembecomes "xylem") - Fallback: if it hits
/without finding.git, it shows the last three path segments instead of the full path - Startup: runs once when the shell starts so the first tab gets named immediately, not just after your first
cd
The echo -ne "\e]0;...\a" part is an OSC 0 escape sequence that tells the terminal to set the window/tab title. Most terminals support this.
#The Ghostty config
After adding the zsh hook and reloading my shell, the tab still showed the directory path.
Ghostty's built-in shell integration sets the tab title to the working directory, and it was overwriting my custom title on every prompt. The fix is one line in your Ghostty config (~/.config/ghostty/config):
shell-integration-features = no-titleThis tells Ghostty to keep all its other shell integration features (marking prompt boundaries, tracking the current directory for Cmd+Click on paths) but leave the tab title alone. Your zsh hook takes it from there.
You'll need to restart Ghostty (not just open a new tab) for this config change to take effect.
#My workflow
I tend to work with multiple panels per tab in Ghostty, usually one tab per project. A typical layout is four panels: Claude Code running in one, GitHub Copilot CLI in another, and two regular shells for running builds, tests, or git commands.
The keyboard shortcuts I use:
Cmd+Dto split right (new panel to the right)Cmd+Shift+Dto split down (new panel below)Cmd+Shift+Enterto toggle a panel to full screen and backCtrl+Tab/Ctrl+Shift+Tabto navigate between tabsCmd+Option+Arrowsto move focus between panels within a tab
With this configuration, a tab in the xylem repo keeps that name as I move between its subdirectories. Outside a repo, the last three path segments give me enough context to identify the directory.