Skip to main content
  1. Posts/

Make tmux Show What Each Window Is Doing

··779 words·4 mins·
Nick Liu
Author
Nick Liu
Building infrastructure for Facebook Feed Ranking at Meta. Previously at Walmart, Twitter, AWS, and eBay. MS in Computer Science at Georgia Tech.
Table of Contents
Taming Claude Code Sessions - This article is part of a series.
Part 3: This Article
If you use tmux, you've hit this: ten windows open and they're all named `zsh` or `node`. Which one had your AI agent running? No idea. Let's make tmux label windows usefully.
Tested with Claude Code 2.1.x · macOS / Linux
New to tmux? It’s a “terminal multiplexer”: it splits one terminal into many windows and panes that survive disconnects. The only vocabulary you need here: a window is like a browser tab inside tmux; the bar at the bottom lists them. The prefix is the key you press before a tmux command, commonly Ctrl+b (mine is Ctrl+a).

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 claude runs the real claude program, not our function again (otherwise we’d loop forever).
  • The line after command claude doesn’t run until claude exits, which is why restoring auto-rename “after” works. Claude handles Ctrl+C itself 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 untouched

Recap
#

  • automatic-rename is why windows are all zsh: 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.

Taming Claude Code Sessions - This article is part of a series.
Part 3: This Article

Related

Stop Losing Your Claude Code Conversations

··623 words·3 mins
You're deep in a great Claude Code conversation. You close the terminal. The next day you want to pick up where you left off… and you can't find it. Sound familiar? Let's fix that. Taming Claude Code Sessions · Part 1 of 4 1 2 3 4 🧪 Tested with Claude Code 2.1.x · macOS / Linux What is a “session,” and where does it go? # Every time you run claude, you start a session, one conversation, with its full history. When you quit, that history doesn’t vanish. Claude Code saves it to disk, organized per project folder, here:

Running Several AI Coding Agents Without Losing Track

··875 words·5 mins
Once you're comfortable with AI coding agents, you start running several at once: one refactoring here, one writing tests there, one stuck waiting for your approval. Keeping them straight is its own little skill. Taming Claude Code Sessions · Part 4 of 4 1 2 3 4 🧪 Tested with Claude Code 2.1.x · macOS / Linux Here are two ways to do it: a lightweight tmux plugin, and (briefly) dedicated “AI terminal” apps.

My Terminal Setup in 2026: Ghostty, tmux, and Neovim

··822 words·4 mins
After years of refining my terminal workflow, I've landed on a stack I genuinely enjoy using every day: **Ghostty** as the terminal emulator, **tmux** with **sesh** for session management, and **Neovim** with **LazyVim** for editing. Everything runs on macOS (Apple Silicon) with a consistent Catppuccin Mocha theme across all tools.