~ $ man tmux-status-bar-design

Designing a tmux status bar that earns its pixels

7 min · updated

The tmux status bar is a single line at the bottom (or top) of the screen. Done well, it tells you your session name, open windows, the time, and whatever system metric you care about — without taking your eyes off the work. Done badly, it is noise that auto-refreshes every second and flickers while you type. This guide is about doing it well.

The three regions

The status bar has three configurable regions: status-left, the window list in the middle, and status-right. You control the left and right strings; tmux manages the window list automatically.

set -g status-left  " #S "
set -g status-right " %H:%M "

#S is the session name. %H:%M is strftime syntax — hours and minutes. Both are evaluated by tmux directly; no shell subprocess for these.

Format strings vs shell segments

tmux provides two ways to embed dynamic content in the status bar:

Use built-in variables whenever possible. Reserve #() for information tmux cannot provide itself: load averages, git branch of a specific directory, free memory.

Shell segments and update intervals

set -g status-interval 15
set -g status-right '#(uptime | grep -oP "load average: \K[^,]+"| xargs) | %H:%M'

status-interval controls how often tmux re-evaluates the #() segments. The default is 15 seconds. Setting it to 1 gives you a live clock but runs every shell command once per second — a visible CPU cost if your segments do any real work. For a clock, 15 seconds is fine. For a segment that calls an external API, 60 seconds is more appropriate.

The command inside #() must print a single line to stdout and exit quickly. If it hangs, tmux shows a stale value until the previous invocation finishes.

Useful built-in variables

VariableWhat it shows
#SSession name
#WCurrent window name
#HHostname (full)
#hHostname (short, up to first dot)
#{pane_current_path}Working directory of the active pane
#{session_windows}Number of windows in the session

Color styling

tmux uses a bracketed style syntax: #[fg=color,bg=color,attr]. Colors can be named (black, white, red), indexed (colour240), or hex (#1e1e2e) when true color is enabled.

set -g status-style         "bg=#1e1e2e,fg=#cdd6f4"
set -g status-left          "#[bg=#89b4fa,fg=#1e1e2e,bold] #S #[default] "
set -g status-right         "#[fg=#a6e3a1] %H:%M #[default]"
set -g window-status-format " #I:#W "
set -g window-status-current-format "#[bold] #I:#W #[default]"

#[default] resets to the base status-style colors. You need it at the end of colored segments, otherwise the color bleeds into adjacent text.

A practical status-right example

set -g status-interval 15
set -g status-right   "#[fg=#a6e3a1]#(cut -d ' ' -f1-3 /proc/loadavg) #[fg=#cdd6f4]| %a %H:%M #[default]"

This reads the 1/5/15-minute load averages from /proc/loadavg directly — faster than callinguptime — and appends the day of week and time. On macOS, replace with sysctl -n vm.loadavg | awk '{print $2,$3,$4}'.

Keeping the left and right from colliding

When status-left and status-right together are wider than the terminal, they overlap the window list or each other. Two options:

set -g status-left-length  30
set -g status-right-length 40

Status bar position

set -g status-position top

Moving the bar to the top keeps it separated from shell prompts, which always land at the bottom. Glancing up for session/host info and down for command output is a natural split. Try it; many people never go back.

Naming windows automatically

set -g automatic-rename on
set -g automatic-rename-format "#{pane_current_command}"

With automatic rename on, the window title tracks whatever program is running in the active pane. vim, node, python — you always know what each window is doing without manually naming them. You can still override a name with prefix , when you want a permanent label.

The discipline behind a good status bar

The same principle that applies to a Claude Code statusline applies here: every segment must earn its pixels. If you glance at a segment and it never influences a decision, remove it. A clock and a session name are almost always worth keeping. CPU percentage updated every second rarely is.

If you want a richer information layer — context window usage, rate limits, git branch per worktree — that belongs in the Claude Code statusline (the line Claude Code renders inside the pane), not the tmux bar. See the tmux + Claude Code layout guide for how these two layers divide responsibility.