# tmux

> Keep shells alive across SSH drops, split a terminal into panes, copy text without a mouse and script sessions from Bash.

Canonical: https://www.wiki.jodisand.me/tmux/
Reviewed: 2026-09-24
Related: [SSH](https://www.wiki.jodisand.me/ssh/index.md), [Bash](https://www.wiki.jodisand.me/bash/index.md), [systemd](https://www.wiki.jodisand.me/systemd/index.md)


## Cheatsheet

Every key below follows the prefix, `C-b` by default. `C-b c` means press Ctrl-b, release, then `c`.

| Task | Command or key |
| --- | --- |
| Start a named session | `tmux new -s work` |
| Attach, creating if missing | `tmux new -A -s work` |
| List sessions | `tmux ls` |
| Attach and kick other clients off | `tmux attach -d -t work` |
| Detach | `C-b d` |
| New window | `C-b c` |
| Next, previous, numbered window | `C-b n`, `C-b p`, `C-b 0`-`9` |
| Rename window | `C-b ,` |
| Split pane below, right | `C-b "`, `C-b %` |
| Move between panes | `C-b` + arrow, or `C-b o` |
| Zoom a pane to full size and back | `C-b z` |
| Kill the current pane | `C-b x` |
| Interactive session and window picker | `C-b s`, `C-b w` |
| Enter copy mode, scroll back | `C-b [`, then PgUp or `C-u` |
| Paste the last copy | `C-b ]` |
| Command prompt | `C-b :` |
| Show every binding | `C-b ?` or `tmux list-keys` |
| Reload config | `tmux source-file ~/.tmux.conf` |
| Run a command in a detached session | `tmux new -d -s job 'make test 2>&1 \| tee test.log'` |
| Kill one session, or everything | `tmux kill-session -t work`, `tmux kill-server` |

Behaviour below is tmux 3.4 or later. Options and commands that arrived in a specific release are marked. Reference: [tmux(1)](https://man.openbsd.org/tmux.1).

## The server, sessions, windows and panes

The first `tmux` command starts a server process bound to a socket in `/tmp/tmux-$UID/default`. The server owns everything: sessions, the windows in them, the panes in each window and the shells running in those panes. The terminal you type in is a client attached to one session. Closing the terminal, losing the SSH connection or pressing `C-b d` drops the client; the server and every process under it keep running.

| Object | Holds | Addressed as |
| --- | --- | --- |
| Server | Sessions | Socket: `-L name` or `-S /path` |
| Session | Windows, a working directory, environment | `-t work` |
| Window | Panes in a layout; one is current | `-t work:2` or `-t work:editor` |
| Pane | One pseudo-terminal running one process | `-t work:2.1` |

Most commands take `-t target`. A bare number or name means a session, `session:window` selects a window and `session:window.pane` a pane. Window names match on prefix, so `-t work:ed` finds `editor` if nothing else starts with `ed`. `tmux display -p '#S:#I.#P'` prints the current target from inside a pane.

```sh
tmux new -s work -n editor -c ~/projects        # session "work", first window "editor", cwd set
tmux new -d -s build -x 200 -y 50               # detached; size matters for tools that read the terminal width
tmux ls                                         # sessions, window counts, attached or not
tmux attach -t work                             # a second client on the same session mirrors it
tmux attach -d -t work                          # detach the others first: fixes a window sized to a small screen
tmux switch-client -t build                     # move this client to another session without detaching
tmux rename-session -t work api
tmux kill-session -t build                      # kills every process in it
```

Panes size to the smallest attached client. When someone attaches from a phone, everyone's window shrinks to that size; `attach -d` or `C-b D` (choose a client to detach) fixes it. Since tmux 3.1 `window-size` defaults to `latest`, which sizes to the most recently active client rather than the smallest, so this bites less than it used to.

## Windows and panes

```sh
tmux new-window -n logs 'journalctl -fu my-app'   # a window running one command closes when that command exits
tmux split-window -h -c '#{pane_current_path}'    # right of the current pane, same directory
tmux split-window -v -l 10 'htop'                 # below, ten lines high
tmux select-pane -t :.+                           # next pane in the current window
tmux resize-pane -Z                               # toggle zoom
tmux resize-pane -D 5                             # five lines shorter
tmux select-layout even-horizontal                # also even-vertical, main-horizontal, main-vertical, tiled
tmux break-pane                                   # current pane becomes its own window
tmux join-pane -s logs -t editor                  # window "logs" becomes a pane in "editor"
tmux swap-pane -U                                 # exchange with the pane above
tmux swap-window -s 3 -t 1
tmux respawn-pane -k                              # kill what is running and restart the pane's command
```

A pane's process is normally the login shell, which is why exiting the shell closes the pane. A pane created with a command instead runs only that command; `remain-on-exit on` keeps a dead pane visible so its last output can be read, and `respawn-pane` restarts it.

| Key | Effect |
| --- | --- |
| `C-b Space` | Cycle through layouts |
| `C-b {`, `C-b }` | Move the pane up or down in the layout |
| `C-b q` | Show pane numbers; press one to jump there |
| `C-b !` | Break the pane into a window |
| `C-b &` | Kill the window and every pane in it, after confirmation |
| `C-b .` | Move the window to another index |
| `C-b f` | Search window names and contents |
| `C-b t` | Show a clock; any key clears it |

## Prefix and key tables

Keys live in tables. `prefix` holds the bindings that follow `C-b`; `root` holds keys that work without a prefix; `copy-mode` and `copy-mode-vi` hold the copy-mode keys. `bind-key` (alias `bind`) adds to `prefix` unless `-T` names another table, and `-n` is shorthand for `-T root`. `-r` makes a key repeatable within `repeat-time` (500 ms), so `C-b` followed by several arrow presses keeps resizing.

```sh
tmux list-keys -T prefix                    # everything under the prefix
tmux list-keys -T copy-mode-vi | grep -i copy
tmux bind -r H resize-pane -L 5             # repeatable
tmux bind -n M-Left select-pane -L          # Alt-Left, no prefix
tmux unbind C-b; tmux set -g prefix C-a; tmux bind C-a send-prefix   # C-a as prefix, C-a C-a sends a literal C-a
```

`send-prefix` matters because the prefix key itself never reaches the application. With `C-a` as prefix, Emacs and Bash's beginning-of-line need `C-a C-a`. Many people keep `C-b` for that reason, or use `C-Space`.

## Copy mode

Copy mode freezes the pane and lets you move around the scrollback (`history-limit` lines, 2000 by default) with the keys of `mode-keys`: `emacs` by default, `vi` if `VISUAL` or `EDITOR` contains `vi`, or whatever the config sets. Text selected in copy mode goes into a tmux paste buffer, and `C-b ]` pastes the most recent one into the current pane as if typed.

| Action | vi keys | emacs keys |
| --- | --- | --- |
| Enter copy mode | `C-b [` | `C-b [` |
| Move | `h j k l`, `w b`, `0 $`, `g G` | arrows, `M-f M-b`, `C-a C-e`, `M-< M->` |
| Page | `C-u C-d`, `C-b C-f` | `M-v C-v` |
| Search | `/` forward, `?` backward, `n N` | `C-s`, `C-r` |
| Start selection | `Space` or `v` (after binding, see below) | `C-Space` |
| Rectangle toggle | `C-v` (after binding) | `R` |
| Copy and leave | `Enter` | `M-w` |
| Leave without copying | `q` or `Escape` | `Escape` |

Commands in copy mode are sent with `send-keys -X`, which is how bindings are written and how scripts drive it:

```sh
set -g mode-keys vi
bind -T copy-mode-vi v send-keys -X begin-selection
bind -T copy-mode-vi C-v send-keys -X rectangle-toggle
bind -T copy-mode-vi y send-keys -X copy-selection-and-cancel
bind -T copy-mode-vi Escape send-keys -X cancel
bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel   # mouse selections go to copy-command too
```

```sh
tmux copy-mode -e            # -e: leave copy mode when scrolled back to the bottom
tmux list-buffers            # every buffer, newest first
tmux show-buffer             # print the newest to stdout
tmux save-buffer ~/out.txt   # write it to a file
tmux load-buffer ~/in.txt    # file into a buffer
tmux set-buffer "$text"      # string into a buffer
tmux paste-buffer -t work:1  # paste into a specific pane
tmux capture-pane -p -S -    # print the whole scrollback of the current pane, no copy mode needed
```

`capture-pane -p -S - -E - -t work:logs > pane.txt` is the reliable way to get a pane's history into a file from a script; `-J` joins wrapped lines.

## Clipboard

Copying in tmux fills a tmux buffer, not the system clipboard. Two mechanisms bridge the gap.

OSC 52 lets tmux hand the text to the terminal emulator, which sets the clipboard itself. It works through SSH because it travels as an escape sequence inside the session, with no X forwarding needed. It needs three things: `set-clipboard` at `on` or `external` (the default is `external`, which lets tmux set the clipboard but stops programs inside tmux from doing so), the terminal's terminfo entry to carry the `Ms` capability, and the terminal to allow OSC 52. Most modern terminals (foot, kitty, WezTerm, Alacritty, iTerm2, Windows Terminal) do; GNOME Terminal and other VTE-based ones did not until VTE 0.76. Add the capability with `terminal-features` when it is missing:

```sh
set -s set-clipboard on                                      # also lets programs inside (Neovim, for example) use OSC 52
set -as terminal-features ',xterm-256color:clipboard'        # tmux 3.2+; the name is the outer TERM, not tmux's own
```

`copy-command` (tmux 3.2+) pipes every copy through an external program instead. It is the right choice when the terminal does not support OSC 52 or when copying must reach a specific clipboard:

```sh
set -s copy-command 'wl-copy'          # Wayland; xclip -selection clipboard for X11; pbcopy on macOS
set -s set-clipboard off               # avoid double-copying on terminals that also handle OSC 52
```

`copy-command` runs on the machine where the tmux server lives. On a remote server it copies into the remote's clipboard, which is useless; use OSC 52 there.

## .tmux.conf essentials

tmux reads `~/.tmux.conf` then `$XDG_CONFIG_HOME/tmux/tmux.conf` (3.1+) when the server starts. Later changes need `tmux source-file` or a new server. `set-option` (alias `set`) takes `-g` for the global value, `-s` for server options, `-w` for window options and `-a` to append to a string option. A wrong option name reports an error on load; `tmux show-options -g` prints the effective values.

```sh
# Terminal: tmux's own TERM, and what the outer terminal can do
set -g default-terminal 'tmux-256color'                   # falls back to screen-256color if terminfo lacks it
set -as terminal-features ',xterm-256color:RGB'           # 24-bit colour on this outer TERM (3.2+); older: terminal-overrides ',*:Tc'
set -s escape-time 10                                     # ms to wait after Escape; default 500 makes Vim feel broken
set -s extended-keys on                                   # pass Ctrl-Shift and similar combinations through (3.2+)
set -g focus-events on                                    # Vim and Neovim see FocusGained/FocusLost
set -g allow-passthrough on                               # apps may send escape sequences straight to the outer terminal (3.3+): images, OSC 52 from inside

# Behaviour
set -g history-limit 50000
set -g mouse on                                           # click panes, drag to resize, wheel to scroll
set -g base-index 1                                       # windows count from 1; 0 is far from the other keys
set -gw pane-base-index 1
set -g renumber-windows on                                # close window 2 of 4 and the rest shift down
set -g mode-keys vi
set -g status-keys emacs                                  # readline-style editing at the : prompt
set -g display-time 2000                                  # message duration, ms
set -g set-titles on
set -g set-titles-string '#S:#W #{pane_title}'

# Keys
unbind C-b
set -g prefix C-Space
bind C-Space send-prefix
bind r source-file ~/.tmux.conf \; display 'reloaded'
bind | split-window -h -c '#{pane_current_path}'
bind - split-window -v -c '#{pane_current_path}'
bind c new-window -c '#{pane_current_path}'
bind -r h select-pane -L
bind -r j select-pane -D
bind -r k select-pane -U
bind -r l select-pane -R

# Status line
set -g status-interval 5
set -g status-left '#[bold]#S #[default]'
set -g status-right '#(uptime | sed "s/.*load average: //") %H:%M'
```

`#{...}` is a format: `pane_current_path`, `session_name`, `window_index`, `pane_pid`, `client_width` and hundreds more, listed under FORMATS in the manual. `#(cmd)` runs a shell command every `status-interval` seconds and inserts its first line. Formats support conditionals, `#{?client_prefix,PREFIX,}`, which many status lines use to show when the prefix is pending.

`default-terminal` must be a `tmux-*` or `screen-*` value; setting it to `xterm-256color` breaks key handling and colours in ways that look unrelated. If `infocmp tmux-256color` fails, the terminfo database is too old; on Fedora and RHEL it is in `ncurses-term`.

## Scripting tmux from Bash

Every tmux command works from a script, whether or not a client is attached. Commands find the server through the socket, so a script and an interactive session on the same machine and user share state. The building blocks are `new-session -d` to start work without attaching, `send-keys` to type into a pane, `has-session` to make scripts idempotent and `capture-pane` or `pipe-pane` to read output.

```sh
#!/usr/bin/env bash
set -euo pipefail

session=dev
root=$HOME/projects/my-app

if ! tmux has-session -t "=$session" 2>/dev/null; then       # "=" forces an exact name match
  tmux new-session -d -s "$session" -n editor -c "$root"
  tmux send-keys -t "$session:editor" 'vim .' Enter
  tmux new-window -t "$session" -n server -c "$root"
  tmux send-keys -t "$session:server" 'make run' Enter
  tmux split-window -t "$session:server" -v -l 15 -c "$root"
  tmux send-keys -t "$session:server.1" 'tail -f log/dev.log' Enter
  tmux select-window -t "$session:editor"
fi

if [[ -n ${TMUX:-} ]]; then
  tmux switch-client -t "$session"      # already inside tmux: nesting an attach is refused
else
  exec tmux attach -t "$session"
fi
```

`send-keys` types characters; `Enter` is a key name, not a string, so `send-keys 'ls' Enter` runs the command while `send-keys 'ls Enter'` types the letters. Use `-l` to send a string literally when it contains something that looks like a key name. Typing into a pane races with the shell's start-up: on a slow host the shell has not printed its prompt yet and the keys are still delivered, which is fine, but a pane started with a command that is still initialising (a REPL, a database shell) may drop them. Wait on the prompt or use `wait-for`:

```sh
tmux new-session -d -s job "make test; tmux wait-for -S job-done"   # signal the channel when the command ends
tmux wait-for job-done                                              # block until it does
tmux capture-pane -p -t job -S - > test-output.txt
```

For output that must be recorded from the start, `pipe-pane` copies everything the pane prints to a command:

```sh
tmux pipe-pane -t work:server -o 'cat >> ~/server.log'   # -o toggles: the same command again stops it
```

`run-shell` executes a command from a binding or script and shows its output in the pane; `display-message -p` prints a format to stdout, which is the way to read state from a script. `if-shell -F '#{==:#{session_name},dev}' 'cmd' 'other'` branches on a format without spawning a shell.

```sh
tmux display -p -t work:server '#{pane_pid}'                       # PID of the shell in the pane
tmux list-panes -a -F '#{session_name}:#{window_index}.#{pane_index} #{pane_current_command}'
tmux list-windows -t work -F '#{window_index} #{window_name} #{window_activity}'
tmux set-environment -t work API_URL https://api.example.com       # new panes in the session inherit it
tmux new-session -d -s api -e API_TOKEN="$API_TOKEN"               # 3.2+: environment for the whole session
```

## Remote persistence with SSH

The standard pattern is a tmux server on the remote host. Work happens inside it, and reconnecting is `ssh host -t 'tmux new -A -s main'`, which attaches when the session exists and creates it otherwise. `-t` forces a pseudo-terminal, which SSH does not allocate when it is given a command. A [ssh_config](https://www.wiki.jodisand.me/ssh/#client-configuration) entry keeps that short:

```ini
Host build
    HostName build.example.com
    RequestTTY yes
    RemoteCommand tmux new -A -s main
```

Detaching (`C-b d`) or a dropped connection leaves everything running. `tmux ls` on the remote shows it as `(attached)` until the SSH connection has timed out, which can take minutes; `attach -d` takes over immediately.

The environment a session captures at creation is what its panes inherit. `SSH_AUTH_SOCK` changes on every new SSH connection, so a shell inside a session that has been alive for days points at a socket that no longer exists and `git push` fails with `Permission denied (publickey)`. `update-environment` lists variables tmux copies from the attaching client into the session's environment (`SSH_AUTH_SOCK`, `DISPLAY`, `SSH_CONNECTION` and a few others by default), but running shells keep their old copy. Refresh it in the shell:

```sh
eval "$(tmux show-environment -s SSH_AUTH_SOCK)"     # re-export the value tmux has now
```

A stable symlink avoids this entirely: point `SSH_AUTH_SOCK` at `~/.ssh/agent.sock` inside tmux and have `~/.ssh/rc` relink it on every connection.

```sh
# ~/.ssh/rc on the remote host: runs on each connection, in sh
if [ -S "$SSH_AUTH_SOCK" ] && [ "$SSH_AUTH_SOCK" != "$HOME/.ssh/agent.sock" ]; then
  ln -sf "$SSH_AUTH_SOCK" "$HOME/.ssh/agent.sock"
fi
```

Then `[[ -n ${TMUX:-} ]] && export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock` in the shell rc makes every pane, old or new, use the current agent.

A tmux server does not survive a reboot. On a personal server a user unit brings one back:

```ini
# ~/.config/systemd/user/tmux.service
[Unit]
Description=tmux server

[Service]
Type=forking
ExecStart=/usr/bin/tmux new-session -d -s main
ExecStop=/usr/bin/tmux kill-server

[Install]
WantedBy=default.target
```

`systemctl --user enable --now tmux` with `loginctl enable-linger "$USER"` so the user manager starts at boot; see [systemd](https://www.wiki.jodisand.me/systemd/). Sessions and their layout are not saved; plugins such as tmux-resurrect restore layouts and cwd, not the running processes.

## Nested sessions

Running tmux inside an SSH session inside a local tmux is common and works; the inner and outer servers just both want `C-b`. Press `C-b C-b` to send one prefix through to the inner tmux, or give the inner server a different prefix in its config. A cleaner approach binds a key to toggle the outer prefix off:

```sh
# outer .tmux.conf
bind -T root F12 set prefix None \; set key-table off \; refresh-client -S
bind -T off F12 set -u prefix \; set -u key-table \; refresh-client -S
```

`key-table off` sends every key straight to the inner session until F12 is pressed again. The `TMUX` variable being set is how tmux refuses `attach` from inside a session; `TMUX= tmux attach` works around it deliberately, and is how the nested case happens by accident when an SSH client passes the variable through.

## Oneliners

```sh
# Attach to "main" or create it; the everyday entry point
tmux new -A -s main

# Run a long job detached, log it, and notify when done
tmux new -d -s backup 'rsync -a /data/ backup.example.com:/data/ 2>&1 | tee ~/backup.log; notify-send "backup finished"'

# Send the same command to every pane in the current window (toggle with the same command)
tmux setw synchronize-panes on

# Type a command into every pane of the window without sync mode
for p in $(tmux list-panes -F '#{pane_id}'); do tmux send-keys -t "$p" 'sudo dnf update -y' Enter; done

# One pane per host, tiled, each running an SSH session
for h in web-1 web-2 db-1; do tmux split-window -c ~ "ssh $h"; tmux select-layout tiled; done; tmux kill-pane -t 0

# Kill every session except the current one
tmux kill-session -a

# Kill sessions with no attached client
tmux ls -F '#{session_name} #{session_attached}' | awk '$2==0{print $1}' | xargs -rn1 tmux kill-session -t

# Save the whole scrollback of the current pane to a file
tmux capture-pane -p -J -S - > ~/pane-$(date +%s).txt

# Search scrollback for a pattern and print matching lines with pane context
tmux capture-pane -p -S - | grep -n 'ERROR'

# Move the current pane into a window of its own, then bring it back later
tmux break-pane -n scratch; tmux join-pane -s scratch -t work:1

# Rename the current window after the running command
tmux rename-window "$(tmux display -p '#{pane_current_command}')"

# Toggle the status line to reclaim a row
tmux set status

# Show the effective value of one option and where it was set
tmux show-options -g escape-time; tmux show-options -gs terminal-features

# Which TERM and colour capabilities does tmux believe the outer terminal has
tmux display -p '#{client_termname} #{client_termfeatures}'

# Resize the current window to the largest attached client
tmux resize-window -A

# Open a popup shell over the current pane (3.2+); Escape or exit closes it
tmux display-popup -E -w 80% -h 80%

# Watch a pane's output in another pane
tmux pipe-pane -o 'cat >> /tmp/watch.log'; tmux split-window 'tail -f /tmp/watch.log'

# Use a private server for a throwaway environment, isolated from the default socket
tmux -L scratch new -s test

# Clear history of the current pane
tmux clear-history

# List every pane with its PID, so `kill` can target the process not the pane
tmux list-panes -a -F '#{session_name}:#{window_index}.#{pane_index} #{pane_pid} #{pane_current_command}'
```

## Scripts

Start a project workspace idempotently and attach or switch to it.

```sh
#!/usr/bin/env bash
# usage: workspace <name> <directory>
set -euo pipefail
name=${1:?session name}
dir=${2:?directory}
[[ -d $dir ]] || { printf 'no such directory: %s\n' "$dir" >&2; exit 1; }

if ! tmux has-session -t "=$name" 2>/dev/null; then
  tmux new-session -d -s "$name" -n shell -c "$dir"
  tmux new-window -t "$name" -n edit -c "$dir" "${EDITOR:-vim}"
  tmux new-window -t "$name" -n git -c "$dir"
  tmux send-keys -t "$name:git" 'git status' Enter
  tmux select-window -t "$name:edit"
fi
if [[ -n ${TMUX:-} ]]; then tmux switch-client -t "$name"; else exec tmux attach -t "$name"; fi
```

Run a command on many hosts in parallel, each in its own pane, and leave the panes open for inspection.

```sh
#!/usr/bin/env bash
# usage: fanout "<command>" host1 host2 ...
set -euo pipefail
cmd=${1:?command}; shift
(( $# )) || { echo 'no hosts' >&2; exit 2; }
session="fanout-$$"
tmux new-session -d -s "$session" -x 220 -y 60 "ssh -o ConnectTimeout=10 $1 $(printf '%q' "$cmd"); echo '[done: $1]'; exec \$SHELL"
shift
for host in "$@"; do
  tmux split-window -t "$session" "ssh -o ConnectTimeout=10 $host $(printf '%q' "$cmd"); echo '[done: $host]'; exec \$SHELL"
  tmux select-layout -t "$session" tiled
done
tmux setw -t "$session" synchronize-panes off
exec tmux attach -t "$session"
```

Report every session, its windows and what each pane is running, for finding forgotten work before a reboot.

```sh
#!/usr/bin/env bash
set -euo pipefail
tmux ls -F '#{session_name}' 2>/dev/null | while IFS= read -r s; do
  attached=$(tmux display -p -t "$s" '#{session_attached}')
  printf '%s (%s clients)\n' "$s" "$attached"
  tmux list-panes -s -t "$s" -F '  #{window_index}:#{window_name}.#{pane_index}  #{pane_current_command}  #{pane_current_path}'
done
```

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| `open terminal failed: missing or unsuitable terminal` | The outer `TERM` has no terminfo entry on this host | `infocmp "$TERM"`; set `TERM=xterm-256color` before `tmux`, or install the terminal's terminfo |
| Colours wrong or only 8 colours inside tmux | `default-terminal` unset or a non-256-colour value; `tmux-256color` terminfo missing | `tmux info \| grep -E 'colors\|Tc\|RGB'`; `infocmp tmux-256color`; install `ncurses-term` |
| True colour washed out in Vim or Neovim | Outer terminal not declared RGB-capable | `set -as terminal-features ',xterm-256color:RGB'` and restart the server |
| `sessions should be nested with care, unset $TMUX to force` | `tmux attach` from inside tmux | `tmux switch-client -t name`, or `TMUX= tmux attach` when nesting is intended |
| Escape takes half a second in Vim | `escape-time` default of 500 ms | `set -s escape-time 10` |
| Home, End, Ctrl-arrows do nothing | `default-terminal` set to `xterm-*`, or the application ignores `tmux-*` | Use `tmux-256color` or `screen-256color`; `cat -v` and press the key to see what arrives |
| Copy does not reach the system clipboard | OSC 52 not enabled or unsupported, or copying on a remote server with `copy-command` | Check `tmux display -p '#{client_termfeatures}'` for `clipboard`; enable `Ms` via `terminal-features`; test with `printf '\033]52;c;%s\a' "$(printf hi \| base64)"` outside tmux |
| Mouse scroll enters copy mode but selection is unusable | `mouse on` intercepts the drag | Hold Shift while selecting to bypass tmux, or use copy mode keys |
| Window shrinks and shows dots on the right | A smaller client is attached | `tmux attach -d`, or `tmux resize-window -A` |
| `git push` fails with `Permission denied (publickey)` in an old session | Stale `SSH_AUTH_SOCK` | `eval "$(tmux show-environment -s SSH_AUTH_SOCK)"` or the symlink pattern above |
| `error connecting to /tmp/tmux-1000/default (No such file or directory)` | No server running, or `/tmp` cleaned by `systemd-tmpfiles` while the server lives on | `tmux ls` confirms; if the process exists, `kill -USR1 <tmux pid>` recreates the socket |
| Keys typed by `send-keys` arrive as literal `Enter` text | The key name was inside the quoted string | Pass key names as separate arguments: `send-keys 'cmd' Enter` |
| Config change has no effect | Server still running with old options | `tmux source-file ~/.tmux.conf`, or `tmux kill-server` and start again |
| Pane closes immediately after `new-window 'cmd'` | The command exited, and a pane lives only as long as its command | Append `; exec $SHELL`, or `setw remain-on-exit on` to inspect the output |

`tmux info` prints every terminfo capability tmux resolved for the outer terminal, which settles most colour and key arguments. `tmux -vv new` writes `tmux-server-*.log` and `tmux-client-*.log` in the current directory with every byte in and out.

## Further reading

- [tmux(1)](https://man.openbsd.org/tmux.1): the complete option, command, key and format reference
- [tmux wiki](https://github.com/tmux/tmux/wiki): FAQ, clipboard, and terminal-specific advice from upstream
- [tmux CHANGES](https://raw.githubusercontent.com/tmux/tmux/master/CHANGES): which release introduced an option
- [OpenSSH ssh_config(5)](https://man.openbsd.org/ssh_config): `RemoteCommand` and `RequestTTY` for the attach-on-connect pattern


