2.1.x · macOS / Linux
Why everything is named zsh
#
By default tmux has a setting called automatic-rename turned on. It
renames each window after whatever program is running in it. A shell? zsh. A
Node program (like Claude Code)? node. Helpful in theory, useless when
everything collapses to the same word.
We want: when I launch my AI agent in a window, name that window something I’ll
recognize (like 🤖 my-app/feature-x) and put it back to normal when I’m done.
Step 1: rename a window yourself (the manual version) #
You can rename the current window any time:
tmux rename-window "my-app"But the moment a new command runs, automatic-rename overwrites it. To make a
name stick, turn auto-rename off for that window first:
tmux set-window-option automatic-rename off
tmux rename-window "🤖 my-app"Doing that by hand every time is no fun. Let’s automate it.
Step 2: a wrapper that labels the window automatically #
A shell function can “wrap” a command: do something before it runs, run it,
then clean up after. Here’s one that wraps claude (swap in any tool you like).
Add it to your ~/.zshrc (or ~/.bashrc):
claude() {
# Not in tmux? Just run the real claude normally.
if [ -z "$TMUX" ]; then
command claude "$@"
return
fi
# Build a label from the project folder + git branch.
local root label branch prev
root="$(git rev-parse --show-toplevel 2>/dev/null)"
label="$(basename "${root:-$PWD}")"
branch="$(git symbolic-ref --quiet --short HEAD 2>/dev/null)"
[ -n "$branch" ] && [ "$branch" != "main" ] && label="$label/$branch"
# Remember the current auto-rename setting so we can restore it.
prev="$(tmux show-window-options -v automatic-rename 2>/dev/null)"
tmux set-window-option automatic-rename off
tmux rename-window "🤖 $label"
command claude "$@" # <- run the real claude; we wait here until it exits
# Put things back the way they were.
if [ "$prev" = "off" ]; then
tmux set-window-option automatic-rename off
else
tmux set-window-option automatic-rename on
fi
}Reload your shell (exec zsh) and run claude inside tmux. The window becomes
🤖 my-app/feature-x while it runs, then snaps back when you exit.
A couple of things worth understanding:
command clauderuns the realclaudeprogram, not our function again (otherwise we’d loop forever).- The line after
command claudedoesn’t run until claude exits, which is why restoring auto-rename “after” works. Claude handlesCtrl+Citself and exits cleanly, so the restore still runs.
Step 3: show the name in your terminal’s tab, too #
The window name now shows in tmux’s status bar. But you can also push it up to
your terminal app’s tab title (Ghostty, iTerm, etc.). Two lines in
~/.tmux.conf:
set -g set-titles on
set -g set-titles-string "#{window_name}"set-titles on lets tmux set the outer terminal’s title; set-titles-string
says what to send. We use #{window_name} on purpose.
Why not the pane title (#T)? Because some full-screen terminal apps (Claude
Code among them) constantly rewrite the pane title with a spinner/status, and if
you forward that, your tab title flickers like crazy. The window name is
stable, so the tab stays calm and readable.
Reload with tmux source-file ~/.tmux.conf (or your reload key) and your
terminal tab will read 🤖 my-app/feature-x.
How to test it without messing up your real tmux #
Nice trick: tmux can run a throwaway server on a separate “socket” with -L, so
you can experiment without touching your real sessions:
tmux -L scratch new-session -d # start an isolated server
tmux -L scratch rename-window hello
tmux -L scratch display-message -p '#{window_name}' # → hello
tmux -L scratch kill-server # clean up, your real tmux untouchedRecap #
automatic-renameis why windows are allzsh: turn it off for a window to pin a name.- A shell wrapper can label the window on launch and restore it on exit.
set-titles on+set-titles-string "#{window_name}"mirrors the name to your terminal tab (use the window name to avoid flicker).
So far we’ve been running one agent per window. What if you want to run a bunch of them at once and jump between them? That’s Part 4.