Skip to main content

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.

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:
TokenShorthandMeaning
{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
Panes are spread out evenly from left to right across the window.
┌──────┬──────┬──────┐
│  1   │  2   │  3   │
│      │      │      │
└──────┴──────┴──────┘

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

  1. Plan your layout: Think about workflow before splitting
  2. Use preset layouts: Leverage built-in layouts for common patterns
  3. Name your panes: Use pane-border-format for context
  4. Master navigation: Learn directional selection for efficiency
  5. Zoom when needed: Use zoom for temporary full-screen focus
  6. Synchronize carefully: Remember to disable synchronization when done
  7. 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