The most surprising thing about tmux is that its "sessions," "windows," and "panes" aren’t just organizational metaphors; they’re actual, distinct entities with their own lifecycles and network addresses that tmux uses to manage them.

Let’s watch it work. Imagine you’ve just SSH’d into a server and want to start a long-running process. You fire up tmux:

$ tmux

This creates a new, default session. Inside that session, there’s one window, and inside that window, there’s one pane. You can see this by typing Ctrl-b (the default tmux prefix) followed by show-environment. Look for TMUX_PANE. It will look something like $TMUX_PANE=0.

Now, let’s create a new window. Press Ctrl-b then c. You’ll see your prompt disappear and a new status line appear at the bottom, indicating you’re on window 1.

# Your prompt might look like this before:
user@server:~$

# After Ctrl-b c, the status line shows:
# 0:bash*  1:bash

You can switch between windows with Ctrl-b n (next) and Ctrl-b p (previous). Let’s go back to window 0: Ctrl-b p.

Now, inside this window, let’s split the pane horizontally. Press Ctrl-b then %. You’ll see the current pane split, and you’ll be in the new pane.

# Your prompt in the top pane
user@server:~$

# Your prompt in the bottom pane
user@server:~$

You can navigate between panes with Ctrl-b followed by an arrow key (Ctrl-b Left, Ctrl-b Right, Ctrl-b Up, Ctrl-b Down). Let’s split the current pane vertically: Ctrl-b then ".

# Top-left pane
user@server:~$

# Top-right pane
user@server:~$

# Bottom pane
user@server:~$

So, a session is the top-level container. It’s like a virtual terminal server. A window is a tab within that session, and a pane is a subdivision of a window. Each of these can have its own independent shell and running processes.

The problem tmux solves is managing multiple, independent terminal environments that persist even if your SSH connection drops. You can detach from a tmux session (Ctrl-b d) and your processes keep running. Later, you can reattach (tmux attach or tmux a) and find everything exactly as you left it.

Internally, tmux uses a client-server architecture. When you run tmux, you’re starting a tmux server process. The tmux command you type in your shell is a client that connects to this server. When you create new windows or panes, the client tells the server to create new TTYs (pseudo-terminals) and associate them with the current session. The server manages these TTYs and multiplexes their output to the connected clients.

The hierarchy is crucial for managing these resources. A session can contain many windows. A window can contain many panes. You can name sessions, windows, and even panes to keep track of what’s what. For example, to name the current window "webserver": Ctrl-b , then type webserver. To name the current session "project-x": Ctrl-b s to list sessions, then Ctrl-b : to enter command mode, then rename-session project-x.

The TMUX_PANE environment variable, which you can see with tmux show-environment TMUX_PANE, is an identifier for the current pane. This is useful for scripting within tmux, allowing one pane to interact with or send commands to another. You can also use tmux list-panes to see all panes within the current window, and tmux list-windows for all windows in the current session.

Each pane is essentially its own pseudo-terminal device. When you split a pane, tmux creates a new TTY and tells the server to attach a new shell to it. The server then manages the communication between these TTYs and the client displaying them. This is why detaching works: the server keeps the TTYs alive, and when you reattach, the client reconnects and resumes displaying their output.

The core of tmux’s power lies in its ability to manage these independent terminal environments. You can have a session for "development" with one window for your code editor (e.g., vim), another for your build process, and a third for running tests. All of this persists even if you close your laptop or lose your internet connection.

A common point of confusion is how to send commands to specific panes. You can use the send-pane command, but you need to specify the target pane. For instance, to send "ls -l" to the pane with ID %% in the current window: tmux send-keys -t %% "ls -l" C-m. The C-m is crucial; it represents the Enter key.

You can also have multiple tmux clients attached to the same session. This is great for pair programming or for managing a server from both your laptop and your phone. All clients see the same session, windows, and panes, and actions taken on one client are reflected on all others.

The next concept you’ll likely grapple with is scripting tmux commands to automate complex window and pane layouts, especially when starting new sessions.

Want structured learning?

Take the full Tmux course →