Format-token fields

When you work with a libtmux object — Server, Session, Window, Pane, or Client — you get a flat set of typed string attributes that report the object’s current state straight from tmux, mirroring tmux’s built-in FORMATS tokens (pane_id, window_zoomed_flag, session_name, etc.). This is why a single Pane can hand you pane.pane_id, pane.window_id, and pane.session_id without you writing a raw tmux command.

Most of the time you just read these attributes and move on. Not every field holds a value on every object, though: the object’s type and your tmux version decide which fields are populated and which stay None.

Which fields hold a value comes down to two gates:

  1. Scope — which kind of tmux object can provide the token. A pane_* token needs pane context, a session_* token needs session context, and so on.

  2. Version — which tmux release first registered the token in format.c’s static table.

If either gate excludes a token, libtmux leaves the field at None rather than risking a server-side fault on an older tmux. You trade an occasional None check for attribute access that stays safe on every supported version.

Why a field is None

A typed field is None for one of three reasons:

  • Not yet introduced. Older tmux doesn’t know the token at all. pane_dead_signal is None on tmux 3.2a because the token landed in 3.3.

  • Wrong scope for this object. A Client row can report client tokens plus the client’s current session/window/pane. buffer_* tokens never apply to client rows.

  • Live-only token. Some tokens (mouse_*, cursor_*, selection_*) only resolve inside a live event context (key binding, copy-mode, popup) — never in a list-* snapshot. libtmux excludes them from every -F template.

The version map for post-3.2a tokens is small and stable. The following are the tokens libtmux currently gates:

Everything not listed above is safe on every supported tmux (≥ 3.2a). Fields for newer tmux tokens will be added as each supported version is validated.

Active child fields

Reach for session.pane_id and you get a real pane id back, not an error. When tmux lists a parent object, it also reports fields from that parent’s active child — so the pane fields on a session row describe the active pane in the session’s current window.

>>> session = server.new_session()
>>> session.pane_id == session.active_window.active_pane.pane_id
True
>>> session.window_id == session.active_window.window_id
True

The relationship is one-way. A Pane carries window_* and session_* fields for its parents, but a Session does not carry client_* fields because tmux cannot infer one attached client from a session row. The client_* tokens only appear on Client rows returned by clients.

So read session.pane_id as “the active pane of the session’s current window,” not “the session’s pane id.” Treat it as the latter and the value will surprise you the moment the active_window changes.

Inspecting which fields apply

For the rarer cases — contributors, or code that introspects libtmux’s own queries — you can ask, for a given list-* subcommand and tmux version, which tokens libtmux will request. Use libtmux.neo.get_output_format():

>>> from libtmux.neo import get_output_format
>>> fields, _ = get_output_format("list-sessions", "3.6a")
>>> 'session_id' in fields
True
>>> 'pane_id' in fields  # active pane for the listed session
True
>>> 'client_name' in fields  # client fields require list-clients
False

For list-clients, the gate widens to include client_* plus every attached session/window/pane token:

>>> from libtmux.neo import get_output_format
>>> fields, _ = get_output_format("list-clients", "3.6a")
>>> all(t in fields for t in ("client_name", "session_id", "pane_id"))
True

The result is cached per (list_cmd, tmux_version) pair.

tmux version detection

You never call this directly, but it’s worth knowing how the version gate gets its answer. libtmux detects the live tmux version via libtmux.common.get_version() and passes it through to get_output_format whenever it builds a -F template. That lookup is memoized for the process lifetime, as is the raw-string libtmux.common.get_version_str(); the two cache independently, so if you’re swapping the tmux binary mid-test, clear both with libtmux.common.get_version.cache_clear() and get_version_str.cache_clear().

The Project page tracks the project’s minimum tmux version (currently 3.2a); see Compatibility for the full matrix.

See also

  • Properties — API reference for format-field helpers

  • libtmux.neo.get_output_format() — the scope and version filter

  • Clients — attached-client fields and live attachment lookups

  • Compatibility — supported tmux versions