# libtmux for PowerShell > The PowerShell library (LibTmux). These pages include its guides, tested examples and API documentation. - [PowerShell API reference](https://libtmux.org/en/powershell/latest/reference/): every public symbol, generated from the source. Hosted on libtmux.org. --- # Concepts Source: https://libtmux.org/en/powershell/latest/concepts/ > Understand captured objects, stable identities, and local versus remote queries. LibTmux cmdlets return native .NET objects. Learn which operations contact tmux, which values are captured, and what identifies the object a later command changes. Start with captured state before building a polling loop or retaining handles between operations. Then use the [complete examples](https://libtmux.org/en/powershell/latest/examples/) to run these ideas against a private server. - [Captured state and I/O](https://libtmux.org/en/powershell/latest/concepts/captured-state/): Know when data was read and distinguish missing capture from an empty result. - [Object identity and placement](https://libtmux.org/en/powershell/latest/concepts/identity/): Keep daemon identity, physical windows, and session placements separate. - [Local selection and source queries](https://libtmux.org/en/powershell/latest/concepts/queries/): Choose Where-Object, structured criteria, or an explicit fresh acquisition. --- # Captured state and I/O Source: https://libtmux.org/en/powershell/latest/concepts/captured-state/ > Separate explicit reads from local object traversal and preserve snapshot boundaries. A captured object describes what tmux reported during a read. Accessing its properties does not refresh it. This makes formatting, filtering, and inspecting a saved graph predictable even after the daemon has stopped. ## Choose the read boundary | Operation | What happens | | --- | --- | | [`New-TmuxServer`]() | Describes an explicit endpoint without contacting tmux. | | [`Connect-TmuxServer`]() | Discovers the generation of an unmaterialized handle; an already connected handle is returned unchanged. | | [`Get-TmuxSnapshot`]() | Acquires a new object graph at the requested depth. | | [`Get-TmuxSession`](), [`Get-TmuxWindow`](), [`Get-TmuxPane`]() | Read the selected owner through their command-specific acquisition path. | | Property access, formatting, or [`Select-TmuxPane`]() | Use captured values locally. | Keep one snapshot when several decisions must refer to the same captured graph. Repeated reads can observe different names, placements, or active panes. Taking a new snapshot returns a replacement graph; it does not update objects retained from an earlier capture. See the [read guide](https://libtmux.org/en/powershell/latest/guides/read/) for the owner accepted by each read cmdlet. ## Missing capture is not an empty collection The default snapshot depth reaches panes. Shallower depths reduce the acquired state, but relationships below that depth are unavailable. Check their [`IsCaptured`](https://libtmux.org/en/csharp/latest/reference/libtmux-capturedrelation-iscaptured/) state before using them. Enumerating an uncaptured relationship raises an error; it does not return an empty list. Required uncaptured fields likewise fail instead of inventing a value. A captured empty list means the read found no children. A captured nullable active child can have no value. Those results differ from a relationship that was never acquired. Use the native captured-value contract when that distinction matters, and choose a nullable convenience projection only when treating missing capture as no value is intentional. ## A snapshot is a bounded observation Acquisition takes several tmux commands. The library rejects contradictions it can detect, such as inconsistent parent or child counts, but concurrent changes can escape those checks. A snapshot is not an atomic transaction or a reservation of the objects it contains. Capture metadata records depth, generation, wall-clock boundaries, and elapsed time. Use elapsed time for duration; the wall clock can move while a read runs. Take a fresh snapshot after mutation or event loss when your next decision needs current topology. Run [create windows and panes](https://libtmux.org/en/powershell/latest/examples/create-layout/) to create a graph, read it once, and traverse its windows locally. The [`Get-TmuxSnapshot` reference](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxsnapshot/) gives the supported depth and parameter details. --- # Object identity and placement Source: https://libtmux.org/en/powershell/latest/concepts/identity/ > Understand endpoint handles, daemon generations, physical windows, and session links. Select the endpoint explicitly, then keep the identity returned with its native objects. A textual pane or session ID alone is not enough to identify an object across different servers or daemon restarts. ## Endpoint and daemon generation [`New-TmuxServer`]() accepts an explicit socket selector. It creates a description, not a daemon. [`Connect-TmuxServer`]() discovers the live generation and returns a connected replacement when the supplied handle is not materialized. Keep that returned handle when subsequent work needs the discovered identity. Pass native objects into mutation cmdlets. Their identity and placement guards can be retained by typed commands. Reconstructing a command from raw target text throws away that information. Raw `-Target` on control attachment uses tmux target syntax at attachment time; it is not the identity of a captured session. ## IDs and names serve different purposes Session, window, and pane IDs have distinct prefixes. PowerShell expands a dollar sign in a double-quoted string, so write a session ID as `'$0'` when entering it literally. A window ID such as `'@1'` and a pane ID such as `'%2'` select different kinds of object. The read cmdlets' `-Id` and `-Name` filters are exact and case-sensitive. They do not interpret wildcards. When both are supplied, both must match. A name can change; retain the native result when you intend to act on the same object. See [reading objects](https://libtmux.org/en/powershell/latest/guides/read/) for matching and empty-result behavior. ## A window can appear in several sessions A physical window can be linked into more than one session and can have more than one placement. Its index belongs to the placement. Do not use a window's name or one session's index as a global key. Captured session-window links preserve these occurrences. A physical pane still belongs to its window; a traversal through multiple session placements can encounter it more than once. Choose whether your operation is about physical windows, distinct sessions, or placements before deduplicating results. Filtering a captured collection changes membership, not the graph referenced by the selected objects. Parent and sibling navigation still describes the original capture. Refreshing one pane does not silently recreate an old parent graph; acquire a new snapshot for a coherent traversal. The [placement guide](https://libtmux.org/en/powershell/latest/guides/placement/) covers links and moves. Continue with [ownership and cleanup](https://libtmux.org/en/powershell/latest/topics/ownership/) before deciding which resources your application may remove. --- # Local selection and source queries Source: https://libtmux.org/en/powershell/latest/concepts/queries/ > Choose ordinary pipelines, reusable criteria, or a fresh daemon-side query. Use a local pipeline to inspect data you already captured. Use an explicit source query when the decision requires a fresh read from tmux. A filter never makes an old snapshot current. ## Choose the simplest useful query | Need | Use | | --- | --- | | An ordinary PowerShell predicate over existing objects | [`Where-Object`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/where-object) | | Reusable, inspectable criteria for captured objects | [`New-TmuxQuery`]() and the matching [`Select-TmuxSession`](), [`Select-TmuxWindow`](), or [`Select-TmuxPane`]() | | A fresh acquisition with a query plan | [`Invoke-TmuxQuery`]() | | The allowed fields and operators | [`Get-TmuxQueryField`]() | The structured selectors preserve order, duplicates, native object identity, and the captured parent graph. They do not reacquire matching objects. When one result is required, `-ExactlyOne` makes both zero matches and multiple matches visible instead of silently taking the first. ## Matching has explicit semantics Criteria field names accept the documented wire names and native-property aliases. Keys are case-insensitive, but supplying two aliases for the same field is an error. Entries in one map combine with AND. A bare field value means equality; an operator map describes another comparison. String comparisons are ordinal and case-sensitive by default, unlike many PowerShell operators. Choose a documented case-insensitive operator deliberately. Numeric criteria require the accepted integer types; they do not coerce arbitrary strings. An omitted condition differs from a condition whose value is null. Relationship predicates operate on captured relationships. If the query needs panes, capture to that depth first. An unavailable relationship raises an error rather than making an [`Every`](https://libtmux.org/en/powershell/latest/guides/query/#match-captured-relationships) or [`None`](https://libtmux.org/en/powershell/latest/guides/query/#match-captured-relationships) condition accidentally true. ## Inspect before dispatching [`Get-TmuxQueryPlan`]() reports pushed and residual predicates, fields, required depth, and fallback reasons without contacting tmux. Supply the intended daemon version when inspecting a version-dependent plan. [`Invoke-TmuxQuery`]() performs the new acquisition. `-AsResult` retains its complete captured graph even when the selected collection is empty. A plan can reduce work; it does not turn a multi-command read into an atomic snapshot. The [query guide](https://libtmux.org/en/powershell/latest/guides/query/) owns the operator catalog, query JSON, relationship criteria, and pushdown modes. Run [create windows and panes](https://libtmux.org/en/powershell/latest/examples/create-layout/) for a complete program using exact local selection after one snapshot. --- # tmux client library for PowerShell Source: https://libtmux.org/en/powershell/latest/core/ > tmux client library for PowerShell. Control tmux, connect to and create servers, navigate sessions, windows, and panes, send keys, watch for changes via control mode, capture pane contents Control tmux, connect to and create servers, navigate sessions, windows, and panes, send keys, watch for changes via control mode, capture pane contents. ## At a glance | Type | Wraps | | ---- | ----- | | [`LibTmux\Get-TmuxServer`](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxserver/) | A tmux server | | [`LibTmux\Get-TmuxSession`](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxsession/) | A session, ID `$n` | | [`LibTmux\Get-TmuxWindow`](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxwindow/) | A window in a session, ID `@n` | | [`LibTmux\Get-TmuxPane`](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpane/) | A pane in a window, ID `%n` | ## Typed API - Typed objects instead of parsed format strings: [`LibTmux\Get-TmuxPane`](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpane/) - Filtering and queries over tmux objects: [`LibTmux\New-TmuxQuery`](https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxquery/) ## What you get over the tmux CLI - Connect to or start a tmux server: [`LibTmux\Connect-TmuxServer`](https://libtmux.org/en/powershell/latest/reference/libtmux-connect-tmuxserver/) - Traversal from a server down to its panes: [`LibTmux\Get-TmuxSnapshot`](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxsnapshot/) - Send keys to a pane: [`LibTmux\Send-TmuxKey`](https://libtmux.org/en/powershell/latest/reference/libtmux-send-tmuxkey/) - Watch for changes through tmux control mode: [`LibTmux\Watch-TmuxEvent`](https://libtmux.org/en/powershell/latest/reference/libtmux-watch-tmuxevent/) - Capture pane contents: [`LibTmux\Get-TmuxPaneContent`](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/) - Arguments passed as a list, with no shell quoting: [`LibTmux\Invoke-TmuxCommand`](https://libtmux.org/en/powershell/latest/reference/libtmux-invoke-tmuxcommand/) - [Guides](https://libtmux.org/en/powershell/latest/guides/): Task guides for PowerShell. - [Topics](https://libtmux.org/en/powershell/latest/topics/): Subject-by-subject, with PowerShell in every code block. - [Examples](https://libtmux.org/en/powershell/latest/examples/): Complete programs, sourced from the code each port tests. - [API reference](https://libtmux.org/en/powershell/latest/reference/): Types and functions of the PowerShell API. --- # Examples Source: https://libtmux.org/en/powershell/latest/examples/ > Complete programs with setup, expected output, and owned-server cleanup. Run a complete program for the task you need. Each page includes the entire program, dependency setup, a run command, expected output, and cleanup. The examples create private tmux servers and leave existing sessions alone. Start with [create windows and panes](https://libtmux.org/en/powershell/latest/examples/create-layout/), then choose another task. - [Create windows and panes](https://libtmux.org/en/powershell/latest/examples/create-layout/): Create a session with two windows, then query a captured snapshot. - [Check command completion](https://libtmux.org/en/powershell/latest/examples/command-completion/): Run a shell command and verify its authenticated nonzero exit status. - [Wait for a service](https://libtmux.org/en/powershell/latest/examples/wait-for-service/): Wait for an HTTP readiness line and check the service responds. --- # Create windows and panes Source: https://libtmux.org/en/powershell/latest/examples/create-layout/ > Create a session with two windows, then query a captured snapshot. Create an isolated tmux server with an editor window containing two panes and a separate logs window. Read their names and pane IDs from one captured snapshot, then remove the session and stop its server. ## Setup PowerShell 7.4.20 with PSResourceGet 1.1.1, POSIX shell and tmux on Linux. Start in an empty directory. The following commands run in a POSIX shell. Install [LibTmux](https://www.powershellgallery.com/packages/LibTmux/) from PowerShell Gallery with PSResourceGet. Installation uses your current user's module directory; the program loads it with `Import-Module LibTmux`. ```console $ pwsh -NoLogo -NoProfile -Command ' $ErrorActionPreference = "Stop" Install-PSResource -Name LibTmux ` -Repository PSGallery -Scope CurrentUser -TrustRepository ' ``` ## Program Save this complete program as `quickstart.ps1`. ```powershell title="quickstart.ps1" $ErrorActionPreference = 'Stop' Import-Module LibTmux $session = $null $failure = $null try { $socket = 'libtmux-home-' + [Guid]::NewGuid().ToString('N') $server = New-TmuxServer -SocketName $socket -ConfigurationFile /dev/null $session = $server | New-TmuxSession ` -Name demo -WindowName editor -Command 'exec /bin/cat' $pane = $session | Get-TmuxPane $null = $pane | Split-TmuxPane -Horizontal -Command 'exec /bin/cat' $null = $session | New-TmuxWindow -Name logs -Command 'exec /bin/cat' $captured = ($server | Get-TmuxSnapshot).Sessions | Select-TmuxSession -Criteria @{ Name = 'demo' } -ExactlyOne foreach ($window in $captured.Windows) { '{0}: {1}' -f $window.Name, ($window.Panes.Id -join ', ') } } catch { $failure = [InvalidOperationException]::new( "tmux quickstart failed: $($_.Exception.Message)", $_.Exception) throw $failure } finally { if ($session) { $cleanupErrors = @() $session | Remove-TmuxSession -Confirm:$false ` -ErrorAction SilentlyContinue -ErrorVariable cleanupErrors if ($cleanupErrors) { if ($failure) { $errors = @($failure) + $cleanupErrors.Exception throw [AggregateException]::new( 'tmux operation and cleanup failed.', [Exception[]]$errors) } throw $cleanupErrors[0] } } } ``` The private socket name is unique to this run. `-ConfigurationFile /dev/null` keeps personal tmux configuration out of the example. Each pane runs `/bin/cat` so it stays alive without a shell prompt or startup commands. `-ExactlyOne` rejects missing or ambiguous session matches. The `finally` block removes the only session; tmux then exits. If an operation and cleanup both fail, the script preserves both errors. ## Run ```console $ unset TMUX TMUX_PANE $ export ENV=/dev/null BASH_ENV=/dev/null SHELL=/bin/sh $ pwsh -NoLogo -NoProfile -File quickstart.ps1 ``` Expected output: ```text editor: %0, %1 logs: %2 ``` ## Related APIs - [`New-TmuxSession`](https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxsession/) - [`Split-TmuxPane`](https://libtmux.org/en/powershell/latest/reference/libtmux-split-tmuxpane/) - [`Get-TmuxSnapshot`](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxsnapshot/) - [`Select-TmuxSession`](https://libtmux.org/en/powershell/latest/reference/libtmux-select-tmuxsession/) - [`Remove-TmuxSession`](https://libtmux.org/en/powershell/latest/reference/libtmux-remove-tmuxsession/) ## Source and verification This program uses [LibTmux at the package source revision](https://github.com/libtmux/libtmux-powershell/blob/fcd0634e9ca887b70d88915c2d8e26c5da2737e5/README.md). The verification runner executes these displayed files and setup commands unchanged, checks the output, and checks that the program stopped its private tmux server. Each example runs independently. --- # Check command completion Source: https://libtmux.org/en/powershell/latest/examples/command-completion/ > Run a shell command and verify its authenticated nonzero exit status. Run `exit 7` inside a disposable shell pane and verify its result. The program waits for the command's authenticated completion status, then removes the session. It does not infer success from text in a terminal. ## Setup PowerShell 7.4.20 with PSResourceGet 1.1.1, POSIX shell and tmux on Linux. Start in an empty directory. The following commands run in a POSIX shell. Install [LibTmux](https://www.powershellgallery.com/packages/LibTmux/) from PowerShell Gallery with PSResourceGet. Installation uses your current user's module directory; the program loads it with `Import-Module LibTmux`. ```console $ pwsh -NoLogo -NoProfile -Command ' $ErrorActionPreference = "Stop" Install-PSResource -Name LibTmux ` -Repository PSGallery -Scope CurrentUser -TrustRepository ' ``` ## Program Save this complete program as `command-completion.ps1`. ```powershell title="command-completion.ps1" $ErrorActionPreference = 'Stop' Import-Module LibTmux $session = $null $failure = $null try { $socket = 'libtmux-example-' + [Guid]::NewGuid().ToString('N') $server = New-TmuxServer -SocketName $socket -ConfigurationFile /dev/null $session = $server | New-TmuxSession ` -Name command -Command 'exec /bin/sh' $pane = $session | Get-TmuxPane $result = $pane | Invoke-TmuxPaneCommand ` -Command 'exit 7' -Timeout 5 -Confirm:$false if ($result.TimedOut -or $result.ExitStatus -ne 7) { throw 'The shell command did not complete with exit status 7.' } 'exit status: {0}' -f $result.ExitStatus } catch { $failure = [InvalidOperationException]::new( "tmux example failed: $($_.Exception.Message)", $_.Exception) throw $failure } finally { if ($session) { $cleanupErrors = @() $session | Remove-TmuxSession -Confirm:$false ` -ErrorAction SilentlyContinue -ErrorVariable cleanupErrors if ($cleanupErrors) { if ($failure) { $errors = @($failure) + $cleanupErrors.Exception throw [AggregateException]::new( 'tmux operation and cleanup failed.', [Exception[]]$errors) } throw $cleanupErrors[0] } } } ``` [`Invoke-TmuxPaneCommand`]() runs the command in a subshell. A nonzero exit status is a result, so this example checks [`ExitStatus`]() explicitly. [`TimedOut`](https://libtmux.org/en/csharp/latest/reference/libtmux-panerunresult-timedout/) means the command may still be running; the script treats that as failure and still cleans up its owned session. This example changes only the private server it creates. The `finally` block retains cleanup errors, including when the command operation also fails. ## Run ```console $ unset TMUX TMUX_PANE $ export ENV=/dev/null BASH_ENV=/dev/null SHELL=/bin/sh $ pwsh -NoLogo -NoProfile -File command-completion.ps1 ``` Expected output: ```text exit status: 7 ``` ## Related APIs - [`Invoke-TmuxPaneCommand`](https://libtmux.org/en/powershell/latest/reference/libtmux-invoke-tmuxpanecommand/) - [Send input to a pane](https://libtmux.org/en/powershell/latest/guides/input/) - [`Remove-TmuxSession`](https://libtmux.org/en/powershell/latest/reference/libtmux-remove-tmuxsession/) ## Source and verification This program uses [LibTmux at the package source revision](https://github.com/libtmux/libtmux-powershell/blob/fcd0634e9ca887b70d88915c2d8e26c5da2737e5/README.md). The verification runner executes these displayed files and setup commands unchanged, checks the output, and checks that the program stopped its private tmux server. Each example runs independently. --- # Wait for a service Source: https://libtmux.org/en/powershell/latest/examples/wait-for-service/ > Wait for an HTTP readiness line and check the service responds. Start Python's HTTP server on an available loopback port, wait for its readiness line, and make an HTTP request. The session is removed on success or failure, which also stops the HTTP server. ## Setup PowerShell 7.4.20 with PSResourceGet 1.1.1, Python 3, a POSIX shell, and tmux on Linux. Start in an empty directory. The following commands run in a POSIX shell. Install [LibTmux](https://www.powershellgallery.com/packages/LibTmux/) from PowerShell Gallery with PSResourceGet. Installation uses your current user's module directory; the program loads it with `Import-Module LibTmux`. ```console $ pwsh -NoLogo -NoProfile -Command ' $ErrorActionPreference = "Stop" Install-PSResource -Name LibTmux ` -Repository PSGallery -Scope CurrentUser -TrustRepository ' ``` ## Program Save this complete program as `wait-for-service.ps1`. ```powershell title="wait-for-service.ps1" $ErrorActionPreference = 'Stop' Import-Module LibTmux $session = $null $failure = $null try { $socket = 'libtmux-example-' + [Guid]::NewGuid().ToString('N') $server = New-TmuxServer -SocketName $socket -ConfigurationFile /dev/null $session = $server | New-TmuxSession -Name http ` -Command 'exec python3 -u -m http.server 0 --bind 127.0.0.1' $pane = $session | Get-TmuxPane $ready = $pane | Wait-TmuxPaneText ` -Pattern '^Serving HTTP on 127\.0\.0\.1 port [0-9]+' ` -CaseSensitive -Timeout 10 -TailLines 4 -Confirm:$false if ($ready.Outcome -notin 'PresentAtEntry', 'Matched') { throw "HTTP readiness ended with $($ready.Outcome)." } $tail = $ready.Tail -join "`n" $port = [regex]::Match($tail, 'port ([0-9]+)').Groups[1].Value $response = Invoke-WebRequest "http://127.0.0.1:$port/" ` -TimeoutSec 5 -NoProxy if ($response.StatusCode -ne 200) { throw "HTTP returned $($response.StatusCode)." } 'readiness: observed' 'HTTP status: {0}' -f $response.StatusCode } catch { $failure = [InvalidOperationException]::new( "tmux example failed: $($_.Exception.Message)", $_.Exception) throw $failure } finally { if ($session) { $cleanupErrors = @() $session | Remove-TmuxSession -Confirm:$false ` -ErrorAction SilentlyContinue -ErrorVariable cleanupErrors if ($cleanupErrors) { if ($failure) { $errors = @($failure) + $cleanupErrors.Exception throw [AggregateException]::new( 'tmux operation and cleanup failed.', [Exception[]]$errors) } throw $cleanupErrors[0] } } } ``` [`Wait-TmuxPaneText`]() accepts a line already visible when observation starts ([`PresentAtEntry`]()) or one observed later ([`Matched`]()). Both are valid here. A matching line only establishes the text condition; [`Invoke-WebRequest`]() checks that the service actually responds. The readiness wait has a ten-second limit, and the HTTP request has a five-second limit. No fixed sleep is needed. The wait closes its control client; the script separately removes its owned session in `finally`. ## Run ```console $ unset TMUX TMUX_PANE $ export ENV=/dev/null BASH_ENV=/dev/null SHELL=/bin/sh $ pwsh -NoLogo -NoProfile -File wait-for-service.ps1 ``` Expected output: ```text readiness: observed HTTP status: 200 ``` ## Related APIs - [`Wait-TmuxPaneText`](https://libtmux.org/en/powershell/latest/reference/libtmux-wait-tmuxpanetext/) - [Wait for an application's readiness line](https://libtmux.org/en/powershell/latest/guides/input/#wait-for-an-applications-readiness-line) - [`Remove-TmuxSession`](https://libtmux.org/en/powershell/latest/reference/libtmux-remove-tmuxsession/) ## Source and verification This program uses [LibTmux at the package source revision](https://github.com/libtmux/libtmux-powershell/blob/fcd0634e9ca887b70d88915c2d8e26c5da2737e5/README.md). The verification runner executes these displayed files and setup commands unchanged, checks the output, and checks that the program stopped its private tmux server. Each example runs independently. --- # Getting started Source: https://libtmux.org/en/powershell/latest/guides/getting-started/ > Getting started: LibTmux documentation. [![powershell](https://github.com/libtmux/libtmux-powershell/actions/workflows/ci.yml/badge.svg)](https://github.com/libtmux/libtmux-powershell/actions/workflows/ci.yml) [![LibTmux](https://img.shields.io/powershellgallery/v/LibTmux?label=LibTmux)](https://www.powershellgallery.com/packages/LibTmux/) [![libtmux.org](https://img.shields.io/badge/docs-libtmux.org-0b7285)](https://libtmux.org/en/powershell/) [![license](https://img.shields.io/badge/license-MIT-blue)](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/LICENSE) Drive [tmux](https://github.com/tmux/tmux) from PowerShell with native cmdlets. [Sessions][session], [windows][window] and [panes][pane] come back as typed objects that an ordinary pipeline can filter. Run a command and read its exit status with [`Invoke-TmuxPaneCommand`][invoke-tmuxpanecommand], find what a server holds with [`Get-TmuxSnapshot`][get-tmuxsnapshot], wait for output with [`Wait-TmuxPaneText`][wait-tmuxpanetext], and apply a reviewed workspace file with [`Invoke-TmuxWorkspace`][invoke-tmuxworkspace]. Releases are numbered `0.1.N`, and each release increments `N`. The API is not settled: any release may change or remove exported identifiers, and the changelog marks each break. Pin an exact version to avoid one. Both modules are available on PowerShell Gallery: [LibTmux](https://www.powershellgallery.com/packages/LibTmux) and [LibTmux.Workspace](https://www.powershellgallery.com/packages/LibTmux.Workspace). It needs PowerShell 7.4 or later and tmux 3.3a or newer on the same Linux host, including WSL. [Compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/) lists what CI runs. tmux release candidates are not supported: a feature can require one only until its release ships, and a candidate such as `X.Y-rcN` ranks below `X.Y`. See [Release candidates](https://libtmux.org/en/tmux/guides/tmux-support/#release-candidates). **Contents** — [Quick start](https://libtmux.org/en/powershell/latest/guides/getting-started/#quick-start) · [Find things](https://libtmux.org/en/powershell/latest/guides/getting-started/#find-sessions-windows-and-panes) · [Service readiness](https://libtmux.org/en/powershell/latest/guides/getting-started/#wait-for-service-readiness) · [Choose how to run](https://libtmux.org/en/powershell/latest/guides/getting-started/#choose-how-to-run) · [Workspaces](https://libtmux.org/en/powershell/latest/guides/getting-started/#build-a-workspace-from-a-file) · [Packages](https://libtmux.org/en/powershell/latest/guides/getting-started/#packages) · [From source](https://libtmux.org/en/powershell/latest/guides/getting-started/#install-from-source) · [Leaves out](https://libtmux.org/en/powershell/latest/guides/getting-started/#what-it-leaves-out) · [Support](https://libtmux.org/en/powershell/latest/guides/getting-started/#support-and-status) · [Documentation](https://libtmux.org/en/powershell/latest/guides/getting-started/#documentation) **Reference** — [Cmdlet reference](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/docs/reference/README.md) · [Compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/) · [Troubleshooting](https://libtmux.org/en/powershell/latest/guides/troubleshooting/) · [MCP](https://libtmux.org/en/powershell/latest/guides/mcp/#discover-before-calling) · [License](https://libtmux.org/en/powershell/latest/guides/getting-started/#license) ## Quick start The command-completion example below needs tmux 3.4 or newer. Ordinary reads and writes support tmux 3.3a; see [optional features](https://libtmux.org/en/powershell/latest/guides/compatibility/#optional-features). Install the module from the PowerShell Gallery in PowerShell 7.4 or later (`pwsh`) on Linux, including WSL. [`Install-PSResource`]() ships with PowerShell 7.4; Windows PowerShell 5.1 has no such command and cannot load the module: ```console $ Install-PSResource -Name LibTmux ``` Import it: ```console $ Import-Module -Name LibTmux -ErrorAction Stop ``` [`New-TmuxServer`][new-tmuxserver] makes a handle on a socket and an empty tmux configuration of its own. It contacts nothing, so your default server stays untouched: ```powershell $server = LibTmux\New-TmuxServer ` -SocketName ('libtmux-readme-' + [Guid]::NewGuid().ToString('N')) ` -ConfigurationFile /dev/null ``` Without a socket, a handle passes tmux none, so tmux picks the server: the one in `TMUX` inside a pane, otherwise its default. `LIBTMUX_SOCKET_PATH` or `LIBTMUX_SOCKET` chooses one instead; [read more](https://libtmux.org/en/powershell/latest/guides/read/). [`Invoke-TmuxPaneCommand`][invoke-tmuxpanecommand] runs a command in a pane and returns a [`LibTmux.PaneRunResult`][panerunresult]. [`New-TmuxSession`][new-tmuxsession] starts the shell, and the `finally` block removes only that session with [`Remove-TmuxSession`][remove-tmuxsession]: ```powershell & { $ErrorActionPreference = 'Stop' $name = 'pane-run-' + [Guid]::NewGuid().ToString('N') $session = $server | New-TmuxSession -Name $name -Command 'exec /bin/sh' try { $pane = $session | Get-TmuxPane $pane | Invoke-TmuxPaneCommand -Command 'exit 7' -Timeout 5 -Confirm:$false } finally { $session | Remove-TmuxSession -Confirm:$false } } ``` The result has `ExitStatus = 7` and `TimedOut = False`. A nonzero exit status comes back in [`ExitStatus`]() and raises no error. If the timeout passes first, the command may still be running and the result has no exit status. [Command completion](https://libtmux.org/en/powershell/latest/guides/input/#run-a-command-to-completion) covers concurrency and output behavior. Every PowerShell block on this page is a copy of a tested source. The [guide test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/GuideExamples.Tests.ps1) fails when a copy drifts, and the [installed workflow test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/ReadmeWorkflow.Tests.ps1) runs the blocks in order on an owned tmux server. Later sections reuse `$server`. ## Find sessions, windows, and panes ### [`Get-TmuxSnapshot`][get-tmuxsnapshot]: what tmux holds, in one read One call returns every session, window and pane as native objects. This example builds a tree with [`New-TmuxSession`][new-tmuxsession], [`Split-TmuxPane`][split-tmuxpane] and [`New-TmuxWindow`][new-tmuxwindow], reads it, and removes it with [`Remove-TmuxSession`][remove-tmuxsession]. `cat` keeps the panes open: ```powershell $captured = & { $ErrorActionPreference = 'Stop' $session = $server | New-TmuxSession -Name demo -WindowName editor -Command 'exec /bin/cat' try { $pane = $session | Get-TmuxPane $null = $pane | Split-TmuxPane -Horizontal -Command 'exec /bin/cat' $null = $session | New-TmuxWindow -Name logs -Command 'exec /bin/cat' ($server | Get-TmuxSnapshot).Sessions | Where-Object Name -CEQ demo } finally { $session | Remove-TmuxSession -Confirm:$false } } ``` `$captured` is a [`LibTmux.Session`][session] that stays readable after cleanup. Its [`Windows`][session-windows] hold [`LibTmux.Window`][window] objects, and each window's [`Panes`][window-panes] hold [`LibTmux.Pane`][pane] objects: | Expression | Captured result | | --- | --- | | `$captured` | A [`Session`]() named `demo` | | [`$captured.Windows`][session-windows] | Two [`Window`]() objects: `editor` and `logs` | | [`$captured.Windows[0].Panes`][window-panes] | Two [`Pane`]() objects in `editor`; `logs` has one | A captured object keeps what tmux reported when you read it. Call [`Get-TmuxSnapshot`][get-tmuxsnapshot] again to see a later change. [Snapshots and linked windows](https://libtmux.org/en/powershell/latest/guides/read/) cover IDs, active children and captured versus unavailable fields. ### Filter the captured graph Walk it with ordinary PowerShell. [`Where-Object`](), navigation, formatting and property access use the captured data and start no tmux client: ```powershell $captured.Windows | Where-Object { $_.Panes.Count -gt 1 } | Select-Object Name, @{ Name = 'PaneCount'; Expression = { $_.Panes.Count } } ``` It prints `editor` with a pane count of 2. `logs` has one pane and drops out: ```text Name PaneCount ---- --------- editor 2 ``` ### [`Select-TmuxWindow`][select-tmuxwindow]: pick windows by criteria The structured equivalent selects the one window with at least two captured panes. `-ExactlyOne` reports zero or multiple matches. This query performs no I/O either: ```powershell $captured.Windows | Select-TmuxWindow -Criteria @{ 'Panes.Count' = @{ Ge = 2 } } -ExactlyOne ``` It returns the `editor` window, the same object as `$captured.Windows[0]`. [The query guide](https://libtmux.org/en/powershell/latest/guides/query/) shows native predicates, Boolean and relationship criteria, and explicit fresh source queries. ## Wait for service readiness ### [`Wait-TmuxPaneText`][wait-tmuxpanetext]: wait for a readiness line It watches a pane's rendered text and returns a [`LibTmux.PaneWaitResult`][panewaitresult]. On tmux 3.7 or newer it uses a temporary control client; on earlier supported releases it polls instead. [`Send-TmuxText`][send-tmuxtext] and [`Send-TmuxKey`][send-tmuxkey] type into the pane first, and [`Get-TmuxPaneContent`][get-tmuxpanecontent] reads its screen. When the application can signal completion itself, use [`Wait-TmuxChannel`][wait-tmuxchannel] with [a cooperative channel](https://libtmux.org/en/powershell/latest/guides/input/#send-a-command-and-wait-for-its-output). With Python 3 on `PATH`, this example starts an HTTP server on a free loopback port, waits for its readiness line, then requests a page. The session's cleanup also stops the server: ```powershell & { $ErrorActionPreference = 'Stop' $session = $server | New-TmuxSession ` -Name ('http-' + [Guid]::NewGuid().ToString('N')) ` -Command 'exec python3 -u -m http.server 0 --bind 127.0.0.1' try { $pane = $session | Get-TmuxPane $ready = $pane | Wait-TmuxPaneText ` -Pattern '^Serving HTTP on 127\.0\.0\.1 port [0-9]+' ` -CaseSensitive -Timeout 10 -TailLines 4 -Confirm:$false if ($ready.Outcome -notin 'PresentAtEntry', 'Matched') { throw "HTTP readiness ended with $($ready.Outcome)." } $tail = $ready.Tail -join "`n" $port = [regex]::Match($tail, 'port ([0-9]+)').Groups[1].Value $uri = "http://127.0.0.1:$port/" $response = Invoke-WebRequest -Uri $uri -TimeoutSec 5 -NoProxy $ready $response.StatusCode } finally { $session | Remove-TmuxSession -Confirm:$false } } ``` The outcome is [`PresentAtEntry`]() or [`Matched`](), followed by HTTP status 200. The wait closes any control client it creates, and the example removes only its own session. A text match shows the readiness line; the HTTP request checks the service. [Pane-text waits](https://libtmux.org/en/powershell/latest/guides/input/#wait-for-an-applications-readiness-line) cover stop patterns, bounded tails, cancellation and disclosed event loss. ## Choose how to run Pick a mode by who owns the client and how a failure is reported: | Task | Use | Example | | --- | --- | --- | | Read or change tmux state | Typed cmdlets and pipelines | [Create sessions and panes](https://libtmux.org/en/powershell/latest/guides/create/) | | Run a shell command and check its exit status | [`Invoke-TmuxPaneCommand`]() | [Run to completion](https://libtmux.org/en/powershell/latest/guides/input/#run-a-command-to-completion) | | Wait for a running application's readiness line | [`Wait-TmuxPaneText`]() | [Readiness and an HTTP health check](https://libtmux.org/en/powershell/latest/guides/getting-started/#wait-for-service-readiness) | | Enter a session interactively | [`Enter-TmuxSession`]() | [Attach your foreground terminal](https://libtmux.org/en/powershell/latest/reference/libtmux-enter-tmuxsession/) | | Run an ordered batch | [`New-TmuxCommand`]() → [`Invoke-TmuxChain`]() | [Compose commands](https://libtmux.org/en/powershell/latest/guides/commands/) | | Reuse a connected client | [`Connect-TmuxControl`]() → [`Invoke-TmuxControlCommand`]() | [Control commands and cleanup](https://libtmux.org/en/powershell/latest/guides/commands/) | | React to output and notifications | [`Watch-TmuxEvent`]() | [Bounded event streams](https://libtmux.org/en/powershell/latest/guides/watch/) | | Keep the prompt available | [`Start-ThreadJob`]() | [Bounded background jobs](https://libtmux.org/en/powershell/latest/guides/watch/#bound-background-output) | | Run commands concurrently | `ForEach-Object -Parallel` | [Independent clients](https://libtmux.org/en/powershell/latest/guides/watch/#run-independent-commands-concurrently) | An older daemon refuses these before anything changes: [`Invoke-TmuxPaneCommand`][invoke-tmuxpanecommand] needs tmux 3.4, and [`Connect-TmuxControl`][connect-tmuxcontrol] and [`Watch-TmuxEvent`][watch-tmuxevent] with a server need 3.7. Other commands are refused on the releases they harm. The [optional features](https://libtmux.org/en/powershell/latest/guides/compatibility/#optional-features) table lists each one, and [`capabilities.json`](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/capabilities.json) holds the same list for an assistant or a script to read. The raw-command cmdlets [`Invoke-TmuxCommand`][invoke-tmuxcommand], [`Invoke-TmuxChain`][invoke-tmuxchain] and [`Invoke-TmuxControlCommand`][invoke-tmuxcontrolcommand] check the command they are given and nothing nested in it, such as an [`if-shell`](https://libtmux.org/en/tmux/latest/manual/if-shell/) string, a [`bind-key`](https://libtmux.org/en/tmux/latest/manual/bind-key/) command or a brace block. On exactly tmux 3.7, name every [`break-pane`](https://libtmux.org/en/tmux/latest/manual/break-pane/), including the one `prefix !` runs, or upgrade to 3.7a: a nested nameless one ends the server. [What the checks do not read](https://libtmux.org/en/powershell/latest/guides/compatibility/#what-the-checks-do-not-read) lists the other failures. ### [`Connect-TmuxControl`][connect-tmuxcontrol]: one client for repeated commands It connects one control client. [`New-TmuxCommand`][new-tmuxcommand] builds a command, [`Invoke-TmuxControlCommand`][invoke-tmuxcontrolcommand] sends it through the client, and [`Disconnect-TmuxControl`][disconnect-tmuxcontrol] ends it. [`Invoke-TmuxChain`][invoke-tmuxchain] sends an ordered batch in one invocation. This example uses the private endpoint from above, reads a session name, then disconnects and removes the session it created: ```powershell & { $ErrorActionPreference = 'Stop' $session = $server | New-TmuxSession -Name control-demo -Command 'exec /bin/cat' try { $client = $server | Connect-TmuxControl -Target 'control-demo' -ErrorAction Stop try { $command = New-TmuxCommand -Name display-message -Arguments @( '-p', '#{session_name}' ) $client | Invoke-TmuxControlCommand -Command $command -ErrorAction Stop } finally { $client | Disconnect-TmuxControl -Confirm:$false } } finally { $session | Remove-TmuxSession -Confirm:$false } } ``` The reply is `control-demo`. The client stays connected across commands inside the inner `try` block. The [control guide](https://libtmux.org/en/powershell/latest/guides/commands/#reuse-a-control-client) covers multiple commands and cancellation. The other modes in short: - [`Enter-TmuxSession`][enter-tmuxsession] attaches your foreground terminal to a session. - Foreground cmdlets and `ForEach-Object -Parallel` occupy their calling pipeline. - Thread jobs return the prompt while they run. - [`Watch-TmuxEvent`][watch-tmuxevent] accepts event-count and text-byte limits. The [mode guide](https://libtmux.org/en/powershell/latest/guides/commands/) explains when chains merge failure attribution. ## Build a workspace from a file Describe a session once in YAML or JSON, review the plan, then apply it. Installing the workspace module also installs its exact core dependency: ```console $ Install-PSResource -Name LibTmux.Workspace ``` Import both modules: ```console $ Import-Module -Name LibTmux, LibTmux.Workspace -ErrorAction Stop ``` ### [`Import-TmuxWorkspace`][import-tmuxworkspace]: read a declaration It parses YAML or JSON without contacting tmux or running the commands in it. [`Get-TmuxWorkspace`][get-tmuxworkspace] finds declaration files, [`Resolve-TmuxWorkspace`][resolve-tmuxworkspace] expands directories and [`Test-TmuxWorkspace`][test-tmuxworkspace] validates one. This declaration has two panes in one window: ```powershell $workspace = LibTmux.Workspace\Import-TmuxWorkspace -Yaml @' session_name: readme-workspace-preview windows: - window_name: editor panes: - shell_command: exec /bin/sh - shell_command: exec /bin/sh '@ ``` It returns a [`LibTmux.Workspace.WorkspaceFile`][workspacefile] and prints nothing. ### [`Get-TmuxWorkspacePlan`][get-tmuxworkspaceplan]: review before anything runs It plans on the same private endpoint. Planning may read tmux state and creates nothing: ```powershell $workspacePlan = $workspace | LibTmux.Workspace\Get-TmuxWorkspacePlan ` -Server $server -ServerStartup CreateOrJoin -ExistingSession Error ``` Review the actions. Their default view keeps command text, option values, paths and environment values hidden; inspect an action's [`Request`][workspaceaction-request] only in a trusted terminal: ```powershell $workspacePlan.Actions ``` It lists the actions in order, from [`CreateSession`][workspaceactionkind-createsession] to [`CaptureResult`][workspaceactionkind-captureresult], with command text shown as `[redacted]`. ### [`Invoke-TmuxWorkspace`][invoke-tmuxworkspace]: preview, then apply `-WhatIf` previews the plan without applying it: ```powershell $workspacePlan | LibTmux.Workspace\Invoke-TmuxWorkspace -WhatIf ``` It prints a `What if:` line followed by the plan's actions. Apply that exact plan, then remove only the session it created. The captured result stays readable after cleanup: ```powershell $workspaceResult = & { $result = $workspacePlan | LibTmux.Workspace\Invoke-TmuxWorkspace -Confirm:$false -ErrorAction Stop try { $result } finally { $result.Session | Remove-TmuxSession -Confirm:$false } } ``` The result is a [`LibTmux.Workspace.WorkspaceResult`][workspaceresult]. Read its windows: ```powershell $workspaceResult.Windows | Select-Object Name, @{ Name = 'PaneCount'; Expression = { $_.Panes.Count } } ``` This returns `editor` with two panes. The [workspace guide](https://libtmux.org/en/powershell/latest/workspace/source-guide/#apply-the-reviewed-plan) covers failure recovery, attaching and exporting a declaration; [`ConvertTo-TmuxWorkspace`][convertto-tmuxworkspace] turns a captured session into a starting declaration. ## Packages | Product | Use it for | | --- | --- | | [LibTmux](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/docs/reference/README.md) | Typed cmdlets, snapshots, input, capture, control clients and event streams | | [LibTmux.Workspace](https://libtmux.org/en/powershell/latest/workspace/source-guide/#plan-and-review) [![LibTmux.Workspace](https://img.shields.io/powershellgallery/v/LibTmux.Workspace?label=LibTmux.Workspace)](https://www.powershellgallery.com/packages/LibTmux.Workspace) | Discover YAML/JSON declarations, resolve directories, review plans and create workspaces | | [LibTmux.Mcp](https://libtmux.org/en/powershell/latest/guides/mcp/#discover-before-calling) | Give an assistant tmux tools through the separately installed .NET MCP server | ### [LibTmux](https://github.com/libtmux/libtmux-powershell/tree/master/src/LibTmux.PowerShell): typed cmdlets for tmux Read, create, arrange and remove sessions, windows and panes, send input and capture output as native objects. The walkthroughs above run on the installed module: - [Read an object graph](https://libtmux.org/en/powershell/latest/guides/getting-started/#find-sessions-windows-and-panes) with [`Get-TmuxSnapshot`][get-tmuxsnapshot] and [`Select-TmuxWindow`][select-tmuxwindow]. - [Check a command's exit status](https://libtmux.org/en/powershell/latest/guides/getting-started/#quick-start) with [`Invoke-TmuxPaneCommand`][invoke-tmuxpanecommand]. - [Wait for a readiness line](https://libtmux.org/en/powershell/latest/guides/getting-started/#wait-for-service-readiness) with [`Wait-TmuxPaneText`][wait-tmuxpanetext]. - [Choose an execution mode](https://libtmux.org/en/powershell/latest/guides/getting-started/#choose-how-to-run), including [`Watch-TmuxEvent`][watch-tmuxevent]. Reference: [every LibTmux cmdlet][libtmux-module] and the [PowerShell Gallery page](https://www.powershellgallery.com/packages/LibTmux). ### [LibTmux.Workspace](https://github.com/libtmux/libtmux-powershell/tree/master/src/LibTmux.Workspace.PowerShell): workspaces from YAML or JSON Describe a session once, review the plan, then apply it. The commands below run in this order: - [`Get-TmuxWorkspace`][get-tmuxworkspace] finds declaration files. - [`Import-TmuxWorkspace`][import-tmuxworkspace] parses YAML or JSON without contacting tmux. - [`Resolve-TmuxWorkspace`][resolve-tmuxworkspace] expands directories and [`Test-TmuxWorkspace`][test-tmuxworkspace] validates the declaration. - [`Get-TmuxWorkspacePlan`][get-tmuxworkspaceplan] plans against a server and [`Invoke-TmuxWorkspace`][invoke-tmuxworkspace] applies the reviewed plan; `-WhatIf` previews it. - [`ConvertTo-TmuxWorkspace`][convertto-tmuxworkspace] turns a captured session into a starting declaration. [Install it](https://libtmux.org/en/powershell/latest/guides/getting-started/#build-a-workspace-from-a-file) with the core module, at the same version. Reference: [every LibTmux.Workspace cmdlet][workspace-module] and the [PowerShell Gallery page](https://www.powershellgallery.com/packages/LibTmux.Workspace). ### [LibTmux.Mcp](https://github.com/libtmux/libtmux-dotnet/tree/master/src/LibTmux.Mcp): tmux tools for assistants A separate .NET tool that lets an MCP client list, read and drive tmux panes. It needs no PowerShell. Reference: the [MCP guide](https://libtmux.org/en/powershell/latest/guides/mcp/), the [tool reference](https://libtmux.org/en/csharp/latest/mcp/tools/) and [NuGet](https://www.nuget.org/packages/LibTmux.Mcp). Install the tool on the Unix host that runs tmux: ```console $ dotnet tool install --global LibTmux.Mcp \ --version 0.1.1 \ --framework net8.0 ``` Register it with Claude Code. This names the tmux socket `work` and offers only the tools that read tmux: ```console $ claude mcp add tmux \ -e LIBTMUX_SOCKET=work \ -e LIBTMUX_TOOLSETS=inspect \ -- libtmux-mcp ``` A client that reads a JSON configuration takes the same command and settings: ```json { "mcpServers": { "tmux": { "command": "libtmux-mcp", "env": { "LIBTMUX_SOCKET": "work", "LIBTMUX_TOOLSETS": "inspect" } } } } ``` - Find a pane with [`list_sessions`][mcp-list_sessions], [`list_windows`][mcp-list_windows] and [`list_panes`][mcp-list_panes]. - Read it with [`capture_pane`][mcp-capture_pane], or [`snapshot_pane`][mcp-snapshot_pane] for structured state. - Wait for output with [`wait_for_text`][mcp-wait_for_text] and a finite timeout. - Read the selected tools and socket from the [`tmux://capabilities` resource][mcp-capabilities] before calling any tool. The [MCP guide](https://libtmux.org/en/powershell/latest/guides/mcp/) covers [client configuration](https://libtmux.org/en/powershell/latest/guides/mcp/#install-and-select-a-server), [discovery before calling](https://libtmux.org/en/powershell/latest/guides/mcp/#discover-before-calling), finite waits and the other toolsets. [Its test](https://libtmux.org/en/powershell/latest/guides/mcp/#check-the-client-workflow-from-this-checkout) starts the installed tool with these settings and checks what it reports. ## Install from source Install the pinned PowerShell and .NET SDK from [.tool-versions](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/.tool-versions) with [mise](https://mise.jdx.dev/): ```console $ mise install ``` Install tmux with your operating system's package manager and check that it is on `PATH`: ```console $ tmux -V ``` From the checkout root, restore the published [.NET 0.1.1 packages](https://www.nuget.org/packages/LibTmux/0.1.1) and build both PowerShell modules: ```console $ pwsh -NoLogo -NoProfile -File eng/Build.ps1 \ -Restore ``` Restore checks the committed lockfiles and stages both modules under `build/Modules`. Developing shared .NET changes uses the optional [review-package workflow](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/.github/CONTRIBUTING.md#review-package-builds). Start PowerShell with the staged module path: ```console $ LIBTMUX_REVIEW_MODULE_ROOT="$PWD/build/Modules" \ pwsh \ -NoLogo \ -NoProfile ``` Import the exact staged manifests so an older installed module cannot shadow the new build: ```powershell $modules = $env:LIBTMUX_REVIEW_MODULE_ROOT Import-Module -Name @( "$modules/LibTmux/0.1.0/LibTmux.psd1", "$modules/LibTmux.Workspace/0.1.0/LibTmux.Workspace.psd1" ) -ErrorAction Stop ``` ### [`examples/QuickStart.ps1`](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/examples/QuickStart.ps1): a private server and three panes Run the [quick start](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/examples/QuickStart.ps1) from the checkout root. It creates a private server, splits the `editor` window, adds `logs`, and returns a captured [`LibTmux.Session`][session]. Show each window's pane IDs: ```powershell (./examples/QuickStart.ps1).Windows | Select-Object Name, @{ Name = 'PaneIds' Expression = { $_.Panes.Id -join ', ' } } ``` It prints the pane IDs from the private server: ```text Name PaneIds ---- ------- editor %0, %1 logs %2 ``` Assign `./examples/QuickStart.ps1` to a variable to keep the session object. Its [`Windows`][session-windows] and [`Panes`][session-panes] remain readable after the script removes its session. The script uses a unique socket, so your default tmux server stays untouched. ## What it leaves out - **Live objects.** A captured object keeps what tmux reported when you read it. [`Get-TmuxSnapshot`][get-tmuxsnapshot] reads again, and [snapshots and linked windows](https://libtmux.org/en/powershell/latest/guides/read/) list what a capture cannot know. - **An implicit server.** A handle from [`New-TmuxServer`][new-tmuxserver] starts no daemon, and importing the module connects to none. The module leaves `TMUX` and `TMUX_PANE` in your session as they are ([compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/)). - **Shell quoting.** [`Send-TmuxText`][send-tmuxtext] sends its text literally and does not quote it for the shell that receives it ([send input](https://libtmux.org/en/powershell/latest/guides/input/)). - **Native Windows.** Run PowerShell and tmux inside WSL, in one Linux environment. Native Windows and psmux are outside this port ([compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/)). - **The MCP server.** LibTmux.Mcp is a separate .NET tool that needs no PowerShell, and the modules install none of its tools ([MCP guide](https://libtmux.org/en/powershell/latest/guides/mcp/)). ## Support and status - **Releases.** Releases are numbered `0.1.N`, and each release increments `N`. The API is not settled: any release may change or remove exported identifiers, and the changelog marks each break. Pin an exact version to avoid one. - **PowerShell.** 7.4 or later. CI runs 7.4.20 and 7.6.6. - **tmux.** 3.3a or newer. CI runs 3.3a and 3.8 on every change, and 3.3a through 3.8 and tmux master before a release; other releases are unverified. [Compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/) holds the contract. - **Systems.** Linux, including WSL: run PowerShell and tmux in the same Linux environment. CI runs Linux x64 on every change and macOS as an advisory trial whose failures never fail the check. CI has no Windows job. - **Built on [libtmux for .NET](https://github.com/libtmux/libtmux-dotnet).** It lives in the same [libtmux organization](https://github.com/libtmux) with the same main author. The cmdlets return its native objects and add PowerShell parameter binding, help, formatting and `-WhatIf` / `-Confirm`. ## Documentation - **Read:** [snapshots and filtering](https://libtmux.org/en/powershell/latest/guides/read/), [structured queries](https://libtmux.org/en/powershell/latest/guides/query/), [pane contents and scrollback](https://libtmux.org/en/powershell/latest/guides/capture/), [attached clients](https://libtmux.org/en/powershell/latest/guides/clients/). - **Automate:** [create](https://libtmux.org/en/powershell/latest/guides/create/), [send text and keys](https://libtmux.org/en/powershell/latest/guides/input/), [arrange and resize](https://libtmux.org/en/powershell/latest/guides/layout/), [link and move windows](https://libtmux.org/en/powershell/latest/guides/placement/), [remove](https://libtmux.org/en/powershell/latest/guides/remove/). - **Configure:** [options](https://libtmux.org/en/powershell/latest/guides/options/), [hooks](https://libtmux.org/en/powershell/latest/guides/hooks/), [environment for new panes](https://libtmux.org/en/powershell/latest/guides/environment/). - **Coordinate:** [chains and control clients](https://libtmux.org/en/powershell/latest/guides/commands/), [event streams, jobs and parallel workers](https://libtmux.org/en/powershell/latest/guides/watch/). - **Assistants:** [install and configure the MCP server](https://libtmux.org/en/powershell/latest/guides/mcp/). - **Workspaces:** [load, review and apply](https://libtmux.org/en/powershell/latest/workspace/source-guide/), [export a starting declaration](https://libtmux.org/en/powershell/latest/workspace/source-guide/#export-a-starting-declaration), [edit a declaration](https://libtmux.org/en/powershell/latest/workspace/source-guide/#edit-the-declaration). Browse cmdlets with `Get-Command -Module LibTmux` and examples with `Get-Help LibTmux\New-TmuxSession -Examples`. Further reading: - [Compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/) — what CI runs and the support contract - [Troubleshooting](https://libtmux.org/en/powershell/latest/guides/troubleshooting/) — endpoint, package, input and stream failures - [Benchmarks](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/benchmarks/README.md) — installed-package workloads, correctness checks, raw samples and reproduction commands - [Contributing](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/.github/CONTRIBUTING.md) — the runners and development checks - [Executable guides](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/examples/Guides.ps1) — run against real tmux through the installed modules, and the README blocks run together in the [installed workflow test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/ReadmeWorkflow.Tests.ps1) ## License [MIT](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/LICENSE). See [third-party notices](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/licenses/THIRD-PARTY-NOTICES.md) for bundled dependencies. [libtmux-module]: https://libtmux.org/en/powershell/latest/reference/ [workspace-module]: https://libtmux.org/en/powershell/latest/workspace/reference/ [new-tmuxserver]: https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxserver/ [new-tmuxsession]: https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxsession/ [split-tmuxpane]: https://libtmux.org/en/powershell/latest/reference/libtmux-split-tmuxpane/ [new-tmuxwindow]: https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxwindow/ [get-tmuxsnapshot]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxsnapshot/ [remove-tmuxsession]: https://libtmux.org/en/powershell/latest/reference/libtmux-remove-tmuxsession/ [select-tmuxwindow]: https://libtmux.org/en/powershell/latest/reference/libtmux-select-tmuxwindow/ [invoke-tmuxpanecommand]: https://libtmux.org/en/powershell/latest/reference/libtmux-invoke-tmuxpanecommand/ [wait-tmuxpanetext]: https://libtmux.org/en/powershell/latest/reference/libtmux-wait-tmuxpanetext/ [send-tmuxtext]: https://libtmux.org/en/powershell/latest/reference/libtmux-send-tmuxtext/ [send-tmuxkey]: https://libtmux.org/en/powershell/latest/reference/libtmux-send-tmuxkey/ [get-tmuxpanecontent]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/ [wait-tmuxchannel]: https://libtmux.org/en/powershell/latest/reference/libtmux-wait-tmuxchannel/ [connect-tmuxcontrol]: https://libtmux.org/en/powershell/latest/reference/libtmux-connect-tmuxcontrol/ [new-tmuxcommand]: https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxcommand/ [invoke-tmuxcontrolcommand]: https://libtmux.org/en/powershell/latest/reference/libtmux-invoke-tmuxcontrolcommand/ [disconnect-tmuxcontrol]: https://libtmux.org/en/powershell/latest/reference/libtmux-disconnect-tmuxcontrol/ [invoke-tmuxchain]: https://libtmux.org/en/powershell/latest/reference/libtmux-invoke-tmuxchain/ [invoke-tmuxcommand]: https://libtmux.org/en/powershell/latest/reference/libtmux-invoke-tmuxcommand/ [watch-tmuxevent]: https://libtmux.org/en/powershell/latest/reference/libtmux-watch-tmuxevent/ [enter-tmuxsession]: https://libtmux.org/en/powershell/latest/reference/libtmux-enter-tmuxsession/ [get-tmuxworkspace]: https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-get-tmuxworkspace/ [import-tmuxworkspace]: https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-import-tmuxworkspace/ [resolve-tmuxworkspace]: https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-resolve-tmuxworkspace/ [test-tmuxworkspace]: https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-test-tmuxworkspace/ [get-tmuxworkspaceplan]: https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-get-tmuxworkspaceplan/ [invoke-tmuxworkspace]: https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-invoke-tmuxworkspace/ [convertto-tmuxworkspace]: https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-convertto-tmuxworkspace/ [session]: https://libtmux.org/en/csharp/latest/reference/libtmux-session/ [window]: https://libtmux.org/en/csharp/latest/reference/libtmux-window/ [pane]: https://libtmux.org/en/csharp/latest/reference/libtmux-pane/ [session-windows]: https://libtmux.org/en/csharp/latest/reference/libtmux-session-windows/ [window-panes]: https://libtmux.org/en/csharp/latest/reference/libtmux-window-panes/ [session-panes]: https://libtmux.org/en/csharp/latest/reference/libtmux-session-panes/ [panerunresult]: https://libtmux.org/en/csharp/latest/reference/libtmux-panerunresult/ [panewaitresult]: https://libtmux.org/en/csharp/latest/reference/libtmux-panewaitresult/ [workspacefile]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacefile/ [workspaceresult]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceresult/ [workspaceaction-request]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceaction-request/ [workspaceactionkind-createsession]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceactionkind-createsession/ [workspaceactionkind-captureresult]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceactionkind-captureresult/ [mcp-list_sessions]: https://libtmux.org/en/csharp/latest/mcp/tools/list_sessions/ [mcp-list_windows]: https://libtmux.org/en/csharp/latest/mcp/tools/list_windows/ [mcp-list_panes]: https://libtmux.org/en/csharp/latest/mcp/tools/list_panes/ [mcp-capture_pane]: https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/ [mcp-snapshot_pane]: https://libtmux.org/en/csharp/latest/mcp/tools/snapshot_pane/ [mcp-wait_for_text]: https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_text/ [mcp-capabilities]: https://libtmux.org/en/csharp/latest/mcp/resources/tmux_capabilities/ --- # Guides Source: https://libtmux.org/en/powershell/latest/guides/ > Guides for LibTmux. Connect to tmux and work with its sessions, windows, and panes. - [Getting started](https://libtmux.org/en/powershell/latest/guides/getting-started/): Read about libtmux for powershell. - [Attaching to tmux](https://libtmux.org/en/powershell/latest/guides/attaching-to-tmux/): Connect to an existing socket and leave its server running. - [Arrange panes and resize windows](https://libtmux.org/en/powershell/latest/guides/layout/): Read about arrange panes and resize windows. - [Capture, refresh and raw commands](https://libtmux.org/en/powershell/latest/guides/capture/): Read about capture, refresh and raw commands. - [Commands and control clients](https://libtmux.org/en/powershell/latest/guides/commands/): Read about commands and control clients. - [Compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/): Read about compatibility. - [Configure and run hooks](https://libtmux.org/en/powershell/latest/guides/hooks/): Read about configure and run hooks. - [Create sessions, windows and panes](https://libtmux.org/en/powershell/latest/guides/create/): Read about create sessions, windows and panes. - [Filter and query tmux objects](https://libtmux.org/en/powershell/latest/guides/query/): Read about filter and query tmux objects. - [Inspect attached clients](https://libtmux.org/en/powershell/latest/guides/clients/): Read about inspect attached clients. - [Link and move windows between sessions](https://libtmux.org/en/powershell/latest/guides/placement/): Read about link and move windows between sessions. - [Read and change options](https://libtmux.org/en/powershell/latest/guides/options/): Read about read and change options. - [Read tmux objects](https://libtmux.org/en/powershell/latest/guides/read/): Read about read tmux objects. - [Remove sessions, windows and panes](https://libtmux.org/en/powershell/latest/guides/remove/): Read about remove sessions, windows and panes. - [Send input to a pane](https://libtmux.org/en/powershell/latest/guides/input/): Read about send input to a pane. - [Set the environment for new panes](https://libtmux.org/en/powershell/latest/guides/environment/): Read about set the environment for new panes. - [Troubleshooting](https://libtmux.org/en/powershell/latest/guides/troubleshooting/): Read about troubleshooting. - [Using the .NET MCP server](https://libtmux.org/en/powershell/latest/guides/mcp/): Read about give an assistant tmux tools. - [Watch events and use runspaces](https://libtmux.org/en/powershell/latest/guides/watch/): Read about watch events and use runspaces. --- # Attaching to tmux Source: https://libtmux.org/en/powershell/latest/guides/attaching-to-tmux/ > Connect to an existing tmux server and find a session with PowerShell. Connect to an explicit socket, read the existing `work` session, and print its name. The program leaves the server running. A missing server or session ends the script with an error. This controls tmux from PowerShell. To open a session in your terminal, use [`tmux attach-session`](https://libtmux.org/en/tmux/latest/manual/attach-session/); the [shared guide](https://libtmux.org/en/tmux/guides/attaching-to-tmux/) covers interactive attachment and detaching. ## Connect to an existing server Save the complete program as `connect.ps1`. The environment variable `LIBTMUX_SOCKET_PATH` selects the existing server. The launcher below sets it to a private socket for trying the example. ```powershell title="connect.ps1" $ErrorActionPreference = 'Stop' Import-Module LibTmux -RequiredVersion 0.1.0 $socket = $env:LIBTMUX_SOCKET_PATH if ([string]::IsNullOrEmpty($socket)) { throw 'Set LIBTMUX_SOCKET_PATH to an existing socket.' } $server = New-TmuxServer -SocketPath $socket | Connect-TmuxServer $sessions = @($server | Get-TmuxSession -Name work) if ($sessions.Count -ne 1) { throw 'The work session does not exist.' } $sessions[0].Name ``` [`New-TmuxServer`](https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxserver/) constructs the endpoint without contacting tmux. [`Connect-TmuxServer`](https://libtmux.org/en/powershell/latest/reference/libtmux-connect-tmuxserver/) discovers the existing daemon, then [`Get-TmuxSession`](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxsession/) reads sessions and applies an exact, case-sensitive name selector. An unmatched selector emits no objects, so the program checks its result explicitly. The handle borrows the daemon. There is no daemon cleanup in this program: the caller owns the server and any other sessions on it. ## Setup and run Use an empty directory on Linux with PowerShell 7.4, POSIX shell, and tmux installed. Run the following commands in a POSIX shell. Install the [LibTmux 0.1.0 module](https://www.powershellgallery.com/packages/LibTmux/0.1.0) with PSResourceGet: ```console $ pwsh -NoLogo -NoProfile -Command ' $ErrorActionPreference = "Stop" Install-PSResource -Name LibTmux -Version 0.1.0 ` -Repository PSGallery -Scope CurrentUser -TrustRepository ' ``` Save the launcher as `run.sh`. It starts an isolated tmux server, runs the program, checks that the session still exists, then stops only that server. Cleanup runs after failures too. A failed shutdown keeps its socket directory and prints its location for inspection. ```sh title="run.sh" #!/bin/sh set -eu binary=$(command -v tmux) directory=$(mktemp -d "${TMPDIR:-/tmp}/libtmux-powershell-attach.XXXXXX") socket="$directory/tmux.sock" cleanup() { status=$? trap - 0 HUP INT TERM if [ -S "$socket" ] && ! "$binary" -S "$socket" kill-server; then printf 'Cannot stop tmux; kept %s\n' "$directory" >&2 exit 1 fi rm -rf "$directory" || exit 1 exit "$status" } trap cleanup 0 trap 'exit 1' HUP INT TERM unset TMUX TMUX_PANE export LIBTMUX_SOCKET_PATH="$socket" TMUX_BIN="$binary" "$binary" -S "$socket" -f /dev/null new-session -d -s work /bin/cat "$@" "$binary" -S "$socket" has-session -t '=work' ``` ```console $ sh run.sh pwsh -NoLogo -NoProfile -File connect.ps1 ``` The program prints `work`. To use your own existing server, set `LIBTMUX_SOCKET_PATH` to its socket and run the program without the launcher. The launcher owns only the demonstration server. ## Find or create a session Reading a session does not reserve its name. If your application creates a session after an unsuccessful lookup, another client may create the same name between those operations. Handle the creation error as well as the lookup. [Read tmux objects](https://libtmux.org/en/powershell/latest/guides/read/) explains captured values and selectors. [Create windows and panes](https://libtmux.org/en/powershell/latest/examples/create-layout/) is a complete program that creates and cleans up its own session. The module's [package source revision](https://github.com/libtmux/libtmux-powershell/tree/fcd0634e9ca887b70d88915c2d8e26c5da2737e5) records the implementation used by this example. --- # Arrange panes and resize windows Source: https://libtmux.org/en/powershell/latest/guides/layout/ > Arrange panes and resize windows: LibTmux documentation. Select native `$window` and `$pane` handles with [`Get-TmuxWindow`]() and [`Get-TmuxPane`](). Layout and size changes support `-WhatIf` and `-Confirm`. Without `-PassThru`, they emit no success output. With it, they return a native replacement handle; previously captured objects remain unchanged. Give a window explicit dimensions in cells: ```powershell $window | Set-TmuxWindowSize -Width 120 -Height 40 -PassThru ``` At least one dimension is required. Resizing switches [`window-size`](https://libtmux.org/en/tmux/latest/catalog/options/window-size/) to `manual`, so the window stops following its clients. Alternatively, use `-Direction Right -Adjustment 5` to grow an edge, or `-Mode Expand` / [`Shrink`]() to use the largest / smallest attached client. These forms are mutually exclusive. Arrange existing panes side by side: ```powershell $window | Set-TmuxLayout -Layout 'even-horizontal' -PassThru ``` Other presets include `even-vertical`, `main-horizontal`, `main-vertical` and `tiled`. Unambiguous prefixes are accepted; unknown or ambiguous names fail before dispatch. Use `-Mode Next`, [`Previous`]() or [`Spread`]() instead of `-Layout` to cycle layouts or spread panes. A captured [`$window.Layout`][window-layout] can be passed back as `-Layout`. On tmux 3.7 and earlier, restoring its sizes can rotate which pane occupies a position; it does not guarantee pane identity at each position. A JSON layout needs tmux 3.8; see [compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/). Set a pane's width in a window with a horizontal split: ```powershell $pane | Set-TmuxPaneSize -Width '40' -PassThru ``` Pane dimensions also accept percentages such as `'50%'`. tmux clamps sizes that do not fit; inspect the replacement handle for the observed dimensions. `-Direction` with `-Adjustment` moves a pane edge instead. Toggle a pane's zoom: ```powershell $pane | Set-TmuxPaneSize -Zoom ``` Repeating the command turns zoom off. `-Zoom` cannot be combined with a size or direction. A stale or disappeared target writes a per-target error; `-ErrorAction Stop` terminates the pipeline. Cancellation does not roll back an already dispatched change. [window-layout]: https://libtmux.org/en/csharp/latest/reference/libtmux-window-layout/ --- # Capture, refresh and raw commands Source: https://libtmux.org/en/powershell/latest/guides/capture/ > Capture, refresh and raw commands: LibTmux documentation. [`Get-TmuxPaneContent`]() reads rendered text from a native [`LibTmux.Pane`](). [`Update-TmuxPane`]() reads current pane metadata into a replacement handle. Both accept a pane directly or through the pipeline and borrow its daemon. [`Invoke-TmuxCommand`]() accepts a native [`LibTmux.Server`]() and literal tmux arguments for operations that do not yet have a dedicated cmdlet. Use the explicit endpoint and pane selection described in [Read tmux objects](https://libtmux.org/en/powershell/latest/guides/read/). The examples below assume `$pane` and `$server` refer to that selected pane and server. None chooses a global active server. ## Capture text Return one string per captured screen line: ```powershell $pane | Get-TmuxPaneContent ``` Capture the retained history as one string, joining wrapped screen lines: ```powershell $pane | Get-TmuxPaneContent -History -JoinWrappedLines -Raw ``` Capture an inclusive range, from ten lines before the visible screen through its fifth line. Zero identifies the top visible line; negative values address scrollback. Omitted bounds use tmux's normal visible-screen bounds. ```powershell $pane | Get-TmuxPaneContent -StartLine -10 -EndLine 4 ``` `-History` selects the oldest retained history and cannot be combined with `-StartLine`. It can be combined with `-EndLine`. `-Raw` emits exactly one string per pane, joining the core's captured lines with LF and adding no extra trailing newline. Internal empty lines remain empty lines. An empty capture emits no objects normally and one empty string with `-Raw`. This is rendered terminal text, not original process output or a byte-exact stream. Sending input or receiving a pane-output event does not establish command completion. Use an explicit completion signal from the application, such as a cooperative wait channel, or [Invoke-TmuxPaneCommand](https://libtmux.org/en/powershell/latest/guides/input/#run-a-command-to-completion) before asserting completed command output. | Switch | Effect | | --- | --- | | [`JoinWrappedLines`][-joinwrappedlines] | Join lines that wrapped on screen; tmux applies this in place of trailing-space handling. | | [`EscapeSequences`][-escapesequences] | Include terminal escape sequences representing captured attributes. | | [`EscapeNonPrintable`][-escapenonprintable] | Represent nonprintable bytes with octal escapes. | | [`PreserveTrailingSpaces`][-preservetrailingspaces] | Retain trailing spaces. | | [`TrimTrailingSpaces`][-trimtrailingspaces] | Request tmux's trailing-space trimming behavior. | | [`AlternateScreen`][-alternatescreen] | Capture the alternate screen. | | [`Quiet`][-quiet] | Return empty content when an alternate screen is absent; other failures remain errors. | | [`ModeScreen`][-modescreen] | Capture a mode screen, such as copy mode. | | [`Pending`][-pending] | Capture an incomplete pending escape sequence. | | [`Hyperlinks`][-hyperlinks] | Include supported hyperlink capture metadata. | | [`LineNumbers`][-linenumbers] | Include supported line-number metadata. | | [`LineFlags`][-lineflags] | Include supported line-flag metadata. | `-PreserveTrailingSpaces` and `-TrimTrailingSpaces` together terminate with [`Tmux.InvalidCapture`][gettmuxpanecontentcommand] before dispatch. Version-dependent switches retain the core's capability policy; availability depends on the tmux version and the core connection's configuration. ## Refresh captured metadata Retain the replacement returned by an explicit refresh: ```powershell $currentPane = $pane | Update-TmuxPane ``` The original `$pane` keeps its previously captured values. Refresh observes tmux and returns another native [`LibTmux.Pane`](); it does not mutate terminal state or acquire ownership of the daemon. It uses the core's refresh and identity rules. Repeated linked-window placement refresh remains subject to the core's contextual-target limitations. ## Run literal tmux arguments Pass each argument as a separate array element. The adapter does not join arguments into a shell command or expand their contents. ```powershell $server | Invoke-TmuxCommand -Arguments @( 'list-sessions', '-F', '#{session_name}' ) ``` For tmux features without a dedicated cmdlet, use the same literal argument boundary. This creates a named paste buffer, reads its text and removes only that buffer. Deleting a buffer by name needs tmux 3.4 or newer; earlier releases act on an unrelated buffer when the name is missing, so [`Invoke-TmuxCommand`]() refuses the command there: ```powershell & { $name = 'libtmux-' + [guid]::NewGuid().ToString('N') $quiet = @{ Confirm = $false; ErrorAction = 'Stop' } $created = $false try { $set = @('set-buffer', '-b', $name, 'hello from PowerShell') $null = $server | Invoke-TmuxCommand -Arguments $set @quiet $created = $true $show = @('show-buffer', '-b', $name) $shown = $server | Invoke-TmuxCommand -Arguments $show @quiet $shown.StandardOutputLines } finally { if ($created) { $delete = @('delete-buffer', '-b', $name) $server | Invoke-TmuxCommand -Arguments $delete @quiet | Out-Null } } } ``` This returns `hello from PowerShell`. [`StandardOutput`]() retains bytes when line projection is unsuitable. For copy mode, use raw [`copy-mode`](https://libtmux.org/en/tmux/latest/manual/copy-mode/) and [`send-keys -X`](https://libtmux.org/en/tmux/latest/manual/send-keys/) commands with an explicit pane ID. `Get-TmuxPaneContent -ModeScreen` reads its rendered screen. Copy-mode commands change the pane's mode, so leave it explicitly with [`send-keys -X cancel`](https://libtmux.org/en/tmux/latest/manual/send-keys/) when finished. Empty non-command arguments are preserved. The first argument must name a command or alias. An empty, whitespace or leading-option argument terminates with [`Tmux.InvalidCommand`][invoketmuxcommandcommand] before confirmation or dispatch. Select the socket on the server handle; global options such as `-S`, `-L` and `-f` cannot replace the command name. Pipeline input must be a native [`LibTmux.Server`](); an object with similarly named properties does not bind as an endpoint. Raw commands can mutate tmux or execute shell work. They always support `-WhatIf` and `-Confirm`, including for commands the caller knows are reads. Confirmation precedes discovery and dispatch. Preview shows the endpoint and command name; argument contents are not included in the confirmation text. ```powershell $server | Invoke-TmuxCommand -Arguments @('kill-session', '-t', '$3') -WhatIf ``` Successful execution emits a native [`LibTmux.TmuxCommandResult`]() with exit code, logical arguments, stdout/stderr bytes and projected lines. A nonzero exit emits no success result and writes [`Tmux.CommandFailed`][invoketmuxcommandcommand]. Its original [`TmuxCommandException.Result`]() retains those diagnostics, and its [`Dispatch`]() is [`Dispatched`](). Transport failures preserve their original exception and dispatch uncertainty. No mutation is automatically retried. Capture and refresh failures use [`Tmux.PaneCaptureFailed`][gettmuxpanecontentcommand] and [`Tmux.PaneRefreshFailed`][updatetmuxpanecommand]. Each error retains the failed owner, allowing later pipeline owners to continue unless `-ErrorAction Stop` is selected. Cancellation uses the same core token and pipeline lifecycle as the read cmdlets; it does not imply rollback or termination of shell work. The [capture integration test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/Capture.Tests.ps1) exercises these contracts against an owned daemon with explicit output readiness, literal argument round trips, error results, refresh replacement and zero-dispatch `-WhatIf`. It owns its sockets, child processes and temporary files. [-joinwrappedlines]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.JoinWrappedLines [-escapesequences]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.EscapeSequences [-alternatescreen]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.AlternateScreen [-quiet]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.Quiet [gettmuxpanecontentcommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/GetTmuxPaneContentCommand.cs [invoketmuxcommandcommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/InvokeTmuxCommandCommand.cs [updatetmuxpanecommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/UpdateTmuxPaneCommand.cs [-escapenonprintable]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.EscapeNonPrintable [-preservetrailingspaces]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.PreserveTrailingSpaces [-trimtrailingspaces]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.TrimTrailingSpaces [-modescreen]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.ModeScreen [-pending]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.Pending [-hyperlinks]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.Hyperlinks [-linenumbers]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.LineNumbers [-lineflags]: https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxpanecontent/#LibTmux%5CGet-TmuxPaneContent.parameter.LineFlags --- # Commands and control clients Source: https://libtmux.org/en/powershell/latest/guides/commands/ > Commands and control clients: LibTmux documentation. Use native command values when composing operations. [`New-TmuxCommand`]() keeps literal argv boundaries, including empty arguments, spaces and punctuation; it does no I/O. Commands can still invoke tmux features that deliberately run a shell, such as [`run-shell`](https://libtmux.org/en/tmux/latest/manual/run-shell/). Shell programs inside those arguments retain those features' normal semantics. [`Connect-TmuxControl`]() needs tmux 3.7 or newer and is refused on an older daemon before a client attaches; chains and raw commands need only 3.3a. Literal [`delete-buffer -b`](https://libtmux.org/en/tmux/latest/manual/delete-buffer/) and [`set-buffer -n`](https://libtmux.org/en/tmux/latest/manual/set-buffer/) items need tmux 3.4; see [optional features](https://libtmux.org/en/powershell/latest/guides/compatibility/#optional-features). Select `$server` first using [explicit endpoint selection](https://libtmux.org/en/powershell/latest/guides/read/). These examples require an existing session named `fixture` and borrow its lifetime. ## Execute an ordered chain Construct the complete array, then execute it once. The result is one native [`TmuxCommandResult`](); read its [`StandardOutputLines`]() or byte-valued [`StandardOutput`](). Generation and placement guards on typed request commands survive chaining. ```powershell $first = New-TmuxCommand -Name 'display-message' -Arguments @('-p', 'first') $second = New-TmuxCommand -Name 'display-message' -Arguments @('-p', 'second') $server | Invoke-TmuxChain -Command @($first, $second) ``` A failure stops later commands, but leaves earlier mutations in place. Output is merged; the result does not attribute separate receipts to each command. Cancellation does not roll back dispatched work. Do not retry a mutation merely because its caller stopped waiting. Admission defaults to 1024 commands and 1048576 UTF-8 bytes of command names and argument text, counting a NUL terminator per item. `-MaxCommands` and `-MaxInputBytes` adjust those limits. Native transport and operating-system limits also apply. These admission limits are not memory or reply-size bounds. ## Reuse a control client An explicit client avoids starting a new tmux client for every command. The native core correlates concurrent replies. Keep its ownership scope visible: this example closes the client on success or failure and leaves the tmux server and session running. ```powershell & { $control = $server | Connect-TmuxControl -Target 'fixture' -ErrorAction Stop try { $command = New-TmuxCommand -Name 'display-message' -Arguments @( '-p', '#{session_name}' ) $control | Invoke-TmuxControlCommand -Command $command -ErrorAction Stop } finally { $control | Disconnect-TmuxControl -Confirm:$false } } ``` `-Target` is raw tmux target syntax, resolved at attachment time. It does not carry the identity captured by a native [`Session`](). A command constructed from raw text likewise has no entity identity guard; pass a native typed request's command directly when it supplies one. [`Invoke-TmuxControlCommand`]() emits native reply strings and emits nothing for an empty reply. Ctrl+C cancels the current wait; a command already dispatched may still run. The borrowed client remains usable when that command finishes. [`Disconnect-TmuxControl`]() explicitly closes the supplied client, including for other callers sharing it. Its native disposal has no cancellation token, so cleanup is awaited. `-WhatIf` performs no dispatch. Previewing a supplied control connection names that connection; its native interface exposes no endpoint metadata to display. The cmdlets run on the calling pipeline. They do not return Tasks or claim that a foreground command leaves the prompt available. ## Collect concurrent command results Use the [finite concurrent-command recipe](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/examples/ConcurrentCommands.ps1) when independent commands need separate results. Run it from the repository root after importing [`LibTmux`](). It accepts native command values, preserves their identity guards and starts at most `-MaxPending` calls at once. By default, each bounded wave finishes before its results are emitted in input order. The next wave then starts. This bounds reordering storage but can leave a slot idle while another command in the wave finishes. Each result carries its zero-based [`Index`][command-example], [`Name`][command-example], [`ExitCode`](), output lines, error lines and [`Utf8Bytes`][command-example]. ```powershell $commands = @(foreach ($name in @('api', 'worker', 'scheduler')) { New-TmuxCommand -Name 'display-message' -Arguments @('-p', $name) }) ./examples/ConcurrentCommands.ps1 -Server $server -Command $commands ` -MaxPending 2 -MaxResultBytes 4096 -Timeout 1 ``` Pass a borrowed control client to reuse its connection. `-CompletionOrder` emits each result as the caller harvests a completed task; simultaneous completions have no guaranteed order. [`Index`][command-example] still identifies its input. The recipe leaves the client open; its owner closes it here. ```powershell & { $control = $server | Connect-TmuxControl -Target 'fixture' -ErrorAction Stop try { $commands = @(foreach ($format in @( '#{session_name}', '#{window_name}', '#{pane_id}')) { New-TmuxCommand -Name 'display-message' -Arguments @( '-p', '-t', 'fixture:0.0', $format ) }) ./examples/ConcurrentCommands.ps1 -Connection $control ` -Command $commands -MaxPending 2 -MaxResultBytes 4096 ` -Timeout 1 -CompletionOrder } finally { $control | Disconnect-TmuxControl -Confirm:$false } } ``` On tmux 3.7 and newer, commands from one server handle share a single control client, so a command that blocks while the client waits holds the commands behind it. A command that is a [`wait-for`](https://libtmux.org/en/tmux/latest/manual/wait-for/) on its own runs in its own process and leaves the others free. A [`wait-for`](https://libtmux.org/en/tmux/latest/manual/wait-for/) nested in a list, such as [`if-shell -F 1 'wait-for release ; display-message -p done'`](https://libtmux.org/en/tmux/latest/manual/if-shell/), is not seen and blocks the shared client until it is released. Keep a blocking command at the top level, or set `LIBTMUX_CONTROL_TRANSPORT=0` before creating the server handle to send every command from its own process. The recipe admits 1–64 commands and 1–16 pending calls; the default is four pending calls. Its cumulative result-text budget defaults to 64 KiB, counting UTF-8 command names and output/error lines plus one byte per item. A result that exceeds the remaining budget is rejected before being retained or emitted. This excludes exception diagnostics, object overhead and downstream consumer storage. Native buffers are separate: process transport allows 64 MiB per output/error stream; default control limits allow 4 MiB per block and 16 MiB per reply. High concurrency with large replies can therefore use substantially more memory than `-MaxResultBytes`. `-Timeout` supplies one deadline for the entire batch, defaulting to one second. Supply `-CancellationToken` for caller-managed cancellation. The script waits synchronously on the calling runspace; it does not promise immediate Ctrl+C handling. On failure, cancellation or consumer termination, it cancels and observes every started task before returning; native cleanup may extend beyond the deadline. Previously emitted results and dispatched mutations remain. Command failures retain the native exception and identify their input with `Exception.Data['LibTmux.ConcurrentCommandIndex']`. Do not automatically retry canceled mutations. [command-example]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/examples/ConcurrentCommands.ps1 --- # Compatibility Source: https://libtmux.org/en/powershell/latest/guides/compatibility/ > Compatibility: LibTmux documentation. This source checkout targets PowerShell 7.4 and .NET 8. The Linux workflow tests the specific PowerShell and tmux versions below; other combinations remain unverified. [LibTmux](https://www.powershellgallery.com/packages/LibTmux) and [LibTmux.Workspace](https://www.powershellgallery.com/packages/LibTmux.Workspace) are published on PowerShell Gallery. Both pin [libtmux for .NET](https://github.com/libtmux/libtmux-dotnet). See the [install guide](https://libtmux.org/en/powershell/latest/guides/getting-started/#quick-start) for package-manager commands and source builds. Publication does not expand the tested platforms below. | Environment | Contract | | --- | --- | | Linux x64 | The [Linux workflow](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/.github/workflows/ci.yml) exercises PowerShell 7.4.20 and 7.6.6 with tmux 3.3a and 3.8 on every change. A full run, which every release performs, adds 3.4, 3.5, 3.6, 3.7a, 3.7b, 3.7c and the current tmux master (`next-3.9`). Check the run for the commit you use; a green older commit does not verify newer code. | | WSL2 | Run PowerShell and tmux inside the same Linux environment. The Windows host's PowerShell process is outside this contract. | | macOS | Intel and Apple Silicon have an advisory [eight-cell trial](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/.github/workflows/macos-trial.yml). Suite failures appear in its job summaries and artifacts without failing the trial check; they do not establish support. | | Native Windows and psmux | Outside this port's scope. | ## Minimum tmux version The minimum for ordinary operations is tmux 3.3a. Versions compare as whole releases, so 3.3 is below the floor and 3.3a is the first supported release. Development builds and release candidates rank below the release they name: `next-3.3a` and a candidate of 3.3a do not qualify, and a report without a dated release, such as `master`, is refused. tmux release candidates are not supported: a feature can require one only until its release ships. See [Release candidates](https://libtmux.org/en/tmux/guides/tmux-support/#release-candidates). ## Optional features A feature that a release cannot run safely is refused for that cmdlet alone, before the requested operation is sent. Version checks may still contact tmux. Each requirement is per feature, so the floor for reads, writes, raw commands and workspaces stays tmux 3.3a. [`capabilities.json`](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/capabilities.json) is the machine-readable list of these features: each entry names the capability, the release it needs, the error and the cmdlets it gates. The `id` in the last column names the entry and its [evidence](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence). | Feature | Needs | Below that release | Id | | --- | --- | --- | --- | | [`Connect-TmuxControl`](), [`Watch-TmuxEvent`]() with a server | 3.7 | Refused before a control client attaches. | [`control-mode`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | [`Invoke-TmuxPaneCommand`]() | 3.4 | Refused before it stages a named buffer. | [`buffer-delete-named`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | Literal [`delete-buffer -b`](https://libtmux.org/en/tmux/latest/manual/delete-buffer/) | 3.4 | Refused by the raw-command cmdlets. | [`buffer-delete-named`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | Literal [`set-buffer -b ... -n`](https://libtmux.org/en/tmux/latest/manual/set-buffer/) | 3.4 | Refused by the raw-command cmdlets. | [`buffer-rename`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | Literal [`break-pane`](https://libtmux.org/en/tmux/latest/manual/break-pane/) without `-n` | not exactly 3.7 | Refused on 3.7. Name the window. | [`break-pane-misnames-windows`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | Session and window names with `:` or `.` | not exactly 3.7 | Refused on 3.7. | [`name-separators-rejected`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | Literal [`split-window -p`](https://libtmux.org/en/tmux/latest/manual/split-window/) | not exactly 3.4 | Refused on 3.4. Use `-l` with a percentage such as `30%`. | [`split-window-percent-size`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | Literal [`refresh-client -l`](https://libtmux.org/en/tmux/latest/manual/refresh-client/) | 3.6a | Refused by the raw-command cmdlets. | [`clipboard-query`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | Literal [`select-layout`](https://libtmux.org/en/tmux/latest/manual/select-layout/) with a layout string | 3.4 for a layout without a checksum | Refused by the raw-command cmdlets. Use a preset name or a layout read from tmux. | [`layout-without-checksum`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | [`Set-TmuxLayout`]() with `main-horizontal-mirrored` or `main-vertical-mirrored` | 3.5 | Refused. Use another preset. | [`layout-mirrored-main`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | | [`Set-TmuxLayout`]() or a workspace window ([`Get-TmuxWorkspacePlan`]()) with a JSON layout | 3.8 | Refused. Use the checksummed layout from [`$window.Layout`](https://libtmux.org/en/csharp/latest/reference/libtmux-window-layout/). The raw-command cmdlets and control connections are not gated; tmux reports the error. | [`layout-json`](https://libtmux.org/en/powershell/latest/guides/compatibility/#evidence) | The raw-command cmdlets are [`Invoke-TmuxCommand`](), [`Invoke-TmuxChain`]() and [`Invoke-TmuxControlCommand`](). [`Wait-TmuxPaneText`]() needs no refusal: it attaches no control client below 3.7 and polls the pane instead. Every refusal raises one type, [`LibTmux.TmuxUnsupportedOnReleaseException`](), whichever cmdlet or literal command meets it. Where a plain release floor decides, the error is its subclass [`LibTmux.TmuxVersionTooLowException`](), so one `catch` of the base type covers both and a `catch` of the subclass keeps working for those rows. The exception carries [`ActualVersion`](), [`SafeReleases`](), [`CapabilityId`]() and `Command`. A workspace layout that the daemon's release lacks fails planning with [`LibTmux.Workspace.WorkspaceFormatException`](), which names the layout path and carries the refusal as its [`InnerException`](). The error still reports the [`NotImplemented`]() category. These inputs are caller errors on every release and are not release refusals: - A session name with `:` or `.` raises [`System.ArgumentException`]() from [`New-TmuxSession`](). - A layout string that is malformed or unknown raises [`LibTmux.TmuxWindowException`]() from [`Set-TmuxLayout`](). [`capabilities.json`]() names the error of each entry and each workaround, and its `apis` list only the cmdlets that raise that error. ### Evidence Each requirement rests on a published source. The libtmux for .NET links below record the compatibility investigations; they do not identify this checkout's dependency version. [Directory.Packages.props](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/Directory.Packages.props) holds the current package pins. - `control-mode`: before 3.7, a notification that fires while a control client identifies itself crashes the whole server, as the [libtmux for .NET one-shot guide](https://github.com/libtmux/libtmux-dotnet/blob/b1e8156/docs/modes/one-shot.md?plain=1#L46-L50) records with the tmux commit that changed it. The same package's [version matrix](https://github.com/libtmux/libtmux-dotnet/blob/b1e8156/docs/modes/matrix.md?plain=1#L178) lists the requirement. - `buffer-delete-named` and `buffer-rename`: before 3.4, a buffer name that does not exist acts on the most recent buffer instead of failing. See the [version matrix](https://github.com/libtmux/libtmux-dotnet/blob/b1e8156/docs/modes/matrix.md?plain=1#L181). - `break-pane-misnames-windows`: [`break-pane`](https://libtmux.org/en/tmux/latest/manual/break-pane/) without `-n` ends a 3.7 server. tmux 3.7a lists ["Fix crash in break-pane when no name is provided"](https://github.com/tmux/tmux/blob/0e418b6/CHANGES#L1-L8). See also the [version matrix](https://github.com/libtmux/libtmux-dotnet/blob/b1e8156/docs/modes/matrix.md?plain=1#L183). - `name-separators-rejected`: 3.7 rejects `:` and `.` in names. tmux 3.7a lists ["Only forbid #( in names, allow #[, empty names, : and ."](https://github.com/tmux/tmux/blob/0e418b6/CHANGES#L1-L8). See also the [version matrix](https://github.com/libtmux/libtmux-dotnet/blob/b1e8156/docs/modes/matrix.md?plain=1#L184). - `split-window-percent-size`: [`split-window -p`](https://libtmux.org/en/tmux/latest/manual/split-window/) is broken on 3.4. tmux 3.5 lists ["Fix split-window -p"](https://github.com/tmux/tmux/blob/ac44566/CHANGES#L88). See also the [version matrix](https://github.com/libtmux/libtmux-dotnet/blob/b1e8156/docs/modes/matrix.md?plain=1#L185). - `clipboard-query`: before 3.6a, [`refresh-client -l`](https://libtmux.org/en/tmux/latest/manual/refresh-client/) can end the server when the attached client leaves before its terminal answers, and on 3.3a it ends the server with a client attached. tmux 3.6a lists ["Newer libevents do not allow event_del on a zero'd event"](https://github.com/tmux/tmux/blob/cc117b5/CHANGES#L21), the [commit](https://github.com/tmux/tmux/commit/0af04295f) that sets up the clipboard query's timer when a client's terminal opens. See also the [version matrix](https://github.com/libtmux/libtmux-dotnet/blob/b1e8156/docs/modes/matrix.md?plain=1#L187). - `layout-without-checksum`: a layout string that is neither checksummed nor a preset name ends tmux 3.3a. The [version matrix](https://github.com/libtmux/libtmux-dotnet/blob/b1e8156/docs/modes/matrix.md?plain=1#L186) lists the requirement. - `layout-mirrored-main`: tmux 3.5 lists ["Add mirrored versions of the main-horizontal and main-vertical layouts"](https://github.com/tmux/tmux/blob/ac44566/CHANGES#L27), so an earlier release rejects the preset. See also the [refusal types](https://github.com/libtmux/libtmux-dotnet/blob/b1e8156/docs/modes/matrix.md?plain=1#L196-L199). - `layout-json`: tmux 3.8 lists ["Layout strings now use a JSON subset format"](https://github.com/tmux/tmux/blob/7f2a35a/CHANGES#L38), so an earlier release rejects the JSON form. ### What the checks do not read The checks read the command a cmdlet is given. They do not read a refused command carried inside another command's text: an [`if-shell`](https://libtmux.org/en/tmux/latest/manual/if-shell/) or [`run-shell -C`](https://libtmux.org/en/tmux/latest/manual/run-shell/) string, a [`bind-key`](https://libtmux.org/en/tmux/latest/manual/bind-key/), [`set-hook`](https://libtmux.org/en/tmux/latest/manual/set-hook/) or [`confirm-before`](https://libtmux.org/en/tmux/latest/manual/confirm-before/) command, a menu, prompt or choose template, a brace block, or an alias in your tmux configuration. Commands typed into a pane are outside them too. Nested, a refused command reaches tmux unchanged, and it fails as follows. | What happens | Command | Releases | | --- | --- | --- | | The server exits | [`break-pane`](https://libtmux.org/en/tmux/latest/manual/break-pane/) without `-n`, direct or nested | Exactly 3.7; fixed in 3.7a | | The server exits | [`select-layout`](https://libtmux.org/en/tmux/latest/manual/select-layout/) with an invalid layout string that has no checksum | 3.3a; 3.4 answers with an error and stays up | | The server exits | [`refresh-client -l`](https://libtmux.org/en/tmux/latest/manual/refresh-client/), when an attached client leaves or does not answer the clipboard query | Below 3.6a | | A different buffer is changed, with no error | [`delete-buffer -b NAME`](https://libtmux.org/en/tmux/latest/manual/delete-buffer/), [`set-buffer -b NAME -n`](https://libtmux.org/en/tmux/latest/manual/set-buffer/), when NAME does not exist | Below 3.4: the most recent buffer is used instead | | tmux answers with an error and nothing changes | [`split-window -p`](https://libtmux.org/en/tmux/latest/manual/split-window/) | Exactly 3.4 | | tmux answers with an error and nothing changes | `:` or `.` in a session or window name | Exactly 3.7 | On exactly tmux 3.7, name every [`break-pane`](https://libtmux.org/en/tmux/latest/manual/break-pane/), including the one the `prefix !` key runs, or upgrade to 3.7a or later. Do not nest any other command that this page lists as refused. ## How the check works Every cmdlet that talks to tmux goes through the [libtmux for .NET](https://github.com/libtmux/libtmux-dotnet) package, which reads the version of the connected daemon first and refuses an older or unreadable one before it sends the requested operation. The client executable does not decide this: an older daemon is refused even when the selected executable reports a newer version. Operations return a [`LibTmux.TmuxVersionTooLowException`]() error rather than an empty result. When no daemon answers, the executable's own version is checked before it can start one; a read, which starts nothing, reports the missing daemon instead. The check adds no tmux hook activity: it asks for a [`run-shell -C`](https://libtmux.org/en/tmux/latest/manual/run-shell/) expansion that tmux rejects while parsing, so no `after-*` hook and no [`command-error`](https://libtmux.org/en/tmux/latest/catalog/hooks/command-error/) hook fires for it. Every command list the package sends starts with a guard on the checked version. If a different daemon replaced the first one in between, the list fails before any command runs. A replacement that is supported is checked again and the command is sent once more; one below the floor is refused; a second mismatch reports that the daemon changed and that the command did not run. A client that finds the checked daemon gone starts none. The Linux workflow keeps tmux 3.2a and unpatched 3.3 as rejection lanes. They run only the version check suite, which checks that reads, creation, raw commands and chains are refused and that nothing changed. A daemon older than 3.2 cannot report its version through that check: a 3.1c daemon answers with the [`run-shell`](https://libtmux.org/en/tmux/latest/manual/run-shell/) usage line, and a 3.0a daemon makes the client print `server version is too old for client`. A client older than 3.2 rejects the `-N` flag the check passes, so its own version decides. All three are refused with [`TmuxVersionTooLowException`](), which says what to do: upgrade tmux and restart the tmux server, or use an older release. The message names the last libtmux for .NET release that supports older tmux, 0.0.0-alpha.21; for these modules it is 0.1.0-alpha2. The Linux workflow also runs real 3.0a and 3.1c daemons behind a 3.3a client and requires the refusal to come back promptly. A refusal is a non-terminating error, like every other operation failure in the module, so it follows `-ErrorAction`. Use `-ErrorAction Stop` where a refused daemon must not fall through as no output, as in `Get-TmuxSession -ErrorAction SilentlyContinue`, which hides it. [`Connect-TmuxControl`]() attaches only after the same check, so [`Invoke-TmuxControlCommand`]() and [`Watch-TmuxEvent`]() need no check of their own on the connection it returns. `Invoke-TmuxCommand kill-server` against an endpoint where no daemon answers returns an empty successful result without dispatching anything. The separate [MCP tool](https://libtmux.org/en/powershell/latest/guides/mcp/) is built on the same package and refuses the same daemons. One registry in the module holds these requirements, and it writes [`capabilities.json`](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/capabilities.json) for the capabilities page of the documentation site. The module reads the daemon's version and infers what that release can do; tmux does not report its capabilities, so a patched build is judged as the release it names. The module checks the typed operations and workspace plans itself. Literal command items sent through [`Invoke-TmuxCommand`](), [`Invoke-TmuxChain`]() and [`Invoke-TmuxControlCommand`]() are checked by the libtmux for .NET package, which reads a command word the way tmux does, by alias, name or unique prefix, and reads a `;` list one command at a time. [What the checks do not read](https://libtmux.org/en/powershell/latest/guides/compatibility/#what-the-checks-do-not-read) lists the nested commands they skip. The version a guard reads is the daemon's, taken just before the command is sent. A daemon replaced in that moment is not caught by the guard, though the package's own check still refuses one below the floor. Sections of the suites that need a control client or a pane command report SKIP below their releases rather than pass, and the features suite asserts the refusals and that nothing changed. The guards for exactly 3.7, a release the workflow does not run, are tested by reporting that version to the version probe. Choose the tmux executable and socket with [New-TmuxServer](https://libtmux.org/en/powershell/latest/guides/read/), or leave the socket out and tmux picks the server. A handle alone starts no daemon. The module does not change `TMUX` or `TMUX_PANE` in the calling process, and it does not connect to a server during import or formatting. Some tmux flags and format expressions vary by version. The typed API checks capabilities where it can; [query plans](https://libtmux.org/en/powershell/latest/guides/query/) show source pushdown and residual work before execution. A failed or unknown capability check is not an empty result. [Capture options](https://libtmux.org/en/powershell/latest/guides/capture/) identify flags whose availability depends on tmux. Use an explicit [raw command](https://libtmux.org/en/powershell/latest/guides/capture/#run-literal-tmux-arguments) for less common tmux operations and inspect its result or error record. The workspace module is a separate PowerShell package over the shared .NET workspace engine. The [MCP server](https://libtmux.org/en/powershell/latest/guides/mcp/) is a separate .NET tool that does not require PowerShell. Its client protocol, toolsets, and task support must be discovered from the installed executable rather than inferred from the PowerShell module version. See [troubleshooting](https://libtmux.org/en/powershell/latest/guides/troubleshooting/) for endpoint, package, input and stream failures. ## Install with PowerShellGet The README installs with PSResourceGet, which PowerShell 7.4 includes. PowerShellGet installs the same packages. Install the core module: ```console $ Install-Module -Name LibTmux ``` Or install the workspace module with its matching core dependency: ```console $ Install-Module -Name LibTmux.Workspace ``` Choose one installer. Both Gallery pages also provide Azure Automation and manual download options. A manual download does not include dependencies; use a package manager to resolve them. Azure Automation runs need a host with PowerShell and tmux as described above. --- # Configure and run hooks Source: https://libtmux.org/en/powershell/latest/guides/hooks/ > Configure and run hooks: LibTmux documentation. Use a native server, session, window or pane to select a hook table. Server hooks are global; tmux has no separate server hook table. Choose a hook supported in the selected scope. For reads and changes, `-Scope` overrides the scope and `-Global` requests global defaults; pane-local hooks stay local. Inspect a configured hook on a previously selected `$session`: ```powershell $session | Get-TmuxHook -Name 'alert-bell' ``` Each native [`TmuxHook`]() has a base [`Name`][tmuxhook-name] and [`Values`][tmuxhook-values], an ordered collection of [`TmuxHookEntry`]() objects with [`Index`][tmuxhookentry-index] and [`Command`][tmuxhookentry-command]. Get accepts base names only; inspect [`Values`][tmuxhook-values] for individual entries. Omit `-Name` to list the selected table. Missing local hooks produce no objects. Set one indexed command and inspect the complete grouped hook: ```powershell $command = 'display-message "build finished"' $session | Set-TmuxHook -Name 'alert-bell[7]' -Command $command -PassThru ``` The command is tmux syntax, not PowerShell syntax. tmux normalizes it; readback preserves that normalized text so it can be passed back unchanged. Without `-PassThru`, setting emits no success output. An unindexed set replaces entries. `-Append` keeps them and lets tmux choose a free index, which may precede existing sparse indices. Use explicit indices when order matters. Multiple changes do not form an atomic replacement. Run a previously configured base hook without waiting for its event. [`Invoke-TmuxHook`]() uses tmux's target-context lookup; `-Scope` and `-Global` do not force a particular table, and an indexed name does not select one entry: ```powershell $session | Invoke-TmuxHook -Name 'alert-bell' ``` The call confirms acceptance by tmux. A hook can start asynchronous work; use a producer signal and [Wait-TmuxChannel](https://libtmux.org/en/powershell/latest/reference/libtmux-wait-tmuxchannel/) to observe that work completing. Remove one indexed entry, preserving its neighbours: ```powershell $session | Remove-TmuxHook -Name 'alert-bell[7]' ``` Use the base name to remove the local hook. Mutations support `-WhatIf` and `-Confirm`; previews perform no tmux I/O. Errors retain the native owner and core exception. `-ErrorAction Continue` permits later owners; [`Stop`][erroraction-stop] terminates the pipeline. Cancellation cannot undo a dispatched command. [tmuxhook-name]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxhook-name/ [tmuxhook-values]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxhook-values/ [tmuxhookentry-index]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxhookentry-index/ [tmuxhookentry-command]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxhookentry-command/ [erroraction-stop]: https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.actionpreference#system-management-automation-actionpreference-stop --- # Create sessions, windows and panes Source: https://libtmux.org/en/powershell/latest/guides/create/ > Create sessions, windows and panes: LibTmux documentation. [`New-TmuxSession`](), [`New-TmuxWindow`]() and [`Split-TmuxPane`]() create tmux objects and emit native [`LibTmux.Session`](), [`LibTmux.Window`]() and [`LibTmux.Pane`]() handles. Each requires its native owner directly or through the pipeline: a server for a session, a session for a window and a pane for a split. Use [explicit endpoints and selection](https://libtmux.org/en/powershell/latest/guides/read/) to choose those owners. Creation supports `-WhatIf` and `-Confirm`. Confirmation occurs before discovery or dispatch, including when creating the first session would start a daemon. A preview emits no created object. Creating objects does not transfer daemon ownership to the module or arrange automatic teardown. Choose an endpoint you control and remove the created resources when done. ## Create a detached session The following command assumes `$server` is an endpoint you own. It creates a detached session with the requested window name and dimensions: ```powershell $session = $server | New-TmuxSession -Name 'work' -WindowName 'editor' -Width 100 -Height 30 ``` Omitting `-Name` lets tmux choose a name. An existing name remains an error; this command does not replace or attach to an existing session. Omitting dimensions retains tmux's defaults. Names and working directories retain tmux's format expansion rules, including the meaning of `#`. Dimensions remain subject to tmux's [`window-size`](https://libtmux.org/en/tmux/latest/catalog/options/window-size/) policy. ## Create a window or split Create a window at an explicit nonnegative index and make it current: ```powershell $window = $session | New-TmuxWindow -Name 'tools' -Index 5 -Activate ``` Omitting `-Index` lets tmux choose an available index. An occupied index remains an error. New windows stay unselected unless `-Activate` is present; selecting one does not attach a PowerShell process to the terminal. Given a selected native `$pane`, place a new pane to its left and request twenty columns: ```powershell $newPane = $pane | Split-TmuxPane -Horizontal -Before -Size 20 ``` Splits default to a new pane below the target. `-Horizontal` selects a left/right split; `-Before` puts the new pane above or left of the target. Use either positive `-Size` cells or `-Percentage` from 1 through 100. Omitting both uses tmux's default split size. Geometry still must fit the available window. `-FullWindow` spans the full window and `-Zoom` requests zooming the new pane. `-Activate` selects it; otherwise the previously active pane stays active. The core owns tmux flag generation and version capability behavior. ## Commands, directories and environment All three cmdlets accept `-Command`, `-StartDirectory` and `-Environment`. `-Command` is one tmux shell-command string. tmux runs it through its shell; quote shell syntax deliberately and keep untrusted input out of that string. Omitting it uses the configured tmux default command or shell. For example, on a Unix host with `/bin/sh` available: ```powershell $window = $session | New-TmuxWindow -Name 'shell' -Command 'exec /bin/sh' ``` `-StartDirectory` is a filesystem path interpreted by the core and tmux. Use an absolute path for predictable behavior. The core expands `~` and `~/`; the adapter does not resolve PowerShell provider paths or change the caller's current directory. tmux may expand formats within the path. `-Environment` accepts a dictionary of string keys and string values. Empty values are retained; numeric and null values are rejected before dispatch with [`Tmux.InvalidCreation`][newtmuxsessioncommand]. Names cannot be empty or contain `=` or NUL; values cannot contain NUL. Validation also applies to `-WhatIf`. Entries are copied before processing owners. They become tmux's per-session or per-process environment entries; the PowerShell host environment remains unchanged. Spaces, quotes and semicolons in each value remain part of that argument. ```powershell $window = $session | New-TmuxWindow -Environment @{ APP_MODE = 'development' OPTIONAL = '' } ``` ## Failures and results Success emits the core's captured created object. Keep that returned handle when later work needs its current metadata; an existing owner handle is not refreshed in place. An empty owner pipeline emits nothing. Wrap a pipeline in `@(...)` when the caller needs an array for zero, one or many results. Creation errors use [`Tmux.SessionCreateFailed`][newtmuxsessioncommand], [`Tmux.WindowCreateFailed`][newtmuxwindowcommand] and [`Tmux.PaneSplitFailed`][splittmuxpanecommand], retain the original core exception and failed owner, and allow later pipeline owners to continue under `-ErrorAction Continue`. `-ErrorAction Stop` stops at the first error. Cancellation reaches the core operation; it does not roll back creation or terminate a command already started in a pane. No mutation is retried. The [creation integration test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/Create.Tests.ps1) exercises native return types, literal names and environment values, directory and geometry requests, zero-dispatch previews and per-owner failures on an owned server. The [startup integration test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/CreateStartup.Tests.ps1) separately verifies first-session daemon creation and owned process teardown. Its Linux child-reaper setting is confined to that disposable test process. [newtmuxsessioncommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/NewTmuxSessionCommand.cs [newtmuxwindowcommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/NewTmuxWindowCommand.cs [splittmuxpanecommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/SplitTmuxPaneCommand.cs --- # Filter and query tmux objects Source: https://libtmux.org/en/powershell/latest/guides/query/ > Filter and query tmux objects: LibTmux documentation. Use [`Where-Object`]() to filter captured objects locally. Use structured criteria when the same selection needs reuse, serialization or an inspectable source plan. Both return native tmux objects that can feed other cmdlets. Import [`LibTmux`]() and select an existing endpoint as `$server` with [New-TmuxServer](https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxserver/). These examples borrow that endpoint and do not create or remove sessions. Inspect the daemon version for source planning, then capture its complete pane graph: ```powershell $captured = $server | Get-TmuxServer -ErrorAction Stop | Get-TmuxSnapshot -ErrorAction Stop ``` ## Start with PowerShell Select panes at least 50 columns wide. Property access and filtering use the captured data; they do not contact tmux. ```powershell $captured.Panes | Where-Object { $_.Width -ge 50 -and $_.Height -gt 0 } ``` For reuse, construct the same condition as a native [`QueryDocument`](): ```powershell $query = New-TmuxQuery -Target Pane -Criteria @{ Width = @{ Ge = 50 } Height = @{ Gt = 0 } } ``` Apply it to the already captured panes. Input order, duplicates and object identity remain intact; parent and child relations retain the complete graph. ```powershell $captured.Panes | Select-TmuxPane -Query $query ``` ## Criteria vocabulary [`Get-TmuxQueryField`]() returns native catalog descriptors. Inspect the numeric width field and its supported wire operations: ```powershell Get-TmuxQueryField -Target Pane | Where-Object WireName -CEQ 'pane_width' ``` Criteria accept a field's catalog wire name or native property path. For example, [`Width`][criteria-parser] and [`pane_width`](https://libtmux.org/en/tmux/latest/catalog/formats/pane_width/) address the same field. Field and operator keys ignore case; specifying both aliases in one map is an error. A bare value means equality. Entries in a map are combined with [`And`][criteria-parser]. The catalog's [`Operators`]() use JSON wire names. Use these PowerShell keys in criteria maps; unsupported field/operator combinations fail at construction. | Criteria key | Native wire operation | Value | | --- | --- | --- | | Bare value or [`Eq`][criteria-parser]; [`Ne`][criteria-parser] | `equal`; `notEqual` | Native scalar value | | [`Lt`][criteria-parser], [`Le`][criteria-parser], [`Gt`][criteria-parser], [`Ge`][criteria-parser] | `lessThan`, `lessThanOrEqual`, `greaterThan`, `greaterThanOrEqual` | Int64-representable integer | | [`StartsWith`][criteria-parser], [`EndsWith`][criteria-parser], [`Contains`][criteria-parser] | `startsWithOrdinal`, `endsWithOrdinal`, `containsOrdinal` | String | | [`EqualIgnoreCase`][criteria-parser] | `stringEqualOrdinalIgnoreCase` | String | | [`StartsWithIgnoreCase`][criteria-parser], [`EndsWithIgnoreCase`][criteria-parser], [`ContainsIgnoreCase`][criteria-parser] | `startsWithOrdinalIgnoreCase`, `endsWithOrdinalIgnoreCase`, `containsOrdinalIgnoreCase` | String | | [`In`][criteria-parser], [`NotIn`][criteria-parser] | `or` of `equal`, optionally `not` | Array or list of scalar values | | [`IsNull`][criteria-parser], [`IsNotNull`][criteria-parser] | `equal` or `notEqual` with null | `$true` only | | [`Regex`][criteria-parser] | `regex` | Map with [`Pattern`][criteria-parser] and optional [`Options`][criteria-parser] list | | [`Some`][criteria-parser], [`Every`][criteria-parser], [`None`][criteria-parser] | `any`, `all`, or negated `any` | Child criteria for a collection relation | | [`Is`][criteria-parser], [`IsNot`][criteria-parser] | `related`, optionally negated | Child criteria for a to-one relation | | [`And`][criteria-parser], [`Or`][criteria-parser], [`Not`][criteria-parser] | `and`, `or`, `not` | Criteria lists for And/Or; one criteria map for Not | Ordinary string equality, membership and substring matching are ordinal and case-sensitive. Compare with PowerShell `-ceq` or `-cin`, not its normally case-insensitive `-eq` or `-in`. [`EqualIgnoreCase`][criteria-parser], [`StartsWithIgnoreCase`][criteria-parser], [`EndsWithIgnoreCase`][criteria-parser] and [`ContainsIgnoreCase`][criteria-parser] explicitly request ordinal case-insensitive matching. No wildcard expansion or string normalization is implicit. The catalog also exposes `stringEqualOrdinal`; the criteria form uses bare string equality or [`Eq`][criteria-parser] for that behavior. Integers are not coerced from strings, Booleans, enums, floating-point or decimal values. IDs accept the matching native ID type or a correctly prefixed string; single-quote session IDs such as `'$0'`. `$null` means explicit absence, while an omitted field is unconstrained. An empty string remains a value. ScriptBlocks belong in [`Where-Object`](); they are not translated into criteria. Collection properties have separate scalar and relation paths: use `'Windows.Count'` for a numeric comparison and [`Windows`][criteria-parser] for [`Some`][criteria-parser], [`Every`][criteria-parser] or [`None`][criteria-parser]. Use explicit [`And`][criteria-parser] with separate maps when a condition needs both paths. [`ActivePane`][criteria-parser] and [`ActivePane.Value`][criteria-parser] are aliases for the same captured to-one relation. Uncaptured relations raise an error; they never become empty data. These construction limits include nodes introduced when membership and operator maps expand into the native query: | Limit | Maximum | | --- | ---: | | Predicate depth | 32 | | Predicate node occurrences | 512 | | String length | 4,096 Unicode scalar values | | Regex pattern length | 1,024 Unicode scalar values | | Encoded JSON | 262,144 UTF-8 bytes | | Membership entries | 128 | Cycles, duplicate aliases, invalid Unicode and values beyond these limits are rejected. Accepted documents own their values; editing the original hashtable or list does not change a query. Serialization uses the one current schema, `libtmux-query` version 2; the module includes its JSON schema file. ## Match captured relationships Select windows with at least one pane that meets both size conditions: ```powershell $captured.Windows | Select-TmuxWindow -Criteria @{ Panes = @{ Some = @{ Width = @{ Ge = 50 }; Height = @{ Gt = 0 } } } } ``` Both conditions apply to the same pane. Two separate [`Some`][criteria-parser] clauses may match different panes. [`Every`][criteria-parser] is true for an empty captured collection; [`Some`][criteria-parser] is false and [`None`][criteria-parser] is true. [`Is`][criteria-parser] and [`IsNot`][criteria-parser] traverse one captured related object. Linked windows retain their session/index placement; a pane ID can therefore appear in several input placements. Selection does not deduplicate them. Combine alternatives and exclusions to select API or log windows while excluding scratch windows: ```powershell $captured.Windows | Select-TmuxWindow -Criteria @{ Or = @(@{ Name = @{ StartsWith = 'api-' } }, @{ Name = 'logs' }) Not = @{ Name = @{ Contains = 'scratch' } } } ``` For a regular expression, pass an explicit pattern and semantic option list: ```powershell $captured.Windows | Select-TmuxWindow -Criteria @{ Name = @{ Regex = @{ Pattern = '^API-'; Options = @('IgnoreCase') } } } ``` Regex uses the .NET dialect with [`CultureInvariant`][regexoptions-cultureinvariant] always enabled. Options accept [`IgnoreCase`][regexoptions-ignorecase], [`Multiline`][regexoptions-multiline], [`ExplicitCapture`][regexoptions-explicitcapture], [`Singleline`][regexoptions-singleline], [`IgnorePatternWhitespace`][regexoptions-ignorepatternwhitespace] and [`CultureInvariant`][regexoptions-cultureinvariant]; execution-only flags such as [`Compiled`][regexoptions-compiled] are rejected. A running match has the native one-second timeout. This is the shared .NET query contract, not a claim of cross-language regex compatibility. ## Store a query or acquire a fresh result [`ConvertTo-TmuxQueryJson`]() returns a JSON string suitable for storage. Restore that string with `New-TmuxQuery -Json`; this round-trip does not read tmux: ```powershell New-TmuxQuery -Json ($query | ConvertTo-TmuxQueryJson) ``` Prepare a plan using the daemon version from the earlier capture. Planning and inspecting `$queryPlan` perform no I/O: ```powershell $queryPlan = $query | Get-TmuxQueryPlan -DaemonVersion $captured.DaemonVersion ``` [`PushedPredicate`](), [`ResidualPredicate`](), [`RequiredFields`](), [`RequiredSnapshotDepth`][query-queryplan-requiredsnapshotdepth] and [`FallbackReasons`]() explain its execution. `-Pushdown Auto` uses exact supported source evaluation; [`Never`]() evaluates locally; [`Require`]() rejects any local residual. A plan does not acquire data. Execute it against the selected endpoint when a fresh result is needed: ```powershell $server | Invoke-TmuxQuery -Plan $queryPlan -AsResult -ErrorAction Stop ``` `-AsResult` emits one native [`QueryResult`](), even with no matches. Its indexed rows refer to the complete [`Snapshot`](); filtering does not prune that graph. Without `-AsResult`, matching native objects flow individually down the pipeline. Alternatively, `Invoke-TmuxQuery -Query $query` plans against a fresh observed daemon version. Execution never starts an absent daemon; a prepared plan must match the observed version. Acquisition is not an atomic transaction. `-NativeFilter` with `-Target` is a separate expert escape hatch for raw tmux format filtering. It cannot combine with `-Query`, `-Plan`, `-Pushdown` or `-AsResult`, and its rows do not promise a complete structured-query snapshot. ## Require exactly one match Resolve the captured development session before handing it to another command: ```powershell $captured.Sessions | Select-TmuxSession -Criteria @{ Name = 'development' } -ExactlyOne ``` `-ExactlyOne` holds the match until finite input completes. Zero or multiple matches terminate with [`Tmux.NoMatch`][queryselection] or [`Tmux.MultipleMatches`][queryselection]. Invalid inputs, unavailable relations, evaluation errors and pipeline stop suppress the retained object. An infinite stream cannot establish exact cardinality. The guarantee concerns successful objects received by the selector. An upstream nonterminating error can skip a requested source while still leaving one match. Use `-ErrorAction Stop` on every upstream acquisition when complete input is required before mutation. It does not roll back changes already made by another command. Local selection never refreshes captured objects; use an explicit acquisition to observe changes. [criteria-parser]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/QueryCriteria.cs [regexoptions-cultureinvariant]: https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regexoptions#system-text-regularexpressions-regexoptions-cultureinvariant [regexoptions-multiline]: https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regexoptions#system-text-regularexpressions-regexoptions-multiline [regexoptions-explicitcapture]: https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regexoptions#system-text-regularexpressions-regexoptions-explicitcapture [regexoptions-singleline]: https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regexoptions#system-text-regularexpressions-regexoptions-singleline [regexoptions-ignorepatternwhitespace]: https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regexoptions#system-text-regularexpressions-regexoptions-ignorepatternwhitespace [regexoptions-compiled]: https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regexoptions#system-text-regularexpressions-regexoptions-compiled [query-queryplan-requiredsnapshotdepth]: https://libtmux.org/en/csharp/latest/reference/libtmux-query-queryplan-requiredsnapshotdepth/ [queryselection]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/QuerySelection.cs [regexoptions-ignorecase]: https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regexoptions#system-text-regularexpressions-regexoptions-ignorecase --- # Inspect attached clients Source: https://libtmux.org/en/powershell/latest/guides/clients/ > Inspect attached clients: LibTmux documentation. Read the terminal and control clients already attached to a selected native `$server`. A plain server handle does not attach a client or own its lifetime. ```powershell $server | Get-TmuxClient ``` Results are native [`Client`]() objects with [`Name`][client-name], [`Tty`][client-tty], [`IsControlClient`](), [`AttachedSessionId`]() and [`Generation`][client-generation]. `-Name` selects an exact, case-sensitive name; it does not interpret wildcards. No clients or no match produces no objects. An unavailable server produces an error. Captured fields stay unchanged when a client switches sessions. Refresh a previously selected `$client` to obtain a new observation: ```powershell $client | Update-TmuxClient ``` This reads current data; it does not redraw the terminal. Refreshing a client that has detached writes the native missing-object error. Resolve the client's current session, window and pane together: ```powershell $client | Get-TmuxClientAttachment ``` The result is a native [`ClientAttachment`](). A detached client or missing session produces no output; [`Window`]() or [`Pane`]() can be null. The operation performs several tmux reads and does not promise an atomic observation. Transport failures remain errors, not empty results. These commands only inspect clients. Detachment, locking and suspension remain available through explicit raw tmux commands. Closing or removing a client must not be confused with removing its session or daemon. [client-name]: https://libtmux.org/en/csharp/latest/reference/libtmux-client-name/ [client-tty]: https://libtmux.org/en/csharp/latest/reference/libtmux-client-tty/ [client-generation]: https://libtmux.org/en/csharp/latest/reference/libtmux-client-generation/ --- # Link and move windows between sessions Source: https://libtmux.org/en/powershell/latest/guides/placement/ > Link and move windows between sessions: LibTmux documentation. A tmux window can appear at different indices in several sessions. Read the window through the session whose placement you intend to change; its native [`Window`]() handle captures that session and index. Start from an [explicit endpoint](https://libtmux.org/en/powershell/latest/guides/read/), then choose the source window and destination session. The examples below use `$window` and `$session` from the same server. Link the window into the destination session at index 5 while leaving that session's selected window alone: ```powershell $window | New-TmuxWindowLink -Session $session -Index 5 -NoSelect -Confirm:$false ``` The command emits no placement handle. Read the destination session's windows and select the new link by physical ID and destination index: ```powershell $window = $session | Get-TmuxWindow | Where-Object { $_.Id -eq $window.Id -and $_.Index -eq 5 } ``` `-ReplaceExisting` permits tmux to displace a window already at the index; it may destroy that window when this was its last link. Move the link from index 5 to index 6 in the same session. Keep the returned replacement handle because the original still describes the old placement: ```powershell $window = $window | Move-TmuxWindow -Index 6 -PassThru -Confirm:$false ``` Use `-DestinationSession $otherSession` to move a link to another session on the same endpoint and daemon generation. Omit `-Index` to use the next free index. `-Direction Before` or [`After`]() inserts relative to a destination; `-NoSelect` keeps the destination's current selection. Remove only this session's link to the window. Links in other sessions and their panes remain: ```powershell $window | Remove-TmuxWindowLink -Confirm:$false ``` Without `-KillIfLast`, tmux refuses to remove a window's final link. With it, the final unlink destroys the physical window and its panes. To destroy the window and every link deliberately, use [Remove-TmuxWindow](https://libtmux.org/en/powershell/latest/guides/remove/). These three commands request confirmation by default. Use `-WhatIf` to preview without contacting tmux. They reject a stale source placement in tmux's native queue; link and cross-session move also reject destination sessions from another endpoint or daemon generation before dispatch. A failed move readback can follow a successful dispatch, so inspect current topology before retrying. See the [installed placement test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/Placement.Tests.ps1) and [command reference](https://libtmux.org/en/powershell/latest/reference/libtmux-move-tmuxwindow/). --- # Read and change options Source: https://libtmux.org/en/powershell/latest/guides/options/ > Read and change options: LibTmux documentation. Pass a native server, session, window or pane to select its option table. Use `-Scope` to override the table and `-Global` to request global defaults. tmux still selects pane-local options when pane scope is requested; `-Global` does not make them global. A server handle with `-Scope Session -Global` addresses global session defaults. Choose the endpoint explicitly with [New-TmuxServer](https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxserver/). Read the effective key mode from a previously selected `$session`: ```powershell $session | Get-TmuxOption -Name 'status-keys' -IncludeInherited ``` Each result is a native [`TmuxOption`](). Its [`Name`][tmuxoption-name], [`Index`][tmuxoption-index], [`Inherited`]() and [`Value`][tmuxoption-value] describe what tmux reported. Omit `-Name` to list a table. A normal read lists local values; `-IncludeInherited` adds inherited values. `-Quiet` makes a missing option produce no rows. [`Where-Object`]() filters returned rows locally. Store a user option and return the value tmux actually stored: ```powershell $session | Set-TmuxOption -Name '@project' -Value 'api' -PassThru ``` `-PassThru` emits a native [`TmuxOptionValue`](); its [`Raw`][tmuxoptionvalue-raw], [`Boolean`][tmuxoptionvalue-boolean], [`Integer`]() and [`State`]() fields preserve tmux's interpretation. Without it, setting emits no success output. `-Append` and `-ExpandFormat` return the stored result, not just the supplied argument. `-PreventOverwrite` asks tmux to refuse replacement and can produce an error. Remove a previously stored user option: ```powershell $session | Remove-TmuxOption -Name '@scratch' ``` Removing a built-in override restores inheritance. An empty string is a stored value, so setting `''` does not remove an option. Indexed names such as [`command-alias[40]`](https://libtmux.org/en/tmux/latest/catalog/options/command-alias/) read, set or remove that specific array entry; listing the base name preserves sparse indices. tmux expands formats in option names, so `#` is not guaranteed literal. Set and Remove support `-WhatIf` and `-Confirm`; previews contact no server. Errors retain the original core exception and owner. `-ErrorAction Continue` permits later owners; [`Stop`][erroraction-stop] terminates the pipeline. Cancellation cannot undo a dispatched mutation. Readback does not make a mutation atomic with other clients. [tmuxoption-name]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxoption-name/ [tmuxoption-index]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxoption-index/ [tmuxoption-value]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxoption-value/ [tmuxoptionvalue-raw]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxoptionvalue-raw/ [tmuxoptionvalue-boolean]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxoptionvalue-boolean/ [erroraction-stop]: https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.actionpreference#system-management-automation-actionpreference-stop --- # Read tmux objects Source: https://libtmux.org/en/powershell/latest/guides/read/ > Read tmux objects: LibTmux documentation. The cmdlets return native objects from [libtmux for .NET](https://github.com/libtmux/libtmux-dotnet). Inspect them with [`Get-Member`](), select their properties and pass them directly to other cmdlets. Create an endpoint with `New-TmuxServer -SocketPath` or `-SocketName`, then pipe it to a read command. Constructing the endpoint performs no I/O. With neither parameter the endpoint passes tmux no socket, and tmux picks the server: the one `TMUX` names inside a tmux pane, otherwise its default socket. `LIBTMUX_SOCKET_PATH` (`-S`) or `LIBTMUX_SOCKET` (`-L`) chooses a socket for such an endpoint instead, the path first; a blank value counts as unset, and a parameter beats both. The endpoint reads the variables when it is made. [`Connect-TmuxServer`]() discovers an unmaterialized endpoint and returns its connected replacement. An already connected handle is returned unchanged. | Command | Typed owner accepted from the pipeline | Output | | --- | --- | --- | | [`Connect-TmuxServer`]() | [`LibTmux.Server`]() | [`LibTmux.Server`]() | | [`Get-TmuxSnapshot`]() | [`LibTmux.Server`]() | Replacement [`LibTmux.Server`]() | | [`Get-TmuxSession`]() | [`LibTmux.Server`]() | [`LibTmux.Session`]() objects | | [`Get-TmuxWindow`]() | [`LibTmux.Server`]() or [`LibTmux.Session`]() | [`LibTmux.Window`]() objects | | [`Get-TmuxPane`]() | [`LibTmux.Server`](), [`LibTmux.Session`](), or [`LibTmux.Window`]() | [`LibTmux.Pane`]() objects | The acquisition commands above read tmux explicitly. `-Id` selects a literal tmux identifier, such as `$0`, `@1`, or `%2`; use single quotes for a session ID. Session and window commands also accept `-Name`. Selectors compare ordinally and distinguish case. They do not expand wildcards. Combining selectors requires both to match. An unmatched selector emits no objects; it is not an error. Wrap a pipeline in `@(...)` when its count matters. For `-Name` and `-Id`, Tab offers values from an explicitly supplied captured server, session or window. Capture first with [`Get-TmuxSnapshot`](). Completion does not contact tmux, refresh a handle or guess an endpoint. An uncaptured owner offers no tmux values. The suggestion comes from the earlier observation; the read command still checks current tmux state when you run it. Owners bind by their native type. Property names on an arbitrary object do not provide pipeline binding. Use [`Where-Object`]() after acquisition for further local filtering. For reusable criteria, use [New-TmuxQuery](https://libtmux.org/en/powershell/latest/reference/libtmux-new-tmuxquery/) and the local [Select-TmuxPane](https://libtmux.org/en/powershell/latest/reference/libtmux-select-tmuxpane/), [Select-TmuxWindow](https://libtmux.org/en/powershell/latest/reference/libtmux-select-tmuxwindow/) or [Select-TmuxSession](https://libtmux.org/en/powershell/latest/reference/libtmux-select-tmuxsession/) commands. [Get-TmuxQueryField](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxqueryfield/) discovers the shared query catalog locally. For a fresh query, pass an explicit endpoint and a query document to [Invoke-TmuxQuery](https://libtmux.org/en/powershell/latest/reference/libtmux-invoke-tmuxquery/). It emits matching native objects; `-AsResult` retains the result and its complete captured graph, including an empty selection. Use [Get-TmuxQueryPlan](https://libtmux.org/en/powershell/latest/reference/libtmux-get-tmuxqueryplan/) with a known daemon version to inspect source evaluation, local residuals and fallback reasons before execution. Planning performs no I/O. The [query guide](https://libtmux.org/en/powershell/latest/guides/query/) walks through native filtering, reusable criteria, relationships and source plans. [`Get-TmuxSnapshot`]() defaults to `-Depth Panes`. Shallower depths are [`Server`][snapshotdepth-server], [`Sessions`][snapshotdepth-sessions], and [`Windows`][snapshotdepth-windows]. It returns a replacement graph and leaves the input handle and earlier snapshots unchanged. [`SnapshotMetadata`]() records the depth, daemon generation, UTC start/end readings and monotonic [`Elapsed`][snapshotmetadata-elapsed] time. UTC can move backwards if the clock is adjusted; use [`Elapsed`][snapshotmetadata-elapsed] for duration. Even `-Depth Server` performs a fresh generation-guarded read. Snapshot acquisition spans several tmux commands; it does not promise an atomic view. Contradictory parent, child-count or active-child observations fail with [`InconsistentSnapshotException`]() and emit no graph. Equal-count changes can escape detection. The command never retries automatically. Uncaptured relations report `IsCaptured = false` and throw when enumerated. Property access never reads tmux. Captured panes expose [`CurrentCommand`]() and [`CurrentPath`](), which remain readable after the daemon exits. A field that was not captured raises [`IncompleteSnapshotException`](); a captured empty string or null retains that value. Captured children retain their root through [`Server`](). Parent properties return the captured instances when that depth is available. [`Session.ActiveWindow`](), [`Session.ActivePane`][session-activepane] and [`Window.ActivePane`][window-activepane] return `CapturedValue`: inspect [`IsCaptured`][capturedvalue-iscaptured], then read [`Value`][capturedvalue-value] for the captured object. Reading an unavailable [`Value`][capturedvalue-value] raises [`IncompleteSnapshotException`](); [`OrNull()`]() explicitly opts into null instead. A pane's [`Window`]() retains its session/index placement, including repeated links to the same window. [`Window.LinkedSessions`]() contains each related session once. Filtering a collection changes only selected membership; traversing its parents still reaches their complete captured children. Active properties use the IDs from their own parent's row, so separate reads can record different selection states. [`Update-TmuxPane`]() refreshes one pane's fields. Its parent navigation does not borrow captured data from an older graph, even when its [`Server`]() names an older captured root. Acquire another snapshot for a new graph. Default tables show native identifiers, captured names or titles, and owner context. Handles resolved only by identifier show blank columns for fields they have not captured. The views distinguish that specific missing-field condition from other failures. Formatting and [`Get-Member`]() use local data and remain usable after the daemon exits. They do not refresh objects. Read failures write an error for the affected owner, including an endpoint with no running server, then allow later pipeline owners to continue. Use `-ErrorAction Stop` to terminate instead. Error IDs are [`Tmux.ConnectFailed`][connecttmuxservercommand], [`Tmux.SnapshotFailed`][gettmuxsnapshotcommand], [`Tmux.SessionReadFailed`][gettmuxsessioncommand], [`Tmux.WindowReadFailed`][gettmuxwindowcommand], and [`Tmux.PaneReadFailed`][gettmuxpanecommand]. The error record retains the core exception and its dispatch metadata when the exception supplies it. Pipeline cancellation cancels the pending core operation; borrowed server handles do not own daemon lifetime. The [installed-module integration test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/Read.Tests.ps1) executes typed pipelines, exact selection, shallow and replacement snapshots, and strict errors against its own tmux server. The fixture owns teardown. The [snapshot integration test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/Snapshot.Tests.ps1) checks provenance, repeated placements, parent navigation after teardown and contradictory reads. The [formatting integration test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/Formatting.Tests.ps1) checks captured objects and identity-only handles after daemon shutdown, including that formatting and member discovery start no tmux processes. The [completion integration test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/Completion.Tests.ps1) checks Tab suggestions after teardown and verifies that completion starts no tmux client. [snapshotdepth-sessions]: https://libtmux.org/en/csharp/latest/reference/libtmux-snapshotdepth-sessions/ [snapshotdepth-windows]: https://libtmux.org/en/csharp/latest/reference/libtmux-snapshotdepth-windows/ [snapshotmetadata-elapsed]: https://libtmux.org/en/csharp/latest/reference/libtmux-snapshotmetadata-elapsed/ [capturedvalue-iscaptured]: https://libtmux.org/en/csharp/latest/reference/libtmux-capturedvalue-iscaptured/ [capturedvalue-value]: https://libtmux.org/en/csharp/latest/reference/libtmux-capturedvalue-value/ [connecttmuxservercommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/ConnectTmuxServerCommand.cs [gettmuxsnapshotcommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/GetTmuxSnapshotCommand.cs [gettmuxsessioncommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/GetTmuxSessionCommand.cs [gettmuxwindowcommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/GetTmuxWindowCommand.cs [gettmuxpanecommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/GetTmuxPaneCommand.cs [snapshotdepth-server]: https://libtmux.org/en/csharp/latest/reference/libtmux-snapshotdepth-server/ [session-activepane]: https://libtmux.org/en/csharp/latest/reference/libtmux-session-activepane/ [window-activepane]: https://libtmux.org/en/csharp/latest/reference/libtmux-window-activepane/ --- # Remove sessions, windows and panes Source: https://libtmux.org/en/powershell/latest/guides/remove/ > Remove sessions, windows and panes: LibTmux documentation. [`Remove-TmuxSession`](), [`Remove-TmuxWindow`]() and [`Remove-TmuxPane`]() accept native core handles directly or through the pipeline. Each removes its target and emits no success output. Select the target using the [explicit endpoint and read commands](https://libtmux.org/en/powershell/latest/guides/read/). These commands have high confirmation impact. The default PowerShell confirmation preference prompts before removal. Review the endpoint and ID in that prompt; use `-Confirm:$false` when an unattended caller has already chosen the target. `-WhatIf` describes the removal without contacting tmux: ```powershell $session | Remove-TmuxSession -WhatIf ``` Remove an owned session after its work finishes: ```powershell $session | Remove-TmuxSession -Confirm:$false ``` An empty pipeline does nothing. A pipeline with several targets processes them in input order. A successful removal emits no handles, Boolean values or task objects, so `@($pane | Remove-TmuxPane -Confirm:$false)` is empty. Captured fields on an old handle remain an observation of the removed object; removal does not rewrite that snapshot. ## Linked windows and cascading removal **Removing a window destroys the physical window, every pane in it, and all its links in every session.** It does not merely unlink the placement through which the window was selected. Repeated placements of that physical window are removed together: ```powershell $window | Remove-TmuxWindow -Confirm:$false ``` To remove one session placement while preserving other links, use [Remove-TmuxWindowLink](https://libtmux.org/en/powershell/latest/guides/placement/). Removing a session destroys windows that are no longer linked elsewhere. A window still linked to another session survives with its panes. Removing the last pane destroys its window. Removing the last window from a session also removes that session; tmux may exit when no sessions remain. These commands do not give the module ownership of the daemon or arrange cleanup for other resources. ```powershell $pane | Remove-TmuxPane -Confirm:$false ``` ## Errors and cancellation Failures retain the native owner and original core exception in the PowerShell error record. The stable error IDs are [`Tmux.SessionRemoveFailed`][removetmuxsessioncommand], [`Tmux.WindowRemoveFailed`][removetmuxwindowcommand] and [`Tmux.PaneRemoveFailed`][removetmuxpanecommand]. Core exceptions retain their available dispatch metadata. A missing target remains an error; `-ErrorAction Continue` permits later pipeline targets to run, while `-ErrorAction Stop` stops before the next target. Handles belong to a specific endpoint and daemon generation. The core rejects an old-generation handle after daemon replacement instead of resolving the same numeric ID against the replacement. Removal is never retried. Stopping the pipeline cancels the active client operation; a removal already accepted by tmux is not rolled back. The [installed removal test](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/Remove.Tests.ps1) checks previews, zero-output pipelines, per-owner errors, linked-window destruction, session sharing, [last-pane](https://libtmux.org/en/tmux/latest/manual/last-pane/) cascades, isolated endpoints and real daemon replacement on owned tmux servers. [removetmuxsessioncommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/RemoveTmuxSessionCommand.cs [removetmuxwindowcommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/RemoveTmuxWindowCommand.cs [removetmuxpanecommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.PowerShell/RemoveTmuxPaneCommand.cs --- # Send input to a pane Source: https://libtmux.org/en/powershell/latest/guides/input/ > Send input to a pane: LibTmux documentation. Select a native pane using [`Get-TmuxPane`]() on the endpoint you intend to change. Input commands use that pane's endpoint and daemon generation. Pipeline input must be a native [`LibTmux.Pane`](); an object with similarly named properties does not bind as an owner. | Command | Input | Enter behavior | | --- | --- | --- | | [Send-TmuxText](https://libtmux.org/en/powershell/latest/reference/libtmux-send-tmuxtext/) | Literal text, including spaces, dashes and tmux format markers | Appends one Enter only with `-Enter` | | [Send-TmuxKey](https://libtmux.org/en/powershell/latest/reference/libtmux-send-tmuxkey/) | An ordered string array of tmux key tokens | Send [`Enter`]() explicitly as a token | The [literal text example](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/docs/reference/LibTmux/Send-TmuxText.md#example-1) types the characters in a key name. The [key sequence example](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/docs/reference/LibTmux/Send-TmuxKey.md#example-1) sends the corresponding control keys. Both examples run against an owned byte receiver in the installed-help suite. [`Send-TmuxText`]() accepts empty text. NUL is rejected before dispatch; newlines and other control characters are delivered. Newlines already in the text can execute commands even when `-Enter` is omitted. Literal sending does not quote text for the receiving shell or application. [`Send-TmuxKey`]() owns a snapshot of its input array and sends tokens in order. It rejects null, empty and NUL-containing tokens. tmux interprets recognized names such as `C-a`; unrecognized names follow tmux's character-sending behavior. One string is not split into multiple tokens on whitespace. Both commands support `-WhatIf` and `-Confirm`. A preview performs no acquisition or input operation. Confirmation identifies the endpoint and pane without displaying the supplied content. Successful commands emit no objects; an empty owner pipeline performs no work. Sending input confirms acceptance by tmux. Use [Invoke-TmuxPaneCommand](https://libtmux.org/en/powershell/latest/reference/libtmux-invoke-tmuxpanecommand/) when a shell command needs a verified exit status, or an explicit signal from the receiving application before asserting completion or [capturing its output](https://libtmux.org/en/powershell/latest/guides/capture/). Use [Wait-TmuxChannel](https://libtmux.org/en/powershell/latest/reference/libtmux-wait-tmuxchannel/) for a cooperative [`tmux wait-for -S`](https://libtmux.org/en/tmux/latest/manual/wait-for/) signal. Give each operation a unique channel with one waiter; its timeout and cancellation cleanup withdraw the registration so it cannot consume a later signal. A successful send is not a command result or shell exit status. Failures retain the original core exception, dispatch information and target pane. `-ErrorAction Continue` permits later owners to run; `-ErrorAction Stop` stops on the first failure. Cancellation stops pending work but cannot undo input already delivered. A failed key sequence can leave earlier keys applied. If literal text was sent but the following Enter fails, the core reports unknown partial dispatch. Retrying can repeat effects; the commands never retry automatically. ## Run a command to completion [`Invoke-TmuxPaneCommand`]() runs a shell command in a writable POSIX shell pane. It needs tmux 3.4 or newer, because it stages a temporary buffer that older releases cannot delete safely; an older daemon is refused before any buffer exists. It returns a native [`LibTmux.PaneRunResult`]() with an authenticated exit status. A nonzero status remains a result; a timeout returns `TimedOut = True` and a null status because the command may still be running. The command runs in a subshell, so `cd` and `export` do not change the pane's parent shell. Completion uses a cooperative tmux [`wait-for`](https://libtmux.org/en/tmux/latest/manual/wait-for/) channel. While waiting, the runner also checks authenticated run status and pane liveness, starting after 250 ms and backing off to five seconds. These checks detect a pane that exits without signalling; they are separate from event-backed pane text waits. With an endpoint in `$server`, create a shell pane and check the status rather than guessing from a prompt or screen capture. The example removes only its session: ```powershell & { $ErrorActionPreference = 'Stop' $name = 'pane-run-' + [Guid]::NewGuid().ToString('N') $session = $server | New-TmuxSession -Name $name -Command 'exec /bin/sh' try { $pane = $session | Get-TmuxPane $pane | Invoke-TmuxPaneCommand -Command 'exit 7' -Timeout 5 -Confirm:$false } finally { $session | Remove-TmuxSession -Confirm:$false } } ``` The result's [`ExitStatus`]() is 7 and [`TimedOut`][panerunresult-timedout] is False. [`Output`]() contains bounded rendered command output, which can include both stdout and stderr. It is not a byte-exact stream. The default view omits output text; inspect [`Output`](), [`LinesMissed`][panerunresult-linesmissed], [`AnchorLost`][panerunresult-anchorlost] and omission counts when needed. [`Get-TmuxPaneContent`]() reads the current pane screen separately. On timeout or cancellation after dispatch, inspect the pane before retrying. The [cmdlet reference](https://libtmux.org/en/powershell/latest/reference/libtmux-invoke-tmuxpanecommand/) describes history suppression, validation and confirmation. ## Wait for an application's readiness line Use [Wait-TmuxPaneText](https://libtmux.org/en/powershell/latest/reference/libtmux-wait-tmuxpanetext/) when an application reports readiness in its terminal output. On tmux 3.7 or newer, it observes rendered text through a temporary control client, checks text already visible at entry, then wakes on output or layout changes. On earlier supported releases it polls without attaching a control client. It returns a native [`LibTmux.PaneWaitResult`](); it does not require a cooperative tmux channel. With Python 3 on `PATH` and the selected endpoint in `$server`, start a local HTTP server on an available loopback port. Wait for its readiness line, then make an HTTP request to verify that the server responds. The `finally` block removes the session and stops the server process: ```powershell & { $ErrorActionPreference = 'Stop' $session = $server | New-TmuxSession ` -Name ('http-' + [Guid]::NewGuid().ToString('N')) ` -Command 'exec python3 -u -m http.server 0 --bind 127.0.0.1' try { $pane = $session | Get-TmuxPane $ready = $pane | Wait-TmuxPaneText ` -Pattern '^Serving HTTP on 127\.0\.0\.1 port [0-9]+' ` -CaseSensitive -Timeout 10 -TailLines 4 -Confirm:$false if ($ready.Outcome -notin 'PresentAtEntry', 'Matched') { throw "HTTP readiness ended with $($ready.Outcome)." } $tail = $ready.Tail -join "`n" $port = [regex]::Match($tail, 'port ([0-9]+)').Groups[1].Value $uri = "http://127.0.0.1:$port/" $response = Invoke-WebRequest -Uri $uri -TimeoutSec 5 -NoProxy $ready $response.StatusCode } finally { $session | Remove-TmuxSession -Confirm:$false } } ``` The observation is [`PresentAtEntry`]() or [`Matched`](), followed by HTTP status 200. The wait owns and closes any control client it creates; it leaves the pane and daemon running. The example separately owns its session and removes it. Patterns use bounded .NET regular expressions and ignore case by default. Use `-SimpleMatch` for literal text, `-CaseSensitive` for case-sensitive matching, and `-StopPattern` for a terminal failure line. Stop patterns take priority over wanted patterns. Without `-Pattern`, the wait returns on new output. [`TimedOut`][panewaitoutcome-timedout] and [`PaneExited`][panewaitoutcome-paneexited] are result outcomes; transport failures and invalid patterns are errors. Ctrl+C cancels observation, not the application. On tmux 3.7 and newer, `-AllowPollingFallback` explicitly permits polling if control observation fails; older releases attach no control client and always poll. Either way a pattern matches a line that wraps across rows as one line. A wait whose server is killed ends as `PaneExited` with the output read so far, without an error. [`PollingFallback`]() and [`EventsDropped`]() disclose degradation. Rendered text can include echoed input and can disappear on repaint or scrollback eviction. A match proves the text condition, not an exit status or continuing service health. The HTTP request above checks service behavior separately. Inspect [`LinesMissed`][panewaitresult-linesmissed], [`AnchorLost`][panewaitresult-anchorlost], [`OmittedTailLines`]() and [`OmittedTailBytes`]() before treating the bounded tail as complete output. Use [command completion](https://libtmux.org/en/powershell/latest/guides/input/#run-a-command-to-completion) for an authenticated exit status and [event streams](https://libtmux.org/en/powershell/latest/guides/watch/) for individual notifications. ## Send a command and wait for its output With an endpoint in `$server`, send literal text to a shell and use `-Enter` to submit it. See [endpoint selection](https://libtmux.org/en/powershell/latest/guides/read/) for setup. The shell signals a unique channel after printing, so capture waits for completed output. The signal uses the endpoint's tmux executable and socket, with paths quoted for the shell. A successful send alone means tmux accepted the input; it does not establish that the receiving program finished. ```powershell & { $ErrorActionPreference = 'Stop' $ready = 'libtmux-demo-' + [Guid]::NewGuid().ToString('N') $binary = $server.ConnectionOptions.TmuxBinaryPath $tmux = (Get-Command $binary -CommandType Application | Select-Object -First 1).Source $selector = if ($server.ConnectionOptions.SocketPath) { "-S '{0}'" -f $server.ConnectionOptions.SocketPath.Replace("'", "'\''") } elseif ($server.ConnectionOptions.SocketName) { "-L '{0}'" -f $server.ConnectionOptions.SocketName.Replace("'", "'\''") } else { '' } $quoted = $tmux.Replace("'", "'\''") $signal = "'{0}' {1} wait-for -S '{2}'" -f $quoted, $selector, $ready $session = $server | New-TmuxSession -Name 'input-demo' -Command 'exec /bin/sh' try { $pane = $session | Get-TmuxPane $text = 'printf "\nhello from PowerShell\n"; ' + $signal $pane | Send-TmuxText -Text $text -Enter $null = $server | Wait-TmuxChannel -Channel $ready -Timeout 10 $pane | Get-TmuxPaneContent } finally { $session | Remove-TmuxSession -Confirm:$false } } ``` The captured screen includes `hello from PowerShell`. [`Wait-TmuxChannel`]() accepts a signal that arrived before the wait, reports a timeout if no signal arrives, and withdraws its waiter on timeout or Ctrl+C. Use one waiter per unique channel: tmux withdrawal also wakes other waiters on that channel. The example removes its `input-demo` session in `finally`. [`Send-TmuxKey`]() sends key tokens such as `C-c` or [`Enter`](); [`Send-TmuxText`]() sends those characters literally. Mutation commands also support `-WhatIf` and `-Confirm`. See [capturing output](https://libtmux.org/en/powershell/latest/guides/capture/). [panerunresult-timedout]: https://libtmux.org/en/csharp/latest/reference/libtmux-panerunresult-timedout/ [panerunresult-linesmissed]: https://libtmux.org/en/csharp/latest/reference/libtmux-panerunresult-linesmissed/ [panerunresult-anchorlost]: https://libtmux.org/en/csharp/latest/reference/libtmux-panerunresult-anchorlost/ [panewaitoutcome-timedout]: https://libtmux.org/en/csharp/latest/reference/libtmux-panewaitoutcome-timedout/ [panewaitoutcome-paneexited]: https://libtmux.org/en/csharp/latest/reference/libtmux-panewaitoutcome-paneexited/ [panewaitresult-linesmissed]: https://libtmux.org/en/csharp/latest/reference/libtmux-panewaitresult-linesmissed/ [panewaitresult-anchorlost]: https://libtmux.org/en/csharp/latest/reference/libtmux-panewaitresult-anchorlost/ --- # Set the environment for new panes Source: https://libtmux.org/en/powershell/latest/guides/environment/ > Set the environment for new panes: LibTmux documentation. A native server selects tmux's global environment; a native session selects its local environment. Reads return that table's entries without merging inherited values. Changes affect future processes. They do not change the environment of a process already running in a pane. Read a stored value from a previously selected `$session`: ```powershell $session | Get-TmuxEnvironment -Name 'APP_MODE' ``` Omit `-Name` to list visible entries. Results are native [`TmuxEnvironmentEntry`]() objects with [`Name`][tmuxenvironmententry-name], [`Value`][tmuxenvironmententry-value] and [`IsRemoved`](). A missing variable produces no object. Set a value for future panes and inspect the stored result: ```powershell $session | Set-TmuxEnvironment -Name 'APP_MODE' -Value 'development' -PassThru ``` An empty string remains a present value. Without `-PassThru`, setting emits no success output. `-ExpandFormats` asks tmux to expand the value as a format before storage. Forget the local entry so a global value can apply again: ```powershell $session | Remove-TmuxEnvironment -Name 'APP_MODE' ``` Suppress inherited values in new pane processes instead: ```powershell $session | Remove-TmuxEnvironment -Name 'APP_MODE' -MarkRemoved ``` `-MarkRemoved` retains an entry with `IsRemoved = true` and `Value = null`. Unsetting, marking removed and setting an empty string are distinct tmux operations. `Set-TmuxEnvironment -Hidden` keeps a variable available to tmux formats but excludes it from new child environments and ordinary reads. Its native `-PassThru` result has `Value = null` and `IsRemoved = false`; the null value means readback is unavailable, not that the variable is empty or removed. Set and Remove support `-WhatIf` and `-Confirm`; previews contact no server. Errors retain the original core exception and owner. `-ErrorAction Continue` permits later owners; [`Stop`][erroraction-stop] terminates the pipeline. Cancellation cannot undo a dispatched mutation. [tmuxenvironmententry-name]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxenvironmententry-name/ [tmuxenvironmententry-value]: https://libtmux.org/en/csharp/latest/reference/libtmux-tmuxenvironmententry-value/ [erroraction-stop]: https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.actionpreference#system-management-automation-actionpreference-stop --- # Troubleshooting Source: https://libtmux.org/en/powershell/latest/guides/troubleshooting/ > Troubleshooting: LibTmux documentation. Start with the endpoint and operation that failed. The cmdlets keep native objects and errors, so an empty result, a failed tmux command and a cancelled wait have different meanings. Use `-ErrorAction Stop` when one failure should stop a script. | Symptom | Check and next action | | --- | --- | | `Import-Module LibTmux` cannot find a dependency | Follow [installation](https://libtmux.org/en/powershell/latest/guides/getting-started/#quick-start) to install from PowerShell Gallery with dependency resolution. Install both PowerShell modules at the same version; importing mixed core assemblies is rejected. For a checkout, use the [source build](https://libtmux.org/en/powershell/latest/guides/getting-started/#install-from-source) and import the staged manifests. For local shared-source changes, retain the exact inspected archives described in [review package builds](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/.github/CONTRIBUTING.md#review-package-builds). | | A server handle exists, but reads cannot reach tmux | [`New-TmuxServer`]() constructs a local handle. Use [Connect-TmuxServer](https://libtmux.org/en/powershell/latest/guides/read/) to discover an existing daemon, or [New-TmuxSession](https://libtmux.org/en/powershell/latest/guides/create/) to create one on that explicit endpoint. Check the selected socket and executable before retrying. | | A handle with no socket reaches a server you did not choose | A handle that names no socket passes tmux none, so tmux uses the server `TMUX` names inside a pane, otherwise its default. Pass `-SocketName` or `-SocketPath`, or set `LIBTMUX_SOCKET_PATH` or `LIBTMUX_SOCKET` before the handle is made; the path wins, a blank value is ignored and `LIBTMUX_SOCKET_NAME` selects nothing. See [read](https://libtmux.org/en/powershell/latest/guides/read/). | | A command targets the wrong session or window | Read the object from the intended server and session. [Window placements](https://libtmux.org/en/powershell/latest/guides/placement/) carry a session-relative index; a physical window can be linked more than once. Raw tmux targets are strings and do not inherit a captured placement guard. | | A move, input or raw mutation failed after dispatch | Read current topology or screen state before deciding whether to retry. A failed readback or cancelled wait can follow a successful tmux mutation. [Placement](https://libtmux.org/en/powershell/latest/guides/placement/) and [literal input](https://libtmux.org/en/powershell/latest/guides/input/) describe the uncertain cases. | | Sent text has no captured output yet | [Sending text](https://libtmux.org/en/powershell/latest/guides/input/) acknowledges input, not program completion. Wait on a cooperative channel or a program-specific result, then [capture](https://libtmux.org/en/powershell/latest/guides/capture/) the pane. A sleep does not establish readiness. | | A watcher reports dropped events | The [event stream](https://libtmux.org/en/powershell/latest/guides/watch/) bounds count and text bytes. A loss marker means history is incomplete; acquire a fresh snapshot when current topology matters. Rendered capture is a screen view, not a reconstruction of missed events. | | Interactive attach fails from a script or CI job | [Enter-TmuxSession](https://libtmux.org/en/powershell/latest/reference/libtmux-enter-tmuxsession/) needs a foreground terminal with stdin and must run outside another tmux client. Workspace apply is detached; pass its successful native [`Session`]() to the attach command in a terminal. | | Workspace apply stops partway through | Inspect the native [`WorkspaceBuildException`][workspacebuildexception] journal and partial result described in the [workspace guide](https://libtmux.org/en/powershell/latest/workspace/source-guide/#startup-host-effects-and-failures). Review the original plan and live server before another apply; host scripts and sent pane commands are not rolled back. | | MCP tools or waits are unavailable | The [MCP server](https://libtmux.org/en/powershell/latest/guides/mcp/) is an independently installed .NET tool. Check the configured executable, socket and `LIBTMUX_TOOLSETS`, then initialize the client and read `tools/list` and `tmux://capabilities`. A cursor or task from an earlier process is not durable. | For repeatable failures, record the command, PowerShell and tmux versions, selected socket kind, error ID and original exception. Avoid including pane contents, secrets or private socket paths in a public report. The [contributor guide](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/.github/CONTRIBUTING.md#testing-tmux-behavior) runs integration checks on owned sockets without touching your default server. [workspacebuildexception]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacebuildexception/ --- # Using the .NET MCP server Source: https://libtmux.org/en/powershell/latest/guides/mcp/ > Using the .NET MCP server: LibTmux documentation. Use the separate [LibTmux.Mcp .NET tool](https://www.nuget.org/packages/LibTmux.Mcp) to let an MCP client inspect panes, wait for output and run commands in tmux. It uses the same .NET library as libtmux for PowerShell. It does not import the PowerShell modules or require a PowerShell launcher. Tool names link to the [.NET MCP tool reference](https://libtmux.org/en/csharp/latest/mcp/tools/), which documents this server. ## Install and select a server Install the published 0.1.1 tool on the Unix host running tmux: ```console $ dotnet tool install LibTmux.Mcp \ --tool-path build/mcp \ --version 0.1.1 \ --framework net8.0 ``` For shared .NET source changes, use the optional [MCP development setup](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/.github/CONTRIBUTING.md#mcp-discovery). A desktop-launched client may need `DOTNET_ROOT` in its server environment when .NET comes from a version manager. For clients using an `mcpServers` configuration, replace these absolute paths with the installed tool, tmux executable and an existing server socket: ```json { "mcpServers": { "tmux": { "command": "/absolute/tool-directory/libtmux-mcp", "env": { "LIBTMUX_TMUX": "/absolute/path/to/tmux", "LIBTMUX_SOCKET_PATH": "/absolute/path/to/tmux/socket", "LIBTMUX_TOOLSETS": "inspect" } } } } ``` Claude Code takes the same settings as `-e` flags and the executable after `--`: ```console $ claude mcp add tmux \ -e LIBTMUX_TMUX=/absolute/path/to/tmux \ -e LIBTMUX_SOCKET_PATH=/absolute/path/to/tmux/socket \ -e LIBTMUX_TOOLSETS=inspect \ -- /absolute/tool-directory/libtmux-mcp ``` Other clients use different configuration formats; see the [.NET MCP client setup](https://libtmux.org/en/csharp/latest/mcp/#install). Launch the executable directly: standard input and output carry MCP messages. To name a socket instead of giving its path, replace `LIBTMUX_SOCKET_PATH` with `LIBTMUX_SOCKET`: ```console $ claude mcp add tmux \ -e LIBTMUX_SOCKET=work \ -e LIBTMUX_TOOLSETS=inspect \ -- /absolute/tool-directory/libtmux-mcp ``` - To choose a socket, set `LIBTMUX_SOCKET`, a name, or `LIBTMUX_SOCKET_PATH`, an absolute path. With both, including when one is inherited, the path wins. A blank value stops the server, where a PowerShell handle ignores it. `LIBTMUX_SOCKET_NAME` selects nothing, and the server refuses to start with it alone. - With neither, the server drives the server tmux picks: the one `TMUX` names, otherwise your default socket. A client started from a tmux pane therefore works on the panes you are using. The server starts no server of its own and leaves `teardown` off, and `tmux://capabilities` reports the selector `default`. Set `LIBTMUX_SOCKET` to keep an assistant on a server of its own. - The choice is fixed at startup; calls cannot switch sockets. - Shut down the client connection when finished. The server leaves a borrowed tmux daemon running. ## Discover before calling After initialization: - Read the server instructions. - Call `tools/list` for schemas, descriptions and annotations. Each advertised tool also carries its capability row in `_meta["com.git-pull.libtmux-mcp/capability"]`. - Read the [`tmux://capabilities` resource][capabilities]. It identifies the selected socket, the effective tools and the observation policy. Choose the tools your client sees: - The example selects `inspect`. Add `manage`, `execute` or `teardown` only for the operations your client needs, then restart it to change the selection. - Toolsets shape the interface; they are not an authorization boundary. Commands execute with the tmux user's authority. - [Tool selection][tool-selection] has the full contract. | Task | Start with | | --- | --- | | Find a session, window or pane | [`list_sessions`][list_sessions], [`list_windows`][list_windows], [`list_panes`][list_panes] | | Read terminal text | [`capture_pane`][capture_pane]; [`snapshot_pane`][snapshot_pane] for structured state | | Find text across panes | [`search_panes`][search_panes] | | Wait for text that has not appeared | [`wait_for_text`][wait_for_text] with a finite timeout | | Read changes across later calls | [`capture_since`][capture_since], retaining its returned cursor | | Run your own command and observe its completion | [`run_shell_command`][run_shell_command] from the `execute` toolset | | Combine independent reads in one request | [`call_read_tools_batch`][call_read_tools_batch]; its operations run serially | Know when a command is done: - Input acknowledgement does not prove a shell command finished. - Use the completion result of [`run_shell_command`][run_shell_command] for a command you start. Cancellation or timeout can leave that command running in its pane. - For a program already running, wait for its output rather than repeatedly capturing the screen. Read output without losing it: - On tmux 3.7 and newer, pane text waits require control observation by default. Older releases attach no control client and poll. - Setting `LIBTMUX_MCP_ALLOW_POLLING_FALLBACK=true` allows repeated captures if control observation fails. Capabilities disclose the policy and affected results report `pollingFallback`. - Give text waits a finite timeout. The server bounds their returned tail. - For captures, select `maxLines`. Check `eventsDropped` and the truncation fields before treating observed output as complete. - A [`capture_since`][capture_since] cursor tracks observation between calls; it is not a background job. - Progress notifications and optional MCP Tasks are separate protocol features, available only where the discovered tool declares them. - [Waits and captured output][waits] has the full contract. To allow the polling fallback, add it to the server's environment: ```console $ claude mcp add tmux \ -e LIBTMUX_SOCKET=work \ -e LIBTMUX_MCP_ALLOW_POLLING_FALLBACK=true \ -- /absolute/tool-directory/libtmux-mcp ``` ## Inspect a pane and wait for readiness After discovery, select a session from [`list_sessions`][list_sessions]. These are `tools/call` parameter objects: replace `$0` and `%0` with IDs returned by your server. The inspect toolset includes all three calls. List the selected session's panes with [`list_panes`][list_panes]: ```json { "name": "list_panes", "arguments": { "session": "$0" } } ``` The response's [`structuredContent.result`][result] contains pane records with `paneId`, `windowId`, `sessionId`, dimensions and the current command. Select one pane and read its rendered screen with [`capture_pane`][capture_pane]: ```json { "name": "capture_pane", "arguments": { "paneId": "%0", "maxLines": 64 } } ``` For this object result: - Read [`structuredContent.content.lines`][lines] directly. - [`content.truncated`][truncated], [`content.droppedLines`][droppedlines] and [`content.droppedBytes`][droppedbytes] disclose output omitted to fit the budget. - A list result has the `result` wrapper; object results do not. - Check `isError` before interpreting either shape. If the application prints `Service ready`, wait for that whole line with [`wait_for_text`][wait_for_text]: ```json { "name": "wait_for_text", "arguments": { "paneId": "%0", "patterns": ["^Service ready$"], "timeoutSeconds": 1, "ignoreCase": false } } ``` The result: - An existing line returns `structuredContent.outcome = "PresentAtEntry"`; a later line returns `"Matched"`. - `matchedPattern` identifies the condition, and `tail` contains bounded rendered text. - Stop-pattern, timeout and pane-death outcomes remain distinct. - A ready-line match is an application-specific condition; it does not establish shell exit status or continuing health. The [official SDK client](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/support/McpDiscovery/Program.cs) reads these three request examples, substitutes discovered IDs and executes them against an installed tool. Its owned fixture prints the ready line before the calls, then checks capture, [`PresentAtEntry`](), an untruncated tail, no event drops, polling only on tmux before 3.7, stdio shutdown and preservation of the borrowed tmux state. Cancel with care: - Use a finite server timeout even when your client can cancel. - With the pinned SDK 2.2.0, cancelling a local token does not reliably send `notifications/cancelled`; it can leave the remote wait running until its timeout. A client that knows its request ID can send that notification itself. - For negotiated MCP Tasks, cancel the task with `tasks/cancel` using its returned task ID. Task records are temporary and disappear on expiry or restart. - Neither cancellation stops the application in the pane. ## Check the client workflow from this checkout After [building the discovery probe](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/.github/CONTRIBUTING.md#mcp-discovery), set `MCP_COMMAND` to the installed executable's absolute path and `MCP_VERSION` to its exact version. Select the desired tmux on `PATH`, then run: ```console $ pwsh -NoLogo -NoProfile -File eng/Test.ps1 \ -Suite Mcp \ -McpCommand "$MCP_COMMAND" \ -McpVersion "$MCP_VERSION" ``` The [official SDK client source](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/support/McpDiscovery/Program.cs) initializes the installed tool, compares discovery with capabilities, then executes [`list_sessions`][list_sessions] and the three request examples above. The suite also: - starts the tool with every `LIBTMUX_` setting that the `claude mcp add` commands and JSON configuration on this page and in the repository README show, and checks that capabilities report each setting; - checks that both socket variables together are refused; - checks that every tool name on those pages is a link to its tool page and that every linked tool exists on the installed server; - checks that the session and pane survive MCP shutdown, then removes the owned fixture. It neither imports the PowerShell modules nor builds, installs or downloads anything during the test. Broader task, cancellation, loss and concurrent-wait acceptance belongs to the .NET protocol suite. [capabilities]: https://libtmux.org/en/csharp/latest/mcp/resources/tmux_capabilities/ [tool-selection]: https://libtmux.org/en/csharp/latest/mcp/topics/tool-selection/ [waits]: https://libtmux.org/en/csharp/latest/mcp/topics/waits-and-output/ [list_sessions]: https://libtmux.org/en/csharp/latest/mcp/tools/list_sessions/ [list_windows]: https://libtmux.org/en/csharp/latest/mcp/tools/list_windows/ [list_panes]: https://libtmux.org/en/csharp/latest/mcp/tools/list_panes/ [capture_pane]: https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/ [snapshot_pane]: https://libtmux.org/en/csharp/latest/mcp/tools/snapshot_pane/ [search_panes]: https://libtmux.org/en/csharp/latest/mcp/tools/search_panes/ [wait_for_text]: https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_text/ [capture_since]: https://libtmux.org/en/csharp/latest/mcp/tools/capture_since/ [run_shell_command]: https://libtmux.org/en/csharp/latest/mcp/tools/run_shell_command/ [call_read_tools_batch]: https://libtmux.org/en/csharp/latest/mcp/tools/call_read_tools_batch/ [result]: https://libtmux.org/en/csharp/latest/mcp/tools/list_panes/#mcp.tool.list_panes.output/properties/result [lines]: https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/#mcp.tool.capture_pane.output/properties/content/properties/lines [truncated]: https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/#mcp.tool.capture_pane.output/properties/content/properties/truncated [droppedlines]: https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/#mcp.tool.capture_pane.output/properties/content/properties/droppedLines [droppedbytes]: https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/#mcp.tool.capture_pane.output/properties/content/properties/droppedBytes --- # Watch events and use runspaces Source: https://libtmux.org/en/powershell/latest/guides/watch/ > Watch events and use runspaces: LibTmux documentation. [`Watch-TmuxEvent`]() emits native notifications and pane output fragments as they arrive. One application write may span several events, and one event may contain multiple lines. Use [rendered capture](https://libtmux.org/en/powershell/latest/guides/capture/) when you need the pane's current screen. The stream is not a durable or byte-exact log. Supply a control connection to borrow it, or a server and raw `-Target` to let the watcher own a temporary client. Stop, early pipeline exit and module removal end the reader; only an internally created client is disposed. The tmux daemon and sessions remain running. Removing the module cancels active watchers only in that runspace, and does not close handles returned by [`Connect-TmuxControl`](). One connection has one event consumer. The package rejects competing watchers; callers must also avoid directly enumerating the same native [`Events`]() stream. Each event is delivered on the pipeline callback before another is fetched. Downstream code may synchronously send a control command on that connection: reply processing does not wait for notification delivery. ## Observe one owned change [`Watch-TmuxEvent`]() attaches a control client, which needs tmux 3.7 or newer. With a server it is refused on an older daemon before anything attaches. After [installing libtmux for PowerShell](https://libtmux.org/en/powershell/latest/guides/getting-started/#install-from-source), paste this script into PowerShell. It creates one session on a socket in a private temporary directory. It connects a control client before renaming the window, so tmux queues the notification even if the job reads it later. The job emits that native event. An event limit, byte budget and five-second deadline bound the observation. The finally block removes the job, client, session and socket directory. If session removal fails, the directory remains so the server is reachable. The default tmux server is untouched. ```powershell & { $ErrorActionPreference = 'Stop' Import-Module LibTmux $name = 'libtmux-watch-' + $PID + '-' + [Guid]::NewGuid().ToString('N') $socketDirectory = Join-Path ([IO.Path]::GetTempPath()) $name $null = New-Item $socketDirectory -ItemType Directory -ErrorAction Stop $ownerOnly = [IO.UnixFileMode]::UserRead -bor [IO.UnixFileMode]::UserWrite -bor [IO.UnixFileMode]::UserExecute [IO.File]::SetUnixFileMode($socketDirectory, $ownerOnly) $socketPath = Join-Path $socketDirectory 'socket' $options = @{ SocketPath = $socketPath; ConfigurationFile = '/dev/null' } $server = New-TmuxServer @options $session = $control = $job = $null try { $session = $server | New-TmuxSession ` -Name watch-demo -WindowName before -Command 'exec /bin/cat' $control = $server | Connect-TmuxControl -Target $session.Name -ErrorAction Stop $job = Start-ThreadJob -ScriptBlock { Import-Module LibTmux $using:control | Watch-TmuxEvent -MaxEvents 16 -MaxOutputBytes 1MB | Where-Object { $_ -is [LibTmux.TmuxNotificationEvent] -and $_.Name -ceq 'window-renamed' -and $_.Arguments -ccontains 'after' } | Select-Object -First 1 } $null = $server | Invoke-TmuxCommand -Arguments @( 'rename-window', '-t', 'watch-demo:0', 'after' ) if (-not ($job | Wait-Job -Timeout 5)) { throw 'The rename notification did not arrive within five seconds.' } $notification = $job | Receive-Job -ErrorAction Stop if ($null -eq $notification) { throw 'The watcher ended without the rename notification.' } $notification } finally { try { if ($job) { $job | Stop-Job $job | Remove-Job } } finally { try { if ($control) { $control | Disconnect-TmuxControl -Confirm:$false } } finally { if ($session) { $session | Remove-TmuxSession -Confirm:$false } if ($session -or -not (Test-Path -LiteralPath $socketPath)) { Remove-Item -LiteralPath $socketDirectory -Recurse -Force } } } } } ``` ## Bound background output A foreground watcher occupies its pipeline until it ends or you press Ctrl+C. [`Start-ThreadJob`]() returns a job immediately and runs the watcher in another runspace. Select `$server` with an absolute socket path and an executable path available to that runspace; the following example watches an existing session named `fixture`. It creates its client inside the job. Retained Job output needs both a count and a text-byte budget, even if nobody calls [`Receive-Job`](). Budgets reset for each input connection or server; piping N owners can emit N times `-MaxEvents`. This example uses one client and retains at most one event and 1048576 UTF-8 text bytes. The job completes after the initial notification; increase both limits deliberately for a longer observation. ```powershell $job = & { $path = $server.ConnectionOptions.SocketPath $binary = $server.ConnectionOptions.TmuxBinaryPath Start-ThreadJob -ScriptBlock { Import-Module LibTmux New-TmuxServer -SocketPath $using:path -TmuxBinaryPath $using:binary | Watch-TmuxEvent -Target 'fixture' -MaxEvents 1 -MaxOutputBytes 1MB } } ``` Collect the result when needed. Always stop and remove the job in cleanup, including after a failed receive. Thread jobs preserve native objects in this process; process jobs serialize results and do not preserve live handles. ```powershell & { try { $job | Receive-Job -Wait -ErrorAction Stop } finally { $job | Stop-Job $job | Remove-Job } } ``` `-MaxEventBytes` defaults to 1048576 and bounds the single event held by the handoff. `-MaxOutputBytes` counts decoded UTF-8 text in output data, pane IDs, notification names and arguments, and exit reasons. Numeric loss counts carry no text bytes. These limits bound text payload, not object overhead or the size of serialized Job data. An event that cannot fit produces an explicit error before output; earlier events remain valid. The native upstream queue separately defaults to 512 events and 4 MiB of decoded UTF-8 payload. [`ServerConnectionOptions.ControlModeEventBufferCapacity`]() and [`ControlModeEventBufferMaxBytes`]() configure those positive limits before connecting. Its byte accounting includes output data, notification names and arguments, and exit reasons; it excludes pane IDs and object overhead. Under count pressure, the queue discards the oldest output from the pane with the most queued output events. Under byte pressure, it selects the pane with the most queued output bytes. If no output remains, it discards the oldest notification. An oversized event is dropped; an oversized exit reason is omitted while the exit event is retained. [`TmuxEventsDroppedEvent`]() reports each loss without blocking command replies. Use a fresh snapshot when current topology matters after loss. Stopping may consume a record that has not reached the pipeline. ## Run independent commands concurrently `ForEach-Object -Parallel` creates worker runspaces. Create and close each client in the worker that uses it. This finite example emits two short replies, and `-ThrottleLimit 2` bounds concurrent workers. Results arrive in completion order; include an identifier in your real workload if input order matters. ```powershell & { $path = $server.ConnectionOptions.SocketPath $binary = $server.ConnectionOptions.TmuxBinaryPath 'first', 'second' | ForEach-Object -ThrottleLimit 2 -Parallel { Import-Module LibTmux $options = @{ SocketPath = $using:path; TmuxBinaryPath = $using:binary } $endpoint = New-TmuxServer @options $control = $endpoint | Connect-TmuxControl -Target 'fixture' -ErrorAction Stop try { $command = New-TmuxCommand -Name 'display-message' -Arguments @( '-p', $_ ) $control | Invoke-TmuxControlCommand -Command $command -ErrorAction Stop } finally { $control | Disconnect-TmuxControl -Confirm:$false } } } ``` --- # Linking and consuming our docs Source: https://libtmux.org/en/powershell/latest/meta/linking/ > Find documentation exports for search engines, bots, LLMs and other documentation sites. We welcome bots, search engines, SEO tools, LLMs and other clients to use our documentation. Read a page in your browser, fetch its Markdown, discover pages through a manifest, or link to documented objects from another site. ## Choose an export The page footer links to the exports for its documentation tree. Use those links to select a language, version or preview. | File or format | Use it for | | --- | --- | | [llms.txt](https://libtmux.org/en/llms.txt) | Discover guides, API references and agent prompts through a Markdown index. | | [llms-full.txt](https://libtmux.org/en/llms-full.txt) | Fetch guides and MCP contracts together as Markdown. API references are linked separately. | | [docs.json](https://libtmux.org/en/docs.json) | Discover page titles, URLs, descriptions, headings and Markdown URLs in a structured manifest. | | Markdown | Read one page as text using its footer's **Markdown** link. | | Raw source | Inspect the source file using its footer's **Raw source** link, where available. | | [objects-full.inv](https://libtmux.org/en/objects-full.inv) | Resolve Sphinx references across shared docs, each port's default version, or its latest until the default has published a catalog, and tmux reference versions. | | objects.inv | Resolve Sphinx references within one port and version, or one tmux documentation tree. | | [targets.json](https://libtmux.org/en/targets.json) | Browse inventory keys, display names and destination URLs as JSON. A scoped catalog sits beside each root inventory. The root one lists fallbacks and ports left out. | The root exports above cover the assembled site. Port exports describe the selected port and version. For a single API declaration, start with `docs.json` and follow its reference and symbol-index links. ## Link from Sphinx The [Intersphinx guide](https://libtmux.org/en/meta/intersphinx/) explains how to configure inventories, choose native roles or portable labels, and preserve references when a page moves or changes its title. Browse [Intersphinx examples](https://libtmux.org/en/meta/intersphinx/examples/) for copyable RST and MyST references to library APIs, tmux C declarations, hooks, format variables, CLI commands and schema fields, paired with their destinations. ## Discover and index pages Use the [sitemap](https://libtmux.org/en/sitemap-index.xml) to discover indexable pages. Follow [robots.txt](https://libtmux.org/robots.txt) and each page's robots metadata: pull-request previews, component demos and search-index shards are excluded from crawling, and alternate versions can carry `noindex`. Choose a versioned documentation tree when a reference needs a particular release. The full inventory follows each port's advertised default; a port's `objects.inv` describes the selected version. --- # Link to libtmux from Sphinx Source: https://libtmux.org/en/powershell/latest/meta/intersphinx/ > Use Intersphinx inventories to reference libtmux APIs and documentation. Sphinx can resolve references to libtmux APIs, guides, headings, MCP objects, schema fields, and other documented targets. The footer links to the full inventory and the inventory for the page's port or tmux version. Browse [Intersphinx examples](https://libtmux.org/en/meta/intersphinx/examples/) for copyable RST and MyST references paired with their destinations. For Markdown exports, manifests and crawler discovery, see [Linking and consuming our docs](https://libtmux.org/en/meta/linking/). ## Configure Intersphinx Enable the built-in extension in your project's `conf.py`: `None` discovers `objects.inv` at the configured base URL. The port mapping above selects the Python `latest` tree. Copy the base URL of another port or version to select its inventory. The full inventory includes shared documentation, the configured default version of each assembled port, and distinct tmux reference versions. It is generated after site assembly. Each port inventory includes the rendered targets in that exact version. The tmux inventory includes the shared tmux guides and the latest CLI manual, options, hooks, formats, and C source reference. A version mapping such as `tmux-3-7c` includes only that release's manual, catalog, and C declarations. Manual and C reference pages link to the same version inventory in the footer. Use mapping names without dots when writing MyST reference roles. ## Choose a reference Every exported target has a portable label that works with `std:ref`, without installing a language or MCP domain. Open `targets.json` beside the inventory and copy its `key`. Its `href` and `display` identify the destination. For example, the Python [`libtmux.Pane`]() declaration has this reStructuredText reference: ```rst :external+libtmux:ref:`Pane ` ``` With MyST enabled in your project, the same label works in Markdown: ```markdown {external+libtmux:ref}`Pane ` ``` Native Python, C++, JavaScript, and C objects also have aliases for their built-in roles. A scoped Python inventory supports: ```rst :external+libtmux-python:py:class:`libtmux.Pane` ``` The tmux mapping provides native C roles and portable manual references: ```rst :external+tmux:c:struct:`cmd` :external+tmux:ref:`capture-pane ` ``` Command options also work with Sphinx's program context: ```rst .. program:: tmuxp load :external+libtmux-python:option:`--append` ``` The full inventory qualifies native names by port, such as `py:libtmux.Pane`. A fully qualified alias includes the product too: `py:core:libtmux.Pane`. Short aliases are offered only when they identify one destination. Configuration values, command options, environment variables, and glossary terms use standard-domain types where their renderers identify those semantics. ## Stable labels A portable key contains `scope:product:category:identity`. Its encoding preserves uppercase letters, punctuation, and Unicode, because `std:ref` lowercases targets. `%50ane` and `pane` therefore remain distinct. Copy the key from the catalog without decoding its percent escapes. Keys are independent of display titles and destination URLs. API public IDs, protocol wire identities, JSON Pointers, named parameters, and native method identities supply their names. Authored documents can retain `inventoryId` and explicit HTML fragment IDs when their titles or routes change. Contributors preserve renamed keys in the inventory alias catalog and use the existing page redirect mechanism for retired routes. ### Preserve published links If `meta/intersphinx.md` moves to `meta/linking.md`, retain its logical ID and list the retired route in the new page's frontmatter: ```yaml inventoryId: intersphinx aliases: - meta/intersphinx ``` The document key remains `site:core:doc:intersphinx`, and the old route redirects to the new page. Retain existing heading fragment IDs when their text changes. When an identity or fragment changes intentionally, map the former keys to current targets in `site/src/data/inventory-aliases.json`. For example, choosing `inventoryId: linking` and changing `stable-labels` to `stable-references` needs these entries: ```json [ { "scope": "site", "from": "site:core:doc:intersphinx", "to": "site:core:doc:linking" }, { "scope": "site", "from": "site:core:heading:intersphinx%23stable-labels", "to": "site:core:heading:linking%23stable-references", "fragment": "stable-labels" } ] ``` The document entry preserves `std:ref` and `std:doc` references. The heading entry preserves `std:ref`; `fragment` also installs the retired HTML anchor at the new destination. Keep the route alias too: inventory aliases do not redirect retired URLs. Copy `to` from the current target catalog. Retain earlier `from` entries and update their destinations when renaming again. Former native role names, such as a Python class name, need preservation in the native metadata. Existing `objects.inv` and `reference/objects.inv` endpoints remain compatibility exports. New integrations should use the full inventory, a port's root inventory, or a tmux root inventory to obtain the complete target catalog and case-safe labels. See the [Sphinx Intersphinx documentation](https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html) for named inventories and cross-reference syntax. --- # Intersphinx examples Source: https://libtmux.org/en/powershell/latest/meta/intersphinx/examples/ > Compare Sphinx and MyST references to APIs, tmux C declarations, hooks, format variables, CLI commands and schema fields. import { referenceHref } from '../../../../lib/api-models' Copy a reference and compare its destination below. These examples cover native language roles, portable labels, full and scoped inventories, and links into tmux C declarations, hooks, format variables and CLI commands. ## Configure the inventories Add these mappings to your Sphinx project's `conf.py`: `None` discovers `objects.inv` at the mapping's base URL. The full inventory uses each port's advertised default version. The `py` mapping explicitly selects `latest`; `tmux` selects the latest tmux manual and C reference. Use the root URL from an inventory's footer link when selecting a preview or another release. ## Native Python roles A named inventory selects the Python tree: ```rst :external+py:py:class:`libtmux.Pane` ``` Destination: [Pane](https://libtmux.org/en/py/latest/reference/libtmux-pane/#libtmux.Pane). The full inventory qualifies native names by port: ```rst :external+full:py:class:`py:libtmux.Pane` ``` Destination: Pane in the Python default version. For automatic lookup, use the ordinary role. A local definition takes precedence over Intersphinx: ```rst :py:class:`libtmux.Pane` ``` Destination: [Pane](https://libtmux.org/en/py/latest/reference/libtmux-pane/#libtmux.Pane). ## Portable labels Portable labels work with the standard reference role, including languages that have no built-in Sphinx domain. Copy the key from `targets.json`. ```rst :external+full:ref:`Pane ` :external+py:ref:`Pane ` ``` Destinations: Full inventory: Pane, [Scoped inventory: Pane](https://libtmux.org/en/py/latest/reference/libtmux-pane/#libtmux.Pane). The external role searches the configured inventories without selecting one. This native name is unqualified only in the scoped Python inventory: ```rst :external:py:class:`libtmux.Pane` ``` Destination: [Pane](https://libtmux.org/en/py/latest/reference/libtmux-pane/#libtmux.Pane). ## MyST roles and inventory URLs Enable `myst_parser` alongside `sphinx.ext.intersphinx` for Markdown sources. Named roles accept the same targets as reStructuredText: ```markdown {external+py:py:class}`libtmux.Pane` ``` Destination: [Pane](https://libtmux.org/en/py/latest/reference/libtmux-pane/#libtmux.Pane). Portable labels retain their percent escapes inside reference roles: ```markdown {external+full:ref}`Pane ` ``` Destination: Pane in the Python default version. MyST's inventory URL syntax also supports native aliases: ```markdown [Pane](inv:py:py:class#libtmux.Pane) ``` Destination: [Pane](https://libtmux.org/en/py/latest/reference/libtmux-pane/#libtmux.Pane). Use role syntax for percent-encoded portable keys: MyST normalizes escapes in `inv:` URLs. Keep mapping names free of dots, as in `tmux-3-7c`, so MyST can parse the role name. When using an inventory URL, specify its domain and object type if a name is both a document and a label. ## tmux C declarations The tmux mapping provides Sphinx's built-in C roles: ```rst :external+tmux:c:struct:`cmd` :external+tmux:c:func:`cmd_find_target` ``` Destinations: [cmd](https://libtmux.org/en/tmux/latest/reference/c-struct-cmd/#c%3Astruct%3Acmd), [cmd_find_target](https://libtmux.org/en/tmux/latest/reference/c-function-cmd_find_target/#c%3Afunction%3Acmd_find_target). Select a release with its own mapping. The full inventory also offers version-qualified native aliases: ```rst :external+tmux-3-7c:c:func:`cmd_find_target` :external+full:c:func:`tmux@3.7c:cmd_find_target` :external+full:c:func:`tmux@latest:cmd_find_target` ``` Destinations: [Scoped: cmd_find_target in 3.7c](https://libtmux.org/en/tmux/3.7c/reference/c-function-cmd_find_target/#c%3Afunction%3Acmd_find_target), [Full: cmd_find_target in 3.7c](https://libtmux.org/en/tmux/3.7c/reference/c-function-cmd_find_target/#c%3Afunction%3Acmd_find_target), [Full: cmd_find_target in latest](https://libtmux.org/en/tmux/latest/reference/c-function-cmd_find_target/#c%3Afunction%3Acmd_find_target). MyST supports the same C roles and a typed inventory URL: ```markdown {external+tmux:c:struct}`cmd` {external+tmux:c:func}`cmd_find_target` {external+full:c:func}`tmux@3.7c:cmd_find_target` [cmd_find_target](inv:tmux:c:function#cmd_find_target) ``` Destinations: [MyST: cmd](https://libtmux.org/en/tmux/latest/reference/c-struct-cmd/#c%3Astruct%3Acmd), [MyST: cmd_find_target](https://libtmux.org/en/tmux/latest/reference/c-function-cmd_find_target/#c%3Afunction%3Acmd_find_target), [MyST full: cmd_find_target in 3.7c](https://libtmux.org/en/tmux/3.7c/reference/c-function-cmd_find_target/#c%3Afunction%3Acmd_find_target), [Inventory URL: cmd_find_target](https://libtmux.org/en/tmux/latest/reference/c-function-cmd_find_target/#c%3Afunction%3Acmd_find_target). The C reference links each declaration to its source file and revision. Portable labels also address its signatures, parameters, and sections. ## tmux hooks Link a hook name to its catalog page with a portable label. The same key works in the scoped tmux inventory and the full inventory: ```rst :external+tmux:ref:`after-new-session ` :external+full:ref:`after-new-session ` ``` Destinations: [Scoped: after-new-session](https://libtmux.org/en/tmux/latest/catalog/hooks/after-new-session/), [Full: after-new-session](https://libtmux.org/en/tmux/latest/catalog/hooks/after-new-session/). In MyST, use the same key inside a reference role. Preserve its percent escapes: ```markdown {external+tmux:ref}`after-new-session ` {external+full:ref}`after-new-session ` ``` Destinations: [MyST scoped: after-new-session](https://libtmux.org/en/tmux/latest/catalog/hooks/after-new-session/), [MyST full: after-new-session](https://libtmux.org/en/tmux/latest/catalog/hooks/after-new-session/). ## tmux formats Link a format variable such as [`#{session_name}`](https://libtmux.org/en/tmux/latest/catalog/formats/session_name/) to its catalog entry: ```rst :external+tmux:ref:`session_name ` :external+full:ref:`session_name ` ``` Destinations: [Scoped: session_name](https://libtmux.org/en/tmux/latest/catalog/formats/session_name/), [Full: session_name](https://libtmux.org/en/tmux/latest/catalog/formats/session_name/). The MyST references select the same scoped or full inventory: ```markdown {external+tmux:ref}`session_name ` {external+full:ref}`session_name ` ``` Destinations: [MyST scoped: session_name](https://libtmux.org/en/tmux/latest/catalog/formats/session_name/), [MyST full: session_name](https://libtmux.org/en/tmux/latest/catalog/formats/session_name/). ## tmux CLI manual The same tmux inventory covers command pages: ```rst :external+tmux:ref:`capture-pane ` ``` Destination: [capture-pane](https://libtmux.org/en/tmux/latest/manual/capture-pane/). The document role works when the target is a whole page: ```rst :external+tmux:doc:`Full manual ` ``` Destination: [Full tmux manual](https://libtmux.org/en/tmux/latest/manual/full/). Select a command's manual page with the document role. Its portable key also works in the full inventory: ```rst :external+tmux:doc:`tmux new-session ` :external+full:doc:`tmux new-session ` ``` Destinations: [Scoped: new-session](https://libtmux.org/en/tmux/latest/manual/new-session/), [Full: new-session](https://libtmux.org/en/tmux/latest/manual/new-session/). Use the same document role in MyST: ```markdown {external+tmux:doc}`tmux new-session ` {external+full:doc}`tmux new-session ` ``` Destinations: [MyST scoped: new-session](https://libtmux.org/en/tmux/latest/manual/new-session/), [MyST full: new-session](https://libtmux.org/en/tmux/latest/manual/new-session/). ## Command options, environment variables, and terms The Python port's workspace documentation exports standard-domain objects. Set the program context before referencing an option: ```rst .. program:: tmuxp load :external+py:option:`--append` ``` Destination: [tmuxp load --append](https://libtmux.org/en/py/latest/workspace/cli/load/#arguments-and-flags-a-append). Environment variables and glossary terms use their own roles. Qualify the product when a term appears in more than one glossary: ```rst :external+py:envvar:`COLUMNS` :external+py:term:`async ` ``` Destinations: [COLUMNS](https://libtmux.org/en/py/latest/workspace/configuration/environment/#cli-and-runtime-variables-columns-lines-rows), [async](https://libtmux.org/en/py/latest/reference/glossary/#async). ## MCP tools and schema fields Portable labels also address protocol objects and individual JSON Schema fields. No custom MCP domain is required: ```markdown {external+py:ref}`Read tools batch ` {external+py:ref}`on_error ` ``` Destinations: [Read tools batch](https://libtmux.org/en/py/latest/mcp/tools/call_read_tools_batch/#mcp.tool.call_read_tools_batch), [on_error](https://libtmux.org/en/py/latest/mcp/tools/call_read_tools_batch/#mcp.tool.call_read_tools_batch.input%2Fproperties%2Fon_error). ## Shared documentation and headings The full inventory includes the shared documentation: ```rst :external+full:doc:`Inventory guide ` :external+full:ref:`Configure Intersphinx ` ``` Destinations: [Inventory guide](https://libtmux.org/en/meta/intersphinx/), [Configure Intersphinx](https://libtmux.org/en/meta/intersphinx/#configure-intersphinx). ## Local files and fallback locations Download an inventory and pass its filename as the second mapping value. The first value remains the documentation URL used in generated links: An ordered list tries a local copy before the HTTP inventory: See the [inventory guide](https://libtmux.org/en/meta/intersphinx/) for key stability and the [Sphinx Intersphinx reference](https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html) for configuration options. --- # AI policy Source: https://libtmux.org/en/powershell/latest/meta/ai-policy/ > Use the libtmux packages with AI tools. When contributing, check what you submit and wait for a maintainer's invitation before preparing a pull request. Last revised October 25, 2026 Use these packages with AI tools as you like. When contributing, check what you submit and wait for a maintainer's invitation before preparing a pull request. This policy covers the libraries, ports, and documentation in the [libtmux](https://github.com/libtmux) and [tmux-python](https://github.com/tmux-python) organizations, including their issues, comments, discussions, reviews, and pull requests. ## 1. For users: About these packages We encourage you to use AI tools with our libraries and documentation, including to generate code that calls the libraries. We want these projects to be useful in the way you work. Some of what we publish supports that workflow: - [MCP integrations](https://libtmux.org/en/py/latest/mcp/) that let assistants interact with tmux. - Markdown documentation and `llms.txt` and `llms-full.txt` resources linked from documentation pages. - [`AGENTS.md`]() and other repository instructions for tools working on the codebase. Use the documentation for the package, language, and version you are working with. ### How the ports are made The ports build on [tmuxp](https://tmuxp.git-pull.com/), started in 2013, and [libtmux](https://libtmux.git-pull.com/), started in 2016. Both projects predate today's LLM coding tools. Current work on the original projects and the ports uses AI assistance. Maintainers guide the design, review changes, test behavior against real tmux, and decide what ships. They remain responsible for what the projects include and maintain. ### Stability Packages in the [libtmux organization](https://github.com/libtmux) are experimental unless their README says otherwise. Names and APIs may change between releases. Pin an exact version and review changes before upgrading. ## 2. For contributors: How to report issues, ideas, suggestions, and security issues A useful issue is a contribution in its own right. Your experience helps us see what breaks, what feels awkward, and what is missing. You do not need to arrive with a patch. Open bugs, ideas, and suggestions in the repository of the package they concern. Report suspected security vulnerabilities privately using the route below. ### Bugs Tell us what you tried, what happened, and what you expected. Include a small example we can run, the library and tmux versions, and the actual output. Include relevant logs and error messages as they appeared, and distinguish what you observed from possible explanations. Bug reports are welcome whether the code you were running was handwritten or generated. Include the code that ran. A conversation transcript is usually unnecessary; include relevant prompts or tool calls when they are needed to reproduce the problem. ### Ideas and suggestions Explain what you wanted to accomplish and where the current design gets in your way. We welcome feedback on: - Usability: what was hard to find or get right, and where the documentation misled you. - Language conventions: whether a port feels natural in the language you use. - Aesthetics: how an API, a page, or an error message reads. - Missing capabilities: what you could not accomplish with the current API. If an API you expected is missing, describe the task and why that API would help. ### Security issues Report suspected security vulnerabilities privately. Use **Report a vulnerability** on the affected repository's security page where available. Include the affected package and version, the tmux version, what you observed, and reproduction steps or relevant code references if available. Distinguish verified behavior from suspected impact. Please coordinate public disclosure with us so we can investigate and, where needed, prepare a fix. Command execution explicitly requested through documented features is expected behavior and does not, by itself, establish a vulnerability. Explain any additional failure, such as data being interpreted as commands unexpectedly or an intended security boundary being crossed. ### Writing your report Short reports, typos, and imperfect English are fine. Translation and writing assistance are welcome; check that the result says what you mean and preserves the facts you observed. Your experience matters more than a polished report. ### Using AI tools If AI materially helped prepare your issue, comment, discussion, review, or pull request, say which tools you used, what they did, and what you checked yourself. Using these tools does not count against a contribution. You remain responsible for what you submit. Do not send generated code, reports, or explanations you have not checked. ### Pull requests Before preparing a pull request, open an issue or comment on an existing issue about the proposed change. Wait for a maintainer to invite a PR for an agreed scope. Opening an issue alone is not an invitation. PRs submitted without that agreement may be closed without review. Arrange security fixes through the private reporting route. Even when we agree that something should change, we may prefer to write the implementation ourselves. Review must consider correctness, supported tmux versions, language conventions, documentation, and ongoing maintenance. Checking those can take more time than writing the change, whether it was handwritten or generated. If we invite a PR, understand the changes, test them, and be able to explain them. Follow the project's contribution instructions, and describe the tests you ran and the versions you used. Generated code and tests can share the same mistake, so passing tests alone do not show that a change fits the project. Submit only material you have the right to contribute on terms compatible with the project's license. Identify outside code, tests, or text incorporated into the contribution, including material adapted with AI assistance, and provide its source and license. Keep required notices, and raise unclear permissions before including the material. These source and licensing requirements apply to maintainers too.

Acknowledgments: Informed by Pallets’ LLM and AI Policy, tmux’s AI contribution guidelines, and OpenJDK’s Interim Policy on Generative AI. Licensing references: the GNU GPL FAQ on translating code and license compatibility. All sources consulted .

--- # Third-party notices Source: https://libtmux.org/en/powershell/latest/meta/third-party-notices/ > Thanks to tmux's creator and contributors, with licences and attribution for the software behind libtmux.org. ## tmux First and foremost, thank you to **[Nicholas Marriott (nicm)](https://github.com/nicm)**, the creator of tmux, and to the many [tmux contributors](https://github.com/tmux/tmux/graphs/contributors). We are grateful for the work that makes tmux possible. libtmux is a separate project. Our libraries and supporting tools control a real tmux server; tmux itself provides the terminal multiplexer. This is the libtmux website. Visit the [official tmux website](https://github.com/tmux/tmux/wiki) for the upstream project and its documentation. See tmux's [COPYING file](https://github.com/tmux/tmux/blob/master/COPYING) and the copyright and permission notices in its source files for its licensing. ### tmux artwork The tmux logomark is by Jason Long. The site uses the unmodified [upstream SVG](https://github.com/tmux/tmux/blob/8f25579c5aef8d93924a20681f394e2a582fd3ad/logo/tmux-logomark.svg) under its [copyright and permission notice](https://libtmux.org/en/brand/tmux/LICENSE.txt). ## Programming-language artwork The homepage language selector uses local copies of the following artwork to identify the selected language. Each source record includes the download URL, retrieval time, file hash, copyright information and usage terms. These marks identify their respective languages and do not imply endorsement of libtmux. The SVG files are copied unchanged except for Scala, whose empty surrounding canvas is cropped. Its paths, gradients and colors are preserved, and the original SVG is retained beside the cropped copy. Rust's supplied SVG includes its own dark-theme colors. | Language | Credit and terms | Local source record | |---|---|---| | Python | Python Software Foundation. The [PSF logo terms](https://www.python.org/psf/trademarks/) permit the unaltered mark to identify Python. | [Python provenance](https://libtmux.org/en/brand/languages/py/provenance.json) | | Ruby | Copyright © 2006, Yukihiro Matsumoto. The [Ruby logo](https://www.ruby-lang.org/en/about/logo/) is licensed under [CC BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). | [Ruby provenance](https://libtmux.org/en/brand/languages/ruby/provenance.json) | | Lua | Copyright © 1998 Lua.org; graphic design by Alexandre Nakonechnyj. The Devicon copy carries its [MIT notice](https://libtmux.org/en/brand/languages/lua/LICENSE.txt); [Lua's logo terms](https://www.lua.org/images/) also apply. Visit [Lua.org](https://www.lua.org/). | [Lua provenance](https://libtmux.org/en/brand/languages/lua/provenance.json) | | TypeScript | Microsoft. The [official branding terms](https://www.typescriptlang.org/branding/) govern the mark; the website repository licenses exclude logo and trademark rights. | [TypeScript provenance](https://libtmux.org/en/brand/languages/ts/provenance.json) | | Rust | The Rust Foundation. [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) and the [Rust trademark policy](https://rustfoundation.org/policy/rust-trademark-policy/) apply. | [Rust provenance](https://libtmux.org/en/brand/languages/rs/provenance.json) | | Go | The [Go gopher](https://go.dev/blog/gopher) is by Renee French, licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). | [Go provenance](https://libtmux.org/en/brand/languages/go/provenance.json) | | C++ | Created by Jeremy Kratz and licensed by the Standard C++ Foundation under its [logo-use terms](https://isocpp.org/home/terms-of-use). | [C++ provenance](https://libtmux.org/en/brand/languages/cxx/provenance.json) | | Swift | Apple Inc., under the [Swift Logo Guidelines](https://developer.apple.com/swift/downloads/swift-logo.zip). Swift and the Swift logo are trademarks of Apple Inc. | [Swift provenance](https://libtmux.org/en/brand/languages/swift/provenance.json) | | Java | Devicon collection copyright (c) 2015 konpa, with its [MIT notice](https://libtmux.org/en/brand/languages/java/LICENSE.txt). This does not establish unrestricted rights to the underlying Java logo; [Oracle's logo terms](https://www.oracle.com/legal/logos/) apply. | [Java provenance](https://libtmux.org/en/brand/languages/java/provenance.json) | | Kotlin | Kotlin Foundation brand guidelines preserve JetBrains copyrights. The [icon-use terms](https://kotlinfoundation.org/guidelines/) permit identifying Kotlin alongside other programming-language icons. | [Kotlin provenance](https://libtmux.org/en/brand/languages/kotlin/provenance.json) | | Scala | Copyright EPFL. [Historical permission](https://groups.google.com/g/scala-user/c/bCC-R0FQn1w) covers noncommercial Scala promotion; the [general artwork-license question](https://github.com/scala/scala-lang/issues/1040) remains unresolved. | [Scala provenance](https://libtmux.org/en/brand/languages/scala/provenance.json) | | C# | Copyright the .NET authors. [Brand-use permission](https://github.com/dotnet/brand/issues/10#issuecomment-669465301) allows the unmodified logo to represent .NET. The repository's CC0 statement covers illustrations; no blanket CC0 claim is made for the logo. | [.NET provenance](https://libtmux.org/en/brand/languages/csharp/provenance.json) | | F# | The F# Software Foundation. Its [logo terms](https://foundation.fsharp.org/logo) require unchanged shape, colors and proportions, without implying Foundation representation. | [F# provenance](https://libtmux.org/en/brand/languages/fsharp/provenance.json) | ## Terminal artwork The tmux CLI selector displays the Windows Terminal artwork by Microsoft Corporation, licensed under [CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0/). The SVG is unmodified. See the [source and provenance](https://libtmux.org/en/brand/tools/terminal/provenance.json) and [copyright and license](https://libtmux.org/en/brand/tools/terminal/LICENSE.txt). ## Documentation toolchain libtmux and this site are built with open-source software. The following tools have their own licences and attribution requirements. | Tool | Licence | Role | |---|---|---| | [Astro](https://astro.build/) | MIT | The site shell | | [Tailwind CSS](https://tailwindcss.com/) | MIT | Styling | | [Pagefind](https://pagefind.app/) | MIT | Site-wide search | | [Expressive Code](https://expressive-code.com/) | MIT | Code blocks | | [Sphinx](https://www.sphinx-doc.org/) | BSD-2-Clause | Python and C++ reference | | [Furo](https://github.com/pradyunsg/furo) | MIT | Sphinx theme | | [Breathe](https://github.com/breathe-doc/breathe) | BSD-3-Clause | Doxygen XML into Sphinx | | [Doxygen](https://www.doxygen.nl/) | GPL-2.0-only | Parses C++ headers to XML | | [API Extractor](https://api-extractor.com/) | MIT | TypeScript API model | | [IBM Plex](https://github.com/IBM/plex) | OFL-1.1 | Typeface | ### A note on Doxygen Doxygen is licensed GPL-2.0-only. It runs as a build step that reads libtmux's own headers and emits XML; that XML is rendered by Breathe and Sphinx, and no Doxygen-generated HTML is published. Running a GPL program over your own input does not place its licence on the output, and libtmux does not distribute Doxygen or any modified version of it. ## Reference hosting The [PyPI blocks logo](https://pypi.org/trademarks/) is a trademark of the Python Software Foundation and identifies links to the Python Package Index. Other package-host icons use [Simple Icons](https://simpleicons.org/) (CC0-1.0). The docs.rs mark is its [`docsdotrs` icon](https://github.com/simple-icons/simple-icons/blob/16.35.0/icons/docsdotrs.svg), inlined unchanged. The book beside javadoc.io links is original artwork for this site: the host publishes no vector logo, and the mark does not imitate its favicon. Some ports deep-link to the canonical host their ecosystem already uses, rather than duplicating it here: - Rust: [docs.rs](https://docs.rs/libtmux), for each published crate - Go: [pkg.go.dev](https://pkg.go.dev/github.com/libtmux/libtmux-go/tmux) - Java, Kotlin and Scala: [javadoc.io](https://javadoc.io/doc/io.github.libtmux/libtmux) - Swift: the [Swift Package Index](https://swiftpackageindex.com/libtmux/libtmux-swift/documentation/libtmux) copy of the DocC reference Those sites are operated independently of this project and carry their own terms. ## libtmux itself Each port is MIT licensed. See the `LICENSE` file in that port's repository for the authoritative text. --- # API glossary Source: https://libtmux.org/en/powershell/latest/reference/glossary/ > Kinds, modifiers and package labels in the PowerShell API reference. ## Symbol kinds Kinds identify declarations in the PowerShell API reference. ### module A PowerShell unit loaded with Import-Module, grouping exported commands and resources. References: [PowerShell modules](https://learn.microsoft.com/en-us/powershell/scripting/developer/module/understanding-a-windows-powershell-module). ### function A PowerShell named script block with parameters and a body. Advanced functions use CmdletBinding and related attributes for cmdlet-style behavior. References: [PowerShell functions](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions). ### cmdlet A PowerShell command participating in pipeline input, parameter binding and object output. The reference uses this label for exported advanced functions as well as binary cmdlets. References: [PowerShell cmdlets](https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/cmdlet-overview). ## Package context Package labels identify where an API is supplied. ### package The distributed PowerShell module supplying these commands, distinct from each exported Verb-Noun command name. References: [PowerShell module distribution](https://learn.microsoft.com/en-us/powershell/scripting/developer/module/writing-a-windows-powershell-module). --- # PowerShell-based tmux workspace manager Source: https://libtmux.org/en/powershell/latest/workspace/ > Validate, plan and load workspace files with the LibTmux.Workspace module. **Workspace Manager concept example** A working example of the core library. It can change without notice. [`LibTmux.Workspace`]() provides PowerShell commands for reading, validating, planning and applying workspace configuration. The module uses [`LibTmux`]() for tmux objects and operations. Install the module with the commands below, then follow the [workspace guide](https://libtmux.org/en/powershell/latest/workspace/source-guide/) to inspect a plan before applying it. The [command reference](https://libtmux.org/en/powershell/latest/workspace/reference/) lists every exported workspace command and its parameter sets. The [PowerShell Gallery package](https://www.powershellgallery.com/packages/LibTmux.Workspace) also provides Azure Automation and manual download options. Manual downloads require you to install the package dependencies separately. --- # LibTmux.Workspace API reference Source: https://libtmux.org/en/powershell/latest/workspace/reference/ > Public LibTmux.Workspace declarations, parameters and source documentation. **Workspace Manager concept example** A working example of the core library. It can change without notice. Import [`LibTmux.Workspace`]() to read, validate, plan and apply workspace files. Each command below lists every parameter set and its pipeline bindings. Read the [package guide](https://libtmux.org/en/powershell/latest/workspace/source-guide/) for installation and complete examples. ## API declarations - [LibTmux.Workspace](https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace/) --- # API glossary Source: https://libtmux.org/en/powershell/latest/workspace/reference/glossary/ > Kinds, modifiers and package labels in the PowerShell API reference. ## Symbol kinds Kinds identify declarations in the PowerShell API reference. ### module A PowerShell unit loaded with Import-Module, grouping exported commands and resources. References: [PowerShell modules](https://learn.microsoft.com/en-us/powershell/scripting/developer/module/understanding-a-windows-powershell-module). ### function A PowerShell named script block with parameters and a body. Advanced functions use CmdletBinding and related attributes for cmdlet-style behavior. References: [PowerShell functions](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions). ### cmdlet A PowerShell command participating in pipeline input, parameter binding and object output. The reference uses this label for exported advanced functions as well as binary cmdlets. References: [PowerShell cmdlets](https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/cmdlet-overview). ## Package context Package labels identify where an API is supplied. ### package The distributed PowerShell module supplying these commands, distinct from each exported Verb-Noun command name. References: [PowerShell module distribution](https://learn.microsoft.com/en-us/powershell/scripting/developer/module/writing-a-windows-powershell-module). --- # Topics Source: https://libtmux.org/en/powershell/latest/topics/ > Make deliberate choices about ownership, command completion, and event streams. Use these topics when a script grows beyond a single command. They explain what your script owns, what a successful return proves, and how to react when a stream loses data. For the object model and query boundaries, start with [Concepts](https://libtmux.org/en/powershell/latest/concepts/). For executable setup and cleanup, use the [complete examples](https://libtmux.org/en/powershell/latest/examples/). - [Ownership and cleanup](https://libtmux.org/en/powershell/latest/topics/ownership/): Separate borrowed daemons, owned clients, jobs, and created sessions. - [Dispatch, completion, and failure](https://libtmux.org/en/powershell/latest/topics/execution/): Choose command chains, control replies, or authenticated shell completion. - [Watching output and state](https://libtmux.org/en/powershell/latest/topics/observations/): Bound stream lifetime and memory, then recover deliberately from event loss. --- # Ownership and cleanup Source: https://libtmux.org/en/powershell/latest/topics/ownership/ > Keep daemon, client, session, and runspace lifetimes explicit. A server handle does not own the tmux daemon. Most cmdlets borrow the native objects supplied to them. Decide who creates and removes each resource before putting operations in a pipeline or background job. ## Match cleanup to what you created | Resource | Lifetime rule | | --- | --- | | Endpoint from [`New-TmuxServer`]() | A description; constructing it starts no daemon. | | An existing server or session | Remains under its existing owner's control. | | A session your example creates | Remove that session in cleanup when its work ends. | | Client from [`Connect-TmuxControl`]() | Close explicitly with [`Disconnect-TmuxControl`](). | | Client created internally by [`Watch-TmuxEvent`]() | The watcher closes it when its reader ends. | | A thread job you start | Stop and remove the job, including after a failed receive. | Disconnecting a control client closes that client for every caller sharing it. It does not mean the daemon should be killed. Cleanup awaits native disposal; that operation has no cancellation token. ## Use an isolated endpoint for automation The complete examples choose a unique socket name and a clean tmux configuration. They remove only the session they create. This makes the resource boundary visible and avoids attaching an example's lifetime to your interactive server. Do not treat `-Confirm:$false` as an ownership check. It suppresses a confirmation prompt; your code must still target the resources it is responsible for. Keep useful `-WhatIf` behavior in operator-facing scripts. ## Preserve failures during cleanup Use a `finally` scope to release resources after success, operation failure, or an early exit. If cleanup fails too, retain both errors rather than replacing the original failure. The [create-layout program](https://libtmux.org/en/powershell/latest/examples/create-layout/) shows that handling in full. Module removal ends active watchers in that runspace. It does not close clients previously returned by [`Connect-TmuxControl`](). A handle transferred to another caller therefore still needs an agreed owner. Thread jobs run in the same process and preserve native objects. Process jobs serialize output and cannot be used to transfer a live native handle unchanged. Create and close a client's resources in the worker that uses them when running independent work. See [runspaces and watchers](https://libtmux.org/en/powershell/latest/guides/watch/) for bounded job recipes and [control clients](https://libtmux.org/en/powershell/latest/guides/commands/) for borrowed-client examples. --- # Dispatch, completion, and failure Source: https://libtmux.org/en/powershell/latest/topics/execution/ > Distinguish accepted input, tmux replies, shell completion, and application readiness. Choose the completion signal that answers your actual question. A successful key-send operation means tmux accepted input. It does not establish that a shell command or service has finished. ## What a result proves | Task | Evidence to use | | --- | --- | | Send key tokens to a pane | [`Send-TmuxKey`]() reports the input operation's result. | | Run a shell command and inspect its exit status | [`Invoke-TmuxPaneCommand`]() waits for authenticated completion. | | Wait for a service to announce readiness | [`Wait-TmuxPaneText`]() observes the stated text condition; check service behavior separately. | | Send a control command | [`Invoke-TmuxControlCommand`]() returns the command reply; deferred work may continue. | | Submit a known sequence of tmux commands | [`Invoke-TmuxChain`]() dispatches the chain in order. | The [command-completion example](https://libtmux.org/en/powershell/latest/examples/command-completion/) checks exit status 7. A nonzero shell exit is a result, not automatically a tmux error. The [service example](https://libtmux.org/en/powershell/latest/examples/wait-for-service/) checks a readiness line and then makes an HTTP request. Seeing echoed input alone proves neither result. ## Commands and chains [`New-TmuxCommand`]() creates an inert command value with literal argument boundaries. Arguments can still invoke tmux features that run shell programs; literal argv handling does not change the semantics of those features. A chain retains guards carried by its typed commands. It returns combined output, not an individual receipt for every step. A failure can skip later commands while leaving earlier changes in place. A chain is not a transaction. Use individual typed operations when later steps need newly acquired object handles. Use bounded concurrent work only for operations whose independence you have established. Result ordering does not imply dispatch ordering. ## Stopping the caller does not undo dispatch Ctrl+C cancels a current wait. A dispatched command may continue, and a timeout may leave its effect uncertain. The library does not make cancellation a rollback or a reason to retry a mutation automatically. PowerShell's error policy also matters: the default continuing behavior can allow later input owners to be processed, whereas `-ErrorAction Stop` terminates the pipeline on the reported failure. Keep the original native exception and its available dispatch evidence when reporting the failure. The [command guide](https://libtmux.org/en/powershell/latest/guides/commands/) covers transport and batch limits. The [input guide](https://libtmux.org/en/powershell/latest/guides/input/) specifies completion, timeout, and key-send behavior for each operation. --- # Watching output and state Source: https://libtmux.org/en/powershell/latest/topics/observations/ > Choose a screen capture or event stream and handle bounded delivery explicitly. A capture reads the pane's rendered screen. [`Watch-TmuxEvent`]() observes future notifications and output fragments. Choose the observation that matches your question; an event stream is not a durable or byte-exact terminal log. ## Start observation before the producer Connect the control client before triggering the change you need to observe. One connection has one event consumer. Competing watchers are rejected, and callers must also avoid enumerating the same native event stream independently. One application write can span several events; one event can contain multiple lines. Matching a marker needs state across fragments. For service readiness, prefer the task-specific [`Wait-TmuxPaneText`]() contract and still check that the service responds, as the [HTTP example](https://libtmux.org/en/powershell/latest/examples/wait-for-service/) does. ## Bound both time and retained output A foreground watcher occupies its pipeline. Use a thread job when the prompt must remain available, and give it an event limit, text-byte budget, and deadline. Job output can accumulate even if nobody receives it. Limits apply per input owner. Piping several owners can multiply the total retained output. The watcher and native transport have separate buffers, and text-byte limits do not include every object or serialization cost. Raising concurrency therefore needs a separate memory decision. ## Treat loss as a state change The upstream queue is bounded. A [`TmuxEventsDroppedEvent`]() reports discarded records so a slow observer does not block command replies. If current topology matters after loss, acquire a new snapshot. A fresh snapshot can restore your view of current state; it cannot recover terminal output that was dropped. Consumer termination can leave a record consumed before it reaches the pipeline. Do not infer an exact delivery count solely from how many records a downstream command prints. ## Keep the right owner alive A watcher supplied with a connection borrows it. A watcher supplied with a server and raw target owns its temporary client and disposes that client when it ends. The daemon and sessions remain running in either case. Stop and remove jobs in cleanup, and close explicitly created control clients after their observers end. The [watch guide](https://libtmux.org/en/powershell/latest/guides/watch/) includes an owned rename observation, background-job limits, and independent-runspace examples. Use the [capture guide](https://libtmux.org/en/powershell/latest/guides/capture/) when the question concerns visible screen state instead of future events. --- # Workspace guide Source: https://libtmux.org/en/powershell/latest/workspace/source-guide/ > Workspace guide: LibTmux documentation. **Workspace Manager concept example** A working example of the core library. It can change without notice. Describe a session once, inspect the proposed tmux operations, and apply the plan you reviewed. [`LibTmux.Workspace`]() handles files and workspace commands; [`LibTmux`]() supplies native server, session, window and pane objects. Both use [libtmux for .NET](https://github.com/libtmux/libtmux-dotnet)'s shared engine. Install [LibTmux.Workspace](https://www.powershellgallery.com/packages/LibTmux.Workspace) as described in the [README](https://libtmux.org/en/powershell/latest/guides/getting-started/#build-a-workspace-from-a-file). Its package dependency installs the matching core module. Choose an explicit `$server` with [New-TmuxServer](https://libtmux.org/en/powershell/latest/guides/read/). The following workflow creates a detached `development` session with two shell panes in your project directory. It needs tmux and `/bin/sh` on a Unix host. The session remains available after the commands finish; remove it when done using [Remove-TmuxSession](https://libtmux.org/en/powershell/latest/guides/remove/). ## Load and resolve the declaration Save this declaration as `development.yaml`. Set `$workspacePath` to its literal file path and `$projectRoot` to your project's absolute directory. ```yaml session_name: development start_directory: ${PROJECT_ROOT} options: default-command: exec /bin/sh windows: - window_name: editor layout: even-horizontal options: automatic-rename: 'off' panes: - options: '@role': editor - focus: true ``` [`Get-TmuxWorkspace`]() emits a [`FileInfo`](). Import parses the file; Resolve returns a declaration with explicit directory expansion. Neither creates sessions or executes commands. ```powershell $resolve = @{ BaseDirectory = Split-Path -LiteralPath $workspacePath Variables = @{ PROJECT_ROOT = $projectRoot } } $workspace = Get-TmuxWorkspace -LiteralPath $workspacePath -ErrorAction Stop | Import-TmuxWorkspace -ErrorAction Stop | Resolve-TmuxWorkspace @resolve -ErrorAction Stop ``` Only the supplied string variables participate in `$NAME` or `${NAME}` expansion; the resolver does not copy the process environment. Supply `HOME` explicitly when the declaration uses `~`. `$$` preserves a literal dollar sign. Resolution expands inherited directories and session, window and pane option values, including global and post-construction options. Unknown variables in option values remain literal; unresolved directory variables are errors. Option names, commands, the host script, session and window names, and environment values remain literal. The base directory also records the origin for an allowed `before_script`. Ordered `shell_command` and `shell_command_before` lists accept command strings and tmuxp-style entries such as `- cmd: exec /bin/sh`. Commands remain literal and run in session-before, window-before, pane-before, then pane-command order. The [workspace corpus](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/fixtures/workspace/corpus.yaml) checks the mixed forms on an owned tmux server. Set `enter: false` on a pane or command to type its text without submitting it. Commands inherit the current Enter setting until another command overrides it; the default is `true`. The [pinned tmuxp fixtures](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/fixtures/workspace/tmuxp-v1.74.0-skip-send.yaml) cover pending text and execution after an explicit Enter. Set [`window_index`](https://libtmux.org/en/tmux/latest/catalog/formats/window_index/) on a window to request a nonnegative session-relative index. Omit it to let tmux choose the next free index. Duplicate requested indices fail validation; an index occupied by an existing window fails when the reviewed plan is applied. The [pinned tmuxp fixture](https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/tests/fixtures/workspace/tmuxp-v1.74.0-window_index.yaml) checks a sparse `0, 5, 1` session on an owned server. tmux treats `PATH` specially. An unattached client can replace a pane's declared `PATH` with the client's value during pane creation, while the session environment retains the declared value. Set `PATH` inside the pane shell when pane commands depend on it. For discovery, [`Get-TmuxWorkspace`]() lists nearby `.tmuxp.yaml`, `.tmuxp.yml` and `.tmuxp.json` files before the first configured global directory. `-Name development` selects a global basename, while `-LiteralPath` chooses one exact file. Use `-AllLocations` to include shadowed global locations. `-Search editor` searches filenames; `-SearchIn Path` also searches parent directories, while `-SearchIn Window` parses declared window names. Search never executes declaration commands. See the [discovery reference](https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-get-tmuxworkspace/) for precedence, ambiguity and traversal limits. ## Choose when options apply Window `options` take effect before startup input, additional panes and the final layout. Put options such as [`main-pane-height`](https://libtmux.org/en/tmux/latest/catalog/options/main-pane-height/) there so the selected layout uses them. Window `options_after` apply after startup commands have been sent and the final layout is selected. This lets each pane receive its own setup text before [`synchronize-panes`](https://libtmux.org/en/tmux/latest/catalog/options/synchronize-panes/) starts broadcasting later input. It does not wait for those setup commands to finish. Root `options` affect this session. Root `global_options` affect the server's global session defaults before the declared windows start. Global changes can affect inherited settings in existing sessions and survive creation cleanup after a later failure. Review their explicit scope before applying. This declaration chooses a shell for new windows, sizes the main pane, and defers synchronized input. The example returns a native plan and changes nothing; review its actions, then apply it using the workflow below. ```powershell & { $declaration = Import-TmuxWorkspace -Yaml @' session_name: option-staging global_options: default-shell: /bin/sh windows: - window_name: workers layout: main-horizontal options: main-pane-height: '5' options_after: synchronize-panes: 'on' panes: - shell_command: printf first - shell_command: printf second '@ $declaration | Get-TmuxWorkspacePlan -Server $server } ``` The option actions retain native [`SetOptionRequest`]() values. Their default view shows `scope=Session global=True` for the global setting and hides option values. `scope=Owner` follows the action's session, window or pane target. The confirmation preview also identifies global effects. ## Validate before contacting tmux Check declaration and policy constraints locally. Success emits `$true`. With `-ErrorAction Stop`, an invalid declaration stops this workflow. ```powershell $workspace | Test-TmuxWorkspace -ErrorAction Stop ``` This does not verify directory existence, shell syntax, tmux option support or session conflicts. Without `-ErrorAction Stop`, an invalid declaration writes an error and then `$false`; later pipeline records can continue. ## Plan and review Planning observes only the selected endpoint and freezes the actions and policies. The default conflict policy refuses an existing session with the same name. [`CreateOrJoin`][workspaceserverstartup-createorjoin] permits application to start an absent daemon or join one that appeared since planning; it grants no ownership of the daemon. Use [`RequireExisting`][workspaceserverstartup-requireexisting] when planning must find one already running. ```powershell $planOptions = @{ Server = $server ExistingSession = 'Error' ServerStartup = 'CreateOrJoin' ErrorAction = 'Stop' } $workspacePlan = $workspace | Get-TmuxWorkspacePlan @planOptions ``` A JSON window layout needs tmux 3.8. On an older server, [`Get-TmuxWorkspacePlan`]() fails with a [`WorkspaceFormatException`]() whose inner exception is the `layout-json` refusal. Planning may probe the version but sends no layout or creation command. Inspect the ordered actions before applying them. The default view shows each action's symbolic target and source, plus a safe summary of its arguments: layout, dimensions when set, option name, readiness timeout and host limits. It marks scripts, pane text, option values, paths and environment without printing their contents. Reading the plan performs no I/O. ```powershell $workspacePlan.Actions ``` To inspect exact arguments in a trusted terminal, read an action's typed [`Request`][workspaceaction-request] property. It contains the script, command, option value and other values that the default view hides. If planning used `-CompensateOnFailure`, inspect [`$workspacePlan.CompensationActions`][workspaceplan-compensationactions] separately; those actions run only after a failed application. Targets are plan symbols bound to created tmux identities during application. The plan includes the transient bootstrap window used to install session options before starting the described panes. It also includes the final [`CaptureResult`][workspaceactionkind-captureresult] observation. tmux hooks can observe that bootstrap lifecycle. Preview the endpoint, session, policies and ordered actions through PowerShell's confirmation mechanism. Each action and conditional cleanup step shows its kind and symbolic target; option actions also show scope and global effects. Request values remain hidden. Preview emits no result and dispatches nothing. ```powershell $workspacePlan | Invoke-TmuxWorkspace -WhatIf ``` ## Apply the reviewed plan After review, apply that exact plan. Omitting `-Confirm:$false` retains the high-impact confirmation prompt. Invocation does not reread the source file or silently construct a replacement plan when its preconditions are stale. ```powershell $workspaceResult = $workspacePlan | Invoke-TmuxWorkspace -Confirm:$false -ErrorAction Stop ``` [`$workspaceResult.Session`][workspaceresult-session] and `.Windows` are native objects from the final captured graph. `.Journal` records action outcomes; `.Unsupported` lists requested final layouts tmux rejected while leaving their windows usable. The observation spans an interval, so concurrent changes can make it fail. To load the workspace into your foreground terminal, run `$workspaceResult.Session | LibTmux\Enter-TmuxSession -ErrorAction Stop` after the successful application. Run it outside tmux with terminal stdin; detach normally to receive one refreshed native session. The borrowed daemon and workspace remain running after you detach. See [Enter-TmuxSession](https://libtmux.org/en/powershell/latest/reference/libtmux-enter-tmuxsession/) for its terminal and cancellation contract. [`Enter-TmuxSession`]() accepts the native Session, not WorkspaceResult. It asks for its own PowerShell confirmation when requested. `-WhatIf` on [`Invoke-TmuxWorkspace`]() emits no result to attach. A failed application with `-ErrorAction Stop` emits no result for this step. Entering a session does not undo workspace effects if the terminal client is cancelled or fails. For an existing session, choose [`Reuse`][workspaceexistingsession-reuse], [`Append`][workspaceexistingsession-append] or [`Replace`][workspaceexistingsession-replace] explicitly when planning. Reuse returns the inspected session without declaration effects; Append adds windows while retaining local session options and applies declared global defaults. Replace removes the inspected session before creating its replacement. Review those actions before approving them. ## Export a starting declaration Capture an existing session at pane depth before converting it. Set `$exportPath` to the literal path for the YAML file you want to write. The conversion reads the capture only; [`Set-Content`]() writes the file. ```powershell ($server | Get-TmuxSnapshot -Depth Panes -ErrorAction Stop).Sessions | Select-TmuxSession -ExactlyOne -ErrorAction Stop -Criteria @{ Name = 'development' } | ConvertTo-TmuxWorkspace -ErrorAction Stop | ConvertTo-TmuxWorkspaceYaml -ErrorAction Stop | Set-Content -LiteralPath $exportPath -Encoding utf8NoBOM -ErrorAction Stop ``` Conversion preserves session-relative window indices. It warns because it omits observed options, environment, terminal text, entity IDs, pane indices and shared-link identity. It cannot reconstruct original startup commands or shell intent. Repeated window links become separate declarations. Check the exported layout and pane paths, add the commands you want on a future load, then import, resolve and review a new plan. For JSON, use [`ConvertTo-TmuxWorkspaceJson`]() in place of the YAML converter. See [ConvertTo-TmuxWorkspace](https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-convertto-tmuxworkspace/) for the captured-field and literal-path rules. ## Edit the declaration Choose a file and an installed editor explicitly. `$workspaceFile` is the [`FileInfo`]() returned by [`Get-TmuxWorkspace`](); `$editor` is an [`ApplicationInfo`]() returned by `Get-Command -Name nvim -CommandType Application -ErrorAction Stop` (or your chosen editor). Set `[string[]] $editorArguments = @()` for no extra arguments. A GUI editor that returns immediately needs its own wait option, such as `@('--wait')` where the selected editor supports it. Run this as a foreground command in your terminal, without assigning, piping or redirecting its output. The file's absolute path is one argument. Arguments are passed separately, including spaces, quotes and empty strings. ```powershell & { $ErrorActionPreference = 'Stop' $PSNativeCommandArgumentPassing = 'Standard' $PSNativeCommandUseErrorActionPreference = $false & $editor @editorArguments $workspaceFile.FullName if ($LASTEXITCODE -ne 0) { throw "Editor exited with code $LASTEXITCODE." } } ``` A nonzero editor exit stops the block with the exit code. Launch errors also stop it. Exit the editor normally when finished. Ctrl+C follows the editor's and terminal's normal behavior; some editors treat it as an editing command and stay open. This recipe has no `-WhatIf`, forced-stop or process-tree cleanup contract. It does not undo edits already saved. Editing runs no workspace command or tmux operation. Import, resolve, validate and review a new plan explicitly afterward. An existing plan still contains the declaration captured when it was created. ## Type a command without submitting it Use `enter: false` to prepare input for review. This example creates a shell, reads the pending command, submits one Enter, and waits for its rendered output. The result contains the reviewed plan, pending text, and completion. The `finally` block removes the session it created. ```powershell & { $ErrorActionPreference = 'Stop' $declaration = Import-TmuxWorkspace -Yaml @' session_name: review-command options: default-command: exec /bin/sh windows: - window_name: review panes: - shell_command: - cmd: "printf '\\nreview %s\\n' complete" enter: false '@ $plan = $declaration | Get-TmuxWorkspacePlan -Server $server $result = $null try { $result = $plan | Invoke-TmuxWorkspace -Confirm:$false $pane = $result.Windows[0].Panes[0] $typed = "printf '\nreview %s\n' complete" $wait = @{ Timeout = 10; Confirm = $false } $pending = $pane | Wait-TmuxPaneText -Pattern $typed -SimpleMatch @wait if ($pending.Outcome -notin 'PresentAtEntry', 'Matched') { throw "Pending input wait ended with $($pending.Outcome)." } $pane | Send-TmuxKey -Key Enter -Confirm:$false $completion = $pane | Wait-TmuxPaneText -Pattern '^review complete$' @wait if ($completion.Outcome -notin 'PresentAtEntry', 'Matched') { throw "Pending command wait ended with $($completion.Outcome)." } [pscustomobject]@{ Pending = $pending.Tail -join "`n" Completion = $completion Plan = $plan } } finally { if ($result) { $result.Session | Remove-TmuxSession -Confirm:$false } } } ``` ## Startup, host effects and failures `-Readiness Immediate` sends configured commands as literal input, applying each command's Enter setting. It does not infer shell readiness or command completion. With `-Readiness Cooperative`, pane startup receives a fresh `LIBTMUX_WORKSPACE_READY` channel and must signal it when it can accept input, using the selected tmux executable and the same server. The shell operation is [`tmux wait-for -S "$LIBTMUX_WORKSPACE_READY"`](https://libtmux.org/en/tmux/latest/manual/wait-for/). A signal sent before the wait is retained. `-ReadinessTimeout` bounds each wait in seconds; completion of the sent command needs its own application signal. See the [shared engine's cooperative startup example](https://github.com/libtmux/libtmux-dotnet/blob/master/src/LibTmux.Workspace/README.md#readiness-and-existing-sessions). A declaration's `before_script` runs on the host only when planning admits it with `-AllowHostScripts`. Resolve the document first. Creation and replacement run the script after the named session exists; Append uses the existing session, and Reuse skips the script. Its working directory is the resolved session `start_directory`, falling back to the document directory. The script is literal shell text passed to `/bin/sh -c`; tmuxp's separate rewrite of a leading `./script` path is not applied. Supply the same policy to [`Test-TmuxWorkspace`]() and [`Get-TmuxWorkspacePlan`](), including `-HostScriptTimeout` and `-MaxHostOutputBytes` when changing their bounds. Invocation uses those frozen settings. Validation, planning and `-WhatIf` never run the script. Review both host scripts and pane commands before applying files from another source. Application failures write [`Tmux.WorkspaceApplyFailed`][invoketmuxworkspacecommand] with a native [`WorkspaceBuildException`][workspacebuildexception]; they do not emit a partial success object. With `-ErrorAction Stop`, a `catch` block can inspect [`$_.Exception`][system-management-automation-errorrecord-exception] through its `.PartialResult`, `.Journal`, `.CompensationJournal`, [`.Dispatch`]() and `.InnerException` properties. With normal error handling, later plans can continue. A stopped PowerShell pipeline may suppress error delivery, so do not rely on receiving a journal after stopping it. This example deliberately appends a window to the `development` session built above, then asks tmux to set an invalid pane option. It requests compensation for the newly created window. The existing session and its `editor` window are borrowed and must remain. Run it only against the session this guide created. ```powershell $workspaceRecovery = & { $broken = Import-TmuxWorkspace -Yaml @' session_name: development windows: - window_name: recovery-demo panes: - options: libtmux-invalid-option: fail '@ -ErrorAction Stop $plan = $broken | Get-TmuxWorkspacePlan -Server $server ` -ExistingSession Append -ServerStartup RequireExisting ` -CompensateOnFailure -ErrorAction Stop try { $null = $plan | Invoke-TmuxWorkspace -Confirm:$false -ErrorAction Stop throw 'The deliberately invalid option was accepted.' } catch { $type = [LibTmux.Workspace.WorkspaceBuildException] if ($_.Exception -isnot $type) { throw } $failure = $_.Exception } [pscustomobject]@{ Plan = $plan Failure = $failure Current = ($server | Get-TmuxSnapshot -Depth Panes -ErrorAction Stop) } } ``` Inspect [`$workspaceRecovery.Failure.Journal`][workspacebuildexception-journal] for the failed action and its dispatch state, then [`$workspaceRecovery.Failure.CompensationJournal`][workspacebuildexception-compensationjournal] for attempted cleanup. The fresh [`$workspaceRecovery.Current.Sessions`][server-sessions] observation shows what remains. A completed cleanup entry records a tmux operation; the fresh observation proves whether `recovery-demo` is gone and `editor` remains. If dispatch is [`Unknown`]() or cleanup failed, the action may have taken effect. Inspect the server and reconcile it before making another plan; do not retry the same plan blindly. `-CompensateOnFailure` at planning requests bounded cleanup of creations whose ownership is proven by that application. Review [`$workspacePlan.CompensationActions`][workspaceplan-compensationactions] too. `-CleanupTimeout` bounds cleanup; it cannot undo shell or host side effects. The module never owns a borrowed daemon and never guesses cleanup targets from names. The declaration format covers session/window/pane options, global session defaults, post-construction window options, layouts, focus, environment, directory inheritance and command lists. Unsupported keys are errors. For complete policy parameters, see [Get-TmuxWorkspacePlan](https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-get-tmuxworkspaceplan/) and [Invoke-TmuxWorkspace](https://libtmux.org/en/powershell/latest/workspace/reference/libtmux-workspace-invoke-tmuxworkspace/). [workspaceserverstartup-createorjoin]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceserverstartup-createorjoin/ [workspaceserverstartup-requireexisting]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceserverstartup-requireexisting/ [workspaceaction-request]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceaction-request/ [workspaceplan-compensationactions]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceplan-compensationactions/ [workspaceactionkind-captureresult]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceactionkind-captureresult/ [workspaceresult-session]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceresult-session/ [workspaceexistingsession-reuse]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceexistingsession-reuse/ [workspaceexistingsession-append]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceexistingsession-append/ [workspaceexistingsession-replace]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceexistingsession-replace/ [invoketmuxworkspacecommand]: https://github.com/libtmux/libtmux-powershell/blob/fa5e60c48b312eb0d957d02aad9edcfc50cff359/src/LibTmux.Workspace.PowerShell/InvokeTmuxWorkspaceCommand.cs [workspacebuildexception]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacebuildexception/ [system-management-automation-errorrecord-exception]: https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.errorrecord.exception?view=powershellsdk-7.4.0 [workspacebuildexception-journal]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacebuildexception-journal/ [workspacebuildexception-compensationjournal]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacebuildexception-compensationjournal/ [server-sessions]: https://libtmux.org/en/csharp/latest/reference/libtmux-server-sessions/