tmux tutor

tmux tutor

Like vimtutor, but for tmux: 28 hands-on lessons that run in your terminal and check your real tmux state before you move on.

Needs only bash and tmux. Progress saves, so you can quit and pick up where you left off. Source on GitHub

Read the lesson in one terminal, do it in the other, then press v. The tutor inspects the live tmux server and tells you whether it worked.

Basics14 lessons, start here

bash <(curl -sL https://raw.githubusercontent.com/alejandroerickson/tmuxtutor/main/tmuxtutor)

Advanced

bash <(curl -sL https://raw.githubusercontent.com/alejandroerickson/tmuxtutor/main/tmuxtutor-advanced)

Run it outside tmux; the tutor warns you if you don't. Or clone https://github.com/alejandroerickson/tmuxtutor.git and run ./tmuxtutor. MIT licensed.

Keys after the prefix

Ctrl+b is the prefix: press it, let go, then press one key. Every lit key does something. Point at one, tap it, or tab in and move with the arrow keys.

The keyboard scrolls sideways. Tap a key to read it below.

Reference

Everything both modules teach, grouped the way tmux nests: sessions hold windows, windows hold panes. Prefix keys first, then commands for the shell, the Ctrl+b : prompt, and ~/.tmux.conf.

Sessions

Keys or commandWhat it does
after Ctrl+b
dDetach from session
sInteractive session list
)Next session
(Previous session
commands
tmux new -s <name>Create a named session
tmux new -d -s <name>Create detached (background)
tmux new -A -s <name>Attach or create
tmux attach -t <name>Reattach to session
tmux aAttach to most recent session
tmux lsList all sessions
tmux kill-session -t <name>Kill a session
tmux kill-serverKill every session (the whole server)
switch-client -t <name>Switch to named session (at prompt)

Windows

KeysWhat it does
after Ctrl+b
cCreate a new window
,Rename current window
nNext window
pPrevious window
0–9Jump to window by number
wInteractive window list
lLast-used window
&Kill current window (confirm y)

Panes

Keys or commandWhat it does
after Ctrl+b
%Split left / right
"Split top / bottom
|Split left / right (custom binding)
-Split top / bottom (custom binding)
arrow keysMove between panes
oCycle to next pane
qShow pane numbers; press one to select that pane
zToggle zoom
xKill pane (confirm y)
{Swap with previous pane
}Swap with next pane
!Break pane into own window
SpaceCycle layout presets
Ctrl+arrowResize pane (moves the divider)
commands
resize-pane -R <n>Move the divider n cells right (at prompt)
join-pane -t :<window>Join pane into another window (at prompt)
select-layout <name>Set layout preset (at prompt)
setw synchronize-panes onSync input across panes (at prompt)
setw synchronize-panes offStop syncing (at prompt)

Copy Mode

Keys or commandWhat it does
after Ctrl+b
[Enter copy mode
]Paste most recent buffer
=Choose from buffer list
in copy mode, with mode-keys vi
/ then textSearch
SpaceStart selection
eExtend to end of word
EnterCopy selection and exit
commands
tmux list-buffersList all paste buffers

Config

Keys or commandWhat it does
after Ctrl+b
:Open command prompt
?List all keybindings
commands and config lines
set -g mouse onEnable mouse support
set -g mode-keys viVi keybindings in copy mode
set -g history-limit 50000Increase scrollback buffer
set -g base-index 1Start window numbering at 1
set -g status-style '…'Style the status bar
tmux source-file ~/.tmux.confReload config file
bind <key> <command>Create a custom key binding
tmux list-keysList all key bindings (shell)
tmux show-options -gShow global options
tmux infoServer and terminal info

Scripting

CommandWhat it does
tmux new-session -d -s <s> -n <w>Create session + named window (detached)
tmux new-window -t <s> -n <w>Add a window to a session
tmux split-window -h -t <s>:<w>Split side by side (like %)
tmux split-window -v -t <s>:<w>Split stacked (like ")
tmux send-keys -t <s>:<w>.<p> '...' EnterSend a command to a pane

Lessons

The same 28 lessons the tutor runs, Basics beside Advanced. Each one ends with what the tutor checks when you press v.

Basics

14 lessons

Basics lesson 1: Create a Session

tmux organizes everything into sessions. A session is the outermost container — it holds windows, panes, and processes. Named sessions are easier to find and reattach to later.

$ tmux new -s learn

The -s flag names the session. A green status bar at the bottom means you are inside tmux.

Checks that a session named "learn" exists.

Basics lesson 2: Detach

tmux's killer feature: you can detach from a session and it keeps running in the background. Close your laptop, SSH back tomorrow — the session is still there.

Ctrl+b then d
detach from the current session

You will be dropped back to a regular shell prompt. The session is still running — just not attached to any terminal.

Checks that session "learn" exists and is detached (attached=0).

Basics lesson 3: Reattach

Your "learn" session is still running in the background. Reattach to pick up where you left off.

$ tmux attach -t learn

Shorthand: tmux a attaches to the most recent session. List all sessions with tmux ls.

Checks that session "learn" is attached (attached != 0).

Basics lesson 4: Create Windows

Inside a session you can have multiple windows — think of them as tabs. Each is a full-screen terminal.

Ctrl+b then c
create a new window
Ctrl+b then n
next window
Ctrl+b then p
previous window
Ctrl+b then 0
jump to window 0

Look at the status bar — the * marks the active window.

Checks that the "learn" session has at least 2 windows.

Basics lesson 5: Name Your Windows

Window names like "0:zsh" don't tell you much. Give them meaningful names so the status bar is useful at a glance.

Ctrl+b then 0
go to window 0
Ctrl+b then ,
rename the current window (type main, press Enter)
Ctrl+b then 1
go to window 1
Ctrl+b then ,
rename it (type work, press Enter)

The rename prompt starts with the current name filled in. Clear it first with Backspace or Ctrl+u.

Checks for windows named "main" and "work" in the "learn" session.

Basics lesson 6: Split into Panes

A window can be divided into panes — multiple terminals visible at once. Navigate to the "work" window and split it.

Ctrl+b then %
split left / right (vertical divider)
Ctrl+b then "
split top / bottom (horizontal divider)
Ctrl+b then arrow keys
move between panes
Ctrl+b then o
cycle to next pane

To reach "work": Ctrl+b then 1 jumps to window 1, or Ctrl+b then w opens the window list.

Checks that the "work" window has at least 2 panes.

Basics lesson 7: Split the Other Way

Add a second split in a different direction to build a multi-pane layout. In the "work" window, pick either pane and split the other way.

Ctrl+b then %
split left / right, if your first split was top / bottom
Ctrl+b then "
split top / bottom, if your first split was left / right

A typical layout is an editor on the left, tests top-right, logs bottom-right. You should end up with 3 panes.

Checks for at least 3 panes in the "work" window.

Basics lesson 8: Zoom a Pane

When you need to focus on one pane, zoom it to fill the entire window. The other panes stay alive — just hidden.

Ctrl+b then z
toggle zoom on the current pane

The status bar shows a Z flag when a pane is zoomed. Press the same combo again to unzoom — but leave it zoomed for now.

Checks that the "work" window has a zoomed pane (zoomed_flag=1).

Basics lesson 9: Kill a Pane

Remove a pane you no longer need. First unzoom if the window is still zoomed, then kill one of the three panes.

Ctrl+b then z
toggle zoom off
Ctrl+b then x
kill current pane (press y to confirm)

Checks for exactly 2 panes in "work" and no zoom.

Basics lesson 10: Create a Window

Practice the full window lifecycle. Create a temporary window and name it "scratch".

Ctrl+b then c
create a new window
Ctrl+b then ,
rename it to scratch (clear the old name first)

Checks for at least 3 windows in "learn", including one named "scratch".

Basics lesson 11: Kill a Window

Now remove the "scratch" window you just created.

Ctrl+b then w
interactive window list — select scratch
Ctrl+b then &
kill current window (press y to confirm)

Checks for exactly 2 windows (main + work) with no "scratch".

Basics lesson 12: Runtime Configuration

tmux settings can be changed at runtime through the command prompt. Open it, type a command, and press Enter.

Ctrl+b then :
open the tmux command prompt

Type these at the prompt

: set -g mouse on
: set -g mode-keys vi

The command prompt supports Tab completion. mouse on enables click-to-select panes, scroll with wheel, and drag-to-resize. mode-keys vi enables vim keybindings in copy mode. To make these permanent, add them to ~/.tmux.conf.

Checks that mouse=on and mode-keys=vi in the running server.

Basics lesson 13: Copy Mode

Copy mode lets you scroll, search, and copy text without a mouse. You will copy a marker string into the tmux paste buffer.

Step 1 — In any pane of the "learn" session, print the marker

$ echo TMUXTUTOR_COPY_TEST

Step 2 — Enter copy mode

Ctrl+b then [
enter copy mode

Step 3 — Find, select, copy (vi keys)

/
search — type TMUXTUTOR_COPY_TEST, press Enter
Space
start selection
e
extend to end of word (or use the arrow keys)
Enter
copy and exit copy mode

Checks that the tmux paste buffer contains "TMUXTUTOR_COPY_TEST".

Basics lesson 14: Build a Workspace

Capstone: put it all together. Build a workspace from scratch with a new session, named windows, and pane splits.

  1. Detach from "learn" Ctrl+b then d
  2. Create a new session tmux new -s project
  3. Rename the first window to editor Ctrl+b then ,
  4. Split it side by side Ctrl+b then %
  5. Create a second window Ctrl+b then c
  6. Rename it to shell Ctrl+b then ,

Result: Session "project" with "editor" (2 panes) + "shell". Clear the old name before typing each new one.

Checks for session "project" with windows "editor" (2+ panes) and "shell".

Advanced

14 lessons

Advanced lesson 1: Kill a Session

Sessions accumulate. Sometimes you need to kill one. Create two throwaway sessions, then kill only the first.

$ tmux new -d -s temp1
$ tmux new -d -s temp2
$ tmux ls
$ tmux kill-session -t temp1

The -d flag creates sessions in the background (detached). The nuclear option tmux kill-server destroys every session. Don't use it here; the tutor needs temp2 alive to verify.

Checks that temp1 is gone and temp2 is still alive.

Advanced lesson 2: Switch Between Sessions

When you have multiple sessions, you can switch between them without detaching and reattaching.

First, have 2 sessions and attach to one

You should still have temp2 from lesson 1. Create another if needed, then attach:

$ tmux new -d -s work
$ tmux attach -t work

Switch with keys

Ctrl+b then s
interactive session list
Ctrl+b then )
next session
Ctrl+b then (
previous session

Or via command prompt

Ctrl+b then :
then type switch-client -t temp2

Checks for at least 2 sessions with at least 1 attached.

Advanced lesson 3: Resize Panes

Control pane geometry. Create session "adv" with a "resize" window, split it, then make the right pane wider.

Step 1 — Create session "adv" with a named window

$ tmux new -d -s adv -n resize

Step 2 — Split side by side

$ tmux split-window -h -t '=adv:=resize'

Or attach and use Ctrl+b then %.

Step 3 — Attach and make the right pane wider

$ tmux attach -t adv
Ctrl+b then Ctrl+Right
small steps: repeat several times
Ctrl+b then :
precise: then type resize-pane -R 20

The command prompt supports Tab completion — type resi then press Tab. Goal: the right pane should be wider than 55% of the window.

Checks that pane 1 occupies at least 55% of the window width.

Advanced lesson 4: Swap Panes

Swap the positions of two panes without moving yourself or retyping anything. Put identifying text in each pane, then swap them.

Step 1 — Select pane 0 and mark it

Ctrl+b then q then 0
flash pane numbers, then select pane 0
$ echo PANE_A

Step 2 — Move to pane 1 and mark it

Ctrl+b then q then 1
or Ctrl+b then o
$ echo PANE_B

Step 3 — Swap the panes (from either pane)

Ctrl+b then {
swap current pane with the previous one
Ctrl+b then }
swap current pane with the next one

Captures pane contents and checks that pane 0 shows PANE_B and pane 1 shows PANE_A (swapped).

Advanced lesson 5: Pane Layouts

tmux has built-in layout presets that rearrange all panes at once. Add a third pane to "resize", then cycle through layouts.

Step 1 — Add a third pane

Ctrl+b then "
or Ctrl+b then % — split again

Step 2 — Cycle through layouts

Ctrl+b then Space
cycle through layout presets

Or set a specific layout

Ctrl+b then :
then type select-layout tiled

Available layouts: even-horizontal (equal columns), even-vertical (equal rows), main-horizontal (big top, rest below), main-vertical (big left, rest right), tiled (grid).

Checks for at least 3 panes in the "resize" window.

Advanced lesson 6: Move Panes Between Windows

Panes can be broken out of a window or joined into another. Create a "staging" window, break a pane from "resize", and join it into "staging".

Step 1 — Create a "staging" window

Ctrl+b then c
create a new window
Ctrl+b then ,
rename it to staging (clear the old name first)

Step 2 — Go back to "resize"

Ctrl+b then w
window list — select resize

Step 3 — Break out a pane

Ctrl+b then !
break current pane into its own window

Step 4 — Join it into "staging"

Ctrl+b then :
then type join-pane -t :staging

Checks that "staging" window has at least 2 panes.

Advanced lesson 7: Paste and Buffers

tmux maintains its own paste buffers independent of the system clipboard. Copy text in copy mode and paste it back. Multiple copies stack up.

Step 1 — In any pane of session "adv", print the marker

$ echo ADVANCED_PASTE_TEST

Step 2 — Make sure vi keys are active

Ctrl+b then :
then type set -g mode-keys vi

Step 3 — Copy it (vi keys)

Ctrl+b then [
enter copy mode
/
search — type ADVANCED_PASTE_TEST, press Enter
Space
start selection
e
extend to end of word (or End)
Enter
copy and exit copy mode

Paste and buffer management

Ctrl+b then ]
paste the most recent buffer
Ctrl+b then =
choose from buffer list
$ tmux list-buffers

Checks that the paste buffer contains "ADVANCED_PASTE_TEST".

Advanced lesson 8: Help and Introspection

tmux has a built-in help system. Browse every keybinding, query options, and inspect the running server.

Ctrl+b then ?
list all keybindings (q to exit)

Shell commands (inside the "adv" session)

$ tmux list-keys
$ tmux show-options -g
$ tmux info

Exercise

Make sure "adv" has at least 2 windows (Ctrl+b then c). Then press Ctrl+b then ?, find the binding that runs last-window, press q to exit help, and use it:

Ctrl+b then l
switch to the last-used window

Checks that session "adv" has at least 2 windows.

Advanced

lessons 9–14

Advanced lesson 9: Edit tmux.conf

Runtime settings vanish when the server exits. Put them in ~/.tmux.conf to make them permanent.

Recommended config lines

set -g mouse on
set -g mode-keys vi
set -g history-limit 50000
set -g base-index 1
set -g status-style 'bg=colour235 fg=colour75'

Reload the config

$ tmux source-file ~/.tmux.conf

You can also reload from the tmux command prompt: Ctrl+b then : then type source-file ~/.tmux.conf. Back up any existing config first with cp ~/.tmux.conf ~/.tmux.conf.bak.

With base-index 1, windows number from 1 and the status bar is no longer green, so Basics lessons that mention window 0 read differently if you run them again.

Checks that ~/.tmux.conf contains mouse on, mode-keys vi, and history-limit, and that mouse is on and history-limit is at least 50000 in the running server.

Advanced lesson 10: Custom Key Bindings

The default split keys % and " are hard to remember. Bind more intuitive keys that look like the dividers they create.

Add to ~/.tmux.conf

bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"

Reload the config

$ tmux source-file ~/.tmux.conf

Try the new bindings

Ctrl+b then |
split side by side (vertical divider)
Ctrl+b then -
split stacked (horizontal divider)

The -c "#{pane_current_path}" flag opens the new pane in the same directory as the current pane.

Checks that both bindings exist in ~/.tmux.conf and are loaded into the running server.

Advanced lesson 11: Synchronized Panes

Type the same command into multiple panes at once — useful for updating several servers simultaneously.

Step 1 — Make sure the current window in "adv" has 2+ panes

Ctrl+b then %
or Ctrl+b then " to split

Turn sync on

Ctrl+b then :
then type setw synchronize-panes on

Now anything you type appears in every pane at once. Try echo SYNC_TEST. Leave sync on for verification.

Turn sync off afterwards

Ctrl+b then :
then type setw synchronize-panes off

Checks that synchronize-panes is "on" and the current window of "adv" has 2+ panes.

Advanced lesson 12: Script a Workspace

tmux's real power is scripting. Every command you have used interactively can be run from a shell script to build a workspace automatically.

Key concepts

-d
create detached
-t session:window
target a window
-t session:window.pane
target a pane
send-keys ... Enter
type a command into a pane

Scripted commands (run them in your regular shell, not inside tmux)

$ tmux new-session -d -s dev -n editor
$ tmux split-window -h -t dev:editor
$ tmux new-window -t dev -n logs
$ tmux send-keys -t dev:editor.0 'echo EDITOR_READY' Enter
$ tmux send-keys -t dev:logs 'echo LOGS_READY' Enter
$ tmux attach -t dev

Checks for session "dev" with "editor" (2+ panes, EDITOR_READY marker) and "logs" (LOGS_READY marker).

Advanced lesson 13: SSH and tmux

tmux really shines over SSH. Set up a real SSH server, connect from another device, and attach to a tmux session remotely. If the connection drops, the session keeps running — just reconnect and reattach.

Step 1 — Install and start the SSH server

SystemCommands
Ubuntu / Debian
$ sudo apt install openssh-server
$ sudo systemctl enable ssh && sudo systemctl start ssh
Fedora
$ sudo dnf install openssh-server
$ sudo systemctl enable sshd && sudo systemctl start sshd
Arch
$ sudo pacman -S openssh
$ sudo systemctl enable sshd && sudo systemctl start sshd
macOS

Enable via System Settings → General → Sharing → Remote Login, or:

$ sudo systemsetup -setremotelogin on

Step 2 — Create a tmux session to connect to

$ tmux new -d -s remote
$ tmux send-keys -t remote 'echo SSH_WORKFLOW_TEST' Enter

Step 3 — Find your IP address

$ hostname -I

Use the first address printed as <ip> in the next step. On macOS, use ipconfig getifaddr en0 instead.

Step 4 — SSH in from your phone, laptop, or another terminal, and attach

$ ssh <user>@<ip>
$ tmux attach -t remote

You should see SSH_WORKFLOW_TEST in the pane — proof that the session survived across connections.

Attach-or-create: tmux new -A -s <name> attaches if the session exists, or creates it if not. The "always works" command.

WAN access: To connect from outside your local network, set up port forwarding on your router (port 22) or use Tailscale for a zero-config VPN.

Security: Consider SSH keys instead of passwords: ssh-keygen on the client, then ssh-copy-id <user>@<ip> to install the key.

Troubleshooting

"Connection refused" on port 22: sshd is not running. Check its status; if it says "not found", install it, then start it.

$ sudo systemctl status ssh
$ sudo apt install openssh-server
$ sudo systemctl start ssh

Is sshd listening? You should see a line with *:22 or 0.0.0.0:22.

$ ss -tlnp | grep :22

WSL2: the IP from hostname -I is the WSL2 VM's internal IP. The Windows host can reach it, but other devices on your network can't without port forwarding from Windows. From another Windows terminal, connect to localhost:

$ ssh <user>@localhost

Password authentication: SSH needs your Linux password. If you have never set one (common on WSL2), set it now:

$ sudo passwd <user>

Checks that sshd is running, session "remote" exists, marker text "SSH_WORKFLOW_TEST" is present, and the session is attached.

Advanced lesson 14: Build a Dev Environment

Capstone: build a multi-session dev environment from scratch using scripted commands. Two sessions, each with multiple windows and panes.

Backend session

$ tmux new-session -d -s backend -n api
$ tmux split-window -h -t backend:api
$ tmux new-window -t backend -n db

Frontend session

$ tmux new-session -d -s frontend -n app
$ tmux split-window -h -t frontend:app
$ tmux new-window -t frontend -n tests

Send markers and attach

$ tmux send-keys -t backend:api.0 'echo BACKEND_API' Enter
$ tmux send-keys -t frontend:app.0 'echo FRONTEND_APP' Enter
$ tmux attach -t backend
Ctrl+b then s
switch between backend and frontend

Result: Two sessions (backend + frontend), each with named windows and split panes. Imagine scripting this into a single dev-start.sh you run every morning.

Checks both sessions exist with correct windows, pane counts, and marker text.