Changelog

For instructions on installing the development version of libtmux, refer to development releases.

pip:

$ pip install --user --upgrade --pre libtmux

pipx:

$ pipx install \
    --suffix=@next \
    --pip-args '\--pre' \
    --force \
    'libtmux'

Run the suffixed executable as:

$ libtmux@next [command]

uv:

$ uv add libtmux --prerelease allow

uvx:

$ uvx --from 'libtmux' --prerelease allow python

libtmux 0.63.x (Yet to be released)

Notes on the upcoming release will go here.

Documentation

Cleaner from_env examples (#719)

The rendered examples for Pane.from_env() and its Server, Session, and Window siblings now hide the incidental environment-setup plumbing, so each example leads with the constructor call it demonstrates instead of the socket-path and $TMUX boilerplate needed to run it.

libtmux 0.62.0 (2026-07-12)

libtmux 0.62.0 teaches libtmux objects to locate themselves and to resolve shared windows the way tmux does. Code running inside tmux can now find its own pane, window, session, and server with Pane.from_env() and its siblings, and a window reports every session that holds it through linked_sessions. Point lookups now resolve a linked window to the session and index tmux itself would act on rather than an arbitrary one. The release also folds ObjectDoesNotExist and MultipleObjectsReturned into the LibTmuxException hierarchy — a breaking change for exception handlers, detailed below. See Locating yourself and When one window is in two sessions for the full story.

Breaking changes

Query errors join the libtmux exception hierarchy (#718)

ObjectDoesNotExist and MultipleObjectsReturned now subclass LibTmuxException. Because TmuxObjectDoesNotExist inherits from ObjectDoesNotExist, it now falls under LibTmuxException as well. Previously, a lookup-specific handler could follow the common libtmux handler:

from libtmux import exc

try:
    pane = server.panes.get(pane_id="%0")
except exc.LibTmuxException:
    pane = None
except exc.ObjectDoesNotExist:
    pane = None

Put the more specific handler first:

from libtmux import exc

try:
    pane = server.panes.get(pane_id="%0")
except exc.ObjectDoesNotExist:
    pane = None
except exc.LibTmuxException:
    pane = None

Blanket retry policies for LibTmuxException should exclude ObjectDoesNotExist and MultipleObjectsReturned: they report deterministic missing or ambiguous lookups, not transient tmux failures.

What’s new

Find where you are running (#714)

Code running inside tmux — a script in a split, a hook, a test harness, an agent — can now ask libtmux where it is. Pane.from_env() returns the pane the calling process is running in, and Server.from_env(), Session.from_env() and Window.from_env() do the same for the rest of the hierarchy. Each takes an optional environment mapping, so code that locates itself stays testable outside a pane.

The answer stays true as tmux moves things around: it survives a move-window, and for a window linked into several sessions it names the session tmux itself would act on. Outside tmux, or with an environment that does not parse, the family raises NotInsideTmux rather than guessing.

See Locating yourself for the whole story — why the session id tmux exports goes stale, the window that contains you versus the one in front of you, and how to test code that locates itself.

Ask a window which sessions hold it (#718)

linked_sessions lists every Session from which a window is reachable. A typical window returns one session; a linked or grouped window can return several, with each session appearing once even when it holds the same window at multiple indexes.

Use linked_sessions when you need every holder. session follows the session_id recorded on that Window instance; use from_window_id() when you need tmux to resolve a window id afresh. See When one window is in two sessions for the relationship between sessions, indexes, and shared windows.

Fixes

Linked windows resolve to the session tmux would use (#713)

A window can be linked into several sessions at once, and libtmux used to pick one of them by accident — whichever sorted last by name. So Window.from_window_id(), Pane.from_pane_id(), Window.refresh() and Pane.refresh() could change their answer when you renamed a session.

libtmux now lets tmux resolve the object, so a window reports the session tmux itself would act on. For a window in a single session — the ordinary case — nothing changes. For a linked or grouped window, note that tmux picks by activity: the session a window reports can change as focus moves between the sessions holding it, where before it was stable but arbitrary. The lookups also got cheaper: they list one window’s panes or one session’s windows instead of scanning the whole server.

A window linked twice now reports tmux’s index (#718)

tmux lets one session link the same window at multiple indexes. Window.from_window_id() and Window.refresh() now give Window.window_index the index tmux would choose: the current link when that window is current, otherwise the lowest-indexed link. Windows held at one index are unaffected.

Missing and ambiguous lookups explain what happened (#718)

QueryList.get() now names both the lookup and its missing or ambiguous outcome. A missing pane_id="%99" raises ObjectDoesNotExist with No objects found: pane_id='%99'; two matches for pane_id="%0" raise MultipleObjectsReturned with Multiple objects returned (2): pane_id='%0'.

Documentation

libtmux 0.61.0 (2026-07-04)

libtmux 0.61.0 hardens support for the tmux 3.7 patch line. It fixes break_pane() naming broken-out windows libtmux instead of tmux’s own default on tmux 3.7a/3.7b, and adds get_version_str() for the raw tmux version string with its point-release suffix intact. The test suite now also passes against tmux 3.7a and 3.7b.

What’s new

New helper: get_version_str() (#699)

libtmux.common.get_version_str() returns the running tmux version verbatim, keeping the point-release suffix ("3.7a") that get_version() strips for numeric comparison. Reach for it to distinguish patch releases whose behavior differs – for example telling tmux 3.7 from 3.7a.

Fixes

break_pane() keeps tmux’s default window name on 3.7a/3.7b (#699)

On tmux 3.7a/3.7b, breaking a pane into a new window without an explicit window_name left it named libtmux instead of tmux’s own default (typically the running command). break_pane() now keeps that natural name; passing window_name is unaffected.

Development

tmux 3.7a/3.7b test compatibility (#698)

libtmux’s test suite now passes against tmux 3.7a and 3.7b, which CI also exercises. A window-name test had assumed the :/. rejection tmux introduced in 3.7, but tmux reverted it in 3.7a as “overly pernickety” — so the test now checks these names are accepted.

libtmux 0.60.0 (2026-06-28)

libtmux 0.60.0 completes tmux 3.7 feature parity. Building on the 3.7 compatibility shipped in 0.59.0, it adds first-class floating panes via new_pane() and new_pane(), types tmux 3.7’s new server, session, window, and pane options, exposes the new pane format variables on Pane, and wraps tmux 3.7’s new command flags. Every 3.7-only surface is version-gated, so tmux 3.2a-3.6 keep working unchanged. See Floating panes for a guide.

What’s new

Typed tmux 3.7 options (#694)

The option dataclasses now type tmux 3.7’s new options. On the server, get-clipboard; on the session, focus-follows-mouse, message-format and prompt-command-cursor-style; and on the window, the copy-mode line-number options, the tree-mode preview options and the window-pane status formats (of these, tree-mode-preview-format is also pane-scoped). The pane remain-on-exit option gained tmux 3.7’s key value, and pane-active-border-style / pane-border-style (widened to pane scope in 3.7) now type on the pane too.

tmux 3.7 pane format variables (#694)

Pane now exposes tmux 3.7’s new pane format variables: the floating-pane geometry and flags (pane_floating_flag, pane_x, pane_y, pane_z, pane_flags, pane_zoomed_flag), the OSC 9;4 progress report (pane_pb_progress, pane_pb_state), pane_pipe_pid, and the bracket_paste_flag and synchronized_output_flag screen-mode flags. Each is version-gated, so the format template stays clean on tmux 3.2a–3.6.

tmux 3.7 command flags (#694)

New tmux 3.7 flags are exposed on existing wrappers: capture_pane() gains hyperlinks (-H, hyperlink targets only), line_numbers (-L) and line_flags (-F); split() / split() gain empty (-E, an empty pane) plus style/active_border_style/ inactive_border_style (-s/-S/-R), message (-m) and keep (-k, remain-on-exit); kill() gains group (-g, kill the session group); and paste_buffer() gains no_vis (-S, paste raw bytes). On the server, command_prompt() gains no_freeze (-C, don’t freeze panes), list_keys() gains format_ (-F, custom output format), run_shell() accepts trailing args expanded as #{1}/#{2}, and refresh_client() gains request_clipboard (-l, request the terminal clipboard). Each warns and is ignored on tmux < 3.7.

Floating panes (new-pane) (#694)

tmux 3.7’s flagship feature, floating panes, is now reachable through Window.new_pane() and Pane.new_pane(). A floating pane sits above the tiled layout like a popup but behaves like a real pane. Pass width/height to size it and x/y to position it, alongside the usual shell, start_directory, environment, zoom and empty, plus style, active_border_style, inactive_border_style, message and keep (remain-on-exit). The returned Pane reports pane_floating_flag == "1". Requires tmux 3.7+. See Floating panes for a guide.

libtmux 0.59.0 (2026-06-27)

libtmux 0.59.0 adds support for tmux 3.7. tmux 3.7 shipped an upstream regression that crashed the server on break-pane; break_pane() now works around it so breaking and rejoining panes works again, and tmux 3.7 joins the tested version matrix alongside 3.2a-3.6.

Fixes

break-pane no longer crashes the tmux 3.7 server (#693)

tmux 3.7 shipped a regression where break-pane aborts the server with a NULL-pointer dereference whenever a pane is broken out of a window without an explicit name (fixed upstream after the 3.7 release). break_pane() now works around this on tmux 3.7 by always supplying a name and applying the requested one afterwards, so breaking a pane into a new window — and joining it back with join() — work again. Older and post-3.7 tmux are unaffected.

libtmux 0.58.1 (2026-06-16)

libtmux 0.58.1 restores compatibility with pytest 9.1. The bundled pytest plugin no longer aborts at import time, so projects that rely on libtmux’s fixtures can move to the latest pytest without their test suite failing before collection.

Fixes

pytest 9.1 compatibility for the pytest plugin (#687)

libtmux’s pytest plugin (see pytest Plugin) now imports cleanly under pytest 9.1, which began rejecting marks applied to fixture functions. Projects that use libtmux’s fixtures can upgrade to pytest 9.1+ without the plugin aborting before test collection.

libtmux 0.58.0 (2026-05-23)

libtmux 0.58.0 fixes subprocess output decoding on non-UTF-8 locales. Both tmux_cmd and ControlMode now enforce UTF-8 when reading tmux output, matching tmux’s own encoding contract.

Fixes

Subprocess encoding on non-UTF-8 locales (#679)

tmux_cmd and ControlMode now pass encoding="utf-8" to subprocess.Popen, ensuring tmux output is decoded correctly regardless of the system locale. Previously, on non-UTF-8 locales, the FORMAT_SEPARATOR character (U+241E) was corrupted during decoding, causing list accessors (sessions, etc.) to return empty results.

libtmux 0.57.1 (2026-05-18)

Restores the “lenient-by-default” behavior for sessions and clients that was changed in 0.57.0.

Behavioral Changes

Lenient Server.sessions and Server.clients accessors

sessions and clients once again return an empty QueryList when tmux fails for any reason (permission errors, subprocess crashes, etc.).

This reverts a change in 0.57.0 that made these accessors raise LibTmuxException. The restored behavior matches the contract sessions has followed since 0.17.0.

  • Upgrade path: Code that added try/except LibTmuxException blocks around these accessors for 0.57.0 can now remove them.

  • Connectivity checks: If you need to distinguish between “no results” and “tmux is unreachable”, use the explicit is_alive() or raise_if_dead() methods.

Stricter search_* methods

The newer search_sessions(), search_windows(), and search_panes() continue to raise on tmux errors. Since these methods take a caller-supplied filter, a tmux failure is considered a meaningful error signal that should not be swallowed.

libtmux 0.57.0 (2026-05-17)

libtmux 0.57.0 broadens tmux support around attached clients, tmux-native filtering, and format-token fields. Client gives callers a typed object for attached terminals, search_*() methods let tmux return only matching sessions, windows, and panes, and more tmux format tokens are exposed as typed attributes. LibTmuxException now records which tmux subcommand failed, making command errors easier to handle downstream.

Breaking changes

LibTmuxException string form gains a subcommand prefix (#672)

When LibTmuxException is raised from a libtmux method, str(exc) now begins with the originating tmux subcommand name followed by ": ". For example, an error from last_window() used to render as "can't find window" and now renders as "last-window: can't find window".

exc.args[0] still carries the original tmux error text, and the new subcommand attribute exposes the tmux subcommand name as a separate field. raise_if_stderr() is the shared helper that populates both.

The error-payload type changed: exc.args[0] is now str, joined with "\n" when tmux emitted multiple stderr lines. Previously it was list[str].

This is a serialization-format change: code that pattern-matches on str(exc) exactly, anchors a regex with ^ against the old shape, or indexes exc.args[0] element-by-element will no longer match.

# Before
try:
    session.last_window()
except LibTmuxException as exc:
    if str(exc) == "can't find window":
        ...

# After — dispatch on the typed attribute
try:
    session.last_window()
except LibTmuxException as exc:
    if exc.subcommand == "last-window":
        ...

# Or — match against the original tmux error text without the prefix
try:
    session.last_window()
except LibTmuxException as exc:
    if exc.args and exc.args[0] == "can't find window":
        ...

Substring matches ("can't find" in str(exc)) and unanchored re.search patterns continue to work unchanged.

Server.sessions, Server.clients, and Server.search_sessions raise on tmux errors (#672)

Previously, a tmux command failure under sessions, clients, or search_sessions() could return an empty QueryList indistinguishable from “no sessions / no clients attached” or “filter matched nothing”. Those accessors now let LibTmuxException propagate for real tmux failures.

Genuine empty results — a server with no attached clients, or a filter that matched zero sessions — still return an empty QueryList. A missing or not-yet-started tmux server is also still treated as an empty result, preserving the historic contract that a fresh Server can be safely introspected before its daemon is up. Other tmux errors, such as socket permission failures or unsupported flags, now surface.

# Before — silent on tmux failure
if not server.clients:
    log("no clients")  # also runs when tmux itself crashed

# After — distinguish the two cases
try:
    clients = server.clients
except LibTmuxException as exc:
    log(f"list-clients failed: {exc}")
else:
    if not clients:
        log("no clients")

What’s new

Client object and Server.clients accessor (#672)

New Client and clients support tmux’s attached-client model directly. Reads like client.client_readonly and client.client_session work on the client object without dropping down to cmd().

Note that client.session_id / client.window_id / client.pane_id reflect the client’s attached view when the object was read — refresh() re-reads them after the client switches focus. client.client_name is the client’s stable identifier.

For typed access to the live attachment, use attached_session, attached_window, and attached_pane. Each property re-reads the client from list-clients before resolving; if tmux no longer reports that client_name, such as after the client detaches, the property returns None. Otherwise, the returned Session / Window / Pane reflects where the client is attached now, not where it was when the Client was constructed. Direct refresh() and from_client_name() calls still surface missing client lookup errors.

attached_pane follows the attached session’s current window. That can differ from the per-client active pane set by select-pane -P; see attached_pane for the exact behavior.

Server.display_message and Window.display_message (#672)

display_message() and display_message() join the existing display_message(). Server reads like #{version} and #{socket_path} work without a pane handle; window reads (#{window_zoomed_flag}, #{window_active_clients_list}) auto-bind to the window’s id.

All three wrappers surface tmux stderr via :func:warnings.warn rather than dropping it silently. tmux uses stderr for both genuine errors and informational messages on some versions, so the wrappers warn rather than raise; callers that want to escalate can wrap the call in :func:warnings.catch_warnings with filterwarnings("error"). See Migration notes for the escalation pattern.

tmux-native filtering with search_*() (#672)

search_panes(), search_windows(), search_sessions(), and the Session/Window analogues take a filter= kwarg routed to tmux’s -f flag. tmux evaluates the expression and returns only matching objects.

Caveat: tmux silently expands a malformed filter expression to empty, which it treats as false — a typo looks identical to “no matches”. Verify filter syntax against the FORMATS section of tmux(1).

Pane.send_keys(cmd=None, …) flag-only invocation (#672)

send_keys() accepts cmd=None together with reset=True or repeat=N to invoke tmux’s flag-only send-keys -R / send-keys -N <n> form without any trailing key argument.

Server.list_buffers(format_string=, filter=) (#672)

list_buffers() gains format_string (-F) and filter (-f) kwargs. Callers can ask tmux to return selected fields (e.g. "#{buffer_name}") or only buffers matching an expression — same bad-filter caveat as the search_* methods.

Server.run_shell(cwd=, show_stderr=) (#672)

run_shell() gains cwd (-c) to set the shell command’s working directory and show_stderr (-E) to merge the command’s stderr into the captured output. Both kwargs are version-gated; older tmux warns and ignores the flag instead of erroring.

Pane.capture_pane(pending=True) (#672)

capture_pane() gains a pending kwarg that returns bytes tmux has read from the pane but not yet committed to the terminal — useful for diagnosing programs whose output stalls mid-sequence.

More format-token fields on tmux objects (#672)

libtmux now asks each list-* subcommand for the format tokens that make sense for that object and tmux version. Tokens the running tmux does not support stay None instead of making the listing fail.

Pane, Window, Session, and Client expose more typed attributes for pane state (pane_dead, pane_in_mode, pane_marked, pane_synchronized, pane_path, pane_pipe), window state (window_zoomed_flag, window_silence_flag, window_flags), session state (session_marked), and client state (client_session, client_readonly, client_termtype). Some fields describe the active child object tmux reports with the row: for example, session.pane_id is the active pane in the session’s current window, not a separate “session pane.” See Format-token fields for details.

Fixes

  • reset() now clears pane scrollback. In 0.56.0 the history clear silently no-op’d, leaving the scrollback intact (#650).

Documentation

  • New API page: Clients.

  • New Format-token fields topic explains why some fields describe an active child object, such as session.pane_id reflecting the active pane in the session’s current window (#672).

libtmux 0.56.0 (2026-05-10)

libtmux 0.56.0 is the tmux command-parity release. It adds more than 50 commands across Server, Session, Window, and Pane, filling in many commands that previously required raw cmd() calls. It also adds attached-client test support so interactive tmux commands can be covered in headless test suites.

What’s new

Interactive tmux commands are now scriptable (#653)

libtmux now exposes Python commands for tmux that normally depend on an attached client: display_popup(), display_menu(), command_prompt(), confirm_before(), detach_client(), detach_client(), detach_all_clients(), display_panes(), choose_buffer(), choose_client(), and choose_tree().

The detach-client API is split by the same scopes tmux actually honors: detach_client() maps to tmux detach-client -s <session_id>, detach_client() maps to tmux detach-client [-t <client>], and detach_all_clients() maps to tmux detach-client -a [-t <keep>]. This keeps each method to one tmux flag group and one subprocess call.

tmux buffer I/O has first-class support (#653)

Named tmux buffers can now be used from libtmux without hand-built commands. set_buffer(), show_buffer(), delete_buffer(), save_buffer(), load_buffer(), list_buffers(), and paste_buffer() cover the common clipboard, capture, and inter-process handoff workflows.

Server commands cover key bindings, clients, shell execution, and access (#653)

Server gains support for key-binding inspection and mutation (bind_key(), unbind_key(), list_keys(), list_commands()), shell/config execution (run_shell(), if_shell(), source_file()), and client/server control (list_clients(), start_server(), lock_server(), lock_client(), refresh_client(), suspend_client(), server_access(), show_messages(), show_prompt_history(), clear_prompt_history()). Session also gains lock_session(), and Pane gains send_prefix().

Windows and panes can be rearranged through the object API (#653)

Window-level operations now include swap(), link(), unlink(), respawn(), last_pane(), next_layout(), previous_layout(), and rotate(). Pane-level operations now include swap(), join(), break_pane(), move(), pipe(), clear_history(), respawn(), copy_mode(), clock_mode(), customize_mode(), and find_window().

Navigation helpers fill in the surrounding topology: wait_for(), last_window(), next_window(), and previous_window().

Improvements (#653)

Several established methods now surface tmux flags that were previously only available by dropping to raw commands. Highlights include send_keys() (literal, hex_keys, key_name, expand_formats, target_client), split() (percentage), capture_pane() (alternate_screen, quiet, buffer output), and display_message() (formatting, delay, notify, verbose, and style/update controls).

Window/session/server additions include extra flags on move_window(), select_layout(), new_session(), new_window(), set_environment(), and show_options().

Attached-client tests are available through control_mode (#653)

The control_mode fixture starts a real tmux -C client attached to the test session. Downstream test suites can exercise commands such as display_popup(), detach_client(), command_prompt(), and confirm_before() without requiring an interactive TTY. The fixture is exported by libtmux.pytest_plugin.

Fixes

Window.move_window() refreshes moved windows (#653)

move_window() now refreshes the moved Window after tmux completes the move. Code that reads attributes after a relative or cross-session move no longer needs a manual refresh() call to avoid stale state.

Documentation

gp-sphinx docs stack moves to the Vite-backed theme path (#666)

The documentation stack now uses gp-furo-theme, a Tailwind v4 respin of Furo, with sphinx-vite-builder owning theme asset builds. This picks up the shared gp-sphinx documentation surface used by sibling projects.

Tests

“No server” tests no longer depend on hardcoded sockets (#665)

test_no_server_* and test_raise_if_dead_no_server_raises now use the server fixture for unique socket names and finalizer cleanup. The tests no longer fail just because a stale tmux daemon survived at one of the old hardcoded socket paths. Fixes #664.

Development

tmux 3.7 is within the known-version range (#653)

TMUX_MAX_VERSION is now "3.7", enabling support and tests for version-gated tmux 3.7 flags such as command_prompt() bspace_exit and show_messages() terminals / jobs. Installations on tmux 3.6 and earlier keep their existing behavior.

libtmux 0.55.1 (2026-04-19)

libtmux 0.55.1 is a documentation and test-isolation release. It makes the pytest plugin’s server cleanup more robust, documents fixtures as first-class API objects, and brings the docs site onto the shared gp-sphinx visual stack.

What’s new

pytest fixtures have generated API reference pages (#656)

The docs now render pytest fixtures with autodoc-style directives for individual fixtures, bulk fixture listings, and a fixture index. Fixture pages show scope, kind, factory metadata, dependencies, generated usage examples, and responsive badge styling through the gp-sphinx fixture extension.

Fixes

pytest plugin server cleanup removes stale socket files (#661)

The server and TestServer finalizers now unlink tmux socket files under /tmp/tmux-<uid>/ after killing the server. This prevents long-lived development machines from accumulating stale libtmux_test* sockets that can break later test runs. Fixes #660.

session_params fixture docs report the right return type (#656)

The session_params fixture docstring now describes the value pytest actually injects.

Documentation

API docs adopt the gp-sphinx presentation stack (#658, #659)

API pages pick up gp-sphinx card layouts, badges, MyST-aware cross references, argparse-label fixes, IBM Plex typography, and the 0.0.1a8 docs-stack bump.

Development

types-docutils is available for type checking (#656)

The dev dependency set now includes types-docutils, keeping the fixture-docs extension visible to mypy.

libtmux 0.55.0 (2026-03-07)

libtmux 0.55.0 improves pane naming, custom tmux binary support, and command diagnostics. The release is useful for projects that run against alternate tmux builds or need clearer subprocess logging.

What’s new

Pane titles can be set and read through short aliases (#636)

set_title() wraps select-pane -T, and title is a short alias for pane_title.

pane.set_title("my-worker")
pane.pane_title
# 'my-worker'
pane.title
# 'my-worker'

The pane_title tmux format variable is now included in libtmux format queries.

Server can use an explicit tmux binary (#636)

Server accepts tmux_bin for alternate binaries such as wemux, byobu, or locally built tmux checkouts.

server = Server(socket_name="myserver", tmux_bin="/usr/local/bin/tmux-next")

The binary path flows through cmd(), raise_if_dead(), fetch_objs(), version checks such as has_version() and has_gte_version(), and option/hook scope guards. Child objects inherit it automatically. When tmux_bin is omitted, command execution falls back to shutil.which("tmux").

tmux commands log before execution (#636)

tmux_cmd() logs the full command line at DEBUG before running it, complementing the existing post-execution output logging and giving operators a better diagnostic trail.

Fixes

Invalid tmux_bin paths raise TmuxCommandNotFound (#636)

Passing a missing binary path now raises TmuxCommandNotFound consistently in both tmux_cmd() and raise_if_dead(), instead of leaking a raw FileNotFoundError.

libtmux 0.54.0 (2026-03-07)

libtmux 0.54.0 adds structured lifecycle logging and tightens failure handling for important object operations. Applications can now filter logs by stable tmux context fields instead of parsing message text.

What’s new

Lifecycle operations emit structured log records (#637)

Create, kill, rename, split, and command-execution paths now log with stable extra keys such as tmux_subcommand, tmux_session, tmux_window, tmux_pane, and tmux_target. The library also installs a NullHandler, uses lazy %s logging, guards heavier debug data, and removes ad-hoc stack printing.

Fixes

Window.rename_window() now propagates tmux failures (#637)

rename_window() no longer catches and logs every exception. tmux errors now surface to callers like the rest of the command API.

Server.kill() handles expected dead-server states (#637)

kill() now captures stderr, ignores expected “no server running” style states, and raises for unexpected tmux errors.

Server.new_session(kill_session=True) checks failed cleanup (#637)

If the pre-create kill-session step fails, new_session() now raises LibTmuxException instead of continuing as though the old session had been removed.

libtmux 0.53.1 (2026-02-18)

libtmux 0.53.1 fixes a session-creation race and moves the developer command surface from Make to Just.

Fixes

Server.new_session() no longer races its own initialization query (#625)

new_session() now parses all required session fields from the tmux new-session -P output instead of creating the session and then immediately querying list-sessions. That removes a race that could raise TmuxObjectDoesNotExist in PyInstaller, Python 3.13+, Docker, and other slower-startup environments. Fixes #624. Thanks @neubig.

Documentation

Documentation publishing uses GitHub OIDC

The docs deployment path moved to GitHub OIDC and AWS CLI credentials.

Development

Developer tasks use just (#617)

The project moved from Makefile to justfile, and docs now reference the just command names.

libtmux 0.53.0 (2025-12-14)

libtmux 0.53.0 narrows the semantics of interactive attachment and fixes a shutdown edge case around attached sessions.

Breaking changes

Session.attach() no longer refreshes after returning (#616)

attach() no longer calls refresh() after attach-session returns. The tmux command is interactive and blocking, so arbitrary state may change while the user is attached. Code that needs fresh state after attaching should call refresh() explicitly.

Fixes

Killing the attached session no longer breaks Session.attach() (#616)

attach() no longer raises TmuxObjectDoesNotExist when the attached session is killed before the user detaches.

libtmux 0.52.1 (2025-12-07)

libtmux 0.52.1 hardens package publishing.

Development

PyPI publishing uses Trusted Publisher (#615)

PyPI releases now use OIDC-based Trusted Publisher instead of API tokens, enabling attestations and reducing long-lived secret exposure.

libtmux 0.52.0 (2025-12-07)

libtmux 0.52.0 expands pane capture so applications can preserve more of the terminal’s rendered output.

What’s new

Pane.capture_pane() exposes more capture-pane flags (#614)

capture_pane() now supports escape_sequences, escape_non_printable, join_wrapped, preserve_trailing, and trim_trailing.

Parameter

tmux flag

Description

escape_sequences

-e

Include ANSI escape sequences.

escape_non_printable

-C

Escape non-printable characters as octal.

join_wrapped

-J

Join wrapped lines back together.

preserve_trailing

-N

Preserve trailing spaces.

trim_trailing

-T

Trim trailing empty positions on tmux 3.4+.

pane.send_keys('printf "\\033[31mRED\\033[0m"', enter=True)
output = pane.capture_pane(escape_sequences=True)

libtmux 0.51.0 (2025-12-06)

libtmux 0.51.0 turns the long-running 0.16-0.33 deprecation period into hard errors for the oldest API spellings. The migration target is the modern object attribute and QueryList interface documented in Migration notes.

Breaking changes

Legacy API methods now raise DeprecatedError (#611)

APIs deprecated in earlier releases now raise DeprecatedError instead of emitting DeprecationWarning.

Deprecated API

Replacement

Deprecated

Raises

Note

kill_server()

kill()

0.30.0

0.51.0

Server

attach_session(), kill_session()

attach(), kill()

0.30.0

0.51.0

Session

select_window(), kill_window(), split_window()

select(), kill(), split()

0.30.0 / 0.33.0

0.51.0

Window

resize_pane(), select_pane(), split_window()

resize(), select(), split()

0.28.0 / 0.30.0 / 0.33.0

0.51.0

Pane

attached_window, attached_pane

active_window, active_pane / active_pane

0.31.0

0.51.0

Session / Window

list_*(), _list_*(), _update_*(), children, where(), find_where(), get_by_id()

sessions / windows / panes with filter() / get()

0.16.0 / 0.17.0

0.51.0

Query helpers

Dict-style access (obj["key"], obj.get(...))

Attribute access, such as window_name

0.17.0

0.51.0

All tmux objects

The 0.50.0 option/hook deprecations remain soft warnings for now:

Deprecated API

Replacement

Deprecated

Note

set_window_option(), show_window_option(), show_window_options()

set_option(), show_option(), show_options()

0.50.0

Window

g option parameter

global_ on set_option(), show_option(), show_options()

0.50.0

Options and hooks

libtmux 0.50.1 (2025-12-06)

libtmux 0.50.1 is a documentation repair release for the 0.50 option and hook API.

Documentation

API documentation anchors and return types were cleaned up (#612)

The docs now use normalized headings and Sphinx module directives for more stable anchors and indexes. Type-hints configuration was adjusted to avoid RST indentation problems and forward-reference warnings, and capture_pane() / display_message() now document their list-returning behavior correctly.

libtmux 0.50.0 (2025-11-30)

libtmux 0.50.0 is the options and hooks release. It adds one typed API for reading and writing tmux options across every object type, adds programmatic hook management, and introduces an indexed container for tmux’s sparse option arrays.

Breaking changes

Window option aliases are deprecated (#516)

The window-specific option helpers remain available but now emit DeprecationWarning. Use the shared option API instead.

Deprecated

Replacement

Window.set_window_option()

set_option()

Window.show_window_option()

show_option()

Window.show_window_options()

show_options()

window.set_window_option("automatic-rename", "on")
# DeprecationWarning: Window.set_window_option() is deprecated

window.set_option("automatic-rename", True)

What’s new

Options share one API across Server, Session, Window, and Pane (#516)

OptionsMixin gives Server, Session, Window, and Pane the same show_options(), show_option(), set_option(), and unset_option() methods.

session.show_option("base-index")
window.set_option("automatic-rename", True)
window.unset_option("automatic-rename")

set_option() supports tmux flags for format expansion, unsetting, global scope, child-pane cleanup, overwrite prevention, warning suppression, and append mode.

Hooks are manageable from Python (#516)

HooksMixin adds hook operations across the tmux object hierarchy: set, show, list, unset, run, and bulk set indexed hook values.

session.set_hook("session-renamed", 'display-message "Renamed!"')
session.show_hook("session-renamed")
session.unset_hook("session-renamed")

Sparse tmux arrays have a Python container (#516)

SparseArray preserves gaps in tmux arrays such as command-alias[0], command-alias[99], and terminal-features[0].

Development

tmux 3.2 is the baseline for options and hooks (#516)

The options and hooks work relies on tmux 3.2+ behavior. Hook scope flags for windows and panes require tmux 3.2+, client-active and window-resized hooks require tmux 3.3+, and pane-title-changed requires tmux 3.5+.

libtmux 0.49.0 (2025-11-29)

libtmux 0.49.0 completes the tmux 3.2 baseline transition announced in 0.48.0.

Breaking changes

tmux 1.8 through 3.1c support was removed (#608)

TMUX_MIN_VERSION is now tmux 3.2a. The TMUX_SOFT_MIN_VERSION compatibility constant, its warning path, and older version guards were removed. Users who need older tmux releases should stay on libtmux 0.48.x.

libtmux 0.48.0 (2025-11-28)

libtmux 0.48.0 starts the tmux 3.2 baseline transition and adds tmux 3.6 to the compatibility grid.

Breaking changes

tmux below 3.2a is deprecated (#606)

tmux versions below 3.2a emit FutureWarning on first use. Set LIBTMUX_SUPPRESS_VERSION_WARNING=1 to silence the transition warning. 0.48.x is the final line intended to support tmux below 3.2a.

What’s new

tmux 3.6 is covered in tests (#607)

The test grid now includes tmux 3.6, and TMUX_MAX_VERSION was raised from 3.4 to 3.6.

Development

TMUX_SOFT_MIN_VERSION marks the transition floor (#606)

The temporary soft-minimum constant records tmux 3.2a as the deprecation threshold for the 0.48.x compatibility window.

libtmux 0.47.0 (2025-11-01)

libtmux 0.47.0 moves the supported Python baseline forward.

Breaking changes

Python 3.9 support was dropped (#602)

Python 3.10 is now the minimum supported Python version. Python 3.9 reached end of life on October 31, 2025; see the Python release status and PEP 596 for the upstream timeline.

Development

Python 3.14 is in the test matrix (#601)

The CI matrix now includes Python 3.14.

libtmux 0.46.2 (2025-05-26)

libtmux 0.46.2 broadens path handling for start directories.

What’s new

Start-directory arguments accept path-like objects (#596, #597, #598)

new_session(), new_window(), split(), split(), and their compatibility aliases accept os.PathLike values in addition to strings. Thanks @Data5tream for the initial work.

libtmux 0.46.1 (2025-03-16)

libtmux 0.46.1 is a maintenance release for the 0.46.x line.

Documentation

Pane.send_keys typo fixed (#593)

The send_keys() documentation had a typo fixed. Thanks @subbyte.

libtmux 0.46.0 (2025-02-25)

libtmux 0.46.0 finishes the libtmux.test helper split by removing root-level imports.

Breaking changes

Root imports from libtmux.test were removed (#580)

Import test helpers from their focused modules.

# Before 0.46.0
from libtmux.test import namer

# From 0.46.0 onward
from libtmux.test.random import namer
# Before 0.46.0
from libtmux.test import RETRY_INTERVAL_SECONDS

# From 0.46.0 onward
from libtmux.test.constants import RETRY_INTERVAL_SECONDS

Development

Test helpers gained more coverage (#580)

The test-helper modules gained stronger coverage for environment cleanup, constants, random-name helpers, docstrings, and coverage markers.

libtmux 0.45.0 (2025-02-23)

libtmux 0.45.0 splits the historical libtmux.test module into focused helper modules.

Breaking changes

Test helpers moved to focused modules (#578)

Import paths changed from the root libtmux.test module to libtmux.test.constants, libtmux.test.environment, libtmux.test.random, and libtmux.test.temporary.

# Old
from libtmux.test import TEST_SESSION_PREFIX, EnvironmentVarGuard, namer

# New
from libtmux.test.constants import TEST_SESSION_PREFIX
from libtmux.test.environment import EnvironmentVarGuard
from libtmux.test.random import namer

Development

CI checks runtime dependencies (#574)

CI now includes a runtime-dependency check, inspired by @ppentchev’s review comments on #572.

libtmux 0.44.2 (2025-02-17)

libtmux 0.44.2 fixes typing import behavior and cleans up version tests.

Fixes

typing_extensions imports are guarded (#572)

typing_extensions is now imported only when needed for type checking, fixing runtime dependency issues. This continues the #564 work.

Development

Version tests are clearer and more stable (#570)

Version-related tests were consolidated into parametrized fixtures with named cases, and the broken test_window_rename test was repaired.

libtmux 0.44.1 (2025-02-17)

libtmux 0.44.1 is a small packaging fix.

Development

typing_extensions is optional at runtime (#563)

Runtime imports now avoid typing_extensions unless the running Python needs it. Thanks @ppentchev.

libtmux 0.44.0 (2025-02-16)

libtmux 0.44.0 adds context-manager support for tmux objects.

What’s new

Server, Session, Window, and Pane can clean themselves up (#566)

Server, Session, Window, and Pane implement context manager protocols that kill the object on exit.

with Server() as server:
    with server.new_session() as session:
        with session.new_window() as window:
            with window.split() as pane:
                pane.send_keys('echo "Hello"')

libtmux 0.43.0 (2025-02-15)

libtmux 0.43.0 improves server initialization and testing ergonomics.

What’s new

Server initialization can be customized (#565)

Server accepts socket_name_factory and on_init callbacks, making it easier to create multiple servers with unique names and track initialized instances.

TestServer creates isolated tmux servers (#565)

The TestServer fixture creates temporary tmux servers with unique socket names, cleanup, tests, documentation, and doctest namespace support.

Documentation

libtmux 0.42.1 (2024-02-15)

libtmux 0.42.1 repairs a typing import edge case.

Fixes

Self is imported only for type checking (#562)

Tests now import Self behind TYPE_CHECKING, avoiding runtime dependency issues. Thanks @ppentchev.

Development

Python-version-specific typing dependencies are explicit (#564)

The testing and lint groups include typing-extensions for Python versions that need it.

libtmux 0.42.0 (2025-02-02)

libtmux 0.42.0 removes the last Python 2 console conversion helpers.

Fixes

tmux_cmd uses text-mode subprocess output (#560)

tmux_cmd() now uses text=True, deprecating console_to_str() and str_from_console(). The compatibility helpers were removed as Python 2-era artifacts. Fixes #558.

libtmux 0.41.0 (2025-02-02)

libtmux 0.41.0 fixes default-socket representation and continues annotation modernization.

Fixes

Server.__repr__() uses the effective UID (#557)

__repr__() now uses os.geteuid() when constructing the default socket path. Fixes #556. Thanks @lazysegtree.

Documentation

Server.colors docs list valid values (#544)

The colors docstring now documents 88 and 256. Thanks @TravisDart.

Development

Annotation evaluation is deferred (#555)

All Python files now use from __future__ import annotations, and Ruff rules UP006 / UP007 enforce modern annotation syntax.

libtmux 0.40.1 (2024-12-24)

libtmux 0.40.1 fixes environment propagation during session creation.

Fixes

Server.new_session() handles environment variables correctly (#553)

new_session() now passes environment values to new tmux sessions correctly. Thanks @ppentchev.

libtmux 0.40.0 (2024-12-20)

libtmux 0.40.0 is a maintenance release with one naming break and broad lint cleanup.

Breaking changes

_global was renamed to global_

The keyword spelling now follows the Python-safe convention used elsewhere in the API.

Development

Ruff handled a broad lint cleanup (#550)

The codebase was reformatted and lint-fixed with Ruff 0.8.4, including preview and unsafe fixes, and legacy test_select_pane stability was improved (#552).

libtmux 0.39.0 (2024-11-26)

libtmux 0.39.0 moves the Python floor forward.

Breaking changes

Python 3.8 support was dropped (#548)

Python 3.9 became the minimum for this release line. tmuxp 1.48.0 remained the last tmuxp release for Python 3.8.

libtmux 0.38.1 (2024-11-26)

libtmux 0.38.1 keeps Python 3.8 support temporarily.

Development

Minimum Python stayed at 3.8

The project held the Python floor at 3.8 for this patch release.

libtmux 0.38.0 (2024-11-26)

libtmux 0.38.0 changes the project management and build backend stack.

Breaking changes

Package management moved from Poetry to uv (#547)

uv replaced Poetry for project and dependency management.

Builds moved from Poetry to hatchling (#547)

hatchling replaced Poetry as the build backend, following Python packaging guidance.

Documentation

Query-list docstrings were fixed

The docs for ObjectDoesNotExist and MultipleObjectsReturned in the query list internals were corrected.

Development

Ruff modernized more string formatting (#540)

Ruff 0.4.2 applied more f-string modernization across the codebase.

libtmux 0.37.0 (04-21-2024)

libtmux 0.37.0 is a test and maintenance release focused on parallel test runs and flaky-test cleanup.

Development

pytest can run in parallel (#522)

pytest-xdist is available for parallel test runs.

$ py.test -n auto

pytest-watcher can also inherit the option:

$ env PYTEST_ADDOPTS='-n auto' make start

The release also relaxed timing-sensitive retry_until() assertions and made test_capture_pane_start poll for the expected state.

Poetry and docs tooling were refreshed (#522)

Poetry moved from 1.8.1 to 1.8.2, and links that had previously been plain text are now automatically linkified.

libtmux 0.36.0 (2024-03-24)

libtmux 0.36.0 is an automated lint-cleanup release.

Development

Ruff applied aggressive automated fixes (#539)

Ruff 0.3.4 was used to apply lint and format fixes across the codebase, including preview and unsafe fixes.

libtmux 0.35.1 (2024-03-23)

libtmux 0.35.1 fixes attached-session detection.

Fixes

Server.attached_sessions handles multiple clients (#537, #538)

attached_sessions now reports attached sessions correctly when multiple clients are attached. Thanks @patrislav1.

libtmux 0.35.0 (2024-03-17)

libtmux 0.35.0 removes redundant target/index handling.

Breaking changes

Redundant targets and window indexes were removed (#536)

Internal command construction no longer carries duplicate target and window_index values through the codebase.

libtmux 0.34.0 (2024-03-17)

libtmux 0.34.0 clarifies how custom command targets are passed.

Breaking changes

cmd() target overrides are keyword-only (#535)

All object-level cmd() methods require the target= keyword for custom or overridden tmux targets. This avoids confusing tmux command targets with inner shell arguments that may also include -t.

Affected methods include cmd(), cmd(), cmd(), and cmd().

libtmux 0.33.0 (2024-03-17)

libtmux 0.33.0 reshapes session/window creation and pane splitting around clearer direction objects and keyword-only calls.

Breaking changes

Window creation and splitting use modern names (#532, #534)

new_window() learned direction via WindowDirection, and new_window() was added as a shorthand from an existing window’s position. Arguments after the window name are keyword-only following PEP 3102.

split_window() is deprecated in favor of split(), and pane splitting moves from vertical / horizontal booleans to PaneDirection. The split API also gained zoom.

What’s new

Pane edge-position helpers were added (#532)

Pane exposes boolean helpers for pane position within a window: at_left, at_right, at_top, and at_bottom.

Development

Poetry moved to 1.8.1

The development dependency manager was updated to Poetry 1.8.1.

libtmux 0.32.0 (2024-03-01)

libtmux 0.32.0 is a packaging and tooling maintenance release.

Development

Package imports and Ruff were refreshed (#531)

Root package implicit imports were added to __init__.py thanks to @ssbarnea, and Ruff moved from 0.2.2 to 0.3.0.

libtmux 0.31.0 (2024-02-17)

libtmux 0.31.0 cleans up command method signatures and renames attached-object properties to active-object properties.

Breaking changes

cmd() methods were streamlined (#527)

cmd(), cmd(), cmd(), and cmd() now use the command string as the first positional argument and drop unused keyword arguments.

Attached-object names became active-object names (#527)

Session.attached_window, Session.attached_pane, and Window.attached_pane were renamed to active_window, active_pane, and active_pane. The old names were deprecated.

Documentation

Command methods gained docs and doctests (#527)

README and quickstart content now document .cmd() usage, and the command methods gained docstrings and doctests.

Development

Server.attached_windows uses QueryList.filter() (#527)

The implementation now relies on filter().

Post-release

v0.31.0post0 (2024-02-17)

Documentation-only updates followed the main release.

libtmux 0.30.2 (2024-02-16)

libtmux 0.30.2 updates known tmux version bounds.

Development

TMUX_MAX_VERSION moved to 3.4

The known tmux maximum version changed from 3.3 to 3.4.

libtmux 0.30.1 (2024-02-16)

libtmux 0.30.1 aligns tests with the 0.30.0 method renames.

Fixes

pytest plugin tests use current method names

The pytest plugin and test modules were updated to call the renamed 0.30.0 methods.

libtmux 0.30.0 (2024-02-16)

libtmux 0.30.0 continues the modern object-method naming pass and adds pane kill support.

What’s new

Panes can be killed directly

kill() was added.

Creation and split methods gained useful arguments

new_session() gained environment-variable support, and split_window() learned size for row/column counts or percentage values.

Development

Legacy method names were deprecated

Window.select_window, Pane.select_pane, Session.attach_session, Server.kill_server, Session.kill_session, and Window.kill_window were renamed to their shorter modern methods and left behind deprecation warnings.

libtmux 0.29.0 (2024-02-16)

libtmux 0.29.0 prepares users for the method-renaming transition.

Fixes

Deprecation warnings use the standard warning class (#526)

APIs scheduled for deprecation now emit DeprecationWarning, and pytest ignores those expected warnings by default.

libtmux 0.28.1 (2024-02-15)

libtmux 0.28.1 is maintenance for the 0.28 transition.

Documentation

0.28 migration docs were refined

The docs and migration guide were updated for the 0.28.0 behavior changes.

Development

CI actions moved to Node 20

GitHub Actions dependencies were bumped to Node 20-compatible versions.

libtmux 0.28.0 (2024-02-14)

libtmux 0.28.0 changes default attachment behavior and modernizes pane/window resizing.

Breaking changes

New windows and splits are detached by default (#523)

new_window() and split_window() no longer attach/select by default. Pass attach=True to keep the older behavior.

Pane resizing moved to Pane.resize() (#523)

Pane.resize_pane() was renamed to resize(). Directional flags now flow through ResizeAdjustmentDirection, and height, width, and zoom controls are supported.

What’s new

Windows can be resized directly (#523)

resize() was added. If pane resizing was ineffective in older releases, resizing the window first may be the better approach.

Fixes

Refresh and pane listing behavior improved (#523)

refresh(), refresh(), and the internal refresh path now capture more state, and Server.panes lists panes across the server instead of only the attached session.

Development

tmux 3.4 entered the test matrix (#909)

The test matrix gained tmux 3.4, and pytest fixture warnings were fixed (#519).

libtmux 0.27.1 (2024-02-07)

libtmux 0.27.1 repairs source distribution contents.

Development

MIGRATION is included in sdists (#517)

The source distribution now includes the migration guide needed by downstream packagers. Related to #508.

libtmux 0.27.0 (2024-02-07)

libtmux 0.27.0 improves typed collection access.

What’s new

QueryList annotations cover descendant collections (#515)

QueryList typing improved for sessions, windows, and panes, with doctests and pytest coverage ported from libvcs.

libtmux 0.26.0 (2024-02-06)

libtmux 0.26.0 tightens a deprecated lookup signature and strengthens linting.

Breaking changes

Deprecated get_by_id() keyword names became explicit (#514)

The already-deprecated get_by_id() helpers now use object-specific keyword names: session_id, window_id, and pane_id.

Documentation

Docstrings were refreshed (#514)

Several docstrings were corrected and clarified.

Development

Ruff lint coverage expanded (#514)

The project enabled flake8-commas, flake8-builtins, and flake8-errmsg rules through Ruff, and CodeQL moved from an advanced configuration file to GitHub’s default setup.

libtmux 0.25.0 (2023-11-25)

libtmux 0.25.0 makes equality comparisons safer and continues docstring coverage work.

Fixes

Object equality returns False on type mismatch (#505, #510)

__eq__(), __eq__(), __eq__(), and __eq__() now return False instead of raising AssertionError when compared with another type. Thanks @m1guelperez for the window implementation.

Documentation

Docstrings were expanded (#509)

Functions, methods, classes, and packages gained docstrings.

Development

pydocstyle is enforced through Ruff (#509)

CI now includes the pydocstyle rule set.

libtmux 0.24.1 (2023-11-23)

libtmux 0.24.1 removes obsolete packaging files.

Development

Legacy requirements files were removed (#507)

The unused requirements/ directory was removed in favor of pyproject.toml, and gp-libs was added to the test dependency group.

libtmux 0.24.0 (2023-11-19)

libtmux 0.24.0 drops Python 3.7 and moves more configuration into modern project files.

Breaking changes

Python 3.7 support was dropped (#497)

Python 3.7 reached end of life on June 27, 2023. A 0.23.x branch can be kept for limited security maintenance if needed.

Development

pytest and dependency groups moved into pyproject.toml (#499)

pytest configuration moved into pyproject.toml, Poetry moved through the 1.6/1.7 line, and development dependencies now use Poetry dependency groups.

Ruff format replaced Black (#506)

Formatting moved from Black to ruff format, keeping the same style while removing a separate dependency.

CI dependencies were refreshed

dorny/paths-filter and codecov/codecov-action were updated.

libtmux 0.23.2 (2023-09-09)

libtmux 0.23.2 marks the final Python 3.7 cut of the 0.23.x line.

Breaking changes

Python 3.7 is at end of life

This release exists as the final Python 3.7-compatible point before the project moves forward.

libtmux 0.23.1 (2023-09-02)

libtmux 0.23.1 is a typo and lint-rule maintenance release.

Development

typos-cli cleaned up spelling issues

Automated typo fixes were applied with typos-cli. The Ruff ERA / eradicate rule was removed because its false positives were too costly.

libtmux 0.23.0 (2023-08-20)

libtmux 0.23.0 is a Ruff-driven code-quality release.

Development

More Ruff rules were applied (#488)

Additional Ruff rules, including import sorting, were applied by hand and with automated fixes.

Post-release

v0.23.0post0 (2023-08-20)

Code comments missed during the initial Ruff QA pass were repaired.

v0.23.0post1 (2023-08-26)

Additional ERA001 cleanups were applied.

v0.23.0post2 (2023-08-28)

More ERA001 cleanups followed.

libtmux 0.22.2 (2023-08-20)

libtmux 0.22.2 removes an obsolete build dependency.

Development

setuptools is no longer required (#495)

The build system no longer requires setuptools. Related to #493 and #494.

libtmux 0.22.1 (2023-05-28)

libtmux 0.22.1 keeps Black available while Ruff formatting matures.

Development

Black returned as a companion formatter

Black was added back temporarily until Ruff fully replaced it for formatting.

libtmux 0.22.0 (2023-05-27)

libtmux 0.22.0 starts the migration to Ruff for linting, import sorting, and formatting.

Development

Ruff replaces several Python quality tools

Ruff replaces Black, isort, flake8, and several flake8 plugins for the main quality loop. Poetry also moved from 1.4.0 to 1.5.0.

libtmux 0.21.1 (2023-04-07)

libtmux 0.21.1 keeps mypy compatibility current.

Fixes

Skip-default-fields repr typing works with mypy 1.2.0

The repr mixin typing was fixed for mypy 1.2.0.

Development

mypy moved to 1.2.0

The type checker dependency was updated.

libtmux 0.21.0 (2023-01-29)

libtmux 0.21.0 changes the internal separator used for tmux format parsing.

Breaking changes

The format separator changed from | to (#475)

LIBTMUX_TMUX_FORMAT_SEPARATOR now defaults to the record-separator glyph, fixing buffer_sample and similar tmux format values that legitimately contain pipes. Related to #471 and #472.

libtmux 0.20.0 (2023-01-15)

libtmux 0.20.0 improves session sizing and test fixture customization.

What’s new

Session creation accepts dimensions (#469)

new_session() accepts x and y for tmux session size. Thanks @rockandska.

The session_params fixture can override session creation (#470)

session_params is a dictionary consumed directly by the session pytest fixture.

libtmux 0.19.1 (2022-01-07)

libtmux 0.19.1 removes a problematic refresh from window option setting.

Fixes

Window.set_window_option() no longer refreshes (#467)

The compatibility method stopped refreshing after setting a window option, matching downstream tmuxp expectations.

libtmux 0.19.0 (2022-01-07)

libtmux 0.19.0 adds ranged pane capture.

What’s new

Pane.capture_pane() accepts start and end (#465)

capture_pane() can capture a specific line range.

libtmux 0.18.3 (2023-01-07)

libtmux 0.18.3 improves failed-object lookup errors.

Fixes

fetch_objs() reports lookup details (#466)

fetch_objs() now raises lookup errors with details about the failed search.

libtmux 0.18.2 (2022-12-30)

libtmux 0.18.2 fixes default-socket session creation.

Fixes

Server session launch works on the default socket (#857)

Creating a new session on the default socket was repaired.

libtmux 0.18.1 (2022-12-28)

libtmux 0.18.1 is a documentation cleanup release.

Fixes

Window pane docs were corrected

Window.panes docstrings and unused documentation were cleaned up.

libtmux 0.18.0 (2022-12-27)

libtmux 0.18.0 gives servers useful representations and default socket paths.

Breaking changes

Server.__repr__ now reports socket identity

__repr__() reports socket_name or socket_path instead of the default Python object repr.

libtmux 0.17.2 (2022-12-27)

libtmux 0.17.2 continues moving pane listing internals behind deprecation paths.

Development

Server pane-listing internals were deprecated

Server._list_panes and Server._update_panes moved to the deprecated API surface.

libtmux 0.17.1 (2022-12-27)

libtmux 0.17.1 tightens documentation and child-collection deprecations.

Fixes

Child collection deprecation warnings were added

Documentation was fixed, and Server.children, Session.children, and Window.children now warn.

libtmux 0.17.0 (2022-12-26)

libtmux 0.17.0 introduces the modern collection and attribute access model.

Breaking changes

Relationships moved to collection attributes (#426)

Use relation attributes such as windows instead of methods such as session.list_windows() or session._windows().

# 0.16 and earlier
session.find_where({"window_name": my_window})

# 0.17 and later
session.windows.get(window_name=my_window, default=None)

Missing results raise ObjectDoesNotExist; ambiguous results raise MultipleObjectsReturned.

tmux data moved from mapping access to attributes (#426)

Use attributes such as window.id instead of window["id"] or window.get("id"). Optional access can use Python’s getattr().

What’s new

Server liveness helpers were added (#448)

is_alive() and raise_if_dead() report whether the tmux server is available.

Development

sphinx-click was removed

The unused development dependency was dropped.

libtmux 0.16.1 (2022-12-12)

libtmux 0.16.1 removes an unnecessary version-parsing dependency.

Fixes

packaging.version.Version is no longer required (#461)

libtmux now avoids strict packaging version parsing so it does not pin or interfere with unrelated application dependencies.

libtmux 0.16.0 (2022-12-10)

libtmux 0.16.0 removes distutils version parsing and improves environment support for new windows.

Breaking changes

tmux version parsing no longer relies on distutils (#351)

The project vendorizes legacy version handling instead of using distutils.version.LooseVersion, which cannot correctly model tmux versions such as 3.1a.

What’s new

Window and session creation accept environment dictionaries (#453)

split_window() and new_window() can pass environment variables into new tmux processes. Thanks @zappolowski.

libtmux 0.15.10 (2022-11-05)

libtmux 0.15.10 continues shell/environment test stabilization.

Development

Shell-specific test assumptions were reduced (#452, #455)

test_capture_pane and environment tests were made more portable, and more Bash-specific assumptions were removed. Thanks @zappolowski.

libtmux 0.15.9 (2022-10-30)

libtmux 0.15.9 fixes command-not-found behavior and updates Python metadata.

Fixes

tmux_cmd() raises TmuxCommandNotFound correctly (#450)

tmux_cmd() now reports missing tmux binaries through TmuxCommandNotFound.

Development

Python 3.11 support metadata was added (#451)

CI uses Python 3.11, trove classifiers include it, and local version-tooling configuration was updated.

libtmux 0.15.8 (2022-10-02)

libtmux 0.15.8 improves compatibility with tmuxp’s empty window names.

Fixes

Empty window_name is supported in Session.new_window() (#444)

new_window() handles window_name="" more reliably for downstream tmuxp. Thanks @trankchung.

libtmux 0.15.7 (2022-09-23)

libtmux 0.15.7 consolidates coverage configuration.

Development

coverage config moved to pyproject.toml (#443)

The separate .coveragerc file was removed.

libtmux 0.15.6 (2022-09-23)

libtmux 0.15.6 removes an obsolete manifest file.

Development

MANIFEST.in was removed

Poetry’s pyproject.toml include configuration now owns source distribution contents.

libtmux 0.15.5 (2022-09-23)

libtmux 0.15.5 cleans up tmuxp workspace metadata.

Development

.tmuxp-before-script.sh was removed from .tmuxp.yaml

The tmuxp workspace config no longer references that helper.

libtmux 0.15.4 (2022-09-21)

libtmux 0.15.4 fixes packaging and pytest compatibility.

Fixes

Stable pytest imports support downstream packagers (#441, #442)

pytest API imports now use stable paths where possible, helping downstream packages such as Arch.

Development

source distributions include test support files (#441, #442)

.tmuxp-before-script.sh and conftest.py are included in source distributions.

libtmux 0.15.3 (2022-09-20)

libtmux 0.15.3 improves pytest plugin examples and doctest discovery.

Documentation

pytest plugin examples were added (#439, #440)

Examples for the pytest plugin were added, and conftest.py moved to the repo root so README doctests can run without proxying through docs/index.md.

libtmux 0.15.2 (2022-09-17)

libtmux 0.15.2 is a maintenance release for test plugin coverage and CI speed.

Development

pytest plugin tests and CI speedups landed (#423, #428)

The pytest plugin gained initial self-tests, trove classifiers note pytest support, and CI avoids unnecessary package downloads while splitting release work into a separate job.

libtmux 0.15.1 (2022-09-11)

libtmux 0.15.1 is a small packaging and docs cleanup.

Documentation

Quickstart documentation was cleaned up

The quickstart page was simplified.

Development

Packaging groups were cleaned up

Old issue package metadata and an extra package grouping were removed.

libtmux 0.15.0 (2022-09-10)

libtmux 0.15.0 adds the pytest plugin and moves the package into the modern src/ layout.

Breaking changes

common.which() was replaced with shutil.which() (#407)

The project now relies on shutil.which() for executable lookup. Thanks @rocksandska.

tmux_cmd preserves interior empty lines (#405)

tmux_cmd() now strips only trailing empty lines. This better matches capture_pane() output. Fixes #402. Thanks @rockandska.

Source files moved into src/ (#414)

The package adopted the src/ layout.

What’s new

pytest plugin added (#411)

libtmux now ships a pytest plugin for tests that need tmux fixtures.

Documentation

Docs doctests and changelog rendering improved (#410, #412)

Documentation examples were corrected, doctests are exercised through pytest-doctest-docutils, changelog issue references are linkified, and autodoc table-of-contents rendering was repaired.

Development

flake8 plugins were added (#408, #409)

flake8-bugbear and flake8-comprehensions joined the development toolchain.

libtmux 0.14.2 (2022-08-17)

libtmux 0.14.2 completes the new_session() fix started in 0.14.1.

Fixes

Server.new_session() works without session_name (#401)

new_session() no longer passes None as the session name. Fixes #399.

libtmux 0.14.1 (2022-08-17)

libtmux 0.14.1 starts fixing unnamed session creation.

Fixes

Server.new_session() accepts omitted session_name (#400)

new_session() can be called without session_name, although 0.14.2 completed the remaining None handling. Fixes #399.

libtmux 0.14.0 (2022-08-05)

libtmux 0.14.0 changes the send_keys history default and sets up executable doctests.

Breaking changes

Pane.send_keys(suppress_history) defaults to False (#395)

send_keys() no longer suppresses shell history unless asked to do so.

Documentation

Doctest fixtures were introduced (#394)

Initial doctest examples landed, temp_window() was fixed, and pytest config moved so doctests can discover the libtmux fixtures.

libtmux 0.13.0 (2022-08-05)

libtmux 0.13.0 reaches strict mypy compliance and removes older item-lookup shortcuts.

Breaking changes

Individual option/environment item lookups were removed (#390)

Bulk methods such as show_environment() and show_options() now keep their dictionary-returning behavior, while single-key access moves to explicit methods such as getenv() and show_option().

# Before
server.show_environment("DISPLAY")

# After
server.getenv("DISPLAY")
# Before
session.show_options("base-index")

# After
session.show_option("base-index")

libtmux.test.retry() was removed after its 0.12 deprecation period (#393).

What’s new

Typing reached mypy --strict (#383, #392)

Core modules now satisfy strict mypy checks.

Development

A stray legacy name was fixed (#391)

The incorrect findWhere() spelling was corrected.

libtmux 0.12.0 (2022-07-13)

libtmux 0.12.0 restores Python 3.7/3.8 support, expands tmux compatibility, and adds the retry helper that replaced the old test retry API.

What’s new

tmux 3.3a is in the supported range

tmux 3.3a was added to CI, and TMUX_MAX_VERSION moved from 2.4 to 3.3.

retry_until() replaces the old retry helper (#368, #372)

libtmux.test.retry.retry_until() polls a callback until it succeeds or times out, raising WaitTimeout by default. Thanks @categulario.

Documentation

API documentation was reorganized (#367)

The docs gained a renewed logo, split API pages for utilities, exceptions, and test helpers, and new Reference sections for server, session, window, and pane objects.

Development

Python 3.7 and 3.8 returned (#375)

Support for Python 3.7 and 3.8 was restored, tox was removed, and core object relations gained type annotations (#385).

libtmux 0.11.0 (2022-03-10)

libtmux 0.11.0 adds early typing work and documents the format-separator escape hatch.

Compatibility

Python 3.7 and 3.8 support was extended later

This release originally marked Python 3.7/3.8 as ending, but 0.12.0 restored support.

tmux format splitting became configurable (#289, #343)

The internal separator used to split tmux format output is configurable through LIBTMUX_TMUX_FORMAT_SEPARATOR. Thanks @JonathanRaiman and @jagguli.

Documentation

The sidebar and development-release docs were reorganized

The docs gained sectioned navigation and instructions for installing developmental releases.

Development

Basic type annotations were added (#359, #361)

Early annotations, cleanup, and one-time Black formatting landed. Thanks @otherJL0.

libtmux 0.10.3 (2022-01-10)

libtmux 0.10.3 is the first experimental Poetry-built release.

Compatibility

Python 3.6 support was dropped (#344)

Python 3.10 metadata was added, with a note that version constraints still needed more compatibility work.

Development

Poetry build support landed (#347)

The project started using poetry build, moved Poetry to 1.1.12, and added pre-commit configuration. Packagers were directed to #346 for issues.

libtmux 0.10.2 (2021-10-30)

libtmux 0.10.2 updates Poetry-era CI and attached-session handling.

Fixes

Multiple attached sessions are supported (#341, #342)

Server.attached_sessions() no longer assumes only one attached client. Thanks @timoses.

Development

Poetry 1.1 tooling was refreshed (#324, #339)

CI uses Poetry 1.1.7, Python was locked at 3.9 to avoid the dataclasses issue, and docs publishing was repaired.

libtmux 0.10.1 (2021-06-16)

libtmux 0.10.1 updates a window-selection compatibility path.

Fixes

Window.select_window() was updated for #271

The compatibility method picked up the session-target fix.

libtmux 0.10.0 (2021-06-16)

libtmux 0.10.0 moves the changelog to Markdown, fixes window selection, and drops Python 3.5.

Breaking changes

Python 3.5 support was dropped

The supported Python range moved forward.

Fixes

select_window() targets the session ID (#271)

Window selection now passes the session ID to tmux’s -t argument. Thanks @Flowdalic.

Documentation

CHANGES was converted to Markdown (#321)

The changelog moved from reStructuredText to Markdown.

libtmux 0.9.0 (2021-06-14)

libtmux 0.9.0 drops Python 2.7 and updates the Python 3 toolchain.

Breaking changes

Python 2.7 support was dropped (#306)

The codebase moved fully to Python 3 syntax. The CI matrix added tmux 3.2a, and Black moved to 21.6b0 (#312, #314).

Fixes

select_window() targets the session ID (#271)

The session-target fix also appears in this release line.

libtmux 0.8.5 (2020-10-25)

libtmux 0.8.5 improves subprocess interaction, version reporting, and environment tests.

What’s new

Subprocess pipes handle large buffers better (#297)

stdin/stdout/stderr handling was improved for large buffer interaction, fixing #251. Thanks @gil-obradors.

get_libtmux_version() reports tmux-compatible versions (#303)

common.get_libtmux_version was added, docs links were repaired, and duplicate Sphinx module descriptions were removed.

Fixes

Environment tests no longer hang on local values (#266)

Local environment variables no longer cause show-environment tests to pause indefinitely.

libtmux 0.8.4 (2020-10-25)

libtmux 0.8.4 updates split-window support, packaging, docs, and CI.

What’s new

Window.split_window accepts percentages (#234)

Window.split_window can pass percentage sizing. Thanks @jinankjain.

Fixes

Invalid escape warnings were fixed (#289)

Warnings from invalid escape sequences were fixed. Thanks @tirkarthi.

Documentation

Documentation moved to docs/ (#295)

Docs publishing moved to the project’s own action, development instructions were refreshed, and the old doc/ tree moved to docs/.

Development

Poetry and CI were expanded (#295, #296)

More packaging moved to Poetry while retaining setup.py, and CI was updated for Python 2.7 caching and internal PR behavior.

libtmux 0.8.3 (2020-08-16)

libtmux 0.8.3 is a Python warning, packaging, and CI cleanup release.

Fixes

Python deprecation warnings were fixed (#278)

Deprecation warnings were cleaned up. Thanks @d1618033 and Flowdalic.

Development

Packaging and CI moved forward (#293)

project_urls were added, the project moved from Pipfile to Poetry, tmux 3.0 option tests were fixed, option-error comments were cleaned up, and CI moved to GitHub Actions.

libtmux 0.8.2 (2019-06-02)

libtmux 0.8.2 is a packaging and changelog-format release.

Documentation

CHANGES used plain reStructuredText

The changelog was converted to plain reStructuredText.

Development

PyPI metadata and Pipfile constraints were updated

project_urls were added to setup.py, Pipfile constraints were loosened, and Pipfile.lock was added.

libtmux 0.8.1 (2019-01-26)

libtmux 0.8.1 fixes several tmux compatibility gaps and moves docs toward NumPy-style docstrings.

What’s new

Pane capture, display, and literal key support landed (#119, #120, #121)

capture_pane(), display_message(), and literal=True support for send_keys() were added. Thanks @ritiek.

Fixes

Client renaming works on tmux 2.7 BSD/macOS (#117)

Renaming clients on BSD/macOS with tmux 2.7 was repaired.

Unicode commands and next-version support improved (#131, #172)

Unicode command handling was fixed for Python 2 thanks to @myw, and next-X.Y version parsing gained support thanks to @sloria.

Documentation

Docs moved to NumPy-style docstrings

Imports were sorted, sphinxcontrib-napoleon was added, and docstrings moved to NumPy style.

libtmux 0.8.0 (2018-03-11)

libtmux 0.8.0 moves the project to the tmux-python organization and broadens session-start support.

Breaking changes

License and organization changed (#46)

The license changed from BSD to MIT, and the project moved into the tmux-python organization.

What’s new

Server.new_session() can run commands at startup (#103)

new_session() learned how to run commands in the new window on session start. Thanks @grimpy.

Fixes

Server.has_session() uses tmux return codes (#68)

has_session() became more robust by checking tmux’s return code. Thanks @jlargentaye.

Development

Dependencies and CI were refreshed

pytest, Sphinx, Travis, PyPy, and supported Python versions were updated.

libtmux 0.7.8 (2018-03-04)

libtmux 0.7.8 ports tmuxp retry support.

What’s new

retry moved in from tmuxp

The retry helper was ported from tmuxp for shared behavior.

libtmux 0.7.7 (2017-11-10)

libtmux 0.7.7 fixes tmux 2.6 session sizing from inside clients.

Fixes

tmux 2.6 no longer receives unsupported -x / -y

libtmux avoids those flags when running from inside a client on tmux 2.6+.

libtmux 0.7.6 (2017-11-09)

libtmux 0.7.6 repairs layout selection and option ambiguity tests.

Fixes

Window.select_layout can be called without arguments

The layout-selection helper accepts the tmux default path again, and tests were updated for tmux 2.6 option ambiguity behavior.

libtmux 0.7.5 (2017-10-07)

libtmux 0.7.5 is a tmux 2.6 hotfix.

Fixes

tmux 2.6 session creation works

Session creation was patched for tmux 2.6 compatibility.

libtmux 0.7.4 (2017-08-19)

libtmux 0.7.4 fixes command targeting.

Fixes

Commands include session IDs (#65)

tmux commands now include the relevant session id. Thanks @askedrelic.

libtmux 0.7.3 (2017-05-29)

libtmux 0.7.3 records exact-match support limits.

Compatibility

Exact matches require tmux 2.1+

Exact matching is only supported on tmux 2.1 and later.

libtmux 0.7.2 (2017-05-29)

libtmux 0.7.2 adds exact matching to session lookup.

What’s new

Server.has_session supports exact matching

has_session() can check for exact session names.

libtmux 0.7.1 (2017-04-28)

libtmux 0.7.1 improves formatted option handling.

Fixes

Formatted options such as pane-border-status are supported (#37)

Option parsing works better for formatted tmux options. Thanks @kaushalmodi.

libtmux 0.7.0 (2017-04-27)

libtmux 0.7.0 drops Python 2.6, adds tmux 2.4 support, and overhauls option errors and version checks.

Breaking changes

Python 2.6 support was dropped

Python 2.7 became the minimum supported Python version.

Version helper names changed

has_version was renamed to get_version, has_required_tmux_version was renamed to has_minimum_version, and comparison helpers such as has_gt_version, has_gte_version, has_lt_version, and has_lte_version were added.

What’s new

Option errors have a dedicated hierarchy

libtmux.exc.OptionError became the base class for libtmux.exc.InvalidOption, libtmux.exc.AmbiguousOption, and libtmux.exc.UnknownOption.

tmux master and OpenBSD versions are represented explicitly

get_version reports tmux built from master with a -master suffix and OpenBSD base tmux with an -openbsd suffix.

Documentation

Session method docs were improved

Session documentation and option-method exception details were cleaned up.

Development

tmux 2.4, PyPy, and version bounds were added

The release added support for tmux 2.4, PyPy/PyPy3, TMUX_MIN_VERSION, and TMUX_MAX_VERSION.

libtmux 0.6.5 (2017-04-02)

libtmux 0.6.5 improves tmux binary lookup.

What’s new

tmux_cmd can search custom paths

tmux_search_paths and append_env_path were added, and TmuxCommandNotFound reports missing tmux executables.

libtmux 0.6.4 (2017-03-25)

libtmux 0.6.4 adds OpenBSD tmux support.

Compatibility

OpenBSD tmux is supported (#32)

The version and command handling paths now account for OpenBSD tmux.

libtmux 0.6.3 (2017-02-08)

libtmux 0.6.3 supports tmux built from master.

Compatibility

tmux master builds are recognized (#25)

Version handling supports tmux built from unreleased master. Thanks @sloria.

libtmux 0.6.2 (2017-01-19)

libtmux 0.6.2 relaxes version parsing and updates packaging.

Fixes

Loose version parsing handles more tmux versions (#197)

LooseVersion replaced StrictVersion for tmux version checks. Thanks @minijackson.

Documentation

README fixes landed (#21)

The README was corrected. Thanks @huwenchao.

Development

Package pins were maintained with pyup.io

Dependency pin maintenance moved through pyup.io.

libtmux 0.6.1 (2016-12-20)

libtmux 0.6.1 fixes logging, start directories, and tmux 2.3 support.

What’s new

start directories are supported for sessions and panes (#19)

New sessions and panes can receive start_directory. Thanks @gandelman-a.

Fixes

Logger behavior was repaired (#18)

Logging was fixed thanks to @geekli.

Development

tmux 2.3 is officially supported

Tests were fixed and tmux 2.3 support was added.

libtmux 0.6.0 (2016-09-16)

libtmux 0.6.0 validates session names and trims unused attachment parameters.

Fixes

Invalid session names raise errors

tmux session names cannot be empty or contain periods or colons; libtmux now raises for those invalid names.

Development

Unused attach/switch parameters were removed

Unused target_session parameters were removed from Server.attach_session and Server.switch_client.

libtmux 0.5.1 (2016-08-18)

libtmux 0.5.1 fixes missing-tmux logging.

Fixes

Missing tmux in PATH logs clearly (#12)

The logger message for a missing tmux executable was corrected.

libtmux 0.5 (2016-06-15)

libtmux 0.5 improves option errors and documentation.

What’s new

Unknown options and unset valid options are distinct (#8)

libtmux.exc.UnknownOption was added, and valid-but-unset options now return None.

Documentation

Major documentation overhaul (#6)

The documentation was substantially refreshed.

libtmux 0.4.1 (2016-05-23)

libtmux 0.4.1 fixes tmux discovery through PATH.

Fixes

which() reads PATH

tmux lookup now uses os.environ["PATH"]. See https://redd.it/4laeut.

libtmux 0.4.0 (2016-05-23)

libtmux 0.4.0 makes tmux format metadata available as object attributes.

Breaking changes

_TMUX metadata became _info

The internal metadata object was renamed.

What’s new

Session, Window, and Pane expose format fields as attributes

Format-backed properties such as session.name, window.name, pane.current_path, session.id, window.id, pane.id, session.index, window.index, and pane.index are available directly. Attached-session, window, and pane relationships also became properties.

Development

findWhere() became find_where

The old camelCase lookup helper was renamed, and README usage was updated.

libtmux 0.3.0 (2016-05-23)

libtmux 0.3.0 switches the project test runner.

Development

pytest became the test runner

The project moved to pytest.

libtmux 0.1.0 (2016-05-22)

libtmux 0.1.0 is the initial standalone libtmux release.

What’s new

libtmux forked from tmuxp

The library began as a fork from tmuxp.