This page describes how the language ports organize their code and where operations live. For the object hierarchy and stable IDs, start with Server, session, window, pane.
Where behavior lives: on the object, or through the serverLink to section
Python, TypeScript, Go, Rust, Java, .NET, and C++ provide operations on session, window, and pane objects. Each object carries its ID and server context. These examples send input, set an option, and kill a pane:
Swift’s Session, Window, and Pane are Sendable value types holding IDs
and state fields. Format-token fields lists their fields.
Perform operations through Server, passing the target value:
The practical effect is that Server is the one thing you hold onto in a
Swift program; a Session or Pane you got back from a snapshot() is
inert data you hand back to the server that produced it, not a handle you
call things on. Every other port’s Server is also where you start, but
Session/Window/Pane stay live actors once you have one.
A generated data table under a hand-written surfaceLink to section
Ports translate object IDs into tmux targets (-t) and read state through
tmux’s FORMATS variables (#{...}). Their field definitions use generated
catalogs, fixed field sets, or captured dictionaries:
| Port | Generated table | Hand-written surface |
|---|---|---|
| Python | libtmux.constants (FORMATS, gated by scope and tmux version) | dataclass fields on Obj (libtmux.neo), None when a gate excludes a token |
| TypeScript | packages/libtmux/src/_generated/format_fields.ts ({ scope, since, token } per row) | camelCase aliases on Pane/Session/Window (packages/libtmux/src/_generated/field_aliases.ts) |
| Go | format_generated.go, option_generated.go (built by internal/generate/formats) | (value, bool) accessor methods: Go’s own “comma ok” idiom for a gate |
| Rust | formats.rs’s per-token macro rows (token, wire name, scope, kind, since version, absent-handling) | typed methods returning Option<T> |
| Java | (typed field accessors generated for the query layer: see Pane_/Session_ in Filtering and queries) | Optional<T> for fields introduced after a port’s tmux floor |
| C++, Swift | fixed field sets; see below | a fixed, curated set of non-optional struct/class fields |
| .NET | a snapshot dictionary read at capture time | typed properties that throw IncompleteSnapshotException for a field the capture didn’t request, rather than gating on tmux version per field |
Swift and C++ expose fixed sets of state fields. Swift includes indices,
dimensions, active state, command, path, and edge flags. C++ declares its fields
in kFields arrays and uses pane->expand("#{...}") for other tokens. See
Format-token fields for optional fields and tokens outside
the fixed sets.
Module layout, by portLink to section
Each port’s own top-level organization, to orient yourself before opening its source:
- Python: one module per tier (
libtmux.server,.session,.window,.pane,.client), pluslibtmux.commonfor shared plumbing,libtmux.neofor the dataclass query layer,libtmux.options/libtmux.hooksas mixins every tier includes, andlibtmux.excfor the exception hierarchy. - TypeScript:
packages/libtmux/src/{server,session,window,pane,client}.tshold the public classes; nearly everything they call into lives under_internal/operations/(one file per concern:pane_io.ts,hooks.ts,options.ts,topology.ts) and_generated/(the format/option/hook catalogs above). Separate packages in the same monorepo cover workspaces (@libtmux/workspace) and an MCP server. - Go: a single
tmuxpackage, split by concern into many files rather than many packages (model.gofor the core structs,lifecycle_kill.go,pane_capture.go,pane_geometry.go,hierarchy.go,plan_server.gofor folded invocations);tmuxqis a separate package for predicate queries over an already-read snapshot (Filtering and queries), andworkspacea separate one again. - Rust:
crates/libtmux/src/{server,session,window,pane}/directories, each split into files by concern (asettings.rsper tier holding that tier’s options-and-hooks methods, matching the pattern in Options and hooks);hooks.rs,options.rs, andformats.rshold the shared, scope-generic machinery those call into. Workspaces and the MCP server are separate crates in the same workspace. - Java:
io.github.libtmuxholdsServer,Session,Window, andPaneasfinalclasses; each exposes its option and hook tables through.options()/.hooks()accessor methods returning a separateOptions/Hooksview scoped to that object, rather than mixing those methods directly into the entity class the way Python and Go do.Session_,Window_, andPane_are a parallel set of typed-field classes that exist only for the query layer. - .NET:
src/LibTmux/gives every entity its own name (Pane.cs,Session.cs, …) but splits each into severalpartial classfiles by concern rather than by inheritance:Pane.Capture.cs,Pane.Input.cs,Pane.Relations.cs,Pane.Scopes.cs,Pane.Topology.cs, and so on all contribute to onePanetype.Options/Hooksare reached through.Options/.Hooksproperties, structurally the same idea as Java’s accessor methods. - C++:
include/libtmux/entities.hppdeclaresSession,Window, andPanetogether as value types (private Rowbases), with their method bodies insrc/rather than the header;server.hpp,options.hpp, andcapabilities.hppare separate headers. A privatetestingcomponent (include/libtmux/testing/) ships separately from the library proper: see Context managers for what it’s for. - Swift:
Sources/LibTmux/Server.swiftis the hub every operation extends;Session.swiftandPane.swiftdeclare the thin value types,Snapshot.swiftholds the relationship queries (Traversal), andOptions.swift,PaneInteraction.swift, andMutations.swiftareextension Serverfiles grouping options/hooks, send/capture, and kill respectively: all reachable only throughServer, per the section above.
Naming conventionsLink to section
Method names follow language conventions: Python, Rust, and C++ use
snake_case; TypeScript, Java, and Swift use camelCase; Go and .NET use
PascalCase. Option and hook names remain tmux’s dash-separated strings, such
as automatic-rename, regardless of the method’s spelling.