# Explicit operations

Source: https://libtmux.org/en/lisp/latest/guides/operations/

> Explicit operations: libtmux documentation.

Named operations take the connection client first and a captured target where
needed. They read current state to validate the target, then use its identity.
Earlier captures remain unchanged. Every operation accepts `:cancel-token`,
`:timeout` and `:output-limit`; the latter two default to the client settings
and cover validation, dispatch and any follow-up acquisition together.

The current APIs require a live daemon. [`new-session`](https://libtmux.org/en/tmux/latest/manual/new-session/) creates a session there;
daemon bootstrap is a separate unfinished part of the implementation.

| Operation | Target / result |
| --- | --- |
| [`rename-window`](https://libtmux.org/en/tmux/latest/manual/rename-window/), [`rename-session`](https://libtmux.org/en/tmux/latest/manual/rename-session/) | Physical entity; command outcome with optional replacement |
| [`select-window`](https://libtmux.org/en/tmux/latest/manual/select-window/) | Window link, preserving session/index context |
| [`select-pane`](https://libtmux.org/en/tmux/latest/manual/select-pane/) | Physical pane |
| [`next-window`](https://libtmux.org/en/tmux/latest/manual/next-window/), [`previous-window`](https://libtmux.org/en/tmux/latest/manual/previous-window/), [`last-window`](https://libtmux.org/en/tmux/latest/manual/last-window/) | Session; outcome containing its selected window link |
| [`last-pane`](https://libtmux.org/en/tmux/latest/manual/last-pane/) | Physical window; outcome containing its selected pane |
| [`new-session`](https://libtmux.org/en/tmux/latest/manual/new-session/) | Selected live daemon; outcome containing the created session |
| [`new-window`](https://libtmux.org/en/tmux/latest/manual/new-window/) | Captured session; outcome containing the physical window |
| [`split-pane`](<https://libtmux.org/en/lisp/latest/reference/libtmux-split-pane/>) | Captured pane; outcome containing the new pane |
| [`capture-pane`](https://libtmux.org/en/tmux/latest/manual/capture-pane/) | Pane; UTF-8 text and diagnostic outcome as two values |
| [`capture-pane-bytes`](<https://libtmux.org/en/lisp/latest/reference/libtmux-capture-pane-bytes/>) | Pane; owned octets and diagnostic outcome as two values |
| [`send-text`](<https://libtmux.org/en/lisp/latest/reference/libtmux-send-text/>), [`send-keys`](https://libtmux.org/en/tmux/latest/manual/send-keys/), [`send-prefix`](https://libtmux.org/en/tmux/latest/manual/send-prefix/) | Pane; command outcome for the send request |
| [`respawn-pane`](https://libtmux.org/en/tmux/latest/manual/respawn-pane/), [`respawn-window`](https://libtmux.org/en/tmux/latest/manual/respawn-window/) | Physical target; explicit process replacement and optional captured result |
| [`pipe-pane`](https://libtmux.org/en/tmux/latest/manual/pipe-pane/) | Pane; explicit shell source, direction and daemon-owned pipe |
| [`switch-client`](https://libtmux.org/en/lisp/latest/reference/libtmux-switch-client/) | Captured terminal client and destination session; outcome with optional replacement |
| [`detach-client`](https://libtmux.org/en/lisp/latest/reference/libtmux-detach-client/), [`refresh-client`](https://libtmux.org/en/lisp/latest/reference/libtmux-refresh-client/), [`suspend-client`](https://libtmux.org/en/lisp/latest/reference/libtmux-suspend-client/), [`lock-client`](https://libtmux.org/en/lisp/latest/reference/libtmux-lock-client/) | Captured terminal client; outcome acknowledging the request |
| [`lock-session`](https://libtmux.org/en/lisp/latest/reference/libtmux-lock-session/), [`lock-server`](https://libtmux.org/en/lisp/latest/reference/libtmux-lock-server/) | Frontends attached to a captured session or the addressed daemon; request outcome |
| [`wait-for`](https://libtmux.org/en/lisp/latest/reference/libtmux-wait-for/) | Literal server channel; signal, wait, lock or unlock outcome |
| [`clear-history`](https://libtmux.org/en/tmux/latest/manual/clear-history/), [`copy-mode`](https://libtmux.org/en/tmux/latest/manual/copy-mode/) | Pane; command outcome |
| [`resize-pane`](https://libtmux.org/en/tmux/latest/manual/resize-pane/), [`resize-window`](https://libtmux.org/en/tmux/latest/manual/resize-window/) | Physical target; outcome with optional replacement |
| [`select-layout`](https://libtmux.org/en/tmux/latest/manual/select-layout/), [`next-layout`](https://libtmux.org/en/tmux/latest/manual/next-layout/), [`previous-layout`](https://libtmux.org/en/tmux/latest/manual/previous-layout/) | Physical window; outcome with optional replacement |
| [`link-window`](https://libtmux.org/en/tmux/latest/manual/link-window/), [`move-window`](https://libtmux.org/en/tmux/latest/manual/move-window/), [`break-pane`](https://libtmux.org/en/tmux/latest/manual/break-pane/) | Explicit link/session/index context; outcome containing the destination link |
| [`swap-windows`](<https://libtmux.org/en/lisp/latest/reference/libtmux-swap-windows/>), [`swap-panes`](<https://libtmux.org/en/lisp/latest/reference/libtmux-swap-panes/>) | Two targets; outcome containing a fresh vector in argument order |
| [`unlink-window`](https://libtmux.org/en/tmux/latest/manual/unlink-window/) | Window link; outcome without a replacement |
| [`move-pane`](https://libtmux.org/en/tmux/latest/manual/move-pane/), [`join-pane`](https://libtmux.org/en/tmux/latest/manual/join-pane/), [`rotate-window`](https://libtmux.org/en/tmux/latest/manual/rotate-window/) | Physical targets; outcome with optional replacement |
| [`list-buffers`](https://libtmux.org/en/tmux/latest/manual/list-buffers/) | Fresh vector of metadata plists and diagnostic outcome |
| [`show-buffer`](https://libtmux.org/en/tmux/latest/manual/show-buffer/) | Owned octets and diagnostic outcome |
| [`set-buffer`](https://libtmux.org/en/tmux/latest/manual/set-buffer/), [`load-buffer`](https://libtmux.org/en/tmux/latest/manual/load-buffer/), [`save-buffer`](https://libtmux.org/en/tmux/latest/manual/save-buffer/), [`delete-buffer`](https://libtmux.org/en/tmux/latest/manual/delete-buffer/), [`paste-buffer`](https://libtmux.org/en/tmux/latest/manual/paste-buffer/) | Explicit buffer data/path/name and optional pane; command outcome |
| [`set-option`](https://libtmux.org/en/lisp/latest/reference/libtmux-set-option/), [`unset-option`](https://libtmux.org/en/lisp/latest/reference/libtmux-unset-option/) | Typed live-catalog option mutation in one explicit table |
| [`set-hook`](https://libtmux.org/en/lisp/latest/reference/libtmux-set-hook/), [`unset-hook`](https://libtmux.org/en/lisp/latest/reference/libtmux-unset-hook/) | Tmux command-source installation/removal; never evaluates source as Lisp |
| [`set-environment`](https://libtmux.org/en/lisp/latest/reference/libtmux-set-environment/), [`unset-environment`](https://libtmux.org/en/lisp/latest/reference/libtmux-unset-environment/), [`remove-environment`](https://libtmux.org/en/lisp/latest/reference/libtmux-remove-environment/) | Raw global/session environment value, deletion or tombstone |
| [`kill-pane`](https://libtmux.org/en/lisp/latest/reference/libtmux-kill-pane/), [`kill-window`](https://libtmux.org/en/lisp/latest/reference/libtmux-kill-window/), [`kill-session`](https://libtmux.org/en/lisp/latest/reference/libtmux-kill-session/) | Exact captured entity; outcome without replacement |
| [`kill-server`](https://libtmux.org/en/lisp/latest/reference/libtmux-kill-server/) | Retained live daemon; proven process exit or uncertain outcome |

Creation defaults to detached mode. Selection uses explicit captured targets.
[`new-window :index`](https://libtmux.org/en/tmux/latest/manual/new-window/) chooses a free session index. [`split-pane`](<https://libtmux.org/en/lisp/latest/reference/libtmux-split-pane/>) accepts
`:horizontal` (left/right) or `:vertical` (top/bottom), with a cell `:size` or
`:percent`. Creation returns a fresh captured entity through [`outcome-value`](<https://libtmux.org/en/lisp/latest/reference/libtmux-outcome-value/>).

For typed option/hook values, inherited table reads and environment presence,
see [decoded configuration](https://github.com/libtmux/libtmux-lisp/blob/c2e5fc4ed3befda21f45dfa5d5868c38fd138311/docs/configuration.md). Raw printers remain available for
unrestricted native inspection.

## Names and child commands

Names and creation `:cwd` strings are literal, including `#[...]` and `#{...}`
text. Rename's `:format-p t` explicitly requests tmux format expansion. Tmux can
normalize or reject a name; inspect the replacement observation for the
resulting name. Cwd text follows tmux's own relative-path rules. Tmux can fall
back from an inaccessible cwd; use child-side evidence when the exact directory
matters.

Creation accepts a nonempty `:command` list/vector of argv strings or a separate
`:shell-command` string. Omission selects tmux's default shell. Supplying an
empty argv is invalid. Strings may contain spaces, quotes, semicolons, dollar
signs, backslashes and Unicode; the encoder preserves their argument boundaries.
One-element argv starts that executable with no added program argument.
`:environment` is a list/vector of `(name . value)` string pairs.

The final encoded tmux command is limited to 16,000 UTF-8 bytes, including NUL
terminators between argv entries. Nested command quoting counts toward this
limit. Oversized named commands fail before their payload is dispatched. They
are never silently split into multiple mutations.

## Terminal input

[`send-text`](<https://libtmux.org/en/lisp/latest/reference/libtmux-send-text/>) preserves literal text such as `C-c`; `:enter t` appends one Return
key in the same request. [`send-keys`](https://libtmux.org/en/tmux/latest/manual/send-keys/) accepts a nonempty list/vector of tmux key
strings and a positive `:repeat` count. Tmux recognizes names such as `C-c` and
`Enter`, and falls back to literal input for unrecognized strings. [`send-prefix`](https://libtmux.org/en/tmux/latest/manual/send-prefix/)
uses the configured prefix; `:second t` selects prefix2.

The pane's current tmux mode handles input. Successful dispatch means tmux
processed the send request; it does not establish application consumption or
readiness. Coordinate dependent work through an application signal.

[`copy-mode`](https://libtmux.org/en/tmux/latest/manual/copy-mode/) enters copy mode; `:page-up t` scrolls on entry, and `:exit t` exits.
Page-up and exit are mutually exclusive. [`clear-history`](https://libtmux.org/en/tmux/latest/manual/clear-history/) removes retained tmux
history; it does not promise to clear the application's current screen.

## Geometry and selection

[`resize-pane`](https://libtmux.org/en/tmux/latest/manual/resize-pane/) and [`resize-window`](https://libtmux.org/en/tmux/latest/manual/resize-window/) accept positive cell `:width`/`:height`, or a
`:direction` (`:left`, `:right`, `:up`, `:down`) with positive `:amount` (default
one). Absolute dimensions range from 1 through 10,000, the common supported
range. Relative amounts range from 1 through 2,147,483,647. Tmux may clamp the
actual layout; the replacement observation contains the resulting dimensions.

Pane `:zoom t` toggles zoom. Window `:fit :smallest` or `:fit :largest` fits the
attached clients. These modes cannot be combined with dimensions or direction.
A window resize sets tmux's [`window-size`](https://libtmux.org/en/tmux/latest/catalog/options/window-size/) option to manual.

[`select-layout`](https://libtmux.org/en/tmux/latest/manual/select-layout/) accepts `:even-horizontal`, `:even-vertical`, `:main-horizontal`,
`:main-vertical`, `:tiled`, or `(:custom "tmux-layout-description")`.
Tmux validates custom checksums and geometry. Layout operations unzoom the
window. [`next-layout`](https://libtmux.org/en/tmux/latest/manual/next-layout/) and [`previous-layout`](https://libtmux.org/en/tmux/latest/manual/previous-layout/) follow tmux's layout ordering.

[`next-window`](https://libtmux.org/en/tmux/latest/manual/next-window/), [`previous-window`](https://libtmux.org/en/tmux/latest/manual/previous-window/) and [`last-window`](https://libtmux.org/en/tmux/latest/manual/last-window/) take a captured session and
return its newly observed active **window link** through [`outcome-value`](<https://libtmux.org/en/lisp/latest/reference/libtmux-outcome-value/>).
Next and previous accept `:activity t` to restrict selection to alerting windows.
[`last-pane`](https://libtmux.org/en/tmux/latest/manual/last-pane/) takes a physical window and returns its observed active pane.
Tmux signals when no last selection exists. These operations and geometry
accept `:observe nil` to omit follow-up acquisition.

## Attached terminal clients

[Fetch-clients](https://libtmux.org/en/lisp/latest/reference/libtmux-fetch-clients/) returns attached-client observations;
they are distinct from the library connection passed as the first argument.
The five client operations above require an ordinary terminal client captured
through that connection. They reject control-mode observations. Preflight
requires one matching name and the same PID, creation time and tty. It also
rejects a name that matches another client's full or abbreviated tty. A missing,
replaced or foreign observation signals [stale-target](https://libtmux.org/en/lisp/latest/reference/libtmux-stale-target/).
Tmux has no dispatch-side client fingerprint guard across the supported floor,
so replacement between preflight and dispatch remains possible.

[`switch-client`](https://libtmux.org/en/tmux/latest/manual/switch-client/) takes an explicit destination session. It preserves that
session's environment by default; `:update-environment t` applies tmux's
[`update-environment`](https://libtmux.org/en/tmux/latest/catalog/options/update-environment/) option using the attached client's environment. Its default
`:observe t` acquires a replacement client observation; `:observe nil` omits
that read. The earlier observation still points to its captured session.

[`refresh-client`](https://libtmux.org/en/tmux/latest/manual/refresh-client/) schedules a full redraw; `:status-only t` schedules only the
status line. [Refresh](https://libtmux.org/en/lisp/latest/reference/libtmux-refresh/) instead acquires a replacement
observation. [`detach-client`](https://libtmux.org/en/tmux/latest/manual/detach-client/) requests detachment of the selected client.
[`suspend-client`](https://libtmux.org/en/tmux/latest/manual/suspend-client/) requests native SIGTSTP suspension; the controlling application
owns resumption. [`lock-client`](https://libtmux.org/en/tmux/latest/manual/lock-client/) asks the frontend to execute its configured
[`lock-command`](https://libtmux.org/en/tmux/latest/catalog/options/lock-command/) through a shell. An already suspended client can make suspend
or lock a no-op; an empty or oversized lock command is also ignored by tmux.
These four calls return no replacement observation.

Success acknowledges the server's request. It does not prove frontend exit,
terminal restoration, completed redraw, process suspension, lock startup or
authentication. Coordinate dependent work through the frontend's own completion
signal. Missing dispatch/completion evidence remains an unknown outcome; the
library never retries these requests automatically.

[`lock-session`](https://libtmux.org/en/lisp/latest/reference/libtmux-lock-session/) requests locking for frontends
attached to the selected session when tmux executes the command.
[`lock-server`](https://libtmux.org/en/lisp/latest/reference/libtmux-lock-server/) requests it across the addressed
daemon. Both use live membership, including frontends attached after the
caller's capture. They return one request outcome, with no per-frontend results.
Control clients, already suspended frontends and empty or oversized lock
commands are skipped; no eligible frontends is a successful no-op.

These requests run the configured frontend lock programs. They do not block
other tmux commands or suspend pane processes. Closing the library client leaves
the frontend programs running. Hooks can add effects or fail after requests
have been sent, so a failed outcome does not undo a lock request. See tmux's
[`server_lock`](https://github.com/tmux/tmux/blob/3.8/server-fn.c#L175-L218).

## Message printing

[`display-message`](https://libtmux.org/en/lisp/latest/reference/libtmux-display-message/) returns two values: owned
strict UTF-8 text and its diagnostic command outcome. It uses tmux's ordinary
`-p` printer and preserves whitespace, including the final newline. Message text
is literal by default, including `#{...}`, `#(...)`, `#[...]` and `%Y`.
Literal input disables expansion; it does not make the printer a byte-identical
echo. Native versions can escape output, including `$` on 3.4. The API retains
that presentation rather than interpreting it as decoded field data.

An optional `:target` accepts a captured session, physical window, pane or
window link owned by the supplied client. Use a link when its session and index
matter. Physical windows and panes let tmux choose their session context;
omitting the target lets tmux choose the complete context. Authority and stale
link checks apply before the request. The call acquires no replacement.

`:format-p t` explicitly enables tmux format and time expansion. A `#()`
expression may start a shell job, but expansion does not wait for its result.
A fresh command client may print an empty or incomplete result. Those jobs
belong to the native command client and are cleaned up on its disconnect;
this API does not provide job completion or background process ownership.

After-hooks can print additional text or have effects. The returned text retains
that output; it does not establish a single field's value or presence. Use
captured getters for local field reads. Decoded configuration acquisition
remains a separate capability. Invalid UTF-8 raises
[`decoding-error`](https://libtmux.org/en/lisp/latest/reference/libtmux-decoding-error/) with the outcome's original bytes.

Tmux 3.4 and newer provide native literal printing. The 3.3a fallback escapes
format and time syntax and conservatively limits the intermediate after time
expansion to 8,191 UTF-8 bytes. That limit is checked after live-version
preflight and before payload dispatch. The encoded command limit also applies.
See [`cmd_display_message_exec`](https://github.com/tmux/tmux/blob/3.8/cmd-display-message.c#L62-L176).

## Commands and key bindings

[`list-commands`](https://libtmux.org/en/lisp/latest/reference/libtmux-list-commands/) and
[`list-keys`](https://libtmux.org/en/lisp/latest/reference/libtmux-list-keys/) return ordinary UTF-8 printer text and
the retained outcome. Both preserve native escaping, whitespace and after-hook output. The
result is intended for inspection, not replay or decoded configuration lookup.

[`list-commands`](https://libtmux.org/en/tmux/latest/manual/list-commands/) lists built-ins. Its optional `:command` accepts exact names or
built-in aliases; configured [`command-alias`](https://libtmux.org/en/tmux/latest/catalog/options/command-alias/) entries are not part of that table.
Through tmux 3.5a, an unknown selector produces no rows. From 3.6, unique
prefixes work, while unknown or ambiguous selectors fail.

[`list-keys`](https://libtmux.org/en/tmux/latest/manual/list-keys/) accepts an optional literal `:table` and `:key`. Omitted table means
all tables. Unknown tables and invalid key syntax remain errors. A valid but
unbound key is an error except on tmux 3.7 through 3.7c, which return empty text.
Those four releases also send a single matching row to the server message log
and any selected frontend's status line instead of stdout, including with
`:format`. Multiple matching rows print normally. Empty text therefore does
not establish that a binding is absent, and inspection can display a status
message. The native [single-row branch](https://github.com/tmux/tmux/blob/3.7c/cmd-list-keys.c#L236-L248)
changes in [tmux 3.8](https://github.com/tmux/tmux/blob/3.8/cmd-list-keys.c#L220-L248).

Its `:format` requires tmux 3.7 or newer; older daemons reject it before payload
dispatch. Both listing functions accept explicit tmux format source without
time expansion, so `%Y` stays literal. Empty formatted rows may be omitted.
Format jobs have the same asynchronous lifetime limits as message printing.

[`bind-key`](https://libtmux.org/en/lisp/latest/reference/libtmux-bind-key/) replaces one binding in `:table`, which
defaults to `"prefix"`. Supply exactly one of `:command` argv or
`:command-source`, explicit tmux source. The argv form preserves token
boundaries and rejects `=` in its command-name token. `:note` is literal text;
`:repeat t` enables native repetition. The stored command nodes run when tmux
dispatches that key, using the key event's context. This does not carry a
captured target's authority into future execution.

Tmux parses binding source immediately. Assignments and directives can alter
the daemon's environment before a later parse error. Aliases resolve during
binding and can introduce parser effects even through argv. A failed bind is
not a rollback; missing completion evidence can leave its outcome unknown.
Keep source and aliases under the application's control. See tmux's
[`cmd_bind_key_exec`](https://github.com/tmux/tmux/blob/3.8/cmd-bind-key.c#L55-L107)
and [assignment grammar](https://github.com/tmux/tmux/blob/3.8/cmd-parse.y#L224-L244).

[`unbind-key`](https://libtmux.org/en/lisp/latest/reference/libtmux-unbind-key/) removes exactly one key, also from
`"prefix"` by default. A missing key in an existing table is a no-op; an absent
table is an error. Removing a table's last binding may delete the table, so a
second removal need not succeed. Neither helper retries or implicitly removes
all bindings. Binding success acknowledges storage and hooks, not later key
execution. [`send-keys`](https://libtmux.org/en/lisp/latest/reference/libtmux-send-keys/) sends pane input and does
not exercise a frontend's key-binding dispatch.

## Server access

[`server-access`](https://libtmux.org/en/lisp/latest/reference/libtmux-server-access/) takes a literal account name
and one access operation. `:allow` adds a writable entry; `:deny` removes one;
`:read-only` and `:read-write` update or add an entry. Duplicate additions and
missing removals remain errors. Tmux resolves names through the daemon's name
service; strings are not treated as numeric UIDs. Root and the daemon-owner UID
cannot be changed. `:group-p t` selects a group name and requires live tmux 3.8;
older daemons reject that request before payload dispatch.

Removal does not create a deny rule. From tmux 3.8, a user without an explicit
entry can still match its connecting peer's GID. An explicit UID entry wins
over the GID entry; supplementary groups are not searched. Socket and directory
access must be configured separately; an ACL entry alone does not make the
endpoint reachable.

Permission changes can affect connected clients. In tmux 3.8, removal and
read-only/read-write updates recompute every client's effective ACL. A writable
entry can therefore clear an unrelated frontend's separately set read-only
flag. A request can schedule disconnection without proving frontend exit, and
a later grant does not cancel an already scheduled exit. `:allow` alone does
not recompute connected-client flags. Earlier captures retain their values;
use [`refresh`](https://libtmux.org/en/lisp/latest/reference/libtmux-refresh/) to acquire a replacement observation.
See the native [command](https://github.com/tmux/tmux/blob/3.8/cmd-server-access.c#L61-L152)
and [ACL update](https://github.com/tmux/tmux/blob/3.8/server-acl.c#L71-L110).

[`list-server-access`](https://libtmux.org/en/lisp/latest/reference/libtmux-list-server-access/) returns ordinary
UTF-8 listing text and an outcome. Native rows use `(R)`/`(W)` before 3.8 and
include `U`/`G` account kinds from 3.8. UID 0 is omitted; a failed name lookup
prints `unknown`. Empty text cannot establish that nobody has access. This
listing is intended for inspection and is not a decoded authorization model.

Tests cover entry lifecycle, literal input, version gates and the frontend
flag effect on private sockets under one OS user. Cross-user connection,
authorization and revocation behavior remain unverified by this library's
suite. No test changes users, socket permissions or privileges. Calls retain
uncertain outcomes and never retry automatically.

## Wait channels

[`wait-for`](https://libtmux.org/en/lisp/latest/reference/libtmux-wait-for/) accepts `:operation :wait` (the default),
`:signal`, `:lock` or `:unlock`, and a nonempty literal channel name. Signal and
unlock work on the supported tmux floor. Wait and lock require tmux 3.8's
client-loss cleanup; older daemons signal
[`unsupported-capability`](https://libtmux.org/en/lisp/latest/reference/libtmux-unsupported-capability/) before dispatch.
This is a capability restriction, not a change to the core tmux floor.

A signal wakes existing waiters. With none waiting, one signal leaves a pending
wake; a second can remove it. This is neither an idempotent latch nor a counting
semaphore. Use an application protocol when acknowledgements or sender identity
matter. Server shutdown can also flush waiting requests.

Locks belong to the daemon channel, not a Lisp client or thread. They survive a
completed call and client closure within the daemon's lifetime. Unlock explicitly;
no resource macro or automatic cleanup unlocks them. Signals and locks share
native channel state, so use different channel names for those protocols.

Each call blocks its caller. Use a second connection client to signal or unlock
another client's pending operation. Timeout and byte limits include preflight.
Cancellation removes the owned command process; tmux 3.8 removes a disconnected
queued waiter. Cancellation or lost receipts cannot prove that a signal was not
consumed or a lock was not granted. Inspect the retained outcome and coordinate
recovery through the application; the library does not retry a channel request.
See [`cmd_wait_for_client_lost`](https://github.com/tmux/tmux/blob/3.8/cmd-wait-for.c#L483-L515).

## Links and pane placement

[`link-window`](https://libtmux.org/en/tmux/latest/manual/link-window/) and [`move-window`](https://libtmux.org/en/tmux/latest/manual/move-window/) take a source **window link**, a destination
session and an explicit free index. The source link preserves session group
context. Neither overwrites an occupied index. Moving removes only the selected
source link; removing a session's last link can destroy that session.
[`unlink-window`](https://libtmux.org/en/tmux/latest/manual/unlink-window/) refuses a last reference unless `:kill-if-last t` is explicit;
tmux session groups affect its last-reference check.

[`swap-windows`](<https://libtmux.org/en/lisp/latest/reference/libtmux-swap-windows/>) takes two links and returns their replacement links in argument
order. `:select t` selects the affected indexes; omission retains current
indexes. An old link whose index now points at another window is stale.

[`move-pane`](https://libtmux.org/en/tmux/latest/manual/move-pane/) and [`join-pane`](https://libtmux.org/en/tmux/latest/manual/join-pane/) take source and destination physical panes.
`:direction`, `:size`, `:percent`, `:before` and `:full-size` control placement;
`:detached t` is the default. An emptied source window and all its links are
destroyed. With `:detached nil`, tmux chooses the session context of the physical
destination. Percentage sizing follows the installed tmux semantics: with
`:full-size t`, 3.3a uses the destination pane's dimensions while 3.8 uses the
whole window. Use `:size` for cell-based control.

[`break-pane`](https://libtmux.org/en/tmux/latest/manual/break-pane/) takes the pane, its explicit source link, a destination session
and a free index. This source link matters when the pane is its window's only
pane: tmux moves that link while preserving other links and the physical window.
The outcome contains the destination link. Its optional `:name` is literal.

Tmux 3.7 has an inverted [new-window](https://libtmux.org/en/tmux/latest/manual/new-window/) naming branch, corrected in 3.7a. The
library selects the safe branch from the live pane count within the guarded
request. For a new window with an explicit name, it follows the break with
[`rename-window`](https://libtmux.org/en/tmux/latest/manual/rename-window/) targeting the moved pane. This adds no subprocess or retry,
but can run an [`after-rename-window`](https://libtmux.org/en/tmux/latest/catalog/hooks/after-rename-window/) hook and is not transactional: a failing
hook can leave the pane moved and renamed. Inspect the retained command
outcome before deciding what to do next. Unnamed single-pane moves keep their
existing name and automatic-rename setting.
See [`cmd_break_pane_exec` in 3.7](https://github.com/tmux/tmux/blob/3.7/cmd-break-pane.c#L116-L123)
and [the corrected 3.7a branch](https://github.com/tmux/tmux/blob/3.7a/cmd-break-pane.c#L116-L123).

[`swap-panes`](<https://libtmux.org/en/lisp/latest/reference/libtmux-swap-panes/>) preserves physical IDs and returns replacements in argument order.
[`rotate-window`](https://libtmux.org/en/tmux/latest/manual/rotate-window/) moves pane positions `:up` (default) or `:down` and advances
the active pane. Both accept `:preserve-zoom t`. Placement operations preserve
older observations; a successful operation may have a separate observation
failure. Unlink has no replacement to observe.

## Pane processes

[`respawn-pane`](https://libtmux.org/en/tmux/latest/manual/respawn-pane/) restarts its process. [`respawn-window`](https://libtmux.org/en/tmux/latest/manual/respawn-window/) restarts the physical
window as one pane, retaining its first pane and destroying every other pane,
including through other session links. Neither kills a running process unless
`:kill t` is supplied. Omit both `:command` and `:shell-command` to reuse the
stored command; explicit argv, shell text, cwd and environment follow creation.
By default, [`outcome-value`](<https://libtmux.org/en/lisp/latest/reference/libtmux-outcome-value/>) supplies a new observation. Earlier captures remain
local and unchanged. A fast-exiting process can disappear before acquisition.

[`pipe-pane`](https://libtmux.org/en/tmux/latest/manual/pipe-pane/) accepts explicit `:shell-command` source. It preserves literal `#`
and `%` text by default; `:format-p t` enables tmux format and time expansion
before the shell runs. Literal commands must fit tmux's 8,191-byte time-format
capacity after format escaping. `:direction` is `:output` (pane to shell),
`:input` (shell to pane) or `:both`. Omitting the command closes the pipe.
`:toggle t` closes an existing pipe without starting its replacement.

Pipe success acknowledges configuration. It does not prove shell startup,
command success or data consumption. Coordinate dependent work through an
application signal. Tmux owns the pipe child, and closing the library client
leaves it running. Pipe replacement or explicit closure releases the pane's
connection to that child.

## Buffers

[`list-buffers`](https://libtmux.org/en/tmux/latest/manual/list-buffers/) returns a fresh vector of plists with `:buffer/name`, `:buffer/size`
in bytes and `:buffer/created` in Unix seconds. It preserves tmux's listing
order, limits decoding to 10,000 rows by default, and returns `#()` when empty.
Names are mutable locators, not captured entity identities.

[`set-buffer`](https://libtmux.org/en/tmux/latest/manual/set-buffer/) accepts a literal NUL-free string or an octet vector. Octets travel
through tmux's stdin buffer loader and preserve NUL and invalid UTF-8. `:append t`
is supported for strings. [`show-buffer`](https://libtmux.org/en/tmux/latest/manual/show-buffer/) returns owned octets without decoding.
Both accept a literal `:name`; setting without a name creates an automatic buffer.
Creation through set/load rejects backslashes, ASCII controls and DEL before
I/O because tmux versions otherwise rewrite or reject them. Spaces and Unicode
are supported. Looking up an existing buffer preserves its actual name.

[`show-buffer`](https://libtmux.org/en/tmux/latest/manual/show-buffer/) uses one ordinary unattached tmux client with stdout reserved for
buffer bytes. The same live server guard, operation budget and alias audit apply.
It succeeds only after normal process completion and complete pipe draining,
with exit zero and empty stderr. A hook cannot hide an error by changing its
exit status. Post-launch read failure retains partial output and diagnostics;
it does not prove that the read was never dispatched. Buffer contents are never
parsed as receipts or errors. This contract does not apply to control mode.

[`load-buffer`](https://libtmux.org/en/tmux/latest/manual/load-buffer/) and [`save-buffer`](https://libtmux.org/en/tmux/latest/manual/save-buffer/) take literal file-path strings; `:name` selects
the buffer. Save overwrites unless `:append t` is supplied. Relative paths follow
the tmux command client's cwd. A literal file named `-` must be spelled `./-`;
use set/show for in-memory bytes. Empty input or an empty loaded file is tmux's
no-op and preserves any existing buffer.
Save success records tmux's reported completion; it does not independently
verify file contents or durability. Tmux 3.3a can suppress some file-write errors.

[`paste-buffer`](https://libtmux.org/en/tmux/latest/manual/paste-buffer/) takes a physical pane and optional `:name`. Newlines become Return
by default. `:raw t` preserves them; a separate `:separator` string replaces
each newline. `:bracketed t` requests bracket markers when the pane enabled
bracketed paste. `:verbatim t` preserves all bytes, disables newer tmux control-byte
sanitization, and cannot add separators or bracket markers. It chooses flags
from the live daemon version. `:delete t` removes the selected buffer after pasting. Input
disablement and application consumption remain tmux/application concerns.

[`delete-buffer :name`](https://libtmux.org/en/tmux/latest/manual/delete-buffer/) requires tmux 3.4 or newer. On 3.3a it signals
[`unsupported-capability`](<https://libtmux.org/en/lisp/latest/reference/libtmux-unsupported-capability/>) before dispatch, because that release can delete an
unrelated top buffer when a named buffer is missing. The condition exposes
[`error-feature`](<https://libtmux.org/en/lisp/latest/reference/libtmux-error-feature/>), [`error-required-version`](<https://libtmux.org/en/lisp/latest/reference/libtmux-error-required-version/>) and [`error-actual-version`](<https://libtmux.org/en/lisp/latest/reference/libtmux-error-actual-version/>); the check
uses the live daemon's version, independently of the selected executable.

Omitting a buffer name for show, save, paste or delete uses tmux's default:
the newest buffer on 3.3a, and the newest **automatic** buffer from 3.4 onward.
It does not select the newest explicitly named buffer on modern tmux.

## Configuration inspection

[`show-options-text`](https://libtmux.org/en/lisp/latest/reference/libtmux-show-options-text/),
[`show-hooks-text`](https://libtmux.org/en/lisp/latest/reference/libtmux-show-hooks-text/) and
[`show-environment-text`](https://libtmux.org/en/lisp/latest/reference/libtmux-show-environment-text/) return native
UTF-8 printer text and a retained command outcome. Supply an explicit scope;
local tables require the matching captured target. Normal client identity,
preflight, last-moment target guards, cancellation and resource limits apply.
These functions acquire state and do not change earlier observations.

This function from the [executed example package](https://github.com/libtmux/libtmux-lisp/blob/c2e5fc4ed3befda21f45dfa5d5868c38fd138311/examples/workspace.lisp)
returns three printer views plus their diagnostic outcomes. The
[REPL tutorial](https://libtmux.org/en/lisp/latest/guides/tutorial/) supplies the package's `tm` nickname and setup.

<!-- example:configuration -->
```lisp
(defun configuration-report (client session)
  "Read native configuration text; return an owned report and diagnostic outcomes."
  (let ((outcomes nil))
    (flet ((inspect-text (reader &rest options)
             (multiple-value-bind (text outcome) (apply reader client options)
               (push outcome outcomes)
               text)))
      (let ((report
              (list :options (inspect-text #'tm:show-options-text
                                           :scope :session :target session
                                           :name "status" :include-inherited t)
                    :hooks (inspect-text #'tm:show-hooks-text
                                         :scope :session :target session)
                    :environment (inspect-text #'tm:show-environment-text
                                               :scope :session :target session))))
        (values report (coerce (nreverse outcomes) 'simple-vector))))))
```
<!-- /example -->

Option and hook `:name` is a literal tmux reference: format-looking characters
stay literal, while native abbreviations and array-reference syntax still
apply. Omit it to list the table. `:scope` selects native flags; tmux can infer
a built-in option's table from its name instead. These raw inspectors do not
enforce the typed mutation catalog's name/type restrictions.
A physical window's native format context need not identify one particular
captured session link; use a session target for session-table inspection.

[`show-options-text`](<https://libtmux.org/en/lisp/latest/reference/libtmux-show-options-text/>) exposes `:include-inherited` (`-A`), `:include-hooks` (`-H`)
and `:value-only` (`-v`). Native whole-table `-A` output does not promise
inherited user `@` options. [`show-hooks-text`](<https://libtmux.org/en/lisp/latest/reference/libtmux-show-hooks-text/>) has no server-scope flag; its named
printer can return an ordinary `@` option without proving event registration.
Its `:monitors` option selects native monitor presentation. Both printers'
`:format` and hook monitor inspection require the live daemon to be tmux 3.8.
Format text is explicit tmux source with no implicit time expansion; `#()`
can start command-client jobs whose results may be incomplete and whose
cleanup follows client disconnect.

Environment scopes are `:global` and captured `:session`. Session output is the
raw table, not a merged child environment. `:hidden t` selects hidden entries;
the default selects ordinary entries. A visibility mismatch may succeed with
empty text, which does not prove absence. `:shell-format t` returns native
shell-looking text as data. Names may contain spaces, format punctuation and
Unicode; only empty text, NUL and `=` are rejected. No reader executes this text.

Escaping, whitespace and ordinary hook output stay in the returned presentation.
Foreign names and multiline values can make bulk text ambiguous. Missing names
remain native errors with outcome evidence; invalid UTF-8 signals a decoding
condition retaining the client and original bytes. These operations do not
claim parsed values, presence, inherited provenance or complete decoded
records. Decoded acquisition remains under development behind its separate
[transport admission gate](https://github.com/libtmux/libtmux-lisp/blob/c2e5fc4ed3befda21f45dfa5d5868c38fd138311/docs/adr/0001-native-common-lisp-engine.md#qualify-control-mode-and-source-filtering-before-exposing-them).

## Configuration mutations

[`set-option`](https://libtmux.org/en/lisp/latest/reference/libtmux-set-option/) and
[`unset-option`](https://libtmux.org/en/lisp/latest/reference/libtmux-unset-option/) address one explicit tmux option
table. Server and global scopes reject a target. Session, window and pane
scopes require a captured target of that type, so the normal generation and
last-moment target guards apply. The exact live daemon version selects the
reviewed option catalog after preflight; the executable's version cannot
silently substitute for it. The current catalogs cover the twelve exact
supported releases from 3.3a through 3.8. An unreviewed neighboring release
signals an error; see [capabilities and current limits](https://libtmux.org/en/lisp/latest/guides/capabilities/).

Literal writes validate the catalog's native Boolean, integer, choice and text
type before payload dispatch. `nil` is a valid false option value and becomes
tmux `off`. `:format-p t` instead accepts explicit tmux format text and lets the
daemon validate its expanded value. Registered array elements use `:key` and
never allocate a vector by the greatest numeric key. Without `:key`, an array
value uses the option's native tmux list grammar and may create several entries;
use `:key` when the value must remain one literal entry. `:append t` is accepted
only where tmux implements it: strings, keyed string-array values and unkeyed
array assignment. Public user-option writes accept the reversible
`@[A-Za-z0-9_.-]+` name grammar.

`:only-if-unset t` requests a local absent-only write. An inherited value permits
a local override. An existing local value, including false or empty text,
refuses replacement and retains the normal condition/outcome evidence. With
`:key`, tmux tests that array element; other local keys may already exist.
Without a key, it tests the local option entry. This condition applies once to
the selected command; hooks and later operations remain independent. The
default keeps ordinary replacement behavior.

[`set-hook`](https://libtmux.org/en/lisp/latest/reference/libtmux-set-hook/) accepts explicit tmux command source; it
does not parse the source as Lisp or execute it locally. Ordinary installation
never uses tmux's immediate-run flag. Tmux can still run a registered native
after-hook such as [`after-set-hook`](https://libtmux.org/en/tmux/latest/catalog/hooks/after-set-hook/) as a consequence of processing the command.
Keyed hook entries do not support appending command text; unkeyed append adds
hook entries through tmux's array grammar. Use
[`unset-hook`](https://libtmux.org/en/lisp/latest/reference/libtmux-unset-hook/) to remove the hook. Registered hooks
stay separate from ordinary option writes, and the live catalog gates dynamic
event sources.

[`set-environment`](https://libtmux.org/en/lisp/latest/reference/libtmux-set-environment/) writes one raw global or
captured-session environment table. It accepts literal text by default,
explicit format expansion through `:format-p t`, and tmux's hidden flag.
[`unset-environment`](https://libtmux.org/en/lisp/latest/reference/libtmux-unset-environment/) deletes an entry;
[`remove-environment`](https://libtmux.org/en/lisp/latest/reference/libtmux-remove-environment/) stores tmux's
removal marker. A tombstone, absence and a present empty string remain distinct.
Names use `[A-Za-z_][A-Za-z0-9_]*` so later named acquisition is reversible.

All seven operations return a
[`command-outcome`](https://libtmux.org/en/lisp/latest/reference/libtmux-command-outcome/), retain effective arguments
and diagnostics, and never retry uncertain mutations. Use the guarded
[text inspectors](https://libtmux.org/en/lisp/latest/guides/operations/#configuration-inspection) for native printer views and
[decoded configuration](https://github.com/libtmux/libtmux-lisp/blob/c2e5fc4ed3befda21f45dfa5d5868c38fd138311/docs/configuration.md) for typed, presence-aware reads. Use
[`run-command`](https://libtmux.org/en/lisp/latest/reference/libtmux-run-command/) when raw tmux argv and its weaker
target contract are intentional.

## Explicit termination

[`kill-pane`](https://libtmux.org/en/lisp/latest/reference/libtmux-kill-pane/),
[`kill-window`](https://libtmux.org/en/lisp/latest/reference/libtmux-kill-window/) and
[`kill-session`](https://libtmux.org/en/lisp/latest/reference/libtmux-kill-session/) accept one captured physical
target. The same preflight and last-moment guards used by other named mutations
reject a missing, replaced or foreign-generation target. These functions do not
expose tmux's broad `-a` forms. Killing a physical window removes all its links;
killing a session removes that session's links and any now-unreferenced panes.

[`kill-server`](https://libtmux.org/en/lisp/latest/reference/libtmux-kill-server/) is deliberately separate from
[`close-client`](https://libtmux.org/en/lisp/latest/reference/libtmux-close-client/). Closing releases library-owned
resources and leaves tmux alive. Server termination succeeds only after a
pre-dispatch receipt and readiness of the pidfd retained for the daemon accepted
during this call's preflight prove both dispatch and process exit. Daemon death
without the receipt remains `:unknown` because another actor could have
terminated it. After observed death, the client remains open but its generation
is invalidated; retained captures still support local traversal and projection.

All four operations are destructive and never retry automatically. Select the
target once, establish cardinality before dispatch, and inspect a retained
condition outcome when completion is uncertain.

## Outcomes and target checks

Mutators return [`command-outcome`](<https://libtmux.org/en/lisp/latest/reference/libtmux-command-outcome/>). [`outcome-value`](<https://libtmux.org/en/lisp/latest/reference/libtmux-outcome-value/>) returns a value and presence
as two values. Rename and selection accept `:observe nil` to omit follow-up
acquisition. Otherwise a successful mutation followed by failed acquisition
still has status `:succeeded`, no value, and an [`outcome-observation-error`](<https://libtmux.org/en/lisp/latest/reference/libtmux-outcome-observation-error/>).

| Evidence | Outcome |
| --- | --- |
| Preflight failed or live guard explicitly rejected the target | `:not-dispatched` |
| Completion receipt, successful tmux process exit and empty stderr | `:succeeded` |
| Completion receipt and nonzero process exit | `:failed` |
| Successful process exit with diagnostic output | `:unknown` |
| Dispatched operation lacks required receipts, or transport lost completion | `:unknown` |
| Server pidfd proves exit but the pre-dispatch receipt is missing | `:unknown` |
| Server receipt and retained pidfd both prove explicit termination | `:succeeded`, phase `:server-terminated` |
| Server exit wait fails after dispatch | `:unknown`, reason `:server-exit-unobserved`; cause retained |

The outcome retains exit status, diagnostic bytes, effective arguments and
elapsed time. A failed command queue can have completed effects; it does not
imply rollback. An unknown mutation is never automatically retried.

Validation checks the live server generation and captured entity identity.
The dispatch connection checks the daemon again and checks physical targets or
session/index/window mappings immediately before the payload. A reused link
index signals [`stale-target`](<https://libtmux.org/en/lisp/latest/reference/libtmux-stale-target/>). These checks do not make selection and mutation
a transaction; tmux hooks and other clients can change state.

Capture preserves whitespace and trailing lines. The text API strictly decodes
UTF-8; decoding failures retain the client and raw command outcome. The byte API
copies output without decoding. Its flags expose tmux's history, wrapping,
alternate-screen, pending-output and escape modes; they do not reconstruct
terminal bytes that tmux did not retain.

## Command aliases and daemon configuration

Named APIs require the original built-in command meanings and stable
[`command-alias`](https://libtmux.org/en/tmux/latest/catalog/options/command-alias/) configuration during each call. [`show-options`](https://libtmux.org/en/tmux/latest/manual/show-options/) is the trusted
bootstrap spelling used to inspect aliases. It must remain the built-in command.
The audit cannot safely inspect an arbitrary override of itself or prevent
configuration changes after inspection.

Before acquisition or a named operation, the library reads [`command-alias`](https://libtmux.org/en/tmux/latest/catalog/options/command-alias/) and
signals [`unsupported-configuration`](<https://libtmux.org/en/lisp/latest/reference/libtmux-unsupported-configuration/>) for collisions with reserved command names.
[`error-setting`](<https://libtmux.org/en/lisp/latest/reference/libtmux-error-setting/>) identifies the option; [`error-commands`](<https://libtmux.org/en/lisp/latest/reference/libtmux-error-commands/>) returns the colliding
spellings. The reserved list is maintained in
[command-policy.lisp](https://github.com/libtmux/libtmux-lisp/blob/c2e5fc4ed3befda21f45dfa5d5868c38fd138311/src/command-policy.lisp). Other alias names are allowed.
The check conservatively rejects an apparent reserved assignment on any line
of a multiline alias value.

Configured tmux hooks keep their ordinary behavior. The library does not remove
aliases or hooks from the user's daemon. [`run-command`](<https://libtmux.org/en/lisp/latest/reference/libtmux-run-command/>) remains an explicit raw
escape hatch with tmux's command grammar and no captured-target or alias audit.
