LibTmux.FSharp 0.0.0-alpha.17

Prefix Reserved
This is a prerelease version of LibTmux.FSharp.
dotnet add package LibTmux.FSharp --version 0.0.0-alpha.17
                    
NuGet\Install-Package LibTmux.FSharp -Version 0.0.0-alpha.17
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LibTmux.FSharp" Version="0.0.0-alpha.17" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LibTmux.FSharp" Version="0.0.0-alpha.17" />
                    
Directory.Packages.props
<PackageReference Include="LibTmux.FSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add LibTmux.FSharp --version 0.0.0-alpha.17
                    
#r "nuget: LibTmux.FSharp, 0.0.0-alpha.17"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package LibTmux.FSharp@0.0.0-alpha.17
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=LibTmux.FSharp&version=0.0.0-alpha.17&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=LibTmux.FSharp&version=0.0.0-alpha.17&prerelease
                    
Install as a Cake Tool

LibTmux.FSharp

Compose tmux from F# with task helpers, native sequences, and typed portable filters over the existing LibTmux objects. This package and the core share a repository, release version, and primary author in the libtmux organization.

build tmux matrix license

Run isolated tmux · Connect to running tmux · Filter snapshots · Read control events

A portable relation filter is an F# value after installing the package below:

open LibTmux.FSharp

let sessionsWithCommands commands =
    Filter.oneOf commands PaneFields.currentCommand
    |> Filter.any WindowFields.panes
    |> Filter.any SessionFields.windows

let editorFilter = sessionsWithCommands [ "nvim"; "vim" ]

printfn "capture depth: %A" (Filter.toDocument editorFilter).RequiredSnapshotDepth

This prints capture depth: Panes. The filter describes sessions containing an editor pane; constructing it makes no tmux call. The complete example below creates a server, captures its object graph, and applies a filter.

Alpha API: pin a package version and upgrade deliberately. The walkthrough uses .NET SDK 10 and tmux 3.2a through 3.7c on Linux or macOS. The package targets net8.0 and net10.0.

Quick start

Install tmux and make sure it is available on PATH.

Create an F# console project:

$ dotnet new console --language F# --framework net8.0 --output tmux-demo

Enter it:

$ cd tmux-demo

Add the F# package; it brings in the matching LibTmux core package and records the selected prerelease version in the project:

$ dotnet package add LibTmux.FSharp --prerelease

Replace Program.fs with this complete program:

open System
open System.Threading
open LibTmux
open LibTmux.FSharp

let runAsync () =
    task {
        let binary =
            match Environment.GetEnvironmentVariable("LIBTMUX_TMUX") with
            | null
            | "" -> "tmux"
            | value -> value

        let options =
            ServerConnectionOptions(
                SocketName = "fsharp-" + Guid.NewGuid().ToString("N"),
                ConfigurationFile = "/dev/null",
                TmuxBinaryPath = binary
            )

        use! ownedServer = LibTmux.Server.CreateOwnedAsync(options, CancellationToken.None)

        use! _ownedSession =
            ownedServer.Value.CreateOwnedSessionAsync(
                NewSessionRequest(Name = "demo", WindowName = "shell", Command = "/bin/sh"),
                CancellationToken.None
            )

        use! _ownedWorker =
            ownedServer.Value.CreateOwnedSessionAsync(
                NewSessionRequest(Name = "worker", WindowName = "idle", Command = "/bin/sh"),
                CancellationToken.None
            )

        let! connected = LibTmux.Server.ConnectAsync(options, CancellationToken.None)

        let! captured =
            connected |> Server.capture CancellationToken.None SnapshotDepth.Panes

        let session =
            captured.Sessions |> Seq.find (fun candidate -> candidate.Name = "demo")

        let window = session.Windows |> Seq.exactlyOne
        let pane = window.Panes |> Seq.exactlyOne

        let command =
            pane
            |> Pane.currentCommand
            |> Option.defaultWith (fun () -> failwith "The captured pane has no command.")

        let localMatches =
            captured.Panes
            |> Seq.filter (fun candidate -> candidate.Id = pane.Id)
            |> Seq.length

        let hasPane =
            Filter.eq pane.Id PaneFields.id
            |> Filter.any WindowFields.panes
            |> Filter.any SessionFields.windows

        let selected =
            captured.Sessions
            |> Query.matching hasPane
            |> Selection.exactlyOne
            |> Result.defaultWith (fun error -> failwithf "Expected one matching session: %A" error)

        if
            captured.Sessions.Count <> 2
            || captured.Panes.Count <> 2
            || window.Name <> "shell"
            || localMatches <> 1
            || selected.Id <> session.Id
        then
            failwith "The captured graph and portable filter did not agree."

        printfn "%s / %s / %s" session.Name window.Name command
        printfn "local pane matches: %d" localMatches
        printfn "portable match: %s" selected.Name
    }

runAsync().GetAwaiter().GetResult()

Run it:

$ dotnet run

It prints demo / shell / sh, local pane matches: 1, and portable match: demo on the Linux tmux used for validation. The captured command name can differ by shell. The program checks the graph and query result before printing. A second worker session also runs a shell; filtering by the captured pane ID selects one session from two.

CreateOwnedAsync starts a server on a unique socket. ConnectAsync attaches a second handle to that socket. use! closes the owned sessions and server when the task ends. Server.capture performs one explicit snapshot acquisition. Traversal through captured.Sessions → session.Windows → window.Panes, Seq.filter, and Query.matching then use captured data locally. The portable filter matches a session through its windows and panes. It does not send a native tmux filter.

The quickstart source is the published block. CI restores only LibTmux.FSharp as a direct package reference from freshly packed artifacts, then runs this program against real tmux on both target frameworks.

Existing tmux

The quickstart's ConnectAsync(options, ct) attaches to a running server by socket name. In an application, use your server's socket name and omit the owned setup. ConnectAsync never starts tmux. A bare ConnectAsync() resolves the default socket; socket selection explains the configuration order. Code running inside a tmux pane can use Server.FromEnvironment() to locate that pane's server.

Choose a read

Need F# call Result
Live state server.GetSessionsAsync(ct) or Server.capture ct depth server Task; contacts tmux
Application-specific local filter captured.Panes |> Seq.filter predicate Lazy sequence over captured objects
Portable relation filter Filter.any then Query.matching Materialized IReadOnlyList; no tmux call
A missing live entity Server.tryFindPane ct id server Task<Pane option>; other failures still throw
Exactly one match Selection.exactlyOne source Result distinguishing zero from many

Captured sessions, windows, panes, and IDs are the core .NET types. A window linked into more than one session has contextual placements; filtering keeps their order and multiplicity. An uncaptured relationship raises IncompleteSnapshotException rather than behaving as empty.

Keep going

Compatibility

Area Contract and verification
.NET Targets .NET 8 and .NET 10 and uses the matching LibTmux package version.
tmux Required Linux CI runs the repository's F# integration example against tmux 3.2a, 3.3a, 3.4, 3.5, 3.6, 3.7a, 3.7b, and 3.7c on both target frameworks. The README quickstart runs against the runner's tmux in the package workflow.
Operating systems Linux is required CI. An advisory macOS arm64 job runs the example with Homebrew tmux on manual dispatch. Native Windows tmux is unsupported.
Trimming and NativeAOT A Linux consumer publishes and runs the static snapshot and native Seq route on both frameworks.

Selection.exactlyOne is unsupported under NativeAOT while FSharp.Core 10.1.302 emits trim and AOT diagnostics for its Result return type.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.0-alpha.17 38 9/27/2026

Alpha. LibTmux, LibTmux.FSharp, LibTmux.Testing, LibTmux.Query.Json, LibTmux.Extensions.DependencyInjection, LibTmux.Workspace, LibTmux.Workspace.Cli and LibTmux.Mcp share one version, so this release covers them together. What changed, per package and per release: https://github.com/libtmux/libtmux-dotnet/blob/master/CHANGELOG.md The public API is not settled and may change without notice between prereleases; pin an exact version.