Prerelease This site documents an alpha of libtmux. Its structure, URLs and APIs are subject to change.

Observing a session

Lua
  • Python Unavailable
  • Ruby Unavailable
  • Lua
  • TypeScript Unavailable
  • Rust Unavailable
  • Go Unavailable
  • Java Unavailable
  • .NET Unavailable
  • C++ Unavailable
  • Swift Unavailable

server:observe(session, options) returns a Request for an observation lease. Pass a session handle from that Server’s snapshot or creation result. Concurrent leases for the same session share one owned persistent client. General commands use the process command API.

Opening verifies the pinned daemon before spawning and checks daemon evidence again through the new connection. Every client uses -N; a missing session fails without creating a session or linking a window. Each endpoint owns at most eight observation clients.

The observation offers:

Handles must belong to the same Server. Their copied private identities select targets; overwriting a public reference method cannot redirect observation. Options are copied on submission. Shared connection limits must agree across leases; conflicting options return option_conflict. Separate Server handles have independent pools even when their socket paths match.

Canceling acquisition releases only that caller’s claim. Startup continues for remaining callers; canceling the final claim closes its client. Acquisition during final cleanup returns closing. Await final close() before reopening; a new connection has a distinct generation and requires new watches. A failed startup also retains its pool entry until native cleanup finishes. A new acquisition on a failed shared connection returns its recorded loss error. Close the old leases before opening a fresh connection.

Watch creation installs its local receiver before a same-connection list-panes coverage check. A pane outside that session returns uncovered_pane. Topology changes invalidate reported coverage and close affected pane watches with observation_gap; opening a new watch performs another bounded check. These checks are observations, not a topology transaction. Capture remains a separate operation with no claimed lossless handoff to the stream.

Reading and closingLink to section

watch:next({ timeout = milliseconds }) returns a Request for one event. An absolute monotonic deadline is also supported. Only one read may be pending on a watch; another returns concurrent_read. Canceling a read detaches that waiter and leaves the watch usable. watch:close() is explicit and idempotent. An explicitly closed watch returns nil, nil; connection failure or loss returns nil, err.

Pane events carry kind = "output", pane, data, sequence, generation and server_generation. data is a Lua byte string, including NUL and non-UTF-8 bytes. Extended output also preserves its decimal age and metadata. A sequence identifies ordering within one connection; it does not imply complete pane history or application completion.

Format events carry kind = "format", a typed value, and explicit session_id, window_id, window-link index and pane context. Only catalog field names are accepted. Unknown or unsupported fields fail before writes; caller text cannot introduce a format expression. Registration acknowledgement establishes readiness. Native values arrive on tmux’s one-second sampling timer, so readiness does not wait for the first sample. Native title normalization and other daemon field behavior remain visible in the returned values. Closing a format watch unregisters its subscription.

Bounds and ownershipLink to section

Defaults are 128 pending housekeeping replies, 128 watches, 4 MiB of retained connection data, and 1 MiB or 1,024 events per watch. Each observation claim, shared attachment and public watch consumes a runtime resource slot; the default runtime limit is 128 resources in total. Runtime byte and logical request limits also apply. Watch byte accounting includes event metadata; subscription projections and queued encoded commands are charged before deferred work begins.

Overflow closes the affected watch with observation_gap. Its partial result reports discarded event count and decoded pane-byte count. Other watches and the shared reader continue. Native %pause also invalidates pane continuity. There is no silent drop policy, output coalescing, or claim that tmux pause is lossless backpressure.

The reader parses bounded slices independently of watch consumption. Completion callbacks run through the runtime scheduler; application callbacks must not block the shared Lua event loop. A persistent connection occupies a resource lease, not an active process slot. A pending next uses the separate bounded logical-request lane.

The serialized writer accepts only private housekeeping operations. Arguments are encoded for tmux’s control-line parser. Bootstrap has its own response; subsequent replies use FIFO attribution and matching guard tuples. A request canceled after a possible write leaves a connection-owned tombstone until its reply drains. A write or framing failure closes the connection and fails pending callers. No command or pane input is retried or replayed.

Normal root return closes resource leases after owned requests retire. Endpoint close or generation invalidation also closes its observation clients. Native cleanup waits for exit, pipe closure and pending write callbacks. Post-exit pipe drain is bounded at 250 ms. Explicit close first ends stdin; after 100 ms it signals only the owned client, escalating after another 100 ms. It never signals the tmux daemon or a pane program.

Attachment effectsLink to section

The client uses attach-session -E -f ignore-size,active-pane with an exact session ID. It issues no shared pane/window selection, resizing, detachment or session-environment updates. Native client listings, attachment state, focus hooks and configured lifecycle policy remain observable. Hooks may themselves change state; preservation fixtures use neutral hooks.

focus-events stays unchanged. Disabling it cannot suppress every attachment focus hook, and tmux provides no supported client flag for that guarantee. The transport does not create hidden sessions or change window links. It omits -r: on tmux 3.7 and 3.7c, a read-only observer can make independent process-lane send-keys fail with “client is read-only”. The private writer restricts observation commands without that flag.

Closing an observer removes its attached client. Native policy such as destroy-unattached can then destroy its session. A startup check cannot guarantee lifetime preservation when options or other clients can change. The library does not rewrite borrowed options or retain hidden clients to prevent that policy.

Housekeeping assumes the server’s native command semantics. Aliases and hooks can change even builtin commands; control framing does not authenticate server output. This transport does not enable general command acceleration.

Automatic reconnect and subscription replay are not implemented. Opening a new connection creates a distinct generation; callers must establish new watches and treat the interval between connections as a gap.

Esc

Type to search.