# 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. --- # 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. The prerelease flag includes the alpha releases. 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 -Prerelease ` -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. The prerelease flag includes the alpha releases. 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 -Prerelease ` -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. The prerelease flag includes the alpha releases. 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 -Prerelease ` -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. Drive [tmux](https://github.com/tmux/tmux) from PowerShell. Create sessions, arrange panes, send input, and read terminal output through native cmdlets. Snapshots return typed objects that you can traverse and filter with ordinary PowerShell pipelines. Built on [libtmux for .NET](https://github.com/libtmux/libtmux-dotnet), in the same [libtmux organization](https://github.com/libtmux) and with the same main author. The cmdlets return its native objects and add PowerShell parameter binding, help, formatting and `-WhatIf` / `-Confirm`. [Install](https://libtmux.org/en/powershell/latest/guides/getting-started/#install) · [Object graph](https://libtmux.org/en/powershell/latest/guides/getting-started/#create-and-read-an-object-graph) · [Run to completion](https://libtmux.org/en/powershell/latest/guides/getting-started/#run-a-command-to-completion) · [Service readiness](https://libtmux.org/en/powershell/latest/guides/getting-started/#wait-for-service-readiness) · [Execution modes](https://libtmux.org/en/powershell/latest/guides/getting-started/#choose-how-to-run) · [Guides](https://libtmux.org/en/powershell/latest/guides/getting-started/#guides) · [MCP](https://libtmux.org/en/powershell/latest/guides/mcp/#discover-before-calling) · [Compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/) · [Troubleshooting](https://libtmux.org/en/powershell/latest/guides/troubleshooting/) · [Cmdlet reference](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/docs/reference/README.md) · [License](https://libtmux.org/en/powershell/latest/guides/getting-started/#license) **Alpha.** APIs may change. Both modules are available on PowerShell Gallery: [LibTmux](https://www.powershellgallery.com/packages/LibTmux) and [LibTmux.Workspace](https://www.powershellgallery.com/packages/LibTmux.Workspace). ## Install Use PowerShell 7.4 or later with tmux on the same Linux host. On Windows, run both inside WSL. PowerShell 7.4 includes the PSResourceGet commands below; see [compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/) for the support contract. Run these commands in PowerShell. Install the core module for sessions, windows, panes, snapshots, input and capture: ```console $ Install-PSResource -Name LibTmux ` -Version 0.1.0-alpha2 ` -Prerelease ` -Repository PSGallery ` -Scope CurrentUser ` -TrustRepository ``` For YAML/JSON workspace declarations, install the matching workspace module. It also installs its exact core dependency, so this command alone installs both modules: ```console $ Install-PSResource -Name LibTmux.Workspace ` -Version 0.1.0-alpha2 ` -Prerelease ` -Repository PSGallery ` -Scope CurrentUser ` -TrustRepository ``` PowerShellGet is an alternative. Install the core module: ```console $ Install-Module -Name LibTmux -AllowPrerelease ``` Or install the workspace module with its matching core dependency: ```console $ Install-Module -Name LibTmux.Workspace -AllowPrerelease ``` Choose one installer. The prerelease flag includes the alpha releases; without it, the installers look for stable releases. 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 in [compatibility](https://libtmux.org/en/powershell/latest/guides/compatibility/). Import both modules to run all the examples on this page: ```console $ Import-Module -Name LibTmux, LibTmux.Workspace ` -RequiredVersion 0.1.0 ` -ErrorAction Stop ``` PowerShell imports use the numeric module version, `0.1.0`; Gallery packages carry the `alpha2` prerelease label. Browse cmdlets with `Get-Command -Module LibTmux` and examples with `Get-Help LibTmux\New-TmuxSession -Examples`. The MCP server is a separate .NET tool; see [MCP setup](https://libtmux.org/en/powershell/latest/guides/mcp/#install-and-select-a-server). [Build from source](https://libtmux.org/en/powershell/latest/guides/getting-started/#install-from-source) for development. The walkthrough below runs directly from the installed modules. ## Create and read an object graph Choose a unique socket and a clean tmux configuration. [`New-TmuxServer`]() creates a handle without contacting tmux. The example does not touch your default server. ```powershell $server = LibTmux\New-TmuxServer ` -SocketName ('libtmux-readme-' + [Guid]::NewGuid().ToString('N')) ` -ConfigurationFile /dev/null ``` Create a session with an editor window, split it, add a logs window, and take one snapshot. `cat` keeps the three panes open without shell setup. The `finally` block removes only the session this example created. ```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 native [`LibTmux.Session`](). Its [`Windows`][session-windows] contain native [`LibTmux.Window`]() objects; each window's [`Panes`][window-panes] contain native [`LibTmux.Pane`]() objects. The graph is still readable after cleanup: | 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 | Walk it and filter locally: ```powershell $captured.Windows | Where-Object { $_.Panes.Count -gt 1 } | Select-Object Name, @{ Name = 'PaneCount'; Expression = { $_.Panes.Count } } ``` The result is `editor` with two panes; `logs` has one. [`Where-Object`](), navigation, formatting, and property access use captured data and start no tmux client. [`Get-TmuxSnapshot`]() explicitly reads fresh state. A linked window can have several session placements; its index belongs to the placement. See [snapshots and linked windows](https://libtmux.org/en/powershell/latest/guides/read/) for IDs, active children and captured versus unavailable fields. The structured equivalent selects the one window with at least two captured panes. `-ExactlyOne` reports zero or multiple matches: ```powershell $captured.Windows | Select-TmuxWindow -Criteria @{ 'Panes.Count' = @{ Ge = 2 } } -ExactlyOne ``` This query also performs no I/O. [The query guide](https://libtmux.org/en/powershell/latest/guides/query/) shows native predicates, Boolean and relationship criteria, and explicit fresh source queries. ## Run a command to completion When the shell's exit status matters, run the command in a pane and inspect its native result. This example uses the private `$server` above and removes only the session it creates: ```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 shell exit is a result, not a tmux error. On timeout, the command may still be running, so the result has no exit status. See [command completion](https://libtmux.org/en/powershell/latest/guides/input/#run-a-command-to-completion) for concurrency and output behavior. ## Wait for service readiness With Python 3 on `PATH`, start an HTTP server on an available loopback port. Use the private `$server` above, wait for the application's readiness line, then make an HTTP request to check that it responds. The session's cleanup also 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 native [`PaneWaitResult`]() has outcome [`PresentAtEntry`]() or [`Matched`](), followed by HTTP status 200. The wait closes its temporary control client; the example removes only its session. A text match proves the readiness condition, and the HTTP request checks service behavior separately. See [pane-text waits](https://libtmux.org/en/powershell/latest/guides/input/#wait-for-an-applications-readiness-line) for stop patterns, bounded tails, cancellation and disclosed event loss. Use [a cooperative channel](https://libtmux.org/en/powershell/latest/guides/input/#send-a-command-and-wait-for-its-output) when the application can signal completion itself. ## Choose how to run | 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) | Connect once to send a command through tmux control mode. 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; use the [control guide](https://libtmux.org/en/powershell/latest/guides/commands/#reuse-a-control-client) for multiple commands and cancellation behavior. Foreground cmdlets and `ForEach-Object -Parallel` occupy their calling pipeline. Thread jobs return the prompt while they run; control mode keeps one client connected for repeated commands. Watchers accept event-count and text-byte limits. Choose a mode by its ownership and failure behavior, not a timing claim; the [mode guide](https://libtmux.org/en/powershell/latest/guides/commands/) explains when chains merge failure attribution. ## Modules and MCP | Product | Use it for | | --- | --- | | [LibTmux](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/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) | 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 | Describe a two-pane workspace. Importing it parses YAML without contacting tmux or running its commands: ```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 '@ ``` Plan on the same private endpoint. Planning may read tmux state; it does not create the workspace: ```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 ``` Preview without applying the plan: ```powershell $workspacePlan | LibTmux.Workspace\Invoke-TmuxWorkspace -WhatIf ``` Apply that exact plan, then remove only the session it created. The captured result remains readable after cleanup: ```powershell $workspaceResult = & { $result = $workspacePlan | LibTmux.Workspace\Invoke-TmuxWorkspace -Confirm:$false -ErrorAction Stop try { $result } finally { $result.Session | Remove-TmuxSession -Confirm:$false } } ``` ```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. For an MCP client, start with the [client configuration](https://libtmux.org/en/powershell/latest/guides/mcp/#install-and-select-a-server), then read `tools/list` and `tmux://capabilities` before calling [`list_sessions` or `capture_pane`](https://libtmux.org/en/powershell/latest/guides/mcp/#discover-before-calling). Install both PowerShell modules at the same version. The MCP server is an independent .NET tool and does not require PowerShell. ## Guides - **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). The marked README blocks run together in the [installed workflow test](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/tests/ReadmeWorkflow.Tests.ps1). The [executable guides](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/examples/Guides.ps1) run against real tmux through the installed modules. See [contributing](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/.github/CONTRIBUTING.md) for the runners and development checks. The [benchmark guide](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/benchmarks/README.md) explains installed-package workloads, correctness checks, raw samples and reproduction commands. ## Install from source For development, install the pinned PowerShell and .NET SDK from [.tool-versions](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/.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 alpha.20 packages](https://www.nuget.org/packages/LibTmux/0.0.0-alpha.20) 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/b06c64f844f3173de66b187eaeaf3915814318c6/.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 ``` Run the [quick start](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/examples/QuickStart.ps1) from the checkout root. It creates a private server, splits the `editor` window, adds `logs`, and returns a captured native [`LibTmux.Session`](). Show each window's pane IDs: ```powershell (./examples/QuickStart.ps1).Windows | Select-Object Name, @{ Name = 'PaneIds' Expression = { $_.Panes.Id -join ', ' } } ``` Output 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 and leaves your default tmux server alone. ## License [MIT](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/LICENSE). See [third-party notices](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/licenses/THIRD-PARTY-NOTICES.md) for bundled dependencies. [session-windows]: https://libtmux.org/en/csharp/latest/reference/libtmux-session-windows/ [window-panes]: https://libtmux.org/en/csharp/latest/reference/libtmux-window-panes/ [workspaceaction-request]: https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceaction-request/ [session-panes]: https://libtmux.org/en/csharp/latest/reference/libtmux-session-panes/ --- # 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`; 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-alpha2 module](https://www.powershellgallery.com/packages/LibTmux/0.1.0-alpha2) with PSResourceGet: ```console $ pwsh -NoLogo -NoProfile -Command ' $ErrorActionPreference = "Stop" Install-PSResource -Name LibTmux -Version 0.1.0-alpha2 -Prerelease ` -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` 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. 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 does not establish command completion: use a cooperative wait channel or control event before asserting captured results. | 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: ```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` and `send-keys -X` 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` 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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/GetTmuxPaneContentCommand.cs [invoketmuxcommandcommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/InvokeTmuxCommandCommand.cs [updatetmuxpanecommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/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`. Shell programs inside those arguments retain those features' normal semantics. 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/b06c64f844f3173de66b187eaeaf3915814318c6/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 } } ``` 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/b06c64f844f3173de66b187eaeaf3915814318c6/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 as prereleases 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/#install) 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/b06c64f844f3173de66b187eaeaf3915814318c6/.github/workflows/ci.yml) exercises PowerShell 7.4.20 and 7.6.6 with tmux 3.2a and 3.7c. 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/b06c64f844f3173de66b187eaeaf3915814318c6/.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. | Choose the tmux executable and socket explicitly with [New-TmuxServer](https://libtmux.org/en/powershell/latest/guides/read/). 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 an implicit global 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. --- # 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. `-Scope` overrides the scope and `-Global` selects its global table. 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 hook without waiting for its event: ```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` policy. On tmux 3.2a, detached creation can use the command client's dimensions unless `window-size` is `manual`. ## 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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/NewTmuxSessionCommand.cs [newtmuxwindowcommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/NewTmuxWindowCommand.cs [splittmuxpanecommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/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` 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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/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` for that scope's global defaults. For example, 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]` 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. [`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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/ConnectTmuxServerCommand.cs [gettmuxsnapshotcommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/GetTmuxSnapshotCommand.cs [gettmuxsessioncommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/GetTmuxSessionCommand.cs [gettmuxwindowcommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/GetTmuxWindowCommand.cs [gettmuxpanecommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/tests/Remove.Tests.ps1) checks previews, zero-output pipelines, per-owner errors, linked-window destruction, session sharing, last-pane cascades, isolated endpoints and real daemon replacement on owned tmux servers. [removetmuxsessioncommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/RemoveTmuxSessionCommand.cs [removetmuxwindowcommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/src/LibTmux.PowerShell/RemoveTmuxWindowCommand.cs [removetmuxpanecommand]: https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/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` 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 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` 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. It observes rendered text through a temporary control client, checks text already visible at entry, then wakes on output or layout changes. 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 its control client; 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. `-AllowPollingFallback` explicitly permits polling if control observation fails; [`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/#install) 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/b06c64f844f3173de66b187eaeaf3915814318c6/.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 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/b06c64f844f3173de66b187eaeaf3915814318c6/.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. ## Install and select a server Install the published alpha.20 tool on the Unix host running tmux: ```console $ dotnet tool install LibTmux.Mcp \ --tool-path build/mcp \ --version 0.0.0-alpha.20 \ --framework net8.0 ``` For shared .NET source changes, use the optional [MCP development setup](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/.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" } } } } ``` 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. Use `LIBTMUX_SOCKET` for a socket name or `LIBTMUX_SOCKET_PATH` for an absolute path. Set only one, including inherited environment variables. 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`, and read `tmux://capabilities`. The resource identifies the selected socket, effective tools and observation policy. Tool discovery supplies schemas, descriptions and annotations. Each advertised tool also carries its capability row in `_meta["com.git-pull.libtmux-mcp/capability"]`. 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. | Task | Start with | | --- | --- | | Find a session, window or pane | `list_sessions`, `list_windows`, `list_panes` | | Read terminal text | `capture_pane`; `snapshot_pane` for structured state | | Find text across panes | `search_panes` | | Wait for text that has not appeared | `wait_for_text` with a finite timeout | | Read changes across later calls | `capture_since`, retaining its returned cursor | | Run your own command and observe its completion | `run_shell_command` from the `execute` toolset | | Combine independent reads in one request | `call_read_tools_batch`; its operations run serially | Input acknowledgement does not prove a shell command finished. Use the completion result of `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. `run_shell_command` uses a cooperative completion channel and also probes authenticated run status and pane liveness, starting after 250 ms and backing off to five seconds. This run watchdog is separate from pane text observation and its optional polling fallback. Pane text waits require control observation by default in alpha.20. Explicitly enabling `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`. Inspect `eventsDropped` and truncation fields before treating observed output as complete. A `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. Read the installed server's schemas and capability rows for those contracts. ## Inspect a pane and wait for readiness After discovery, select a session from `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: ```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: ```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: ```json { "name": "wait_for_text", "arguments": { "paneId": "%0", "patterns": ["^Service ready$"], "timeoutSeconds": 1, "ignoreCase": false } } ``` 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/b06c64f844f3173de66b187eaeaf3915814318c6/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 polling or event drops, stdio shutdown and preservation of the borrowed tmux state. 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 explicitly send that notification. For negotiated MCP Tasks, cancel the task with `tasks/cancel` using its returned task ID. Neither cancellation stops the application in the pane. Task records are temporary and disappear on expiry or restart. ## Check the client workflow from this checkout After [building the discovery probe](https://github.com/libtmux/libtmux-powershell/blob/b06c64f844f3173de66b187eaeaf3915814318c6/.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/b06c64f844f3173de66b187eaeaf3915814318c6/tests/support/McpDiscovery/Program.cs) initializes the installed tool, compares discovery with capabilities, then executes `list_sessions` and the three request examples above. The suite 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. [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 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 } } } ``` --- # Third-party notices Source: https://libtmux.org/en/powershell/latest/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). Three ports deep-link to the canonical host their ecosystem already uses, rather than duplicating it here: - Rust: [docs.rs](https://docs.rs/libtmux) - Go: [pkg.go.dev](https://pkg.go.dev/github.com/libtmux/libtmux-go/tmux) - Java and Kotlin: [javadoc.io](https://javadoc.io/doc/io.github.libtmux/libtmux) 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. --- # Workspace Manager Source: https://libtmux.org/en/powershell/latest/workspace/ > Validate, plan and load workspace files with the LibTmux.Workspace module. [`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. 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/) --- # 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. 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/#install). 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/b06c64f844f3173de66b187eaeaf3915814318c6/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/b06c64f844f3173de66b187eaeaf3915814318c6/tests/fixtures/workspace/tmuxp-v1.74.0-skip-send.yaml) cover pending text and execution after an explicit Enter. Set `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/b06c64f844f3173de66b187eaeaf3915814318c6/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` 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` 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 ``` 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"`. 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/b06c64f844f3173de66b187eaeaf3915814318c6/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/