Architecture¶
When you use libtmux, you work through a hierarchy of typed Python
objects — Server, Session,
Window, and Pane — each a
proxy for the tmux entity it represents. You navigate from one to the
next (a server’s sessions, a session’s windows, a window’s panes), and
every method you call turns into a tmux command directed at that exact
object.
You don’t need anything on this page to use the API; the objects and their methods work out of the box. This is reference material for when you’re curious how libtmux tracks those objects, keeps their identities stable across refreshes, and lays out the code underneath. Skim the first section and stop whenever you’ve seen enough.
Under the hood, libtmux is a typed
abstraction layer built on two tmux primitives: targets (-t), which
direct a command at an individual session, window, or pane, and
FORMATS, the template variables tmux exposes to describe each object’s
properties.
Object hierarchy¶
libtmux mirrors tmux’s object hierarchy as a typed Python ORM, so the parent-child relationships you know from tmux carry over directly into the objects you hold:
Server
├── Session
│ └── Window
│ └── Pane
└── Client (attached view)
Object |
Child |
Parent |
|---|---|---|
None |
||
None |
||
None |
The Session, Window, Pane, and Client classes share a common dataclass
base (Obj) defined in libtmux.neo, which fetches each object’s
fields from tmux; the parent and child links above are plain properties
on each class.
One object breaks the ownership chain: Client is a
view, not a child. Each attached terminal points at the
Session/Window/Pane it is currently displaying, but is not owned by
them — so its view can change the moment a user switches sessions. See
Clients for the view-vs-identity distinction.
Internal identifiers¶
When tmux state changes, libtmux needs a way to recognize that the same
window is still the same window. tmux assigns each session, window, and
pane a unique ID for exactly this, and libtmux stores it as a dataclass
attribute on each object (session_id, window_id, pane_id) to track
objects reliably across state refreshes rather than relying on names or
indexes that shift around.
Core objects¶
These are the five classes you’ll actually hold and call methods on. Each level wraps the tmux commands and format queries for its tier of the hierarchy:
Data flow¶
Every interaction follows the same round-trip: you act on a Python object, libtmux talks to tmux, and the result comes back as more typed objects. Reading state and changing it both cost a tmux call, which is why an object can go stale and why you refresh it rather than trust a cached value indefinitely.
User creates a
Server(connects to a running tmux server)Queries use tmux format strings (
libtmux.constants) to fetch stateResults are parsed into typed Python objects
Mutations dispatch tmux commands via the
cmd()methodObjects refresh state from tmux on demand
Module map¶
The codebase splits along the same hierarchy: one module per tier, plus shared plumbing. The first block is what you import and use day to day; the second is lower-level and mostly of interest to contributors or deeper integrations.
Module |
Role |
|---|---|
|
Server connection and session management |
|
Session operations |
|
Window operations and pane management |
|
Pane I/O and capture |
|
Attached-client view and live-attachment lookup |
Base classes, command execution |
The remaining modules are advanced — reach for them only when the core objects don’t cover your case:
Module |
Role |
|---|---|
|
Modern dataclass-based query interface |
Format string constants |
|
tmux option get/set |
|
tmux hook management |
|
Exception hierarchy |
Naming conventions¶
tmux commands use dashes (new-window). libtmux replaces these with
underscores (new_window) to follow Python naming conventions.