Migration and deprecation notes for libtmux are here, see {ref}changelog as
well.
1. 📌 For safety, **always** pin the package
2. 📖 Check the migration notes _(You are here)_
3. 📣 If you feel something got deprecated and it interrupted you - past, present, or future - voice your opinion on the [tracker].
We want to make libtmux fun, reliable, and useful for users.
API changes can be painful.
If we can do something to draw the sting, we'll do it. We're taking a balanced approach. That's why these notes are here!
(Please pin the package. 🙏)
[tracker]: https://github.com/tmux-python/libtmux/discussions
This table provides a quick reference for all deprecated APIs. See version-specific sections below for detailed migration examples and code samples.
| Class | Deprecated | Replacement | Since | Raises |
|---|---|---|---|---|
| Server | kill_server() |
kill() |
0.30.0 (2024-02-16) | 0.51.0 |
| Session | attach_session() |
attach() |
0.30.0 (2024-02-16) | 0.51.0 |
| Session | kill_session() |
kill() |
0.30.0 (2024-02-16) | 0.51.0 |
| Window | select_window() |
select() |
0.30.0 (2024-02-16) | 0.51.0 |
| Window | kill_window() |
kill() |
0.30.0 (2024-02-16) | 0.51.0 |
| Window | split_window() |
split() |
0.33.0 (2024-03-17) | 0.51.0 |
| Window | set_window_option() |
set_option() |
0.50.0 (2025-11-30) | (warning) |
| Window | show_window_option() |
show_option() |
0.50.0 (2025-11-30) | (warning) |
| Window | show_window_options() |
show_options() |
0.50.0 (2025-11-30) | (warning) |
| Pane | select_pane() |
select() |
0.30.0 (2024-02-16) | 0.51.0 |
| Pane | resize_pane() |
resize() |
0.28.0 (2024-02-14) | 0.51.0 |
| Pane | split_window() |
split() |
0.33.0 (2024-03-17) | 0.51.0 |
| Class | Deprecated | Replacement | Since | Raises |
|---|---|---|---|---|
| Session | attached_window |
active_window |
0.31.0 (2024-02-17) | 0.51.0 |
| Session | attached_pane |
active_pane |
0.31.0 (2024-02-17) | 0.51.0 |
| Window | attached_pane |
active_pane |
0.31.0 (2024-02-17) | 0.51.0 |
| Method(s) | Deprecated | Replacement | Since | Raises |
|---|---|---|---|---|
| Options/hooks methods | g |
global_ |
0.50.0 (2025-11-30) | (warning) |
split_window() / split() |
percent |
size |
0.28.0 (2024-02-14) | 0.51.0 |
split_window() / split() |
vertical/horizontal |
direction (PaneDirection) |
0.33.0 (2024-03-17) | 0.51.0 |
resize_pane() |
-U, -D, -L, -R |
adjustment_direction |
0.28.0 (2024-02-14) | 0.51.0 |
Server.get_by_id() |
id |
session_id |
0.16.0 (2022-12-10) | 0.51.0 |
Session.get_by_id() |
id |
window_id |
0.16.0 (2022-12-10) | 0.51.0 |
Window.get_by_id() |
id |
pane_id |
0.16.0 (2022-12-10) | 0.51.0 |
| Class | Deprecated | Replacement | Since | Raises |
|---|---|---|---|---|
| Server | list_sessions() / _list_sessions() |
sessions property |
0.17.0 (2022-12-26) | 0.51.0 |
| Server | where({...}) |
sessions.filter(**kwargs) |
0.17.0 (2022-12-26) | 0.51.0 |
| Server | find_where({...}) |
sessions.get(default=None, **kwargs) |
0.17.0 (2022-12-26) | 0.51.0 |
| Server | _list_panes() / _update_panes() |
panes property |
0.17.0 (2022-12-26) | 0.51.0 |
| Server | _list_windows() / _update_windows() |
windows property |
0.17.0 (2022-12-26) | 0.51.0 |
| Server | get_by_id(id) |
sessions.get(session_id=..., default=None) |
0.16.0 (2022-12-10) | 0.51.0 |
| Session | list_windows() / _list_windows() |
windows property |
0.17.0 (2022-12-26) | 0.51.0 |
| Session | where({...}) |
windows.filter(**kwargs) |
0.17.0 (2022-12-26) | 0.51.0 |
| Session | find_where({...}) |
windows.get(default=None, **kwargs) |
0.17.0 (2022-12-26) | 0.51.0 |
| Session | get_by_id(id) |
windows.get(window_id=..., default=None) |
0.16.0 (2022-12-10) | 0.51.0 |
| Window | list_panes() / _list_panes() |
panes property |
0.17.0 (2022-12-26) | 0.51.0 |
| Window | where({...}) |
panes.filter(**kwargs) |
0.17.0 (2022-12-26) | 0.51.0 |
| Window | find_where({...}) |
panes.get(default=None, **kwargs) |
0.17.0 (2022-12-26) | 0.51.0 |
| Window | get_by_id(id) |
panes.get(pane_id=..., default=None) |
0.16.0 (2022-12-10) | 0.51.0 |
| All | children property |
sessions/windows/panes |
0.17.0 (2022-12-26) | 0.51.0 |
| Pattern | Deprecated | Replacement | Since | Raises |
|---|---|---|---|---|
| Dict key access | obj['key'] |
obj.key |
0.17.0 (2022-12-26) | 0.51.0 |
| Dict get | obj.get('key') |
obj.key |
0.17.0 (2022-12-26) | 0.51.0 |
| Dict get w/ default | obj.get('key', None) |
getattr(obj, 'key', None) |
0.17.0 (2022-12-26) | 0.51.0 |
| Item | Removed In | Migration |
|---|---|---|
| tmux < 3.2a support | 0.49.0 (2025-11-29) | Upgrade tmux or use libtmux 0.48.x |
console_to_str() |
0.42.0 (2025-02-02) | Use text=True in subprocess |
str_from_console() |
0.42.0 (2025-02-02) | Use text=True in subprocess |
common.which() |
0.12.0 (2022-07-13) | Use shutil.which() |
| Method | Old Default | New Default | Since |
|---|---|---|---|
Session.new_window() |
attach=True |
attach=False |
0.28.0 (2024-02-14) |
Window.split_window() |
attach=True |
attach=False |
0.28.0 (2024-02-14) |
Detailed migration steps for the next version will be posted here.
When {exc}~libtmux.exc.LibTmuxException is raised from a libtmux method,
str(exc) now starts with the originating tmux subcommand name followed
by ": ". exc.args[0] still
carries the original tmux error text, and the new
{attr}~libtmux.exc.LibTmuxException.subcommand attribute exposes
the tmux subcommand name on its own.
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].
Who is affected: code that pattern-matches str(exc) exactly,
anchors a regex with ^ against the previous shape, or indexes
exc.args[0] element-by-element expecting a list. Substring
containment ("can't find" in str(exc)) and unanchored
re.search patterns continue to match unchanged.
Before:
try:
session.last_window()
except LibTmuxException as exc:
if str(exc) == "can't find window":
handle_missing_last_window()After (0.57.0+) — dispatch on the typed attribute:
try:
session.last_window()
except LibTmuxException as exc:
if exc.subcommand == "last-window":
handle_missing_last_window()Or — match against the original tmux error text in exc.args[0]:
try:
session.last_window()
except LibTmuxException as exc:
if exc.args and exc.args[0] == "can't find window":
handle_missing_last_window(){class}~libtmux.Client is new in 0.57.0, so this isn't a behavior
change — but new users of {attr}~libtmux.Server.clients should know
that client.session_id, client.window_id, and
client.pane_id reflect the client's attached view at the moment the
{class}~libtmux.Client was read. They go stale as soon as the client
switches sessions, changes window, or detaches.
For typed access that reflects the client's live attachment, use
{attr}~libtmux.Client.attached_session,
{attr}~libtmux.Client.attached_window, and
{attr}~libtmux.Client.attached_pane:
# Snapshot (may be stale)
client = server.clients.get(client_name=ctl.client_name)
session_id = client.session_id # str captured when the object was read
# Live (re-reads list-clients; returns None if tmux no longer reports the client)
attached = client.attached_session # libtmux.Session | None
window = client.attached_window # libtmux.Window | None
pane = client.attached_pane # libtmux.Pane | NoneThe client.client_name field (typically the tty path on Unix) is
the client's stable identifier and does not have this caveat. The
attached_* properties translate a missing list-clients row into
None for convenience; direct {meth}~libtmux.Client.refresh and
{meth}~libtmux.Client.from_client_name calls still raise when that
client row is gone.
{attr}~libtmux.Client.attached_pane follows the attached session's current
window. That can differ from the per-client active pane set by
select-pane -P.
{meth}~libtmux.Pane.reset now bundles send-keys -R and
clear-history into one tmux command sequence targeted at the pane.
This closes a race where output written between separate commands could
land in the scrollback that the second command then cleared.
Who is affected: test fixtures and downstream code that intercepts
Pane.cmd (for example with unittest.mock.patch.object(pane, "cmd")) will no longer observe reset()'s tmux invocation. Patch
Server.cmd instead, or assert on the resulting pane state directly.
The three display_message wrappers now report tmux stderr via
:func:warnings.warn rather than raising
{exc}~libtmux.exc.LibTmuxException. tmux uses stderr for both genuine
errors and informational messages, and the right escalation depends on
tmux version and requested format; the wrappers default to warning so callers
can decide. To escalate to an exception, wrap the call in
:func:warnings.catch_warnings with filterwarnings("error"):
import warnings
with warnings.catch_warnings():
warnings.filterwarnings("error", category=UserWarning)
result = pane.display_message("#{pane_id}", get_text=True)All tmux objects (Server, Session, Window, Pane) now share a consistent options
interface through {class}~libtmux.options.OptionsMixin:
# Get all options
session.show_options()
# Get a single option
session.show_option('base-index')
# Set an option
window.set_option('automatic-rename', True)
# Unset an option
window.unset_option('automatic-rename')All tmux objects now support hook management through
{class}~libtmux.hooks.HooksMixin:
# Set a hook
session.set_hook('session-renamed', 'display-message "Renamed!"')
# Get hook value
session.show_hook('session-renamed')
# Get all hooks
session.show_hooks()
# Remove a hook
session.unset_hook('session-renamed')The following Window methods are deprecated and will be removed in a future
release:
| Deprecated | Replacement |
|---|---|
Window.set_window_option() |
{meth}Window.set_option() <libtmux.Window.set_option> |
Window.show_window_option() |
{meth}Window.show_option() <libtmux.Window.show_option> |
Window.show_window_options() |
{meth}Window.show_options() <libtmux.Window.show_options> |
Before (deprecated):
window.set_window_option('automatic-rename', 'on')
window.show_window_option('automatic-rename')
window.show_window_options()After (0.50.0+):
window.set_option('automatic-rename', True)
window.show_option('automatic-rename')
window.show_options()The g parameter for global options is deprecated in favor of global_:
Before (deprecated):
session.show_option('status', g=True)
session.set_option('status', 'off', g=True)After (0.50.0+):
session.show_option('status', global_=True)
session.set_option('status', 'off', global_=True)Using the old g parameter will emit a {class}DeprecationWarning.
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
)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-
{meth}
Server.cmd(), {meth}Session.cmd(), {meth}Window.cmd(), {meth}Pane.cmd()require passingtargetinstead of['-t', target],['-tTargetName'], etc. This change is to avoid issues mistakenly interpreting-tin other shell values as targets.Before:
session.cmd('send-keys', 'echo hello', '-t', '0')
With 0.35.0 and after:
session.cmd('send-keys', 'echo hello', target='0')
Window.split_window()to {meth}Window.split()Pane.split_window()to {meth}Pane.split()
-
Commands: Param change
{meth}
Server.cmd(), {meth}Session.cmd(), {meth}Window.cmd(), {meth}Pane.cmd()- 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
-
{meth}
Session.new_window()+ {meth}Window.split_window()no longer attaches by default (#523)- 0.28.0 and greater: Defaults to
attach=False. - 0.27.1 and below: Defaults to
attach=True.
For the old behavior in 0.28.0 and beyond, pass
attach=Trueexplicitly. - 0.28.0 and greater: Defaults to
-
Pane.resize_pane()renamed to {meth}Pane.resize()(via #523)This convention will be more consistent with {meth}
Window.resize(). -
{meth}
Pane.resize_pane()'s params changed (#523)-
No longer accepts
-U,-D,-L,-Rdirectly, instead accepts {class}~libtmux.constants.ResizeAdjustmentDirection(see below).-
0.27.1 and below:
pane.resize_pane("-D", 20),pane.resize_pane("-R", 20) -
0.28.0 and beyond:
from libtmux.constants import ResizeAdjustmentDirection pane.resize_pane(adjustment_direction=ResizeAdjustmentDirection.Down, adjustment=25) pane.resize_pane( adjustment_direction=ResizeAdjustmentDirection.Right, adjustment=25 )
-
-
-
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>
-
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)