# Changelog

## libtmux-mcp 0.1.x (unreleased)

<!-- KEEP THIS PLACEHOLDER - DO NOT REMOVE OR MODIFY THIS LINE -->
_Notes on upcoming releases will be added here_
<!-- END PLACEHOLDER - ADD NEW CHANGELOG ENTRIES BELOW THIS LINE -->

## libtmux-mcp 0.1.0a12 (2026-06-13)

libtmux-mcp 0.1.0a12 hardens the MCP server's read-only and safety surface and adds a one-call `run_command` tool. Read-only tools can no longer trigger tmux format-job shell evaluation, an invalid safety tier fails closed instead of exposing write tools, and large successful results keep their structured payload. Panes and windows also gain liveness and active-pane metadata, and the package ships a `py.typed` marker. The fastmcp floor rises to 3.4.2 to pick up its explicit `starlette>=1.0.1` floor (CVE-2026-48710).

### Dependencies

**Minimum `fastmcp>=3.4.2`** (was `>=3.4.0`). Picks up fastmcp 3.4.1's explicit `starlette>=1.0.1` floor, so installs can no longer resolve to a Starlette version affected by CVE-2026-48710 — previously this was constrained only transitively through `mcp`. (#77)

### What's new

**One-call command completion with {tooliconl}`run-command`**

{tooliconl}`run-command` runs a shell command in a pane, waits for it to finish, and returns the exit status, timeout state, and tail-preserved output in a single call — no manual {tooliconl}`send-keys` + {tooliconl}`wait-for-channel` + {tooliconl}`capture-pane` sequence. The command runs in a subshell so its state changes don't leak into later calls, and `suppress_history` keeps secret-bearing commands out of shell history where the shell ignores space-prefixed input. (#73)

**Richer, typed pane and window metadata**

{tooliconl}`snapshot-pane` now reports `pane_pid`, `pane_dead`, and `alternate_on` for liveness and alternate-screen decisions, and window results carry `active_pane_id` for reliable follow-up targeting. The package also ships a `py.typed` marker so downstream type checkers see its inline annotations. (#75)

### Fixes

**Read-only tools no longer evaluate tmux `#()` format jobs**

{tooliconl}`search-panes` and {tooliconl}`display-message` are advertised as read-only, but tmux `#(...)` formats schedule shell jobs during expansion. Both now reject or route around `#()` so a read-only call can never spawn a shell. (#68, #69)

**Invalid `LIBTMUX_SAFETY` fails closed**

An unrecognized `LIBTMUX_SAFETY` value now falls back to `readonly` instead of `mutating`, so a typo in the safety tier can no longer expose write tools the operator meant to hide. (#71)

**Large structured results keep their structured payload**

The global response backstop was truncating big successful results into text-only responses before tool-level caps ran, dropping the structured metadata schema-bearing tools depend on. It now matches FastMCP's 1 MB default, leaving per-tool line caps to handle terminal truncation. (#70)

**{tooliconl}`clear-pane` clears scrollback reliably**

{tooliconl}`clear-pane` now uses libtmux's single-call reset path; the previous two-call sequence could leave scrollback intact. Its annotations also disclose that it is destructive and non-idempotent. (#74)

**Stdio transport pinned at startup**

The server runs with an explicit stdio transport so an inherited FastMCP transport environment can't change its startup surface and break stdio clients, and `--help` / `--version` resolve locally without starting the server. (#72)

## libtmux-mcp 0.1.0a11 (2026-06-06)

libtmux-mcp 0.1.0a11 redesigns how tool failures reach agents. Error messages now arrive exactly as raised — no more `Internal error:` mangling — with structured detail and recovery hints that tell agents what to do next, from stale pane ids to stray arguments leaked by client schedulers. Expected, agent-correctable failures log at WARNING so ERROR records always mean an operator should look. The fastmcp floor rises to 3.4.0 to build on its error-result and log-level support.

### Dependencies

**Minimum `fastmcp>=3.4.0`** (was `>=3.2.4`). Enables the error-result and log-level improvements below; the bump alone also restores resource titles on the `tmux://` hierarchy and brings MCP-compliant telemetry span attributes.

### What's new

**Tool errors arrive clean, with structured detail and recovery hints**

Failed tool calls now return their message exactly as raised — previously every failure was prefixed with `Internal error:`. Error results carry a structured `_meta` payload (`error_type`, `expected`, `suggestion`), and not-found errors point at {tooliconl}`list-sessions` / {tooliconl}`list-windows` / {tooliconl}`list-panes` to resolve stale or guessed ids. (#64)

**Unknown tool arguments get a do-this-next hint**

When a call includes arguments a tool doesn't accept, the error result now names exactly which argument(s) to remove or fix. When the stray key is `wait_for_previous` — a scheduling flag Gemini CLI can leak into batched tool calls — the hint says so and names the connected client, so agents recover in one read instead of re-deriving the problem from a validation traceback. (#64)

**Expected tool failures log at WARNING, not ERROR**

Agent-correctable failures — unknown ids, invalid arguments, safety-tier denials, transient tmux errors — now log at WARNING in the server's log stream. A missing tmux binary and unexpected exceptions stay at ERROR, so ERROR records are always worth attention. (#64)

## libtmux-mcp 0.1.0a10 (2026-05-24)

### What's new

**Incremental pane observation with {tooliconl}`capture-since`**

{tooliconl}`capture-since` gives agents a cursor-based way to observe a pane without re-reading the same terminal output on every turn. The first call returns the current visible screen and an opaque cursor; later calls return only rows written or rewritten after that cursor while tmux still retains the needed history. If scrollback was cleared or trimmed, the result sets `lines_missed=True`, returns a conservative current visible capture, and issues a fresh cursor. Malformed cursors, cross-pane replay, pane death, and pane respawn fail clearly instead of silently switching processes. (#60)

## libtmux-mcp 0.1.0a9 (2026-05-24)

libtmux-mcp 0.1.0a9 tightens pane polling correctness for agents waiting on terminal output. Search and wait tools now handle wrapped content, history-limit risk reporting, and pane lifecycle changes with clearer results instead of silent false positives.

### Fixes

**{tooliconl}`search-panes` matches wrap-spanning slow-path text**

{tooliconl}`search-panes` now joins tmux-wrapped visual rows when it uses the captured-content slow path, so long build, test, or log lines can match across the pane width. Plain fast-path searches still use tmux's native visual-row search; pass `regex=True` or a content range when exact text may span a wrap boundary. (#55)

**{tooliconl}`wait-for-text` reports trim-risk warnings in results**

{tooliconl}`wait-for-text` now returns `risk_band_warned=True` when polling enters tmux's history-limit trim-risk band. Clients that do not surface MCP warning notifications can still detect that matching was best-effort and switch to {tooliconl}`wait-for-channel` for deterministic command completion. (#54)

**{tooliconl}`wait-for-content-change` fails on pane lifecycle changes**

{tooliconl}`wait-for-content-change` now raises a tool error when the watched pane dies or is respawned during the wait. Those lifecycle changes invalidate the entry content baseline, so callers no longer receive a misleading `changed=True` result for a different pane process. (#53)

## libtmux-mcp 0.1.0a8 (2026-05-23)

libtmux-mcp 0.1.0a8 bumps libtmux to 0.58.0, fixing session and window listing on systems whose locale is not UTF-8.

### Dependencies

**Minimum `libtmux>=0.58.0`** (was `>=0.56.0`). Picks up the 0.57.x command-coverage and client-awareness releases and the 0.58.0 non-UTF-8 locale fix — session and window listing could silently return empty results when the system locale was not UTF-8.

### What's new

**Installer picker now covers config scope and file locations**

The MCP install widget on the front page, {doc}`/quickstart`, and {ref}`clients` now lets you pick a config scope per LLM client alongside the install method — *local* / *user* / *project* for Claude Code, *user* / *project* for Codex and Gemini, *project* / *global* for Cursor. JSON-only clients (Cursor, Claude Desktop) also show the destination config-file path next to the snippet so the paste target is never a guess. Your scope choice is remembered per-client, so switching between clients restores each one's last selection.

**Installer picker can apply or bypass dependency cooldowns**

A new *Configure cooldowns* control on the install widget lets you tack a cooldown onto the snippet without leaving the page. Pick a delay in days (uv's `--exclude-newer`, pip's `--uploaded-prior-to`, pipx's `--pip-args`) to wait out community vetting before pulling a fresh release, or pick *Bypass any global cooldown* to skip a `~/.config/uv/uv.toml` cutoff and grab the latest libtmux-mcp anyway. The setting persists across pages, and the embedded *What are cooldowns?* expander links to the [Datadog Security Labs writeup](https://securitylabs.datadoghq.com/articles/dependency-cooldowns/) and [cooldowns.dev](https://cooldowns.dev/) if you want the supply-chain context. (#31)

### Documentation

**MCP install widget ships working cooldown snippets**

The install widget on the front page, {doc}`/quickstart`, and {ref}`clients` now emits a runnable snippet in every method × cooldown cell. uvx days panels apply the cooldown to transitive dependencies while exempting libtmux-mcp itself, so a fresh release stays installable. pipx and pip days panels fall back to the bare install command — neither tool exposes a per-package cooldown override today — and their cooldown note redirects readers to the uvx tab when they want true cooldown enforcement. (#58)

## libtmux-mcp 0.1.0a7 (2026-05-16)

### Breaking changes

**{tooliconl}`wait-for-text` waits for new output, not stale scrollback**

{tooliconl}`wait-for-text` now matches lines written *after* the call begins. The previous behaviour returned `found=True` on the first poll whenever the pattern already lived in the pane, so agents synchronising on command output got the wrong result. For the synchronous "is the pattern in the pane right now?" case, call {tooliconl}`search-panes` instead.

Baseline-loss events surface as `ToolError`: pane respawn, pane death, `clear-history`, and any other event that drops history below the entry baseline. Pane resize that pulls lines back from history into the visible region is exempted — the anchor stays valid.

Trim during heavy output near `history-limit` can't be reliably detected from polling alone. When polling approaches that limit, the tool emits a `notifications/message` warning so MCP clients can decide whether to keep waiting, retry, or switch to {tooliconl}`wait-for-channel`. For deterministic command completion, compose `tmux wait-for -S <channel>` into the shell command and call {tooliconl}`wait-for-channel`. (#45)

**{tooliconl}`wait-for-text` drops `content_start` / `content_end`**

The new baseline anchor follows the pane's grid position automatically, so the manual capture-range parameters have no remaining purpose. Drop them from call sites. (#45)

```python
# Before
wait_for_text(pattern="OK", content_start=-100)

# After
wait_for_text(pattern="OK")
```

**Wait result models drop `timed_out`**

{class}`~libtmux_mcp.models.WaitForTextResult` and {class}`~libtmux_mcp.models.ContentChangeResult` drop the `timed_out` field. It was mechanically the boolean negation of the primary result (`not found` / `not changed`) and carried no information beyond that. Callers should switch to `not result.found` / `not result.changed`. (#47)

```python
# Before
result = wait_for_text(pattern="OK")
if result.timed_out:
    ...

# After
result = wait_for_text(pattern="OK")
if not result.found:
    ...
```

### Dependencies

**Minimum `libtmux>=0.56.0`** (was `>=0.55.1`). Picks up libtmux 0.56's typed wrappers for the tmux commands the server invokes — the MCP now uses libtmux's public API instead of raw command-line escapes for pane lifecycle, scrollback, and session navigation. (#46)

### Fixes

**{tooliconl}`wait-for-channel` recipe no longer exits the parent shell**

The `run_and_wait` prompt template previously appended `exit $__mcp_status` to its shell payload to preserve the command's exit status. In an interactive shell that exits the shell itself, destroying single-pane sessions. The recipe now signals completion via `tmux wait-for -S` without exiting, and the equivalent example in {doc}`/tools/pane/wait-for-channel` is similarly fixed. Exit-status preservation in interactive shells is documented as out-of-scope; agents that need it should inspect the captured output for command-specific success markers. (#47)

**{tooliconl}`wait-for-text` matches patterns across visually-wrapped lines**

Long patterns like `"Build failed: module not found"` that tmux wraps at the pane's column width are now matched against the joined logical line. Previously the wrap split the pattern across two captured rows and neither row matched. The joined line is returned in `matched_lines` and can exceed the pane width. (#45)

**{tooliconl}`wait-for-text` rejects misused `pattern` / `interval` / `timeout`**

Empty `pattern`, `interval` below 10 ms, and non-positive `timeout` each raise `ToolError` at entry. Previously they silently matched every line, spun the tmux server in a tight loop, or completed a surprise single probe. (#45)

### Documentation

**Wait family is re-framed around {tooliconl}`wait-for-channel` as the deterministic primitive**

The {tooliconl}`send-keys` docstring, server system instructions, {tooliconl}`wait-for-text` docstring, and the user-facing quickstart, gotchas, prompting, troubleshooting, recipes, and send-keys topics now point agents at {tooliconl}`wait-for-channel` with composed `tmux wait-for -S` for command completion. {tooliconl}`wait-for-text` and {tooliconl}`wait-for-content-change` are reframed as the fallbacks for output the agent does not author. The `run_and_wait` recipe shows the canonical safe-completion pattern. (#45)

## libtmux-mcp 0.1.0a6 (2026-05-09)

libtmux-mcp 0.1.0a6 is the activation and registration cleanup release. It makes the server much easier for MCP clients to discover from ordinary "pane", "window", and "session" prompts, standardizes new setup docs around the `tmux` registration slug, and adds migration guidance for existing `libtmux` registrations. Existing installs keep working; the release changes defaults and documentation so new installs line up with the tool prefix users actually see.

### What's new

**Bare tmux prompts now find the server**

Agents no longer need the word "tmux" in every prompt before this server becomes relevant. The server instructions now name the positive cases users naturally write, such as "split this pane", "current window", and "this session", while steering clients away from unrelated browser tabs, editor splits, tiling-window-manager panes, and notebook cells. The discovery anchors most likely to answer those prompts - {tooliconl}`list-panes`, {tooliconl}`list-windows`, and {tooliconl}`snapshot-pane` - also carry the preload hint used by clients that keep a small always-available schema set. See {ref}`prompting` for the user-facing activation contract. (#37)

**New installs are documented as `tmux`**

The recommended registration slug is now `tmux`, matching the MCP `serverInfo.name` and the `mcp__tmux__*` tool-call prefix surfaced by clients. The package name, import name, and existing user-created `libtmux` registrations are unchanged; only the documented install target moves to the clearer slug. See {ref}`migration` for the walkthrough. (#40)

### Documentation

Hierarchy-noun tool titles now include a `tmux` qualifier in catalog-style displays, so entries like "List tmux Sessions" stay understandable when a client shows tools from several MCP servers together. Tmux-specific verbs such as {tooliconl}`send-keys`, {tooliconl}`pipe-pane`, {tooliconl}`snapshot-pane`, {tooliconl}`capture-pane`, and {tooliconl}`paste-text` keep their shorter names because the verb already identifies the tmux operation. (#38)

The {ref}`prompting` guide gains an activation and discovery section with positive triggers, anti-triggers, a client-level `alwaysLoad` example, and a project-instructions fragment for teams that want stronger bias toward tmux when users say "this pane" or "current window". (#39)

## libtmux-mcp 0.1.0a5 (2026-05-06)

libtmux-mcp 0.1.0a5 makes layout-relative pane targeting a first-class workflow. Agents can ask for "the bottom-right pane" directly, reason from typed geometry returned on pane models, and avoid parsing tmux format strings for common layout questions. The release also polishes the documentation site after the theme migration and extends the local MCP swap helper so Claude users can choose project-local or user-global config.

### What's new

**Layout-relative pane targeting via {tooliconl}`find-pane-by-position`**

{tooliconl}`find-pane-by-position` resolves a window corner - top-left, top-right, bottom-left, or bottom-right - to a single {class}`~libtmux_mcp.models.PaneInfo`. This replaces the old workaround of calling {tooliconl}`display-message` with `#{pane_at_bottom}` / `#{pane_at_right}` and parsing raw string output. Single-pane and otherwise ambiguous layouts resolve deterministically, so the common "use the only pane" case does not require an extra branch in the agent workflow. (#34)

**Pane responses now carry geometry**

{class}`~libtmux_mcp.models.PaneInfo`, {class}`~libtmux_mcp.models.PaneContentMatch`, and {class}`~libtmux_mcp.models.PaneSnapshot` now include window-relative coordinates, edge predicates, and the pane TTY. That means an agent can inspect returned data to decide whether a pane is at the left edge, bottom edge, or a specific corner instead of making another tmux query. The older `pane_width` and `pane_height` fields intentionally keep their existing string typing in this alpha; changing those fields is left for a later breaking-change window. (#34)

### Documentation

The docs site moves onto `gp-furo-theme` with `sphinx-vite-builder` handling the theme asset pipeline, so the rendered site follows the same gp-sphinx docs stack used by the rest of the project documentation. (#33)

The install widget and above-the-fold typography no longer shift after first paint. Saved install-widget choices now render in the correct panel immediately, and the fonts and logo used on the landing page are loaded early enough to avoid visible swaps. (#36)

The new corner-finder appears anywhere a reader is likely to look for targeting guidance: the homepage tool chain, tools index, pane tools page, prompting guide, recipes, and example responses. Existing {tooliconl}`display-message` guidance now points layout-relative pane selection at {tooliconl}`find-pane-by-position` instead of teaching agents to expand pane-edge format variables by hand. (#34)

### Development

`scripts/mcp_swap.py` gains `--scope {user,project}` for Claude. Project scope keeps the safe local override used while working in this checkout; user scope intentionally changes the fallback used from other projects. Codex, Cursor, and Gemini have only a global layer, so the flag is accepted there without creating a fake per-project mode. (#35)

## libtmux-mcp 0.1.0a4 (2026-05-02)

libtmux-mcp 0.1.0a4 adds pane recovery and closes the last gap in the core hierarchy's single-object metadata reads. Agents can restart a stuck pane without losing its identity, fetch known sessions or windows directly, and use a bundled development script to point local MCP clients at a checkout. The {tooliconl}`respawn-pane` parameter name settles on `shell` before the stable API, replacing the earlier alpha spelling `shell_command`.

### What's new

**Restart wedged panes in place with {tooliconl}`respawn-pane`**

{tooliconl}`respawn-pane` restarts the process in an existing tmux pane while preserving the `pane_id` and the window layout. That is the right recovery primitive for long-running agent sessions: {tooliconl}`kill-pane` followed by {tooliconl}`split-window` creates a new pane, invalidates stored handles, and can disturb the surrounding layout. The final alpha API uses `shell` for the replacement command to match {tooliconl}`split-window` and libtmux's upstream respawn naming. (#27)

**Direct metadata reads for sessions and windows**

{tooliconl}`get-session-info` and {tooliconl}`get-window-info` complete the server/session/window/pane metadata pattern alongside {tooliconl}`get-server-info` and {tooliconl}`get-pane-info`. Callers that already have an ID or a scoped index no longer need to call a list tool and filter the response. Buffers, hooks, options, and environment values keep their existing show/load/read tools rather than gaining redundant `get_*_info` wrappers. (#27)

### Documentation

{ref}`safety` now documents {tooliconl}`respawn-pane` as a mutating recovery tool with real process side effects, including the `kill=true` default and the visibility tradeoffs of passing command or environment data through tmux. The same update refreshes socket-guard notes for macOS, tightens guidance around {tooliconl}`display-message` and {tooliconl}`pipe-pane`, and adds dedicated tool pages for the new recovery and metadata tools. (#27)

### Development

`scripts/mcp_swap.py` lands as local dogfooding infrastructure for Claude, Codex, Cursor, and Gemini. It detects installed clients, shows the current libtmux-mcp registration, rewrites config to run this checkout through `uv`, and reverts from backups. The `just mcp-use-local` and `just mcp-revert` recipes wrap that flow for branch QA. (#27)

## libtmux-mcp 0.1.0a3 (2026-04-19)

libtmux-mcp 0.1.0a3 is a focused correctness release after the FastMCP alignment work. It fixes caller identity across multiple tmux sockets, moves channel waits off the FastMCP event loop, and raises the libtmux floor to pick up upstream pytest-fixture cleanup. The result is less surprising metadata in multi-server setups and fewer stalled clients during long waits.

### Dependencies

Minimum `libtmux>=0.55.1` (was `>=0.55.0`) for [tmux-python/libtmux#661](https://github.com/tmux-python/libtmux/pull/661), which fixes pytest-plugin socket cleanup under `/tmp/tmux-<uid>/`.

### Fixes

**Pane caller identity is socket-aware**

The `is_caller` pane annotation no longer treats pane `%0` on every tmux server as the current agent pane just because the pane IDs match. The annotation now compares the caller's tmux socket as well, matching the self-protection checks used around destructive tools. This fixes {class}`~libtmux_mcp.models.PaneInfo`, {class}`~libtmux_mcp.models.PaneSnapshot`, and {class}`~libtmux_mcp.models.PaneContentMatch` responses in multi-socket environments. (#22, fixes #19)

**Channel waits no longer stall the MCP server**

{tooliconl}`wait-for-channel` and {tooliconl}`signal-channel` now run their blocking tmux subprocess work outside the event loop. Other tool calls and client keepalives can continue while a wait is pending, matching the async behavior already used by {tooliconl}`wait-for-text` and {tooliconl}`wait-for-content-change`. (#21, fixes #18)

## libtmux-mcp 0.1.0a2 (2026-04-19)

libtmux-mcp 0.1.0a2 is the FastMCP alignment release. It expands the server from a basic tmux wrapper into a broader agent automation surface with discovery, waits, buffers, hooks, pane/window navigation, prompt recipes, middleware, and bounded terminal output. The release includes one response-shape breaking change: {tooliconl}`search-panes` now returns a paginated {class}`~libtmux_mcp.models.SearchPanesResult` instead of a bare list. (#15)

### Breaking changes

**{tooliconl}`search-panes` returns {class}`~libtmux_mcp.models.SearchPanesResult`**

{tooliconl}`search-panes` now returns a result object with matches and pagination metadata instead of the earlier `list[`{class}`~libtmux_mcp.models.PaneContentMatch``]` shape. Existing callers should iterate over `.matches`; callers that search large tmux workspaces can also inspect `truncated`, `truncated_panes`, `total_panes_matched`, `offset`, and `limit`.

```python
# Before
for match in search_panes(...):
    ...

# After
for match in search_panes(...).matches:
    ...
```

**Minimum `fastmcp>=3.2.4`** (was `>=3.1.0`). The newer FastMCP release is required for {class}`~libtmux_mcp.middleware.ReadonlyRetryMiddleware` and per-parameter input-schema descriptions.

### What's new

**Discovery and synchronization tools**

{tooliconl}`list-servers` discovers live tmux servers, including explicitly provided socket paths. The wait family adds content waits ({tooliconl}`wait-for-text`, {tooliconl}`wait-for-content-change`) and tmux channel synchronization ({tooliconl}`wait-for-channel`, {tooliconl}`signal-channel`) so agents can wait for explicit milestones instead of sleeping or repeatedly capturing panes. (#15)

**Buffers, hooks, and richer pane/window control**

Agent-namespaced buffer tools - {tooliconl}`load-buffer`, {tooliconl}`paste-buffer`, {tooliconl}`show-buffer`, and {tooliconl}`delete-buffer` - support staged multi-line input without overloading keystroke simulation. Read-only hook tools ({tooliconl}`show-hook`, {tooliconl}`show-hooks`) expose tmux hook state without adding write-hooks that survive process death. The pane and window surface grows with {tooliconl}`snapshot-pane`, {tooliconl}`pipe-pane`, {tooliconl}`display-message`, {tooliconl}`paste-text`, {tooliconl}`select-pane`, {tooliconl}`swap-pane`, {tooliconl}`select-window`, {tooliconl}`move-window`, {tooliconl}`enter-copy-mode`, and {tooliconl}`exit-copy-mode`. (#15)

**Prompt recipes for common agent workflows**

Four MCP prompts ship for repeatable tmux work: `run_and_wait`, `diagnose_failing_pane`, `build_dev_workspace`, and `interrupt_gracefully`. Clients that only expose tools can opt into tool-shaped prompt access with `LIBTMUX_MCP_PROMPTS_AS_TOOLS=1`. See {ref}`prompts-overview` for the prompt catalog. (#15)

**Middleware for safer long-running automation**

The middleware stack now includes {class}`~libtmux_mcp.middleware.AuditMiddleware` for digest-redacted argument summaries, {class}`~libtmux_mcp.middleware.SafetyMiddleware` for safety-tier visibility, {class}`~libtmux_mcp.middleware.ReadonlyRetryMiddleware` for transient readonly libtmux failures, and {class}`~libtmux_mcp.middleware.TailPreservingResponseLimitingMiddleware` for oversized tool output. Timing and error-handling middleware round out the request path. (#15)

**Tail-preserving bounded output**

{tooliconl}`capture-pane`, {tooliconl}`snapshot-pane`, and {tooliconl}`show-buffer` accept `max_lines` and report whether older lines were trimmed. Truncation keeps the newest terminal output, which is usually the active prompt or most recent command result. Pass `max_lines=None` when a caller intentionally wants the full scrollback or buffer. (#15)

**Better schemas and startup failures**

Tool input schemas now include parameter descriptions extracted from docstrings, so clients can explain arguments without separate docs lookups. Startup also fails with a clear {exc}`RuntimeError` when `tmux` is not available on `PATH`, and {attr}`~libtmux_mcp.models.SessionInfo.active_pane_id` tells callers which pane was created by {tooliconl}`create-session`. (#15)

### Fixes

- {tooliconl}`search-panes` neutralizes tmux format-string injection in the regex fast path.
- The macOS self-kill guard resolves the live tmux socket before falling back to `TMUX_TMPDIR` reconstruction.
- The `build_dev_workspace` prompt uses real tool parameter names, avoids waiting for prompts after screen-grabbing commands, and replaces a Linux-specific log default with `log_command`.
- {class}`~libtmux_mcp.middleware.ReadonlyRetryMiddleware` logs retry warnings under `libtmux_mcp.retry`.

### Documentation

The tools documentation gains category pages for {doc}`/tools/buffer/index`, {doc}`/tools/hook/index`, and {doc}`/tools/index`. The pane tools docs explain the {class}`~libtmux_mcp.models.SearchPanesResult` migration, while {ref}`safety` documents the audit log, socket caveats, {tooliconl}`pipe-pane`, and {tooliconl}`set-environment`. (#15)

## libtmux-mcp 0.1.0a1 (2026-04-13)

libtmux-mcp 0.1.0a1 expands the tmux control surface around the workflows agents actually perform after they find a pane. It adds richer screen snapshots, waits, navigation, pane/window movement, copy-mode entry points, live logging, and bracketed paste support. The docs also adopt the gp-sphinx visual stack so the generated API and tool pages become easier to scan. (#11)

### What's new

**Screen snapshots and waits**

{tooliconl}`snapshot-pane` returns terminal content together with cursor position, copy-mode state, and scroll position in a single read. {tooliconl}`wait-for-content-change` lets an agent wait for any visible update when it does not know the exact text to expect. {class}`~libtmux_mcp.models.PaneSnapshot` and {class}`~libtmux_mcp.models.ContentChangeResult` carry those responses in typed models. (#11)

**Pane and window navigation**

{tooliconl}`select-pane`, {tooliconl}`swap-pane`, {tooliconl}`select-window`, and {tooliconl}`move-window` let agents navigate within tmux and rearrange panes or windows without asking a user to manually focus the target. Directional window selection is scoped to the requested session, and pane selection handles next/previous relative navigation through concrete pane IDs. (#11)

**Terminal I/O helpers**

{tooliconl}`pipe-pane` logs live pane output to a file, {tooliconl}`display-message` exposes tmux format expansion as a read-only metadata escape hatch, {tooliconl}`enter-copy-mode` and {tooliconl}`exit-copy-mode` control copy-mode state, and {tooliconl}`paste-text` uses tmux buffers for multi-line input where raw keystroke simulation is fragile. (#11)

### Documentation

The API docs adopt the gp-sphinx documentation stack: card-style API layouts, safety and scope badges, MyST cross-reference roles, improved CLI-doc section scoping, IBM Plex typography, and FastMCP-aware tool rendering. The docs dependency stack is then refreshed to gp-sphinx `0.0.1a8`. (#10, #14)

## libtmux-mcp 0.1.0a0 (2026-03-22)

libtmux-mcp 0.1.0a0 is the first standalone alpha release, extracted from libtmux's MCP branch. It packages libtmux-backed tmux control as an MCP server with typed tools, hierarchy resources, safety tiers, and socket-aware server selection. The release establishes the base contract that later alphas expand: inspect tmux state, make scoped mutations, and keep destructive operations behind an explicit safety tier.

### What's new

**Standalone MCP server for tmux**

The package exposes tmux sessions, windows, panes, options, and environment operations through MCP tools backed by libtmux. It includes the console entry point, FastMCP server wiring, and the first set of Pydantic response models for tool output.

**Browsable tmux hierarchy**

`tmux://` resources let MCP clients browse the tmux hierarchy from server to sessions, windows, and panes. Tool resolvers accept the normal tmux identifiers so callers can move between resource browsing and concrete tool calls.

**Safety and socket isolation**

The initial server ships with readonly, mutating, and destructive safety tiers, controlled by `LIBTMUX_SAFETY`. Socket selection through `LIBTMUX_SOCKET` and `LIBTMUX_SOCKET_PATH` lets the same process target isolated tmux servers, and `TMUX_PANE` awareness marks the pane that belongs to the calling agent.

**Typed implementation baseline**

Server caching, resolver helpers, standardized error handling, and strict mypy coverage provide the internal foundation for later tool families. All initial tool responses are typed through Pydantic models rather than ad hoc dictionaries.
