Overview
Panes are rectangular subdivisions of a tmux window, each containing an independent pseudo terminal. From the man page (tmux.1:1722-1749):
Each pane takes up a certain area of the display and is a separate terminal. A window may be split into panes using the split-window command.
Windows may be split horizontally or vertically, and panes can be resized, moved, and arranged in various layouts.
Pane Architecture
From window.c:930-973, panes are created with:
static struct window_pane *
window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
{
struct window_pane *wp;
wp = xcalloc(1, sizeof *wp);
wp->window = w;
wp->options = options_create(w->options);
wp->id = next_window_pane_id++; // Unique ID
RB_INSERT(window_pane_tree, &all_window_panes, wp);
wp->fd = -1; // Will be set to pty file descriptor
wp->sx = sx; // Width
wp->sy = sy; // Height
screen_init(&wp->base, sx, sy, hlimit); // Screen buffer
wp->screen = &wp->base;
return (wp);
}
Creating Panes
Splitting Windows
# Split horizontally (side by side)
Prefix %
$ tmux split-window -h
# Split vertically (top and bottom)
Prefix "
$ tmux split-window -v
# Split with command
$ tmux split-window -h 'htop'
# Split with specific size
$ tmux split-window -h -l 30 # 30 columns wide
$ tmux split-window -v -p 25 # 25% of height
From the man page default key bindings (tmux.1:284-292):
Prefix " - Split the current pane into two, top and bottom
Prefix % - Split the current pane into two, left and right
Prefix ! - Break the current pane out of the window
Pane Identification
Panes are identified by:
- Pane ID: Prefixed with
% (e.g., %0, %1) - unique and unchanging
- Pane index: Position within window (starting at 0 by default)
From window.c:906-928:
struct window_pane *
window_pane_find_by_id(u_int id)
{
struct window_pane wp;
wp.id = id;
return (RB_FIND(window_pane_tree, &all_window_panes, &wp));
}
The pane ID is passed to the child process in the TMUX_PANE environment variable.
Navigating Panes
Key Bindings
From the man page (tmux.1:313-376):
Prefix o - Select the next pane in the current window
Prefix ; - Move to the previously active pane
Prefix Up/Down/Left/Right - Change to the pane in that direction
Prefix q - Briefly display pane indexes
Selecting Panes
From the man page (tmux.1:847-878), special pane tokens:
| Token | Shorthand | Meaning |
|---|
{last} | ! | The last (previously active) pane |
{next} | + | The next pane by number |
{previous} | - | The previous pane by number |
{top} | | The top pane |
{bottom} | | The bottom pane |
{left} | | The leftmost pane |
{right} | | The rightmost pane |
{up-of} | | The pane above the active pane |
{down-of} | | The pane below the active pane |
{left-of} | | The pane to the left of the active pane |
{right-of} | | The pane to the right of the active pane |
{active} | @ | The active pane |
# Select pane by direction
$ tmux select-pane -U # Up
$ tmux select-pane -D # Down
$ tmux select-pane -L # Left
$ tmux select-pane -R # Right
# Select last pane
$ tmux select-pane -l
# Select by index
$ tmux select-pane -t :.2
Pane Selection Logic
From window.c:1387-1610, directional pane finding:
/*
* Find the pane directly above another. We build a list of those adjacent to
* top edge and then choose the best.
*/
struct window_pane *
window_pane_find_up(struct window_pane *wp)
{
struct window *w = wp->window;
struct window_pane *next, *best, **list;
u_int edge, left, right, end, size;
// Find all panes whose bottom edge touches this pane's top edge
// Then select the most recently used (MRU) pane from candidates
return best;
}
Resizing Panes
From the man page (tmux.1:391-396):
# Resize in steps of one cell
Prefix C-Up # Resize up
Prefix C-Down # Resize down
Prefix C-Left # Resize left
Prefix C-Right # Resize right
# Resize in steps of five cells
Prefix M-Up
Prefix M-Down
Prefix M-Left
Prefix M-Right
# Resize with command
$ tmux resize-pane -U 5 # Up 5 lines
$ tmux resize-pane -D 5 # Down 5 lines
$ tmux resize-pane -L 10 # Left 10 columns
$ tmux resize-pane -R 10 # Right 10 columns
# Resize to specific size
$ tmux resize-pane -x 80 # 80 columns wide
$ tmux resize-pane -y 24 # 24 lines tall
From window.c:1080-1106:
void
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
{
if (sx == wp->sx && sy == wp->sy)
return;
// Queue resize event
r = xmalloc(sizeof *r);
r->sx = sx;
r->sy = sy;
r->osx = wp->sx;
r->osy = wp->sy;
TAILQ_INSERT_TAIL(&wp->resize_queue, r, entry);
wp->sx = sx;
wp->sy = sy;
screen_resize(&wp->base, sx, sy, wp->base.saved_grid == NULL);
}
Pane Layouts
From layout-set.c:39-50, tmux provides seven preset layouts:
static const struct {
const char *name;
void (*arrange)(struct window *);
} layout_sets[] = {
{ "even-horizontal", layout_set_even_h },
{ "even-vertical", layout_set_even_v },
{ "main-horizontal", layout_set_main_h },
{ "main-horizontal-mirrored", layout_set_main_h_mirrored },
{ "main-vertical", layout_set_main_v },
{ "main-vertical-mirrored", layout_set_main_v_mirrored },
{ "tiled", layout_set_tiled },
};
Applying Layouts
From the man page (tmux.1:377-384):
# Cycle through layouts
Prefix Space
# Apply specific layout (M-1 through M-7)
Prefix M-1 # even-horizontal
Prefix M-2 # even-vertical
Prefix M-3 # main-horizontal
Prefix M-4 # main-vertical
Prefix M-5 # tiled
# Or use command
$ tmux select-layout even-horizontal
$ tmux select-layout main-vertical
$ tmux select-layout tiled
even-horizontal
even-vertical
main-horizontal
main-vertical
tiled
Panes are spread out evenly from left to right across the window.┌──────┬──────┬──────┐
│ 1 │ 2 │ 3 │
│ │ │ │
└──────┴──────┴──────┘
Panes are spread out evenly from top to bottom.┌─────────────────────┐
│ 1 │
├─────────────────────┤
│ 2 │
├─────────────────────┤
│ 3 │
└─────────────────────┘
A large main pane on top with smaller panes in a row below.┌─────────────────────┐
│ │
│ Main │
│ │
├──────┬──────┬───────┤
│ 2 │ 3 │ 4 │
└──────┴──────┴───────┘
A large main pane on the left with smaller panes in a column on the right.┌──────────┬──────────┐
│ │ 2 │
│ ├──────────┤
│ Main │ 3 │
│ ├──────────┤
│ │ 4 │
└──────────┴──────────┘
Panes are tiled in a grid as evenly as possible.┌──────────┬──────────┐
│ 1 │ 2 │
│ │ │
├──────────┼──────────┤
│ 3 │ 4 │
│ │ │
└──────────┴──────────┘
Swapping and Moving Panes
# Swap panes
Prefix { # Swap with previous pane
Prefix } # Swap with next pane
$ tmux swap-pane -U # Swap with pane above
$ tmux swap-pane -D # Swap with pane below
# Move pane to new window
Prefix !
$ tmux break-pane
# Join pane from another window
$ tmux join-pane -s :2.1 # Join pane 1 from window 2
From the man page (tmux.1:363-366):
Prefix { - Swap the current pane with the previous pane
Prefix } - Swap the current pane with the next pane
Rotating Panes
# Rotate panes forwards
Prefix C-o
# Rotate panes backwards
Prefix M-o
$ tmux rotate-window
$ tmux rotate-window -D # Backwards
Zooming Panes
From window.c:656-681, panes can be temporarily zoomed:
int
window_zoom(struct window_pane *wp)
{
struct window *w = wp->window;
if (w->flags & WINDOW_ZOOMED)
return (-1);
if (window_count_panes(w) == 1)
return (-1);
// Save layout and zoom pane
TAILQ_FOREACH(wp1, &w->panes, entry) {
wp1->saved_layout_cell = wp1->layout_cell;
wp1->layout_cell = NULL;
}
w->saved_layout_root = w->layout_root;
layout_init(w, wp);
w->flags |= WINDOW_ZOOMED;
return (0);
}
# Toggle zoom (within tmux)
Prefix z
# Or use command
$ tmux resize-pane -Z
Zooming a pane temporarily makes it occupy the entire window. The flag Z appears in the status line when a pane is zoomed.
Pane Synchronization
Send input to all panes in a window simultaneously:
# Enable synchronization
$ tmux set-option synchronize-panes on
# Disable synchronization
$ tmux set-option synchronize-panes off
# Toggle with key binding
$ tmux bind-key S set-option synchronize-panes
From window.c:1189-1220, synchronized input is copied to all visible panes:
static void
window_pane_copy_key(struct window_pane *wp, key_code key)
{
struct window_pane *loop;
TAILQ_FOREACH(loop, &wp->window->panes, entry) {
if (loop != wp &&
TAILQ_EMPTY(&loop->modes) &&
loop->fd != -1 &&
(~loop->flags & PANE_INPUTOFF) &&
window_pane_visible(loop) &&
options_get_number(loop->options, "synchronize-panes"))
input_key_pane(loop, key, NULL);
}
}
Pane Borders
Customize pane border appearance:
# Set border style
$ tmux set-option -g pane-border-style fg=blue
$ tmux set-option -g pane-active-border-style fg=red,bold
# Show pane border status
$ tmux set-option -g pane-border-status top # or bottom
$ tmux set-option -g pane-border-format ' #{pane_index} #{pane_current_command} '
Pane Marking
Mark a pane for commands that target marked panes:
# Mark current pane
Prefix m
# Clear marked pane
Prefix M
# Use in commands
$ tmux swap-pane -s '{marked}'
$ tmux join-pane -s '{marked}'
From the man page (tmux.1:338-342):
Prefix m - Mark the current pane
Prefix M - Clear the marked pane
Capturing Pane Content
# Capture visible pane content
$ tmux capture-pane -p
# Capture pane history
$ tmux capture-pane -p -S -1000
# Save to file
$ tmux capture-pane -p -S - > pane-content.txt
# Capture from specific pane
$ tmux capture-pane -p -t %2
Pane Numbers
From window.c:1749 and the man page:
# Display pane numbers
Prefix q
# Display for longer
$ tmux set-option -g display-panes-time 3000 # 3 seconds
# Customize colors
$ tmux set-option -g display-panes-colour blue
$ tmux set-option -g display-panes-active-colour red
Panes are numbered beginning from zero in the order they are created. The pane-base-index option can change the starting index.
Best Practices
- Plan your layout: Think about workflow before splitting
- Use preset layouts: Leverage built-in layouts for common patterns
- Name your panes: Use
pane-border-format for context
- Master navigation: Learn directional selection for efficiency
- Zoom when needed: Use zoom for temporary full-screen focus
- Synchronize carefully: Remember to disable synchronization when done
- Set sensible sizes: Use percentage-based splits for flexibility
# Example: development layout script
#!/bin/bash
tmux split-window -h -p 30 # 30% width for side pane
tmux select-pane -L # Back to main pane
tmux split-window -v -p 20 # 20% height for bottom pane
tmux select-pane -U # Back to top-left