For instructions on installing the development version of libtmux, refer to development releases.
pip:
$ pip install --user --upgrade --pre libtmuxpipx:
$ pipx install \
--suffix=@next \
--pip-args '\--pre' \
--force \
'libtmux'
// Usage: libtmux@next [command]uv:
$ uv add libtmux --prerelease allowuvx:
$ uvx --from 'libtmux' --prerelease allow pythonNotes on the upcoming release will go here.
New {meth}~libtmux.Pane.set_title method wraps select-pane -T, and
{attr}~libtmux.Pane.title provides a short alias for
{attr}~libtmux.Pane.pane_title:
pane.set_title("my-worker")
pane.pane_title
# 'my-worker'
pane.title
# 'my-worker'The pane_title format variable is now included in libtmux's format queries
(it was previously excluded).
{class}~libtmux.Server now accepts a tmux_bin parameter to use an
alternative tmux binary (e.g. wemux, byobu, or a custom build):
server = Server(socket_name="myserver", tmux_bin="/usr/local/bin/tmux-next")The path is threaded through {meth}~libtmux.Server.cmd,
{meth}~libtmux.Server.raise_if_dead, {func}~libtmux.neo.fetch_objs,
all version-check functions ({func}~libtmux.common.has_version,
{func}~libtmux.common.has_gte_version, etc.), and hook scope guards in
{class}~libtmux.hooks.HooksMixin. All child objects (Session, Window,
Pane) inherit it automatically.
Falls back to shutil.which("tmux") at execution time when not set.
{class}~libtmux.common.tmux_cmd now logs the full command line at
DEBUG level before execution, complementing the existing post-execution
stdout logging. This enables diagnostic output and is a prerequisite for a
future dry-run mode.
Previously, passing a non-existent binary path raised a raw
FileNotFoundError from subprocess. It now raises
{exc}~libtmux.exc.TmuxCommandNotFound consistently, in both
tmux_cmd and raise_if_dead.
All lifecycle operations (create, kill, rename, split) now emit INFO-level log
records with structured extra context. Every log call includes scalar keys
such as tmux_subcommand, tmux_session, tmux_window, tmux_pane, and
tmux_target for filtering in log aggregators and test assertions via
caplog.records.
- Add
NullHandlerto library__init__.pyper Python logging best practices - Add DEBUG-level structured logs for
tmux_cmdexecution withisEnabledForguards - Replace f-string log formatting with lazy
%sformatting throughout - Replace
traceback.print_stack()calls with properlogger.debug(exc_info=True) - Replace
logger.exception()in options parsing withlogger.warning()andtmux_option_keycontext - Remove unused logger definitions from modules that don't log
Previously rename_window() caught all exceptions and logged them, masking
tmux errors. It now propagates the error, consistent with all other command
methods.
Server.kill() previously discarded the tmux return value. It now checks
stderr, raises on unexpected errors, and silently returns for expected
conditions ("no server running", "error connecting to").
When kill_session=True and the existing session kill fails, new_session()
now raises LibTmuxException with the stderr instead of proceeding silently.
Fixed {exc}~libtmux.exc.TmuxObjectDoesNotExist raised by
{meth}~libtmux.Server.new_session in some environments (e.g. PyInstaller-bundled
binaries, Python 3.13+, Docker containers).
Previously, new_session() ran tmux new-session -P -F#{session_id} to create the
session, then immediately issued a separate list-sessions query to hydrate the
{class}~libtmux.Session object. In certain environments the session was not yet
visible to list-sessions, causing a spurious failure.
The fix expands the -F format string to include all session fields and parses the
new-session -P output directly into the returned Session, eliminating the
follow-up query entirely. This is also one fewer subprocess call per session
creation.
Closes: #624. Thank you @neubig!
- Migrate from
Makefiletojustfilefor running development tasks - Update documentation to reference
justcommands
Move documentation deployment to GitHub OIDC and AWS CLI.
{meth}~libtmux.Session.attach previously called {meth}~libtmux.neo.Obj.refresh
after the attach-session command returned. This was semantically incorrect since
attach-session is a blocking interactive command where session state can change
arbitrarily during attachment.
This was never strictly defined behavior as libtmux abstracts tmux internals away.
Code that relied on the session object being refreshed after attach() should
explicitly call session.refresh() if needed.
Fixed an issue where {meth}~libtmux.Session.attach would raise
{exc}~libtmux.exc.TmuxObjectDoesNotExist when a user killed the session while
attached (e.g., closing all windows) and then detached.
PyPI publishing now uses OIDC-based Trusted Publisher instead of API tokens. This improves security and enables package attestations for supply chain verification.
The {meth}~libtmux.pane.Pane.capture_pane method now supports 5 new parameters
that expose additional tmux capture-pane flags:
| Parameter | tmux Flag | Description |
|---|---|---|
escape_sequences |
-e |
Include ANSI escape sequences (colors, attributes) |
escape_non_printable |
-C |
Escape non-printable chars as octal \xxx |
join_wrapped |
-J |
Join wrapped lines back together |
preserve_trailing |
-N |
Preserve trailing spaces at line ends |
trim_trailing |
-T |
Trim trailing empty positions (tmux 3.4+) |
Capturing colored output:
# Capture with ANSI escape sequences preserved
pane.send_keys('printf "\\033[31mRED\\033[0m"', enter=True)
output = pane.capture_pane(escape_sequences=True)
# Output contains: '\x1b[31mRED\x1b[0m'Joining wrapped lines:
# Long lines that wrap are joined back together
output = pane.capture_pane(join_wrapped=True)Version compatibility:
The trim_trailing parameter requires tmux 3.4+. If used with an older version,
a warning is issued and the flag is ignored. All other parameters work with
libtmux's minimum supported version (tmux 3.2a).
Legacy API methods (deprecated in 0.16-0.33) now raise {exc}~libtmux.exc.DeprecatedError (hard error) instead of emitting {class}DeprecationWarning.
See {doc}migration for full context and examples.
| Deprecated API | Replacement | Deprecated | Raises | Note |
|---|---|---|---|---|
kill_server() |
{meth}~libtmux.Server.kill |
0.30.0 | 0.51.0 | Server |
attach_session(), kill_session() |
{meth}~libtmux.Session.attach, {meth}~libtmux.Session.kill |
0.30.0 | 0.51.0 | Session |
select_window(), kill_window(), split_window() |
{meth}~libtmux.Window.select, {meth}~libtmux.Window.kill, {meth}~libtmux.Window.split |
0.30.0 / 0.33.0 | 0.51.0 | Window |
resize_pane(), select_pane(), split_window() |
{meth}~libtmux.Pane.resize, {meth}~libtmux.Pane.select, {meth}~libtmux.Pane.split |
0.28.0 / 0.30.0 / 0.33.0 | 0.51.0 | Pane |
attached_window, attached_pane |
{attr}~libtmux.Session.active_window, {attr}~libtmux.Session.active_pane / {attr}~libtmux.Window.active_pane |
0.31.0 | 0.51.0 | Session/Window |
list_*(), _list_*(), _update_*(), children, where(), find_where(), get_by_id() |
{attr}~libtmux.Server.sessions / {attr}~libtmux.Session.windows / {attr}~libtmux.Window.panes with {meth}~libtmux.common.QueryList.filter / {meth}~libtmux.common.QueryList.get |
0.16.0 / 0.17.0 | 0.51.0 | Query/filter helpers |
Dict-style access (obj["key"], obj.get(...)) |
Attribute access (e.g., {attr}~libtmux.window.Window.window_name) |
0.17.0 | 0.51.0 | All tmux objects |
The following deprecations from 0.50.0 continue to emit {class}DeprecationWarning (soft deprecation):
| Deprecated API | Replacement | Deprecated | Note |
|---|---|---|---|
set_window_option(), show_window_option(), show_window_options() |
{meth}~libtmux.window.Window.set_option, {meth}~libtmux.window.Window.show_option, {meth}~libtmux.window.Window.show_options |
0.50.0 | Window |
g parameter on options/hooks methods |
global_ on {meth}~libtmux.options.OptionsMixin.set_option, {meth}~libtmux.options.OptionsMixin.show_option, {meth}~libtmux.options.OptionsMixin.show_options |
0.50.0 | Options & hooks |
- Normalize docs headings and Sphinx module directives to fix anchor and index generation issues.
- Tweak Sphinx type-hints configuration to avoid RST indentation conflicts and suppress forward-reference warnings.
- Refresh docstrings and cross-references (pane/window APIs, environment helpers, pytest plugin) for clearer return types and stable anchors.
- Fix incorrect return type annotations for
capture_pane()anddisplay_message()methods (changed fromstr | list[str]tolist[str]- the methods always return a list).
libtmux 0.50 brings a major enhancement to option and hook management. The new
{class}~options.OptionsMixin and {class}~hooks.HooksMixin classes provide a
unified, typed API for managing tmux options and hooks across all object types.
Highlights:
- Unified Options API: New
show_option(),show_options(),set_option(), andunset_option()methods available on Server, Session, Window, and Pane. - Hook Management: Full programmatic control over tmux hooks with support for indexed hook arrays and bulk operations.
- SparseArray: New internal data structure for handling tmux's sparse indexed
arrays (e.g.,
command-alias[0],command-alias[99]). - tmux 3.2+ baseline: Removed support for tmux versions below 3.2a, enabling cleaner code and full hook/option feature support.
All tmux objects now share a consistent options interface through
{class}~options.OptionsMixin:
import libtmux
server = libtmux.Server()
session = server.sessions[0]
window = session.windows[0]
pane = window.panes[0]
# Get all options as a structured dict
session.show_options()
# {'activity-action': 'other', 'base-index': 0, ...}
# Get a single option value
session.show_option('base-index')
# 0
# Set an option
window.set_option('automatic-rename', True)
# Unset an option (revert to default)
window.unset_option('automatic-rename')New methods on Server, Session, Window, and Pane:
| Method | Description |
|---|---|
show_options() |
Get all options as a structured dict |
show_option(name) |
Get a single option value |
set_option(name, value) |
Set an option |
unset_option(name) |
Unset/remove an option |
New parameters for set_option():
| Parameter | tmux flag | Description |
|---|---|---|
_format |
-F |
Expand format strings in value |
unset |
-u |
Unset the option |
global_ |
-g |
Set as global option |
unset_panes |
-U |
Also unset in child panes |
prevent_overwrite |
-o |
Don't overwrite if exists |
suppress_warnings |
-q |
Suppress warnings |
append |
-a |
Append to existing value |
New {class}~hooks.HooksMixin provides programmatic control over tmux hooks:
session = server.sessions[0]
# Set a hook
session.set_hook('session-renamed', 'display-message "Renamed!"')
# Get hook value
session.show_hook('session-renamed')
# 'display-message "Renamed!"'
# Get all hooks
session.show_hooks()
# {'session-renamed': 'display-message "Renamed!"'}
# Remove a hook
session.unset_hook('session-renamed')Indexed hooks and bulk operations:
tmux hooks support multiple values via indices (e.g., session-renamed[0],
session-renamed[1]). The bulk operations API makes this easy:
# Set multiple hooks at once
session.set_hooks('session-renamed', {
0: 'display-message "Hook 0"',
1: 'display-message "Hook 1"',
5: 'run-shell "echo hook 5"',
})Hook methods available on Server, Session, Window, and Pane:
| Method | Description |
|---|---|
set_hook(hook, value) |
Set a hook |
show_hook(hook) |
Get hook value (returns SparseArray for indexed hooks) |
show_hooks() |
Get all hooks |
unset_hook(hook) |
Remove a hook |
run_hook(hook) |
Run a hook immediately |
set_hooks(hook, values) |
Set multiple indexed hooks at once |
tmux uses sparse indexed arrays for options like command-alias[0],
command-alias[99], terminal-features[0]. Python lists can't represent
gaps in indices, so libtmux introduces {class}~_internal.sparse_array.SparseArray:
>>> from libtmux._internal.sparse_array import SparseArray
>>> arr: SparseArray[str] = SparseArray()
>>> arr.add(0, "first")
>>> arr.add(99, "ninety-ninth") # Gap in indices preserved!
>>> arr[0]
'first'
>>> arr[99]
'ninety-ninth'
>>> list(arr.keys())
[0, 99]
>>> list(arr.iter_values()) # Values in index order
['first', 'ninety-ninth']- {class}
~constants.OptionScopeenum:Server,Session,Window,Pane OPTION_SCOPE_FLAG_MAP: Maps scope to tmux flags (-s,-w,-p)HOOK_SCOPE_FLAG_MAP: Maps scope to hook flags
The following methods are deprecated and will be removed in a future release:
| Deprecated | Replacement |
|---|---|
Window.set_window_option() |
Window.set_option() |
Window.show_window_option() |
Window.show_option() |
Window.show_window_options() |
Window.show_options() |
The old methods will emit a {class}DeprecationWarning when called:
window.set_window_option('automatic-rename', 'on')
# DeprecationWarning: Window.set_window_option() is deprecated
# Use the new method instead:
window.set_option('automatic-rename', True)| Feature | Minimum tmux |
|---|---|
| All options/hooks features | 3.2+ |
Window/Pane hook scopes (-w, -p) |
3.2+ |
client-active, window-resized hooks |
3.3+ |
pane-title-changed hook |
3.5+ |
Support for tmux versions below 3.2a has been removed. This completes the deprecation announced in v0.48.0.
- Minimum tmux version is now 3.2a (
TMUX_MIN_VERSION) - Removed
TMUX_SOFT_MIN_VERSIONconstant and deprecation warning system - Removed version guards throughout the codebase
- For users on older tmux, use libtmux v0.48.x
tmux versions below 3.2a are now deprecated. libtmux 0.48.0 will be the last version to support tmux below 3.2. This is to ensure support for hooks, options, and newer tmux features.
A FutureWarning will be emitted on first use. Support for these versions will be removed in a future
release. Set LIBTMUX_SUPPRESS_VERSION_WARNING=1 to suppress the warning.
- Added
TMUX_SOFT_MIN_VERSIONconstant (3.2a) for deprecation threshold (#606)
Added tmux 3.6 to test grid and TMUX_MAX_VERSION 3.4 -> 3.6.
- Drop support for Python 3.9; the new minimum is Python 3.10 (#602). See also:
- Add Python 3.14 to test matrix (#601)
-
Add
StrPathtype support forstart_directoryparameters (#596, #597, #598):Server.new_session: Accept PathLike objects for session start directorySession.new_window: Accept PathLike objects for window start directoryPane.splitandPane.split_window: Accept PathLike objects for pane start directoryWindow.splitandWindow.split_window: Accept PathLike objects for pane start directory- Enables
pathlib.Pathobjects alongside strings for all start directory parameters - Includes comprehensive tests for all parameter types (None, empty string, string paths, PathLike objects)
Thank you @Data5tream for the initial commit in #596!
Maintenance only, no bug fixes or new features
A version branch has been created at v0.46.x, the next release of v0.47.0 may be a few months in waiting (watchers / snapshots are in development in #587).
- Typo fix for
Pane.send_keys(#593), thank you @subbyte!
Root-level of imports from libtmux.test are no longer possible.
# Before 0.46.0
from libtmux.test import namer# From 0.46.0 onward
from libtmux.test.named import namerSame thing with constants:
# Before 0.46.0
from libtmux.test import (
RETRY_INTERVAL_SECONDS,
RETRY_TIMEOUT_SECONDS,
TEST_SESSION_PREFIX
)# From 0.46.0 onward
from libtmux.test.constants import (
RETRY_INTERVAL_SECONDS,
RETRY_TIMEOUT_SECONDS,
TEST_SESSION_PREFIX
)Several improvements to the test helper modules:
- Enhanced
EnvironmentVarGuardinlibtmux.test.environmentto better handle variable cleanup - Added comprehensive test suites for test constants and environment utilities
- Improved docstrings and examples in
libtmux.test.randomwith test coverage annotations - Fixed potential issues with environment variable handling during tests
- Added proper coverage markers to exclude type checking blocks from coverage reports
Test helper functionality has been split into focused modules (#578):
libtmux.testmodule split into:libtmux.test.constants: Test-related constants (TEST_SESSION_PREFIX, etc.)libtmux.test.environment: Environment variable mockinglibtmux.test.random: Random string generation utilitieslibtmux.test.temporary: Temporary session/window management
Breaking: Import paths have changed. Update imports:
# Old (0.44.x and earlier)
from libtmux.test import (
TEST_SESSION_PREFIX,
get_test_session_name,
get_test_window_name,
namer,
temp_session,
temp_window,
EnvironmentVarGuard,
)# New (0.45.0+)
from libtmux.test.constants import TEST_SESSION_PREFIX
from libtmux.test.environment import EnvironmentVarGuard
from libtmux.test.random import get_test_session_name, get_test_window_name, namer
from libtmux.test.temporary import temp_session, temp_window-
CI: Check for runtime dependencies (#574)
Kudos @ppentchev for inspiration on the command (comment).
- Fix
typing_extensionsissue by wrapping it inTYPE_CHECKING, continuation of #564, via #572.
- Improved test organization and coverage in
test_common.py(#570):- Consolidated version-related tests into parametrized fixtures using NamedTuples
- Added comprehensive test cases for various version formats (master, next, OpenBSD, dev, rc)
- Improved test readability with clear test IDs and logical grouping
- Consistent use of pytest parametrize convention across test suite
- Fix broken test for
test_window_rename(#570)
- Types: Only import
typing_extensionswhen necessary, via #563, @ppentchev!
Added context manager support for all major object types:
Server: Automatically kills the server when exiting the contextSession: Automatically kills the session when exiting the contextWindow: Automatically kills the window when exiting the contextPane: Automatically kills the pane when exiting the context
Example usage:
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"')
# Do work with the pane
# Everything is cleaned up automatically when exiting contextsThis makes it easier to write clean, safe code that properly cleans up tmux resources.
Server now accepts 2 new optional params, socket_name_factory and on_init callbacks (#565):
socket_name_factory: Callable that generates unique socket names for new serverson_init: Callback that runs after server initialization- Useful for creating multiple servers with unique names and tracking server instances
- Socket name factory is tried after socket_name, maintaining backward compatibility
Add TestServer pytest fixture for creating temporary tmux servers (#565):
- Creates servers with unique socket names that clean up after themselves
- Useful for testing interactions between multiple tmux servers
- Includes comprehensive test coverage and documentation
- Available in doctest namespace
- Fix links to the "Topics" section
- More docs for "Traversal" Topic (#567)
- tests: Import
Selfin aTYPE_CHECKINGguard to prevent dependency issues. Via #562, Thank you @ppentchev!
- dev dependencies: Include
typing-extensionsfor Python version < 3.11 via thetestingandlintgroups, via #564.
-
tmux_cmd: Migrate to totext=TrueThis deprecates usage of
console_to_str()andstr_from_console().Resolves #558 via #560.
-
compat: Remove
console_to_str()andstr_from_console()These are both deprecated artifacts of libtmux' Python 2.x compatiblity layer.
- {meth}
Server.__repr__(): Use {meth}os.geteuid()for defaultsocket_path. Thank you @lazysegtree! (#557, resolves #556)
Server: Fixcolorsdocstring to note it accepts88or256, Thank you @TravisDart! (via #544)
- Add
from __future__ import annotationsto defer annotation resolution and reduce unnecessary runtime computations during type checking. - Enable Ruff checks for PEP-compliant annotations:
For more details on PEP 563, see: https://peps.python.org/pep-0563/
Server.new_session: Fix handling of environmental variables passed to new sessions. Thank you @ppentchev! (#553)
Maintenance only, no bug fixes or new features
_globalrenamed toglobal_
-
Aggressive automated lint fixes via
ruff(#550)via ruff v0.8.4, all automated lint fixes, including unsafe and previews were applied for Python 3.9:
ruff check --select ALL . --fix --unsafe-fixes --preview --show-fixes; ruff format .
-
Tests: Stability fixes for legacy
test_select_panetest (#552)
Maintenance only, no bug fixes or new features
-
Drop Python 3.8. end of life was October 7th, 2024 (#548)
tmuxp 1.48.0 was the last release for Python 3.8.
The minimum python for tmuxp as of 1.49.0 is Python 3.9
- Keep minimum Python version at 3.8 for now.
uv is the new package and project manager for the project, replacing Poetry.
Build system moved from poetry to hatchling.
-
Code quality: Use f-strings in more places (#540)
via ruff 0.4.2.
- Fix docstrings in
query_listforMultipleObjectsReturnedandObjectDoesNotExist.
Maintenance only, no bug fixes or new features
-
Add
pytest-xdist(PyPI, GitHub) for parallel testing (#522).pytest:
py.test -n autopytest-watcher:
env PYTEST_ADDOPTS='-n auto' make startentr(1):
make watch_test test="-n auto" -
Improve flakey tests:
retry_until()tests: Relax clock inassert(#522).tests/test_pane.py::test_capture_pane_start: Useretry_until()to poll, improve correctness of test (#522).
- Automatically linkify links that were previously only text.
-
poetry: 1.8.1 -> 1.8.2
See also: https://github.com/python-poetry/poetry/blob/1.8.2/CHANGELOG.md
Maintenance only, no bug fixes or new features
-
Aggressive automated lint fixes via
ruff(#539)via ruff v0.3.4, all automated lint fixes, including unsafe and previews were applied:
ruff check --select ALL . --fix --unsafe-fixes --preview --show-fixes; ruff format .
Branches were treated with:
git rebase \ --strategy-option=theirs \ --exec 'poetry run ruff check --select ALL . --fix --unsafe-fixes --preview --show-fixes; poetry run ruff format .; git add src tests; git commit --amend --no-edit' \ origin/master
-
{attr}
Server.attached_sessionsfix for when multiple clients attached, thank you @patrislav1 (#537)- #538 fix to
QueryList.
- #538 fix to
- Eliminate redundant targets /
window_index's across codebase (#536).
Commands: All cmd() methods using custom or overridden targets must use the keyword argument
target. This avoids entanglement with inner shell values that include -t for
other purposes. These methods include:
- {meth}
Server.cmd() - {meth}
Session.cmd() - {meth}
Window.cmd() - {meth}
Pane.cmd()
-
Session.new_window():- Learned
direction, via {class}~libtmux.constants.WindowDirection). - PEP 3102 keyword-only arguments after window name (#534).
- Learned
-
Added {meth}
Window.new_window()shorthand to create window based on that window's position.
-
Window.split_window()to {meth}Window.split()- Deprecate
Window.split_window()
- Deprecate
-
Pane.split_window()to {meth}Pane.split()-
Deprecate
Pane.split_window() -
Learned
direction, via {class}~libtmux.constants.PaneDirection).- Deprecate
verticalandhorizontalin favor ofdirection.
- Deprecate
-
Learned
zoom
-
It's now possible to retrieve the position of a pane in a window via a
bool helper::
- {attr}
Pane.at_left - {attr}
Pane.at_right - {attr}
Pane.at_bottom - {attr}
Pane.at_right
-
poetry: 1.7.1 -> 1.8.1
See also: https://github.com/python-poetry/poetry/blob/1.8.1/CHANGELOG.md
Maintenance only, no bug fixes or new features
- Add implicit imports to
__init__.py(#531), thank you @ssbarnea.
- ruff 0.2.2 -> 0.3.0
- Streamline
{Server,Session,Window,Pane}.cmd(), across all usages to:- Use
cmd: stras first positional - Removed unused keyword arguments
**kwargs
- Use
-
Session.attached_windowrenamed to {meth}Session.active_windowSession.attached_windowdeprecated
-
Session.attached_panerenamed to {meth}Session.active_paneSession.attached_panedeprecated
-
Window.attached_panerenamed to {meth}Window.active_paneWindow.attached_panedeprecated
Server.attached_windowsnow usesQueryList's.filter()
- Document
.cmdin README and quickstart - Add doctests and improve docstrings to
cmd()methods across:- {meth}
Server.cmd() - {meth}
Session.cmd() - {meth}
Window.cmd() - {meth}
Pane.cmd()
- {meth}
- Documentation updates
- Updated
TMUX_MAX_VERSIONfrom 3.3 to 3.4
- Adjusted pytest plugin and test module: Updated to use renamed methods from version 0.30.0.
- Introduced {meth}
Pane.kill()method
Window.select_window()renamed to {meth}Window.select()- Deprecated
Window.select_window()
- Deprecated
Pane.select_pane()renamed to {meth}Pane.select()- Deprecated
Pane.pane_select()
- Deprecated
Session.attach_session()renamed to {meth}Session.attach()- Deprecated
Session.attach_session()
- Deprecated
Server.kill_server()renamed to {meth}Server.kill()- Deprecated
Server.kill_server()
- Deprecated
Session.kill_session()renamed to {meth}Session.kill()- Deprecated
Session.kill_session()
- Deprecated
Window.kill_window()renamed to {meth}Window.kill()- Deprecated
Window.kill_window()
- Deprecated
-
{meth}
Server.new_session(): Support environment variables -
{meth}
Window.split_window(): Supportsizevia-lSupports columns/rows (
size=10) and percentage (size='10%')
- Use {exc}
DeprecationWarningfor APIs set to be deprecated (#526)
- pytest: Ignore {exc}
DeprecationWarningby default (#526)
Maintenance only, no bug fixes or new features
- CI: Bump actions to node 20+ versions
- Refine docs and add migration for v0.28.0
To ensure consistency and principle of least surprise, keep these set to
not use -a unless explicitly specified.
Breaking: {meth}Session.new_window() + {meth}Window.split_window() no longer attaches by default.
- 0.28.0 and greater: Defaults to
attach=False. - 0.27.1 and below: Defaults to
attach=True.
To keep the old behavior in 0.28.0 and beyond, pass attach=True explicitly.
-
Breaking:
Pane.resize_pane()renamed to {meth}Pane.resize()(#523)This convention will be more consistent with {meth}
Window.resize(). -
Breaking: {meth}
Pane.resize()'s params changed (#523)- No longer accepts
-U,-D,-L,-Rdirectly, instead accepts {class}~libtmux.constants.ResizeAdjustmentDirection).
- No longer accepts
-
{meth}
Pane.resize():-
Accept adjustments via
adjustment_directionw/ {class}~libtmux.constants.ResizeAdjustmentDirection+adjustment. -
Learned to accept manual
heightand / orwidth(columns/rows or percentage) -
Zoom (and unzoom)
-
-
{meth}
Window.resize(): Newly added
Tip: If {meth}Pane.resize() was not taking affect <= 0.27.1, try to resize with
{meth}Window.resize() first.
-
{meth}
Window.refresh()and {meth}Pane.refresh(): Refresh more underlying state (#523) -
{meth}
Obj._refresh: Allow passing args (#523)e.g.
-a(all) tolist-panesandlist-windows -
Server.panes: Fix listing of panes (#523)Would list only panes in attached session, rather than all in a server.
- Pane, Window: Improve parsing of option values that return numbers (#520)
Obj._refresh: Allow passinglist_extra_argsto ensurelist-windowsandlist-panescan return more than the target (#523)
- pytest: Fix
usefixturewarning (#519) - ci: Add tmux 3.4 to test matrix (#909)
- Include
MIGRATIONin source distribution tarball (#517, for #508)
-
QueryList typings (#515)
-
This improves the annotations in descendant objects such as:
Server.sessionsSession.windowsWindow.panes
-
Bolster tests (ported from
libvcs): doctests and pytests
-
get_by_id()(already deprecated) keyword argument renamed fromidtoServer.get_by_id(session_id),Session.get_by_id(window_id), andWindow.get_by_id(pane_id)(#514)
- Various docstring fixes and tweaks (#514)
-
Strengthen linting (#514)
-
Add flake8-commas (COM)
-
Add flake8-builtins (A)
-
Add flake8-errmsg (EM)
-
- Move CodeQL from advanced configuration file to GitHub's default
-
Server.__eq__,Session.__eq__,Window.__eq__,Pane.__eq__now returnsFalseinstead of raisingAssertionErrorwhen type mismatches (#505, #510)Thank you @m1guelperez for
Window.__eq__! (#505)
- ci: Add pydocstyle rule to ruff (#509)
- Add docstrings to functions, methods, classes, and packages (#509)
- Remove
requirements/folder, which was unused and deprecated by pyproject.toml (#507) - pyproject: Add
gp-libstotestdependency group
Maintenance only, no bug fixes or new features
- Python 3.7 Dropped (#497)
-
Move pytest configuration to
pyproject.toml(#499) -
Poetry: 1.5.1 -> 1.6.1 (#497), 1.6.1 -> 1.7.0 (direct to trunk)
See also: https://github.com/python-poetry/poetry/blob/1.7.0/CHANGELOG.md
-
Packaging (poetry): Fix development dependencies
Per Poetry's docs on managing dependencies and
poetry check, we had it wrong: Instead of using extras, we should create these:[tool.poetry.group.group-name.dependencies] dev-dependency = "1.0.0"
Which we now do.
-
Move formatting from
blacktoruff format(#506)This retains the same formatting style of
blackwhile eliminating a dev dependency by using our existing rust-basedrufflinter. -
CI: Update action packages to fix warnings
- dorny/paths-filter: 2.7.0 -> 2.11.1
- codecov/codecov-action: 2 -> 3
Maintenance only, no bug fixes or new features
-
Cut last python 3.7 release (EOL was June 27th, 2023)
For security updates, a 0.23.x branch can be maintained for a limited time, if necessary.
Maintenance only, no bug fixes or new features
-
Automated typo fixes from typos-cli:
typos --format brief --write-changes -
ruff: Remove ERA /
eradicatepluginThis rule had too many false positives to trust. Other ruff rules have been beneficial.
Maintenance only, no bug fixes or new features
-
Code quality improved via ruff rules (#488)
This includes fixes made by hand, and with ruff's automated fixes. Despite selecting additional rules, which include import sorting, ruff runs nearly instantaneously when checking the whole codebase.
- Fixes code comments cleaned up by
ruff, but missed in QA. In the future, even when using an automated tool, we will review more thoroughly.
- Fixes for more
ERA001issues.
- Yet more
ERA001fixes.
- build system: Remove
setuptoolsrequirement (#495, in related to #493, #494)
Maintenance only, no bug fixes or new features
-
Add back
blackfor formattingThis is still necessary to accompany
ruff, until it replaces black.
Maintenance only, no bug fixes or new features
-
Move formatting, import sorting, and linting to ruff.
This rust-based checker has dramatically improved performance. Linting and formatting can be done almost instantly.
This change replaces black, isort, flake8 and flake8 plugins.
-
poetry: 1.4.0 -> 1.5.0
See also: https://github.com/python-poetry/poetry/releases/tag/1.5.0
- Update mypy to 1.2.0
- SkipDefaultFieldsReprMixin: Fix typing for mypy 1.2.0
-
Default format separator (
LIBTMUX_TMUX_FORMAT_SEPARATOR):|->␞(#475, in re: #471, #472)Fixes
buffer_samplewith pipes causingfetch_objs()-powered listings to fail unexpectedly.
- Server.new_session: Accept
xandy, thanks @rockandska (#469) - New test fixture:
session_params. The dict is used directly in thesessionpytest fixture (#470)
-
Window.set_window_option(): Remove.refresh()(#467)See also: tmux-python/tmuxp#860
pane.capture_pane()learned to acceptstartandendline numbers (#465)
fetch_objsnow raisesObjectDoesNotExistwith detailed information on lookup that failed (#466)
- Server: Launching of new session with default socket (#857)
- Window.panes: Fix docstring
- Remove unused code documentation
-
Server: Add
__repr__and setsocket_pathif none set.Before (0.17 and below):
<libtmux.server.Server object at ...>
New
__repr__(0.18+):Server(socket_name=test)
Server(socket_path=/tmp/tmux-1000/default)
- Server: Move
_list_panesand_update_panesto deprecated
- Documentation fixes
- Add deprecation warning to
Server.children,Session.children,Window.children.
-
Finding objects / relations
-
0.16 and below:
session._windows(),session.list_windows(), etc.0.17 and after: {attr}
session.windows <libtmux.Session.windows> -
0.16 and below:
session.find_where({'window_name': my_window})0.17 and after: {meth}
session.windows.get(window_name=my_window, default=None) <libtmux.Session.windows>- If not found and not
default, raises {exc}~libtmux._internal.query_list.ObjectDoesNotExist - If multiple objects found, raises {exc}
~libtmux._internal.query_list.MultipleObjectsReturned
- If not found and not
-
0.16 and below:
session.where({'window_name': my_window})0.17 and after: {meth}
session.windows.filter(window_name=my_window) <libtmux.Session.windows>
-
-
Accessing attributes
-
0.16 and below:
window['id']0.17 and after:
window.id -
0.16 and below:
window.get('id')0.17 and after:
window.id -
0.16 and below:
window.get('id', None)0.17 and after:
getattr(window, 'id', None)
-
Server.is_alive()Server.raise_if_dead()
- Remove unused
sphinx-clickdevelopment dependency
-
Remove reliance on
packaging.version.Version(#461)This is too critical of a package to pin a dependency as it may interfere with other packages the user relies on. In addition, libtmux doesn't need strict compatibility with
packaging.
-
Fix
distutilswarning, vendorizeLegacyVersion(#351)Removal of reliancy on
distutils.version.LooseVersion, which does not supporttmux(1)versions like3.1a.Fixes warning:
DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
The temporary workaround, before 0.16.0 (assuming setup.cfg):
[tool:pytest] filterwarnings = ignore:.* Use packaging.version.*:DeprecationWarning:: ignore:The frontend.Option(Parser)? class.*:DeprecationWarning::
Window.split_window()andSession.new_window()now support an optional dictionary of environmental variables, via (#453), credit @zappolowski.
There will be more improvements over the coming weeks and months to shore up flakiness across shells and environments.
- Compatibility improvement for
test_capture_paneandenv(#452), credit: @zappolowski! - Remove more BASHisms from tests (#455)
tmux_cmd(): Fix raise of TmuxCommandNotFound (#450)
- Use python 3.11 (#451)
- Add python 3.11 to trove classifiers (#451)
- Add python 3.11 to asdf and pyenv configurations (#451)
Session.new_window(): Improve support forwindow_name: ''downstream in tmuxp (#444, credit: @trankchung)
- Move
.coveragerc->pyproject.toml(#443)
Maintenance only, no bug fixes or new features
-
Remove
MANIFEST.inThis is handled by poetry's
includein pyproject.toml.
Maintenance only, no bug fixes or new features
- Remove
.tmuxp-before-script.shfrom.tmuxp.yaml
- Use stable
pytestAPI imports where possible to fix issues in downstream packaging on Arch (#441, via #442)
- Add
.tmuxp-before-script.sh(used by.tmuxp.yaml) andconftest.pyto source distributoins (#441, via #442)
-
Examples for pytest plugin (#439)
-
Move conftest.py to root level (#440)
- https://docs.pytest.org/en/stable/deprecations.html#pytest-plugins-in-non-top-level-conftest-files
- Less conftest.py files
- We can now run py.test for
README.mdwithout needing to proxy throughdocs/index.md
Maintenance release, no features or fixes
- pytest plugin: Initial tests (for testing the plugin itself, #423)
- pyproject.toml: Note pytest framework in trove classifiers
-
CI speedups (#428)
- Avoid fetching unused apt package
- Split out release to separate job so the PyPI Upload docker image isn't pulled on normal runs
- pyproject.toml: Drop old issues package, remove anther package from grouping
- Cleanup quickstart page
- Added a pytest plugin, #411.
- Remove
common.which()in favor of {func}shutil.which, Credit: @rocksandska, via #407 - Fixes #402: {func}
common.tmux_cmdwill only strip trailing empty lines. Before this change, all empty lines were filtered out. This will lead to a more accurate behavior when using {meth}Pane.capture_pane. Credit: @rockandska, via #405. - Source files for
libtmuxmodules moved tosrc/, via #414.
- Add flake8-bugbear (#408)
- Add flake8-comprehensions (#409)
- Test doctests in documentation via pytest-doctest-docutils (#410)
- Examples updated for correctness, #412 (cherry-picked from #410)
- Render changelog in linkify_issues (#410)
- Fix Table of contents rendering with sphinx autodoc with sphinx_toctree_autodoc_fix (#410)
- {meth}
Server.new_sessionreally works withoutsession_name, #401 fixes #399. Improved tests and doctests added.
-
{meth}
Server.new_sessionworks withoutsession_name, #400 fixes #399This still passed
Noneto the session name, this was fixed in v0.14.2.
- {meth}
Pane.send_keys:suppress_historydefault value changed fromTruetoFalse, #395
-
Initial doctests examples stubbed out #394
-
Fix bug in
temp_window()context manager, #394 -
Pytest configuration
conftest.pymoved tolibtmux/conftest.py, so doctest can detect the fixtures #394
-
Improved typings
Now
mypy --strictcompliant (#383)Smaller touchups from #392
-
Deprecated individual item lookups (#390)
-
Removed key lookups from {meth}
libtmux.common.EnvironmentMixin.show_environmentOnly
EnvironmentMixin.show_environment()(without an argument) exists, and it still returns adict. -
Add key lookups via {meth}
libtmux.common.EnvironmentMixin.getenv# Before server.show_environment('DISPLAY') # After server.getenv('DISPLAY') # Before session.show_environment('DISPLAY') # After session.getenv('DISPLAY')
-
Removed key lookups from {meth}
Session.show_optionssession.show_options() # still returns dict, without an argument # Old session.show_options('DISPLAY') # Now session.show_option('DISPLAY')
-
Removed key lookups from {meth}
Window.show_window_optionswindow.show_window_options() # still returns dict, without an argument # Old window.show_window_options('DISPLAY') # Now window.show_window_option('DISPLAY')
-
-
Remove
libtmux.test.retry(), deprecated since 0.12.x (#393)
- Fix incorrect function name
findWhere()(#391)
-
Brought back python 3.7 and 3.8 support (#375)
-
Support for tmux 3.3a
-
Add to CI
-
Bump
TMUX_MAX_VERSIONfrom 2.4 -> 3.32.4 to 3.3a already worked, this is just the constant being updated.
-
-
Remove tox and tox-poetry-installer
This created issues with running poetry while inside the virtualenv.
-
Typings: Core relations, e.g.
Pane.window,Pane.session,Pane.server,Window.server#385
- Renewed logo
- Try out sphinx-autoapi for its table of contents generation (#367)
- Break up API documentations for utilities, exception, and test helpers and remove duplicate docs from API page. Server, session, window, and pane docs are in the Reference section now.
-
retry(): Add deprecation warning. This will be removed in 0.13.x (#368, #372) -
New function
retry_until(): Polls a callback function for a set period of time until it returnsTrueor times out. By default it will raise {exc}libtmux.exc.WaitTimeout, withraises=Falseit will returnFalse. Thank you @categulario! (#368, #372) -
#384 Chore: Use absolute modules rather than root-level to avoid cyclic imports.
# Bad / Old from libtmux import Server # Good / New from libtmux.server import Server
-
#382 [mypy] support added:
- Basic mypy tests now pass
-
Python 3.7 and 3.8 returns in 0.12.0
Note: This was not the final Python 3.7 and 3.8 release as originally stated. Python 3.7 and 3.8 support was extended in 0.12.0.
-
Internal: Use new separator to split
tmux(1)formatting information (#289, #343)The separator is configurable via
LIBTMUX_TMUX_FORMAT_SEPARATOR. If you ever have compatibility issues in the future let us know which default works best across versions.Credit: @JonathanRaiman and @jagguli
-
Basic type annotations (#359, #361) via @otherJL0
- Code cleanup (#362) from @otherJL0
- Format with black w/ string normalization. This is a one-time diff (#354)
- Sidebar reorganized into sections
- Added documentation on fetching developmental releases of libtmux
First experimental release using poetry build (#347). If you are packaging and run
across any difficulty please see #346.
-
Drop python 3.6 (#344)
-
Add python 3.10, though still
packaging.versionissues remain (#344)A compat module and version constraints will need to be added for this
- poetry: 1.1.7 -> 1.1.12 (#344)
- Add
.pre-commit-config.yaml(#344)
-
#324: Update poetry to 1.1
- CI: Use poetry 1.1.7 and
install-poetry.pyinstaller - Relock poetry.lock at 1.1 (w/ 1.1.7's fix)
- CI: Use poetry 1.1.7 and
-
#339 (CI): Lock python at 3.9 to avoid poetry issue with
dataclasses -
ci: Fix publishing docs (similar to #339)
-
#341 #342:
Server.attached_sessions()now supports multiple attached sessions.Remove attached sessions limitation to not detect multiple attached clients, thank you @timoses
- Update
Window.select_window()for #271
- #321: Convert to markdown
- #271: Fix
select_window()by providing the session ID as argument to-t. Thanks @Flowdalic - Drop python 3.5 support
Python 2.7 support dropped.
- #306: chore: Remove python 2.7 support
- #314: chore: Python 3.x syntax tweaks
- #312: ci: Add tmux 3.2a to CI
- chore: Update black to 21.6b0
- #271: Fix select_window() by providing the session ID as argument to -t.
- #297: Enchance subprocess interaction std[in|out|err]. Needed for interact with big buffer, fixes #251, thank you @gil-obradors!
- #303 Add
common.get_libtmux_versionwhich gives the tmux version as a loose constraint. Fix linking to terms inside docs, and duplicate description of module which sphinx warned about in api.rst. - #266 Fix issue on local tests where env variables would cause show-environment to pause tests indefinitely.
- #234:
Window.split_window: Allow passingpercent, Thank you @jinankjain! - #289: Fix warning due to invalid escape sequences, Thank you @tirkarthi!
- #295: Publish docs via our own action
- #295: Move more packaging over to poetry, though we'll keep setup.py for the moment to ensure compatibility package maintainers.
- #295: New development instructions
- #295: Move doc/ to docs/
- #296: CI: Test python 2.7, cache python packages, prevent running internal PRs twice
-
#278: Fix Python deprecation warnings, thanks @d1618033
Also thanks Flowdalic for a similar PR at #294
-
Add
project_urlsto setup.py -
#293 Move from Pipfile to poetry
-
Fix show_option test in tmux 3.0
-
Clean up handle_option_error comments
-
Move CI to a GitHub action
- CHANGES updated to plain reStructuredText
- Add
project_urlsto setup.py for pypi. - Looser Pipfile versions, add Pipfile.lock
- #117 Fix issue with renaming clients with tmux 2.7 on BSD/macOS machines.
- #121 Support
literal=True(-l) inPane.send_keysfrom @ritiek - #131 Fix for unicode commands in Python 2, thanks @myw
- #172 Support for next-X.Y versions from @sloria
- #120
capture_panesupport forPane - #119
display_messagesupport forPane - Sort imports with isort
- Add sphinxcontrib-napoleon package for documentation
- Move docstrings over to numpy's style
- #46 Change license from BSD to MIT
- Move to new organization, tmux-python
- Support package updates to pytest, sphinx, etc.
- Travis/CI: Limit tests to Python 2.7 and 3.6 (removed 3.3 to 3.5)
- Travis/CI: Update pypy veersions
- #103
Server.new_sessionlearned how to run commands in window on session start, thanks @grimpy! - #68 Make Server.has_session() use returncode, thanks
@jlargentaye! This should make
has_sessionmore robust.
- Port
retryfunction from tmuxp (tmux-python/tmuxp#354)
- Don't add -x/-y in tmux >= 2.6 if running tmuxp from inside client.
- Allow
Window.select_layoutwith no args - Fix test where
bell-was no longer ambiguous as of tmux 2.6
- Hotfix to support tmux 2.6 session creation
- #65 Add session id to commands, thanks @askedrelic
- Exact matches only supported on 2.1 and up
- Support exact matching in
Server.has_session
- #37 Improve support for formatted options like
pane-border-status. Thanks @kaushalmodi.
-
Support for python 2.6 dropped. New minimum version is 2.7
-
Add support for tmux 2.4, pypy and pypy3
-
Overhaul error handling when setting and showing options
- Added
handle_option_errorfor handling option errors - Added {exc}
libtmux.exc.OptionErrorbase exception - Added {exc}
libtmux.exc.InvalidOptionandlibtmux.exc.AmbiguousOption - {exc}
libtmux.exc.UnknownOptionnow extends {exc}libtmux.exc.OptionError
- Added
-
Overhaul version checking
has_versionhas been renamed toget_versionget_versionwill return tmux built from git master as the latest version supported by the libtmux version with-masterat the end, e.g.2.4-masterget_versionwill return tmux on openbsd base system as the latest version supported by the libtmux version with-openbsdat the end, e.g.2.4-openbsdhas_required_tmux_versionhas been renamed tohas_minimum_version- added
has_gt_version,has_gte_version,has_lt_version,has_lte_version,
-
Fixed up documentation in some session methods
-
Added pydoc exception info to option methods in window and sessions.
-
Added
TMUX_MIN_VERSIONandTMUX_MAX_VERSION
- Fix
whichcommand - Add
TmuxCommandNotFoundexception - Add
tmux_search_pathsandappend_env_pathkwargs totmux_cmd.
- #32 support for OpenBSD's tmux
- #25 support for working with tmux
master, thanks @sloria.
- #197 use
LooseVersioninstead ofStrictVersionfor version checks. Thanks @minijackson. - Pin packages with pyup.io
- #21 Readme fix from @huwenchao.
- #18 Fix logger, courtesy of @geekli
- #19 Add support for
start_directoryin new sessions and panes, courtesy of @gandelman-a. - Fix tests and add official support for 2.3
- Raise exception for invalid session names. tmux does not allow names that are empty, contain periods or colons.
- Remove unused
target_sessionparam inServer.attach_sessionandServer.switch_client.
- #12 - fix logger message when tmux doesn't exist in
PATH
- #8 new exception
UnknownOption - #8 return
Nonefor options that are valid tmux options, but unset at that scope. - #6 major documentation overhaul
- update
which()to find tmux viaos.environ['PATH']. https://redd.it/4laeut
- attributes for formatters are now accessible via
Session,WindowandPaneobjects.session.nameis equivalent tosession.get('session_name'), you can do the same with other properties in_info.window.name,pane.current_path,session.id,window.id,pane.id,session.index,window.index,pane.index, etc. attached_sessions,attached_windowandattached_paneare now properties._TMUXmetadata object changed to_info..findWhere()is nowfind_where.- README and usage fixes
- switch to pytest
- libtmux forked from tmuxp.