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:
- Built-in format variables (
#S,#W,#H,#{pane_current_path}, etc.) — evaluated inline by tmux, zero overhead. - Shell segments (
#(command)) — tmux runs the command in a subshell and inserts the output. Runs on every status refresh.
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
| Variable | What it shows |
|---|---|
#S | Session name |
#W | Current window name |
#H | Hostname (full) |
#h | Hostname (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
status-left-lengthandstatus-right-lengthto cap each side's width explicitly. - Keep segments short. A session name, a load number, and a clock fit in 40 characters on each side.
set -g status-left-length 30
set -g status-right-length 40Status bar position
set -g status-position topMoving 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.