# Traversal

Source: https://libtmux.org/en/tmux/topics/traversal/

> Moving up and down the server/session/window/pane tree, and the two questions that come up once you have more than one object.

Use relationships to move between sessions, windows, and panes. [Server,
session, window, pane](https://libtmux.org/en/tmux/concepts/server-session-window-pane/) explains the
hierarchy and snapshot model. This page covers relationship calls, collection
membership, and object identity.

## Down the hierarchy

List children through the parent object or a captured snapshot. Whether a read
issues another tmux command depends on the API, independently of whether the
call is async; see [Server, session, window,
pane](https://libtmux.org/en/tmux/concepts/server-session-window-pane/).

### Python
Read [`Server.sessions`](<https://libtmux.org/en/py/latest/reference/libtmux-server-sessions/>), then [`Session.windows`](<https://libtmux.org/en/py/latest/reference/libtmux-session-windows/>) and [`Window.panes`](<https://libtmux.org/en/py/latest/reference/libtmux-window-panes/>)
to traverse from the server down to its panes.

### TypeScript
Await [`Server.sessions`](<https://libtmux.org/en/ts/latest/reference/server-server-sessions/>), then read [`Session.windows`](<https://libtmux.org/en/ts/latest/reference/session-session-windows/>) and
[`Window.panes`](<https://libtmux.org/en/ts/latest/reference/window-window-panes/>) from the loaded graph.

### Go
Call [`Server.Sessions`](<https://libtmux.org/en/go/latest/reference/tmux-server-sessions/>) with a context to read the sessions.
[`Session.Windows`](<https://libtmux.org/en/go/latest/reference/tmux-session-windows/>) and [`Window.Panes`](<https://libtmux.org/en/go/latest/reference/tmux-window-panes/>) traverse their captured relationships.

### Rust
Use [`Server.sessions`](<https://libtmux.org/en/rs/latest/reference/server-server-sessions/>), [`Session.windows`](<https://libtmux.org/en/rs/latest/reference/session-session-windows/>), and [`Window.panes`](<https://libtmux.org/en/rs/latest/reference/window-window-panes/>)
to read each level of the hierarchy.

### Java
Use [`Server.sessions`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-server-server-sessions/>), [`Session.windows`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-session-session-windows/>), and [`Window.panes`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-window-window-panes/>)
to read each level of the hierarchy.

### C#
Use [`Server.GetSessionsAsync`](<https://libtmux.org/en/csharp/latest/reference/libtmux-server-getsessionsasync/>), [`Session.GetWindowsAsync`](<https://libtmux.org/en/csharp/latest/reference/libtmux-session-getwindowsasync/>), and
[`Window.GetPanesAsync`](<https://libtmux.org/en/csharp/latest/reference/libtmux-window-getpanesasync/>) to read each level of the hierarchy.

### C++
Use [`Server::sessions`](<https://libtmux.org/en/cxx/latest/reference/libtmux-server-sessions/>), [`Session::windows`](<https://libtmux.org/en/cxx/latest/reference/libtmux-session-windows/>), and [`Window::panes`](<https://libtmux.org/en/cxx/latest/reference/libtmux-window-panes/>)
to read each level of the hierarchy.

### Swift
Read sessions through [`Server.sessions()`](<https://libtmux.org/en/swift/latest/reference/server-sessions()/>). Once you have a
[`Snapshot`](<https://libtmux.org/en/swift/latest/reference/snapshot/>), use its relationship queries, including [`Snapshot.windows(of:)`](<https://libtmux.org/en/swift/latest/reference/snapshot-windows(of-)/>),
to find the windows and panes for those captured objects.

[`session.windows`](<https://libtmux.org/en/ts/latest/reference/session-session-windows/>) and [`window.panes`](<https://libtmux.org/en/ts/latest/reference/window-window-panes/>) read the graph loaded by
[`await server.sessions()`](<https://libtmux.org/en/ts/latest/reference/server-server-sessions/>) without additional tmux commands.
[`server.attached_sessions()`](<https://libtmux.org/en/rs/latest/reference/server-server-attached_sessions/>) lists only sessions with an attached client.

## All panes in a session

Use a session-wide pane collection when the task spans several windows, such
as finding a command or capturing output from every pane. A window linked to
multiple sessions still refers to the same tmux panes. Check whether the API
reads live state or traverses a captured graph before reusing its result.

### Python

[`libtmux.Session.panes`](<https://libtmux.org/en/py/latest/reference/libtmux-session-panes/>) runs a session-scoped `list-panes -s` read. Use it to
list panes across the session's windows without manually listing each window.

### TypeScript

[`session.Session.panes`](<https://libtmux.org/en/ts/latest/reference/session-session-panes/>) returns a [`Selection`](<https://libtmux.org/en/ts/latest/reference/selection-selection/>) from the session's captured
graph. Reading it does not issue another tmux command; refresh the snapshot
when you need newer state.

### Rust

[`session.Session.panes`](<https://libtmux.org/en/rs/latest/reference/session-session-panes/>) performs a live listing and returns a [`Result`](<https://doc.rust-lang.org/std/result/enum.Result.html>) from
the async call. Handle a command failure before using the returned panes.

### Go

[`tmux.Session.Panes`](<https://libtmux.org/en/go/latest/reference/tmux-session-panes/>) reads captured relations without another tmux command.
The relation must have been included in the read that produced the session;
an uncaptured relation does not establish that the session has no panes.

### C#

[`LibTmux.Session.Panes`](<https://libtmux.org/en/csharp/latest/reference/libtmux-session-panes/>) reads the session's captured relations. It does not
issue a tmux command; an incomplete capture may lack the required relation.

### C++

[`libtmux::Session::panes`](<https://libtmux.org/en/cxx/latest/reference/libtmux-session-panes/>) runs a session-scoped `list-panes` command. Inspect
the returned result before traversing the panes.

### Swift

[`Snapshot.panes(of:)`](<https://libtmux.org/en/swift/latest/reference/snapshot-panes(of-)/>) accepts a session or a window. The session overload
traverses the captured graph and deduplicates pane IDs without a tmux read.

### Java

Java has no direct session-wide pane member. Traverse [`Session.windows()`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-session-session-windows/>)
and then [`Window.panes()`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-window-window-panes/>) in the captured relations. Deduplicate pane IDs
when combining results from sessions that may share linked windows.

## Up the hierarchy

Parent lookups may read captured data or query tmux again. Check the method's
read and failure semantics; [Server, session, window,
pane](https://libtmux.org/en/tmux/concepts/server-session-window-pane/) introduces that distinction:

### Python
Read [`Pane.window`](<https://libtmux.org/en/py/latest/reference/libtmux-pane-window/>) for a pane’s window and [`Window.session`](<https://libtmux.org/en/py/latest/reference/libtmux-window-session/>) for
a window’s session.

### TypeScript
[`Pane.window`](<https://libtmux.org/en/ts/latest/reference/pane-pane-window/>) and [`Window.session`](<https://libtmux.org/en/ts/latest/reference/window-window-session/>) are getters that follow the
relationships in the loaded graph.

### Go
[`Pane.Window`](<https://libtmux.org/en/go/latest/reference/tmux-pane-window/>) returns `(Window, bool)` and [`Window.Session`](<https://libtmux.org/en/go/latest/reference/tmux-window-session/>) returns
`(Session, bool)`. Check the boolean before using the parent.

### Rust
[`Pane.window`](<https://libtmux.org/en/rs/latest/reference/pane-pane-window/>) and [`Window.session`](<https://libtmux.org/en/rs/latest/reference/window-window-session/>) asynchronously return
`Result<Option<Window>, Error>` and `Result<Option<Session>, Error>`.
Handle both a command failure and an absent parent.

### Java
Call [`Pane.window`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-pane-pane-window/>) and [`Window.session`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-window-window-session/>) to find an object’s parent.

### C#
Read the [`Pane.Window`](<https://libtmux.org/en/csharp/latest/reference/libtmux-pane-window/>) and [`Window.Session`](<https://libtmux.org/en/csharp/latest/reference/libtmux-window-session/>) properties.

### C++
Call [`Pane::window`](<https://libtmux.org/en/cxx/latest/reference/libtmux-pane-window/>) and [`Window::session`](<https://libtmux.org/en/cxx/latest/reference/libtmux-window-session/>) to find an object’s parent.

### Swift
Use [`Pane.windowID`](<https://libtmux.org/en/swift/latest/reference/pane-windowid/>) to look up the window in a [`Snapshot`](<https://libtmux.org/en/swift/latest/reference/snapshot/>).
Find a window’s sessions through the snapshot’s relationships; a window
does not store a single session field.

Check the boolean from a relationship lookup. It reports whether the relation
was captured, not whether the object still exists in tmux. Use a live read when
current existence matters.
Handle both a command failure and an absent parent in the optional result.
[`.Window`](<https://libtmux.org/en/csharp/latest/reference/libtmux-window/>), [`.Session`](<https://libtmux.org/en/csharp/latest/reference/libtmux-session/>), [`.ActiveWindow`](<https://libtmux.org/en/csharp/latest/reference/libtmux-session-activewindow/>), and `.ActivePane` read captured state
synchronously. They throw [`IncompleteSnapshotException`](<https://libtmux.org/en/csharp/latest/reference/libtmux-incompletesnapshotexception/>) when the capture lacks
the required context.

## One walk, down and back up

List a session's windows, then look up a parent and compare its identity with
the starting object:

```python
session = server.sessions[0]
window = session.windows[0]
pane = window.panes[0]

pane.window.window_id == window.window_id
window.session.session_id == session.session_id
```

```typescript
const session = (await server.sessions())[0];
const window = session.windows[0];
const pane = window.panes[0];

pane.window.id === window.id;
window.session.id === session.id;
```

```go
sessions, err := server.Sessions(ctx)
if err != nil {
    return err
}
for _, session := range sessions {
    windows, captured := session.Windows()
    if !captured {
        return fmt.Errorf("session %s has no captured window relations", session.ID())
    }
    for _, window := range windows {
        back, captured := window.Session()
        if !captured {
            return fmt.Errorf("window %s has no captured session", window.ID())
        }
        fmt.Println(window.ID(), "belongs to session:", back.ID() == session.ID())
    }
}
```

```rust
let sessions = server.sessions().await?;
let session = &sessions[0];
let windows = session.windows().await?;
let window = &windows[0];

let back = window.session().await?; // Result<Option<Session>, Error>
back.is_some_and(|s| s.id() == session.id())
```

```java
Session session = server.sessions().get(0);
Window window = session.windows().get(0);

Session back = window.session();
back.equals(session);
```

```csharp
Session session = (await server.GetSessionsAsync())[0];
Window window = (await session.GetWindowsAsync())[0];

Session back = window.Session; // property, read from the captured snapshot
back.Equals(session);
```

```cpp
auto sessions = server.sessions();       // expected<vector<Session>, CommandFailure>
const auto& session = sessions->at(0);

auto windows = session.windows();        // expected<vector<Window>, CommandFailure>
const auto& window = windows->at(0);

auto back = window.session();            // expected<Session, CommandFailure>
*back == session; // operator== is defined directly on Session/Window/Pane
```

```swift
let sessions = try await server.sessions()
let session = sessions[0]

let snapshot = try await server.snapshot()
let window = snapshot.windows(of: session)[0]
let pane = snapshot.panes(of: window)[0]

// An array, not one Session: link-window can put a window in more than one.
snapshot.sessions(of: window).contains(session)
```

## The active child

The active window and pane identify where untargeted input goes. Use their
accessors or inspect the active flags in a captured snapshot:

### Python
Read [`Session.active_window`](<https://libtmux.org/en/py/latest/reference/libtmux-session-active_window/>) and [`Window.active_pane`](<https://libtmux.org/en/py/latest/reference/libtmux-window-active_pane/>) for the
selected objects.

### TypeScript
Read the [`Session.activeWindow`](<https://libtmux.org/en/ts/latest/reference/session-session-activewindow/>) and [`Window.activePane`](<https://libtmux.org/en/ts/latest/reference/window-window-activepane/>) getters.

### Go
[`Session.ActiveWindow`](<https://libtmux.org/en/go/latest/reference/tmux-session-activewindow/>) returns `(Window, bool)` and
[`Window.ActivePane`](<https://libtmux.org/en/go/latest/reference/tmux-window-activepane/>) returns `(Pane, bool)`. Check the boolean before use.

### Rust
[`Session.active_window`](<https://libtmux.org/en/rs/latest/reference/session-session-active_window/>) and [`Window.active_pane`](<https://libtmux.org/en/rs/latest/reference/window-window-active_pane/>) asynchronously
return `Result<Option<Window>, Error>` and `Result<Option<Pane>, Error>`.
Handle errors and the absence of an active object.

### Java
[`Session.activeWindow`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-session-session-activewindow/>) returns `Optional<Window>`, and
[`Window.activePane`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-window-window-activepane/>) returns `Optional<Pane>`.

### C#
Read the [`Session.ActiveWindow`](<https://libtmux.org/en/csharp/latest/reference/libtmux-session-activewindow/>) and [`Window.ActivePane`](<https://libtmux.org/en/csharp/latest/reference/libtmux-window-activepane/>) properties.

### C++
Call [`Session::active_window`](<https://libtmux.org/en/cxx/latest/reference/libtmux-session-active_window/>) and [`Window::active_pane`](<https://libtmux.org/en/cxx/latest/reference/libtmux-window-active_pane/>).

### Swift
Filter the snapshot’s windows or panes by their `isActive` flag.
For example, inspect the windows returned by [`Snapshot.windows(of:)`](<https://libtmux.org/en/swift/latest/reference/snapshot-windows(of-)/>)
for the selected session.

Filter snapshot children by `isActive`.
[Format-token fields](https://libtmux.org/en/tmux/topics/format-tokens/) describes the underlying
`window_active` and `pane_active` fields.

## Is it in that collection?

Checking membership generally goes through whatever your language uses for
collection membership, since most of these calls already return an ordinary
array, slice, or list:

[`QueryList`](<https://libtmux.org/en/py/latest/reference/libtmux-_internal-query_list-querylist/>) supports [`in`](<https://docs.python.org/3/reference/expressions.html#in>): use `window in session.windows` or
`pane in window.panes`.
Use standard collection membership operations with the object identity
comparison described below.
`Selection<T>` is iterable. Iterate and compare IDs, or spread it into an array
for standard array operations.
Iterate over the slice and compare each object's stable ID, such as [`Pane.ID()`](<https://libtmux.org/en/go/latest/reference/tmux-pane-id/>).
Confirm the objects belong to the same server before comparing IDs.
Iterate over the vector and compare each object's `id()`. Confirm the objects
belong to the same server before comparing IDs.
Use the collection's `contains(where:)` to compare IDs. Confirm the objects
belong to the same server before comparing IDs.

## Is this the same object?

Compare IDs to determine whether two handles refer to the same tmux object on
the same server. Check what handle equality includes before using it as an
identity test:

### Python
Compare [`Window.window_id`](<https://libtmux.org/en/py/latest/reference/libtmux-window-window_id/>) or [`Pane.pane_id`](<https://libtmux.org/en/py/latest/reference/libtmux-pane-pane_id/>) when checking whether
two handles name the same object on the same server.

### TypeScript
Compare the handles’ `id` properties when checking identity on the
same server.

### Go
Compare [`Pane.ID`](<https://libtmux.org/en/go/latest/reference/tmux-pane-id/>) values. [`PaneID`](<https://libtmux.org/en/go/latest/reference/tmux-paneid/>) is a string type and supports
`==`; include the server context when comparing objects from different servers.

### Rust
Compare [`Pane.id`](<https://libtmux.org/en/rs/latest/reference/pane-pane-id/>) values when checking identity on the same server.

### Java
[`Pane.equals`](<https://libtmux.org/en/java/latest/reference/io-github-libtmux-pane-pane-equals/>) compares the server identity and pane ID.

### C#
[`Pane.Equals`](<https://libtmux.org/en/csharp/latest/reference/libtmux-pane-equals/>) compares a generation counter and the pane ID.

### C++
[`Session`](<https://libtmux.org/en/cxx/latest/reference/libtmux-session/>), [`Window`](<https://libtmux.org/en/cxx/latest/reference/libtmux-window/>), and [`Pane`](<https://libtmux.org/en/cxx/latest/reference/libtmux-pane/>) define `operator==` for equality checks.

### Swift
Compare the `id` values when checking identity on the same server.
The equality behavior described below also includes captured state.

**Swift's equality compares captured state.** Compiler-synthesized equality for
[`Session`](<https://libtmux.org/en/swift/latest/reference/session/>), [`Window`](<https://libtmux.org/en/swift/latest/reference/window/>), and [`Pane`](<https://libtmux.org/en/swift/latest/reference/pane/>) compares every stored property, including
dimensions and current command. Two reads can compare unequal even when they
describe the same tmux object. Compare `.id` when checking identity on the same
server.
