Skip to content

tmux panes, sessions, and nested terminals

Run:

Terminal window
tmux

Then create two panes. Put top in one and a shell in the other. You now have terminal emulation nested inside terminal emulation.

Ghostty does not own the PTY connected to every program in every tmux pane. Ghostty owns the outer relationship with the tmux client. The tmux server owns separate PTYs for pane programs.

Ghostty Surface
↕ outer PTY
local tmux client ↔ tmux server
↕ pane PTY 1 → shell/top
↕ pane PTY 2 → shell/editor
↕ pane PTY 3 → another program

The tmux server may outlive the Ghostty window and client. That is why detached sessions can continue running.

The shell launches a tmux client like any other foreground terminal program. The client connects to a tmux server, starting one if necessary. The server owns sessions, windows, panes, pane terminal state, and child processes.

ANIMATED DATA FLOW

From Ghostty prompt to a tmux session

A network control room receives one finished program assembled by a producer who manages several live feeds.

STEP 01 OF 05

Shell in Ghostty PTY

Starts a tmux client as the foreground process.

DATA INtmux command
DATA OUTtmux client attached to Ghostty PTY
1 / 5

Suppose top redraws in the left pane.

  1. top writes text and terminal control sequences to its pane’s PTY slave.
  2. The tmux server reads the pane PTY master.
  3. tmux parses the terminal protocol and updates its private terminal state for that pane.
  4. tmux decides which pane cells are visible and where borders/status belong.
  5. tmux emits a second terminal stream representing the combined screen.
  6. The tmux client writes that stream to the outer PTY.
  7. Ghostty parses the stream and updates its own terminal state.
  8. Ghostty shapes glyphs and renders the final GPU frame.

This means output may be parsed twice:

program output → tmux pane parser/state → composed output → Ghostty parser/state → pixels

A control sequence understood by the pane does not simply pass through unchanged. tmux may consume it, translate its effect into pane state, and later emit different sequences to reproduce the composed screen.

</>
Ghostty creates its terminal modelsrc/terminal/Terminal.zig:305–370Use this as a comparison point: tmux needs a similar conceptual model for every pane it emulates.
Read excerptGitHub

Input travels through routing decisions in the opposite direction.

ANIMATED DATA FLOW

A key reaches one tmux pane

A director decides whether a control-room instruction belongs to the producer or one selected reporter.

STEP 01 OF 04

Ghostty input

Applies Ghostty bindings and encodes remaining input under outer terminal modes.

DATA INnative key event
DATA OUTouter terminal input bytes
1 / 4

The tmux prefix is consumed by tmux rather than forwarded. Ghostty keybindings may consume a key even earlier. Debugging input therefore asks: which layer first claimed the key?

  • A session is a persistent workspace owned by the tmux server.
  • A window is one full tmux screen inside a session.
  • A pane is one rectangular terminal inside a window, usually backed by its own PTY and child process.
  • A client is an attached terminal view. Multiple clients can attach to the same session.

These are tmux concepts, not Ghostty tabs/windows/splits. You can place a tmux client inside a Ghostty split, producing two separate layout systems.

Detaching closes the client view without killing the server’s pane processes. Later, another tmux client can attach—possibly from another Ghostty window or SSH connection. The server uses retained pane state to paint the new client.

Ghostty scrollback outside tmux and tmux copy-mode history are also different stores. Full-screen applications often use alternate screens, and tmux may preserve history per pane.

Resize is a negotiation across layers:

Ghostty native view changes size
→ Ghostty computes outer rows/columns
→ kernel updates outer PTY
→ tmux client/server learns client size
→ tmux recomputes layout
→ tmux updates each pane PTY size
→ pane applications redraw
→ tmux recomposes
→ Ghostty renders

A resize bug can therefore belong to the native view, outer PTY, tmux layout, pane PTY, or application.

When tmux enters copy mode, it may intercept keys and draw its own selection/history interface. Ghostty still sees only tmux’s outer terminal stream. Ghostty’s native selection and tmux copy mode are separate features with different owners and history stores.

Ghostty launches a tmux client on one outer PTY. The client communicates with a persistent tmux server. The server owns sessions and creates one PTY-backed child environment per pane. It parses pane output into private pane state, composes visible panes and status, then emits a new terminal stream through the client to Ghostty. Ghostty parses that composed stream and renders it. Input travels from Ghostty to tmux, where tmux either consumes it as a command or routes it to the selected pane.

A split-screen producer chooses content semantically. tmux composes terminal cells and protocol behavior according to deterministic terminal rules. Ghostty does not know that the visible borders represent tmux panes.