Skip to content

About

Native PowerShell cmdlets for tmux sessions, windows and panes, with workspace planning. Built on LibTmux for .NET.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

libtmux for PowerShell

libtmux for PowerShell

Drive 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, in the same libtmux organization and with the same main author. The cmdlets return its native objects and add PowerShell parameter binding, help, formatting and -WhatIf / -Confirm.

Install · Object graph · Run to completion · Service readiness · Execution modes · Guides · MCP · Compatibility · Troubleshooting · Cmdlet reference · License

Alpha. APIs may change. Both modules are available on PowerShell Gallery: LibTmux and 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 for the support contract.

Run these commands in PowerShell. Install the core module for sessions, windows, panes, snapshots, input and capture:

$ 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:

$ Install-PSResource -Name LibTmux.Workspace `
    -Version 0.1.0-alpha2 `
    -Prerelease `
    -Repository PSGallery `
    -Scope CurrentUser `
    -TrustRepository

PowerShellGet is an alternative. Install the core module:

$ Install-Module -Name LibTmux -AllowPrerelease

Or install the workspace module with its matching core dependency:

$ 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.

Import both modules to run all the examples on this page:

$ 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.

Build 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.

$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.

$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 contain native LibTmux.Window objects; each window's Panes contain native LibTmux.Pane objects. The graph is still readable after cleanup:

Expression Captured result
$captured A Session named demo
$captured.Windows Two Window objects: editor and logs
$captured.Windows[0].Panes Two Pane objects in editor; logs has one

Walk it and filter locally:

$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 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:

$captured.Windows |
    Select-TmuxWindow -Criteria @{ 'Panes.Count' = @{ Ge = 2 } } -ExactlyOne

This query also performs no I/O. The query guide 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:

& {
    $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 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:

& {
    $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 for stop patterns, bounded tails, cancellation and disclosed event loss. Use a cooperative channel 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
Run a shell command and check its exit status Invoke-TmuxPaneCommand Run to completion
Wait for a running application's readiness line Wait-TmuxPaneText Readiness and an HTTP health check
Enter a session interactively Enter-TmuxSession Attach your foreground terminal
Run an ordered batch New-TmuxCommand → Invoke-TmuxChain Compose commands
Reuse a connected client Connect-TmuxControl → Invoke-TmuxControlCommand Control commands and cleanup
React to output and notifications Watch-TmuxEvent Bounded event streams
Keep the prompt available Start-ThreadJob Bounded background jobs
Run commands concurrently ForEach-Object -Parallel Independent clients

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:

& {
    $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 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 explains when chains merge failure attribution.

Modules and MCP

Product Use it for
LibTmux Typed cmdlets, snapshots, input, capture, control clients and event streams
LibTmux.Workspace Discover YAML/JSON declarations, resolve directories, review plans and create workspaces
LibTmux.Mcp 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:

$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:

$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 only in a trusted terminal:

$workspacePlan.Actions

Preview without applying the plan:

$workspacePlan | LibTmux.Workspace\Invoke-TmuxWorkspace -WhatIf

Apply that exact plan, then remove only the session it created. The captured result remains readable after cleanup:

$workspaceResult = & {
    $result = $workspacePlan |
        LibTmux.Workspace\Invoke-TmuxWorkspace -Confirm:$false -ErrorAction Stop
    try { $result } finally {
        $result.Session | Remove-TmuxSession -Confirm:$false
    }
}
$workspaceResult.Windows |
    Select-Object Name, @{ Name = 'PaneCount'; Expression = { $_.Panes.Count } }

This returns editor with two panes. The workspace guide covers failure recovery, attaching and exporting a declaration. For an MCP client, start with the client configuration, then read tools/list and tmux://capabilities before calling list_sessions or capture_pane.

Install both PowerShell modules at the same version. The MCP server is an independent .NET tool and does not require PowerShell.

Guides

The marked README blocks run together in the installed workflow test. The executable guides run against real tmux through the installed modules. See contributing for the runners and development checks.

The benchmark guide 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 with mise:

$ mise install

Install tmux with your operating system's package manager and check that it is on PATH:

$ tmux -V

From the checkout root, restore the published .NET alpha.20 packages and build both PowerShell modules:

$ 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. Start PowerShell with the staged module path:

$ 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:

$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 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:

(./examples/QuickStart.ps1).Windows | Select-Object Name, @{
    Name = 'PaneIds'
    Expression = { $_.Panes.Id -join ', ' }
}

Output from the private server:

Name   PaneIds
----   -------
editor %0, %1
logs   %2

Assign ./examples/QuickStart.ps1 to a variable to keep the session object. Its Windows and Panes remain readable after the script removes its session. The script uses a unique socket and leaves your default tmux server alone.

License

MIT. See third-party notices for bundled dependencies.

About

Native PowerShell cmdlets for tmux sessions, windows and panes, with workspace planning. Built on LibTmux for .NET.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages