# Server, session, window, pane

Source: https://libtmux.org/en/ruby/latest/concepts/server-session-window-pane/

> The object hierarchy every libtmux port mirrors from tmux itself, and the client that sits outside it.

libtmux models tmux's server, session, window, and pane objects:

```
Server
├── Session
│   └── Window
│       └── Pane
└── Client (attached view)
```

A `Server` contains sessions. Each `Session` contains links to windows, and each
`Window` contains panes. Commands run inside a `Pane`, where you send input and
capture output. A window can be linked to more than one session.

## Stable identity, not name or index

tmux assigns a unique ID to each session, window, and pane at creation. The ID
remains stable for that object's lifetime even if its name or index changes:

| Object | ID prefix | Example |
|--------|-----------|---------|
| Session | `$` | `$13` |
| Window | `@` | `@3243` |
| Pane | `%` | `%5433` |
| Server | - | identified by socket name or path instead |

Python handles use the object ID to refresh their fields. Immutable snapshots,
such as those in TypeScript, Swift, and Go, use IDs to identify the same tmux
object across reads.

Walking the whole tree, in each port:

## Client: a view, not a child

A `Client` represents a terminal attached to a session. Several clients can view
the same server, and each can switch sessions or windows independently. Client
fields describe the view at the time of the read.

A [control-mode connection](../transports/) is also a client. It appears in
`list-clients`, counts toward `session_attached`, and affects
attachment-dependent behavior such as `destroy-unattached`. Closing the last
attached client can therefore destroy a session configured with that option.

## What differs between ports

Ports differ in how they read state and report failures:

- **Refreshing state.** Python objects reflect their last read until you call
  `.refresh()`. TypeScript, Swift, and Go also provide snapshots whose
  relationships can be queried without another tmux command.
- **Blocking and async calls.** Python and Java use blocking calls. Rust,
  TypeScript, .NET, and Swift provide async APIs. Go uses ordinary calls with
  contexts for cancellation and deadlines.
- **Failure handling.** Python and .NET raise exceptions. C++ returns
  `expected<T, CommandFailure>`. Some commands have an expected negative answer,
  such as `has-session` when a session is absent; check the method's result
  contract before treating that answer as a failure.

See [Control mode vs one-shot](../transports/) for command costs and connection
behavior.
