# libtmux for C# > The C# library (LibTmux). These pages include its guides, tested examples and API documentation. - [C# API reference](https://libtmux.org/en/csharp/latest/reference/): every public symbol, generated from the source. Hosted on libtmux.org. --- # tmux MCP for C# Source: https://libtmux.org/en/csharp/latest/mcp/ > Run LibTmux.Mcp as a .NET tool with bounded results and a selectable tool catalog. [`LibTmux.Mcp`]() is a .NET tool package whose executable is `libtmux-mcp`. It serves tmux tools and a static capability resource over standard input and output. The tool targets .NET 8 and .NET 10 and requires a POSIX host with tmux. Its registered operations include `capture_pane`, `run_shell_command`, and `capture_since`. ## Toolsets Use `LIBTMUX_TOOLSETS=inspect` for discovery and terminal reads. Additional toolsets enable changes, execution, and teardown. The [tool-selection topic](https://libtmux.org/en/csharp/latest/mcp/topics/tool-selection/) explains exact-name filters, defaults, and the capability resource. The [complete examples](https://libtmux.org/en/csharp/latest/mcp/examples/) include project files and cleanup for their owned tmux servers. [Workspace Manager](https://libtmux.org/en/csharp/latest/workspace/) is the separately packaged [`LibTmux.Workspace`]() library. The MCP catalog does not include a workspace-file operation. [Package contract](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Mcp/README.md). - [Tools](https://libtmux.org/en/csharp/latest/mcp/tools/): Every MCP operation, with its arguments and results. - [Guides](https://libtmux.org/en/csharp/latest/mcp/guides/): Install the tool, choose a socket, and verify the client's connection. - [Topics](https://libtmux.org/en/csharp/latest/mcp/topics/): Tool selection, command waits, capture limits, and cancellation. - [Examples](https://libtmux.org/en/csharp/latest/mcp/examples/): Complete clients for session inspection and bounded command execution. - [Language API](https://libtmux.org/en/csharp/latest/mcp/reference/): Embedding and implementation types. --- # C# MCP API Source: https://libtmux.org/en/csharp/latest/mcp/reference/ > Find the C# server composition API and current MCP protocol catalog. For MCP client requests, use the [tool reference](https://libtmux.org/en/csharp/latest/mcp/tools/). This page covers language APIs for embedding or extending the server. [`LibTmux.Mcp`]() is distributed as a .NET tool package. Installing its executable does not provide a NuGet library reference for embedding. ## Source API [`McpServerComposition.Add`]() registers the server in a service collection and returns the MCP builder for transport composition. It accepts the connection options, caller pane ID, and a [`ServerPolicy`]() containing wait and output limits. The public overload selects tools without teardown. Tool handlers are internal implementation details. [Composition source](https://github.com/libtmux/libtmux-dotnet/blob/320dc64f4b8b7815842471327a5e6b84a1499bf8/src/LibTmux.Mcp/McpServerComposition.cs). ## Protocol API The [tool reference](https://libtmux.org/en/csharp/latest/mcp/tools/) uses names such as `capture_pane` and `run_shell_command`. Results provide structured content and bounded text. Read `tmux://capabilities` for the startup-frozen selection. The current surface has no workflow prompts or dynamic resource templates. For the separately published configuration library, see [Workspace builder API](https://libtmux.org/en/csharp/latest/workspace/reference/). ## API declarations - [LibTmux.Mcp.ActionResult](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-actionresult/) - [LibTmux.Mcp.BoundedText](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-boundedtext/) - [LibTmux.Mcp.CaptureResult](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-captureresult/) - [LibTmux.Mcp.ChannelWaitResult](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-channelwaitresult/) - [LibTmux.Mcp.EnvironmentEntry](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-environmententry/) - [LibTmux.Mcp.HookEntry](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-hookentry/) - [LibTmux.Mcp.KeyStep](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-keystep/) - [LibTmux.Mcp.LibTmuxMcp](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-libtmuxmcp/) - [LibTmux.Mcp.MatchedLine](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-matchedline/) - [LibTmux.Mcp.McpServerComposition](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-mcpservercomposition/) - [LibTmux.Mcp.OptionEntry](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-optionentry/) - [LibTmux.Mcp.PaneInfo](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-paneinfo/) - [LibTmux.Mcp.PaneInputResult](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-paneinputresult/) - [LibTmux.Mcp.PaneMatch](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-panematch/) - [LibTmux.Mcp.PaneSnapshot](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-panesnapshot/) - [LibTmux.Mcp.RunResult](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-runresult/) - [LibTmux.Mcp.SearchResult](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-searchresult/) - [LibTmux.Mcp.ServerInstructions](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-serverinstructions/) - [LibTmux.Mcp.ServerPolicy](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-serverpolicy/) - [LibTmux.Mcp.SessionInfo](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-sessioninfo/) - [LibTmux.Mcp.TailResult](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-tailresult/) - [LibTmux.Mcp.TmuxConnectionAccessor](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-tmuxconnectionaccessor/) - [LibTmux.Mcp.TmuxServerInfo](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-tmuxserverinfo/) - [LibTmux.Mcp.WaitOutcome](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-waitoutcome/) - [LibTmux.Mcp.WaitResult](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-waitresult/) - [LibTmux.Mcp.WindowInfo](https://libtmux.org/en/csharp/latest/mcp/reference/libtmux-mcp-windowinfo/) [Protocol catalog](https://libtmux.org/en/csharp/latest/mcp/tools.json) --- # C# workspace manager Source: https://libtmux.org/en/csharp/latest/workspace/ > Describe a tmux session in a file, then load, inspect and capture it. **Workspace Manager for C# is in development.** The `tmux-workspace` CLI is published to NuGet as a prerelease. Pin its version when automation depends on its output. `tmux-workspace` creates tmux sessions from YAML or JSON. A file describes windows, panes, commands, directories and environment. Load it from a terminal or request machine output for automation. ## Load a workspace from the terminal 1. [Install the command and load a workspace](https://libtmux.org/en/csharp/latest/workspace/guides/installation/). 2. [Configure windows and panes](https://libtmux.org/en/csharp/latest/workspace/configuration/). 3. [Capture and reload a session](https://libtmux.org/en/csharp/latest/workspace/guides/export-session/). The [CLI manual](https://libtmux.org/en/csharp/latest/workspace/cli/) covers discovery, search, editing, loading, capture, conversion and import. [Examples](https://libtmux.org/en/csharp/latest/workspace/examples/gallery/) provide complete configurations with their prerequisites. ## Automate and inspect Use `load -d` when the caller should return without attaching. `--json` returns a result, and `--ndjson` supports a stream of records. Read [automation](https://libtmux.org/en/csharp/latest/workspace/guides/automation/) for retry and cleanup decisions and [errors](https://libtmux.org/en/csharp/latest/workspace/reference/exit-codes/) for failure handling. Loaded workspaces are ordinary tmux sessions. Select the same socket when inspecting them from tmux or the [MCP server](https://libtmux.org/en/csharp/latest/mcp/). ## Build from application code The [workspace library](https://libtmux.org/en/csharp/latest/workspace/internals/) has its own API and configuration contract. Use it when a program needs direct control over construction. The CLI task guides here describe the `tmux-workspace` executable and link to its documented source revision. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). - [CLI Manual](https://libtmux.org/en/csharp/latest/workspace/cli/): Commands, options and machine output. - [Configuration](https://libtmux.org/en/csharp/latest/workspace/configuration/): Workspace fields, normalization and execution. - [Install and load](https://libtmux.org/en/csharp/latest/workspace/guides/installation/): Load a workspace on a private socket, then capture it. - [Example gallery](https://libtmux.org/en/csharp/latest/workspace/examples/gallery/): Workspace files to start from, with their prerequisites. - [Runtime support](https://libtmux.org/en/csharp/latest/workspace/reference/compatibility/): Runtime requirements and supported behavior. - [Internals](https://libtmux.org/en/csharp/latest/workspace/internals/): The workspace library, for building sessions from code. --- # Load a workspace Source: https://libtmux.org/en/csharp/latest/workspace/cli/load/ > Create or reuse a session from a workspace file, with explicit attachment and output choices. Load a saved configuration into tmux. Use `-d` for scripts so the command returns after construction without attaching a terminal. Command delivery does not mean the programs running in those panes have finished or become ready. ## Load without attaching Continue the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/) with its [`workspace.yaml`](https://libtmux.org/en/csharp/latest/workspace/guides/installation/#create-the-input) and private socket: ```console $ tmux-workspace load \ -S "$WORKSPACE_TMP/tmux.sock" \ -f /dev/null \ -d \ --json \ workspace.yaml ``` `-S` selects the socket path; `-L` selects a socket name. `-f` supplies tmux's configuration when starting a server. Keep the same endpoint for later capture, inspection and cleanup. Pass `-s another-name` to override the final input's session name. ## Existing sessions and append A session with the requested name is reused. Loading is not a reconciliation operation that removes extra windows. Inspect a failed result before retrying: earlier inputs and changes to a borrowed session can remain. Inside tmux, `--append` adds windows to the invoking pane's session. It needs valid `TMUX` and `TMUX_PANE` values for the selected daemon. Use `-d` when loading onto a different server. Multiple inputs are processed in their supplied order. ## Attachment and output Human loading can attach a terminal or switch a tmux client. For automation, choose `-d` or an authenticated append explicitly; machine output does not answer interactive questions. `--yes` accepts supported confirmations. `--json` returns a result; `--ndjson` emits records as work proceeds. Read [output](https://libtmux.org/en/csharp/latest/workspace/reference/output/) and [errors](https://libtmux.org/en/csharp/latest/workspace/reference/exit-codes/) before consuming those records. `--no-progress` disables the terminal display; it does not disable errors. `-2` requests 256-color handling from tmux. Use [configuration](https://libtmux.org/en/csharp/latest/workspace/configuration/) for fields and [hooks](https://libtmux.org/en/csharp/latest/workspace/configuration/hooks/) for bootstrap scripts and extensions. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Capture a workspace Source: https://libtmux.org/en/csharp/latest/workspace/cli/freeze/ > Capture a running tmux session as a starting point for a workspace file. Capture a running tmux session as a starting point for a workspace file. Capture reads live state. It cannot recover original command arguments, command history, script definitions or plugin intent. ## Inspect a session After the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/) creates `workspace-guide`, request a machine result from its private socket: ```console $ tmux-workspace freeze \ -S "$WORKSPACE_TMP/tmux.sock" \ --json \ workspace-guide ``` ## Save the captured document Name the destination and format explicitly: ```console $ tmux-workspace freeze \ -S "$WORKSPACE_TMP/tmux.sock" \ --json \ --workspace-format yaml \ --save-to captured-workspace.yaml \ workspace-guide ``` Use a new destination, or pass `--force` to authorize replacement. Review captured commands and directories before loading the file on another machine. The saved document encoding is separate from the CLI result format selected by `--json` or `--ndjson`. See [export and reload](https://libtmux.org/en/csharp/latest/workspace/guides/export-session/) for the complete workflow. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Convert workspace files Source: https://libtmux.org/en/csharp/latest/workspace/cli/convert/ > Convert a complete workspace document between YAML and JSON. Convert a complete workspace document between YAML and JSON. Conversion preserves mapping fields; it does not establish that every field can be loaded. ## Inspect the result Start with [`workspace.yaml`](https://libtmux.org/en/csharp/latest/workspace/guides/installation/#create-the-input) from the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/): ```console $ tmux-workspace convert --json workspace.yaml ``` Without a destination, machine mode returns the converted document in its result. YAML comments and textual formatting do not survive conversion to JSON. ## Save a file Choose an explicit destination and encoding: ```console $ tmux-workspace convert \ --json \ --workspace-format json \ --save-to workspace.json \ workspace.yaml ``` Replacing an existing destination requires `--force`. Keep that choice separate from `--yes`, which answers prompts. Review the result before [loading it](https://libtmux.org/en/csharp/latest/workspace/cli/load/). [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Edit a workspace Source: https://libtmux.org/en/csharp/latest/workspace/cli/edit/ > Resolve a workspace file or saved name and open it in an editor. Resolve a workspace file or saved name and open it in an editor. Use an explicit path when editing a particular file. ## Open the file With `vi` installed and [`workspace.yaml`](https://libtmux.org/en/csharp/latest/workspace/guides/installation/#create-the-input) saved: ```console $ EDITOR=vi tmux-workspace edit workspace.yaml ``` The CLI waits for the editor and reports a failed child through its exit status. Editor values can contain quoted arguments. They are parsed as an argument list; shell pipelines and redirection require an explicit shell or wrapper. [Discovery](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/) explains saved workspace names. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Inspect runtime diagnostics Source: https://libtmux.org/en/csharp/latest/workspace/cli/debug-info/ > Collect the workspace CLI runtime, configuration and tmux diagnostics.. Collect the workspace CLI runtime, configuration and tmux diagnostics. ## Collect a report ```console $ tmux-workspace debug-info --json ``` Review the report before sharing it. Paths, session names and raw tmux values can describe your environment even when home-directory prefixes are redacted. Use the failed command exit status and stderr to diagnose its actual failure. See [troubleshooting](https://libtmux.org/en/csharp/latest/workspace/guides/troubleshooting/) and the [machine output reference](https://libtmux.org/en/csharp/latest/workspace/reference/output/). [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # List saved workspaces Source: https://libtmux.org/en/csharp/latest/workspace/cli/ls/ > List the workspace files found in project and global configuration locations. List the workspace files found in project and global configuration locations. Listing does not load sessions or run pane commands. ## List records ```console $ tmux-workspace ls --json ``` Include each document configuration: ```console $ tmux-workspace ls --full --json ``` For a human display grouped by directory, use `--tree`: ```console $ tmux-workspace ls --tree ``` Machine output preserves record values and has its own structure; do not parse the human tree. See [discovery](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/) for the locations searched and [output](https://libtmux.org/en/csharp/latest/workspace/reference/output/) for the result format. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Search workspaces Source: https://libtmux.org/en/csharp/latest/workspace/cli/search/ > Search the fields of discovered workspace documents. Search the fields of discovered workspace documents. Use literal matching when the input should be treated as text rather than a regular expression. ## Find a session name ```console $ tmux-workspace search \ --json \ --fixed-strings \ --field session \ workspace ``` Repeat `--field` to restrict additional fields. Query terms combine with AND; `--any` selects OR. `--ignore-case`, `--smart-case`, `--word-regexp`, and `--invert-match` control matching. Inspect the installed `search --help` for supported field names and aliases. Check both the exit status and [machine result](https://libtmux.org/en/csharp/latest/workspace/reference/output/). An empty successful search and a failed pattern are different outcomes. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Evaluate in a workspace Source: https://libtmux.org/en/csharp/latest/workspace/cli/shell/ > Use the optional Python runtime to inspect a workspace through the native command. `tmux-workspace shell` opens the optional Python inspection environment for a loaded session. Code passed to `-c` executes in that environment, with tmux objects such as `server`, `session`, `window` and `pane` available. ## Runtime requirement Install tmuxp 1.74.0 in a separate Python environment and set `TMUX_WORKSPACE_PYTHON` to that environment's Python executable. The native CLI checks the runtime before evaluating code. Ordinary workspace loading does not require this inspection runtime. ## Evaluate with a selected server Continue the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/) through its detached load. Select its socket, session and window: ```console $ tmux-workspace shell \ -S "$WORKSPACE_TMP/tmux.sock" \ -c 'print(pane.pane_id)' \ --json \ workspace-guide editor ``` The result includes captured output and child status. Check the command's exit status before consuming it. An interactive shell needs a terminal; use `-c` when stdout belongs to automation. `shell --help` lists backend and startup choices. Optional shell backends must be installed in the selected Python environment. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Import a workspace Source: https://libtmux.org/en/csharp/latest/workspace/cli/import/ > Choose a source format and translate it into a workspace document. Translate a saved Teamocil or tmuxinator configuration into a native workspace document. Import reads and translates the file without creating tmux sessions or running its pane commands. - [Teamocil](https://libtmux.org/en/csharp/latest/workspace/cli/import-teamocil/) translates a session with named windows and panes. - [tmuxinator](https://libtmux.org/en/csharp/latest/workspace/cli/import-tmuxinator/) translates a project with ordered windows. ```console $ tmux-workspace import --help ``` Select a child command and an explicit source path. Preview with `--json` before choosing `--save-to`. An existing destination requires `--force`. Review commands, directories and layout in the translated document before loading it. Source features the importer cannot preserve fail visibly. Use [convert](https://libtmux.org/en/csharp/latest/workspace/cli/convert/) to change YAML/JSON encoding without translating fields. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Import from Teamocil Source: https://libtmux.org/en/csharp/latest/workspace/cli/import-teamocil/ > Translate Teamocil windows and pane commands into a workspace document. Import a Teamocil file without starting tmux. Save this source as `teamocil.yaml`: ```yaml title="teamocil.yaml" session: name: imported-team windows: - name: editor layout: even-horizontal panes: - commands: [printf ready] - commands: [printf second] ``` ## Preview the translation ```console $ tmux-workspace import teamocil --json ./teamocil.yaml ``` The translated document preserves window and pane order. Several commands in one Teamocil `commands` list become one semicolon-separated shell input in that pane. Review the absolute working directories selected by the import. ## Save the workspace ```console $ tmux-workspace import teamocil \ --json \ --workspace-format yaml \ --save-to imported-teamocil.yaml \ ./teamocil.yaml ``` Use `--force` only to replace an existing destination deliberately. Unsupported fields, such as pane widths and filters, fail before saving. Conversion does not prove that a command or directory will be available when you [load](https://libtmux.org/en/csharp/latest/workspace/cli/load/) the result. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Import from tmuxinator Source: https://libtmux.org/en/csharp/latest/workspace/cli/import-tmuxinator/ > Translate a tmuxinator project into a workspace document. Import a saved tmuxinator project without starting tmux. Save this source as `tmuxinator.yaml`: ```yaml title="tmuxinator.yaml" name: imported-project windows: - editor: - printf ready - printf second ``` ## Preview the translation ```console $ tmux-workspace import tmuxinator --json ./tmuxinator.yaml ``` The window's command list remains sequential commands in one pane. Use an explicit source `panes` list when the project needs separate panes. ## Save the workspace ```console $ tmux-workspace import tmuxinator \ --json \ --workspace-format yaml \ --save-to imported-tmuxinator.yaml \ ./tmuxinator.yaml ``` Existing destinations require `--force`. The importer rejects unexpanded ERB templates and unsupported lifecycle or runtime fields before writing. It does not evaluate Ruby. Review the translated commands and absolute directories before [loading](https://libtmux.org/en/csharp/latest/workspace/cli/load/) the file. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # tmux-workspace CLI manual Source: https://libtmux.org/en/csharp/latest/workspace/cli/ > Use `tmux-workspace` to load, inspect and save workspace files. Use `tmux-workspace` to load, inspect and save workspace files. Complete [installation](https://libtmux.org/en/csharp/latest/workspace/guides/installation/) and put the executable on `PATH` before using these commands. ## Sessions
load
Create a session from a workspace file.
freeze
Capture a running session into a workspace document.
## Workspace files
ls
List saved configurations.
search
Find saved configurations.
edit
Open a configuration in your editor.
convert
Change a document between YAML and JSON.
import
Translate Teamocil or tmuxinator configuration.
## Diagnostics and completion
debug-info
Report runtime and tmux information.
completion
Generate completion for your shell.
## Command options Show the options accepted by the installed command: ```console $ tmux-workspace load --help ``` ## Machine output `--json` requests one JSON result. `--ndjson` requests a stream of records and takes precedence when both are present. Select detached loading with `-d` when automating session creation. Check the exit status as well as the result; a failed load can leave completed tmux operations in place. The [output reference](https://libtmux.org/en/csharp/latest/workspace/reference/output/) describes the result records, and [automation](https://libtmux.org/en/csharp/latest/workspace/guides/automation/) covers scripts. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Shell completion Source: https://libtmux.org/en/csharp/latest/workspace/cli/completion/ > Generate completion for the installed workspace command. Generate completion using the installed `tmux-workspace` command. The script matches that executable's command definitions. ## Enable Bash completion ```console $ tmux-workspace --generate bash > tmux-workspace.bash ``` Check the generated script before loading it in your current Bash session: ```console $ bash -n tmux-workspace.bash ``` ```bash source ./tmux-workspace.bash ``` Keep the script in your shell's completion directory to load it in later sessions. Regenerate it after upgrading the CLI. ## Other shells `--generate zsh` and `--generate fish` generate the other supported shells. Follow the selected shell's completion setup before sourcing its script. Generating a script does not start tmux or load workspace files. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Concepts Source: https://libtmux.org/en/csharp/latest/concepts/ > tmux objects, command transports, queries, and workspaces. libtmux lets you create sessions, arrange windows and panes, send commands, and read output from tmux. Start with the object hierarchy, then read about the transport, query, or workspace behavior your program needs. Use the API reference for signatures, defaults, and failure conditions. - [Server, session, window, pane](https://libtmux.org/en/csharp/latest/concepts/server-session-window-pane/): Understand the tmux object hierarchy and attached clients. - [Control mode vs one-shot](https://libtmux.org/en/csharp/latest/concepts/transports/): Choose subprocess commands, persistent connections, and batching. - [Filtering and queries](https://libtmux.org/en/csharp/latest/concepts/queries/): Find objects and handle absent or ambiguous matches. - [Workspaces](https://libtmux.org/en/csharp/latest/concepts/workspaces/): Build pane layouts from code or configuration files. --- # Server, session, window, pane Source: https://libtmux.org/en/csharp/latest/concepts/server-session-window-pane/ > How tmux servers, sessions, windows, panes and attached clients relate to each other. libtmux models tmux's server, session, window, and pane objects: ``` Server ├── Session │ └── Window │ └── Pane └── Client (attached view) ``` A [`Server`]() contains sessions. Each [`Session`]() contains links to windows, and each [`Window`]() contains panes. Commands run inside a [`Pane`](), where you send input and capture output. A window can be linked to more than one session. ## Stable identity, not name or index tmux assigns a unique ID to each session, window, and pane at creation. The ID remains stable for that object's lifetime even if its name or index changes: | Object | ID prefix | Example | |--------|-----------|---------| | Session | `$` | `$13` | | Window | `@` | `@3243` | | Pane | `%` | `%5433` | | Server | - | identified by socket name or path instead | Use stable IDs to identify the same tmux object across reads. Names and indexes can change while a program is running. Read the hierarchy: ```csharp foreach (Session session in await server.GetSessionsAsync()) { Console.WriteLine(session.Name); foreach (Window window in await session.GetWindowsAsync()) { Console.WriteLine($" {window.Index} {window.Name}"); foreach (Pane pane in await window.GetPanesAsync()) { Console.WriteLine($" {pane.Index} {pane.Width}x{pane.Height}"); } } } ``` ## Client: a view, not a child A [`Client`]() represents a terminal attached to a session. Several clients can view the same server, and each can switch sessions or windows independently. Client fields describe the view at the time of the read. A [control-mode connection](https://libtmux.org/en/csharp/latest/concepts/transports/) is also a client. It appears in `list-clients`, counts toward `session_attached`, and affects attachment-dependent behavior such as `destroy-unattached`. Closing the last attached client can therefore destroy a session configured with that option. --- # Control mode vs one-shot Source: https://libtmux.org/en/csharp/latest/concepts/transports/ > Choose subprocesses, command batches, or persistent connections to send commands and receive events. libtmux sends commands to tmux through subprocesses or persistent control-mode connections. tmux also accepts several commands in one invocation: 1. **One-shot subprocess.** Each command spawns a fresh `tmux` process, which sends the request to the server, prints the result, and exits. 2. **A persistent control-mode client.** `tmux -C attach-session` starts one long-lived tmux process that stays attached and speaks a line-oriented protocol over its stdout: commands go in, replies and asynchronous notifications (`%window-add`, `%output`, ...) come out, without starting a process per call. 3. **One invocation, several commands.** tmux accepts more than one command per invocation (`;`-joined, or one `-F`-tagged `list-*` per line). Grouping operations this way reduces process starts without opening a control-mode connection. ## Available transports The default one-shot mode runs commands through subprocesses. [`Server.Chain`]() groups commands, and [`EnterControlModeAsync`]() opens a persistent command connection. Choose based on whether you need command results, notifications, or a batch of changes. ## Notifications and commands are separable Use [`EnterControlModeAsync`]() for commands on a persistent connection. ## A control client is a real client A persistent control connection attaches a tmux client. It appears in `list-clients`, increments `session_attached`, and affects `destroy-unattached`, client hooks, and idle-client accounting. Each connection counts separately. ## Why fold several commands into one invocation Creating an object can require a second command to read its resulting state. Batching can reduce repeated reads and process starts. A [`Chain`]() groups operations without attaching a control client. ## What this costs in practice A persistent connection avoids starting a client for each command. A chain groups a known sequence into one invocation. For occasional commands, use the default subprocess transport; measure your workload before changing transports for performance. Use a notification stream when your program needs tmux events. ## Sending a command The example uses the subprocess API. See the reference for batching and control-mode setup. ```csharp using LibTmux; // One-shot: every call underneath this handle spawns a `tmux` process. Server server = await Server.ConnectAsync(); Session session = await server.CreateSessionAsync(new NewSessionRequest(name: "work")); Window window = (await session.GetWindowsAsync())[0]; Pane pane = (await window.GetPanesAsync())[0]; await pane.SendTextAsync("echo hello"); ``` To inspect tmux's control protocol, attach a control client: ```console $ tmux -C attach-session -t work ``` --- # Filtering and queries Source: https://libtmux.org/en/csharp/latest/concepts/queries/ > How you get from every session on the server to the one pane you mean, and what happens when zero or several match. Use a collection filter to find matching sessions, windows, or panes. Use an exactly-one lookup when your next operation requires a single target. - **Filtering returns a collection; exactly-one lookup checks the result count.** A filter returns zero or more matches. An exactly-one operation returns one object or reports a missing or ambiguous match. - **Choose where to filter.** Filter a snapshot in your program when you need several queries over the same data. A tmux format filter can reduce the rows returned by a live read. The cost depends on the data and queries you need. ## Typed and local filters Typed field operations let the compiler reject incompatible comparisons: Examples of typed and local filters: ```csharp IReadOnlyList windows = await session.GetWindowsAsync(ct); IEnumerable building = windows.Where( each => each.Name.StartsWith("build", StringComparison.Ordinal)); // A declarative query is a document, not just a lambda run in place. IReadOnlyList sessions = await server.GetSessionsAsync(ct); IReadOnlyList matched = sessions.Matching( session => session.Name.StartsWith("build", StringComparison.Ordinal)); ``` ## Result counts [Filtering and querying](https://libtmux.org/en/csharp/latest/guides/querying-and-filtering/) shows exactly-one lookups and their error handling. Do not index the first result until the operation has established that a match exists. --- # Workspaces Source: https://libtmux.org/en/csharp/latest/concepts/workspaces/ > Build pane layouts with the object API or a workspace configuration file. A workspace arranges windows and panes for a task, such as editing code, running a development server, and following logs. Build it with the object API when the layout depends on program logic. Use a declarative builder when you want to store the layout in a configuration file, such as [tmuxp](https://tmuxp.git-pull.com/) YAML or JSON. ## Building one imperatively Create a window, split it into panes, apply a layout, and send each pane its command: ```csharp Window window = await session.CreateWindowAsync(new NewWindowRequest(name: "dev")); Pane main = (await window.GetPanesAsync())[0]; Pane terminal = await main.SplitAsync(new SplitPaneRequest(percentage: 30)); Pane logs = await terminal.SplitAsync(new SplitPaneRequest(direction: PaneDirection.Right)); await window.SelectLayoutAsync(new SelectLayoutRequest("main-vertical")); ``` A split creates a pane; direction and size control its placement. Applying a layout rearranges existing panes while their processes continue running. tmux provides `even-horizontal`, `even-vertical`, `main-horizontal`, `main-vertical`, and `tiled` layouts. Choose detached creation when the user's current window should retain focus. Splits and resizes issue tmux commands; [Control mode vs one-shot](https://libtmux.org/en/csharp/latest/concepts/transports/) covers their transport costs and batching. ## Building one declaratively These packages read or build workspace configurations based on tmuxp: [`LibTmux.Workspace`]() reads tmuxp YAML. See [Workspace Manager](https://libtmux.org/en/csharp/latest/workspace/) for configuration fields and the CLI. ```csharp WorkspaceFile workspace = WorkspaceFile.Parse(yaml); WorkspaceResult result = await new WorkspaceBuilder(server).BuildAsync(workspace, ct); ``` ## Cleaning up An ownership scope kills its session when `await using` exits: ```csharp await using OwnedSessionScope scope = await server.CreateOwnedSessionAsync( new NewSessionRequest(name: "temp-session")); Window window = (await scope.Value.GetWindowsAsync())[0]; Pane pane = (await window.GetPanesAsync())[0]; await pane.SendTextAsync("echo temporary workspace"); // session is gone here, even if an exception unwound through the block ``` See [Context managers](https://libtmux.org/en/csharp/latest/topics/context-managers/) for cleanup support in each port. Use explicit kill methods when the handle does not provide scope-based cleanup. --- # Workspace configuration Source: https://libtmux.org/en/csharp/latest/workspace/configuration/ > Define the session, windows, panes and commands loaded by the workspace CLI. A workspace document describes one tmux session. Save this as `configuration.yaml`: ```yaml title="configuration.yaml" session_name: configuration-example windows: - window_name: editor layout: even-horizontal panes: - printf ready - null ``` Load it on the private socket from the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/): ```console $ tmux-workspace load \ -S "$WORKSPACE_TMP/tmux.sock" \ -d \ --json \ configuration.yaml ``` The CLI parses the document and validates its execution fields before creating windows and sending commands. YAML and JSON use the same field names. A successful load means construction and command delivery completed; pane applications can still be starting or failing independently. ## Choose the fields for your task - [Session](https://libtmux.org/en/csharp/latest/workspace/configuration/session/) sets the name, shared options and environment. - [Windows](https://libtmux.org/en/csharp/latest/workspace/configuration/windows/) sets indexes, layouts and option timing. - [Panes](https://libtmux.org/en/csharp/latest/workspace/configuration/panes/) defines commands, launch shells and focus. - [Commands](https://libtmux.org/en/csharp/latest/workspace/configuration/commands/) controls ordering, Enter and delays. - [Environment](https://libtmux.org/en/csharp/latest/workspace/configuration/environment/) separates loader settings from pane variables. - [Directories](https://libtmux.org/en/csharp/latest/workspace/configuration/directories/) explains discovery and working directories. - [Layouts](https://libtmux.org/en/csharp/latest/workspace/configuration/layouts/) arranges the panes. - [Hooks](https://libtmux.org/en/csharp/latest/workspace/configuration/hooks/) runs checked bootstrap programs and optional extensions. ## CLI and application code These pages describe the `tmux-workspace` executable. Application code uses the separate [workspace library](https://libtmux.org/en/csharp/latest/workspace/internals/), whose accepted fields and build semantics have their own contract. A successful generic [conversion](https://libtmux.org/en/csharp/latest/workspace/cli/convert/) preserves document values; it does not validate that a loader can execute them. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Session configuration Source: https://libtmux.org/en/csharp/latest/workspace/configuration/session/ > Name a workspace and apply session options and environment. Set `session_name` and an ordered, nonempty `windows` list. Use a simple name without tmux target separators such as `:` and `.`. ```yaml title="session.yaml" session_name: session-example environment: PROJECT_MODE: development options: status: false windows: - window_name: shell panes: [null] ``` ## Session fields | Field | Effect | | --- | --- | | `session_name` | Session to create or reuse | | `windows` | Windows to construct in order | | `start_directory` | Starting directory inherited by child configuration | | `environment` | Variables supplied to the workspace | | `options` | Options applied to this session | | `global_options` | Options applied globally on the selected tmux server | | `shell_command_before` | Commands prepended to each pane's commands | | `suppress_history` | History policy inherited by windows and panes | | `before_script` | Checked bootstrap process | | `workspace_builder_options` | Builder settings such as prompt readiness | Use `global_options` only when every session on that server should share the change. Select a private socket for examples and automated jobs. An existing session is reused under the loader's policy. Use `load -s NAME` when a second copy needs another name. Loading does not remove unrelated sessions or reconcile away extra windows. Read [environment](https://libtmux.org/en/csharp/latest/workspace/configuration/environment/), [commands](https://libtmux.org/en/csharp/latest/workspace/configuration/commands/) and [hooks](https://libtmux.org/en/csharp/latest/workspace/configuration/hooks/) for the behavior behind those fields. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Window configuration Source: https://libtmux.org/en/csharp/latest/workspace/configuration/windows/ > Set window names, indexes, layouts, options and focus. Each item in `windows` creates one window with its own ordered pane list. Set `window_index` when the tmux index matters independently of list position. ```yaml title="windows.yaml" session_name: windows-example windows: - window_name: tools window_index: 2 layout: even-horizontal focus: true options: automatic-rename: false options_after: synchronize-panes: true panes: - printf left - printf right ``` `options` applies during construction. `options_after` applies after initial pane commands, which is useful for enabling synchronized typing after each pane has received its own setup. Later input in a synchronized pane can reach the other panes in that window. ## Launch settings `start_directory` supplies a directory for panes that do not override it. `window_shell` supplies their launch command; a pane's `shell` overrides it. Set `environment` for a window-wide launch map and read [environment inheritance](https://libtmux.org/en/csharp/latest/workspace/configuration/environment/) before overriding it per pane. Use distinct explicit indexes. `focus: true` selects the window after building. An explicit [layout](https://libtmux.org/en/csharp/latest/workspace/configuration/layouts/) makes the intended arrangement clear across terminal sizes. [Pane configuration](https://libtmux.org/en/csharp/latest/workspace/configuration/panes/) controls each pane's contents. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Pane configuration Source: https://libtmux.org/en/csharp/latest/workspace/configuration/panes/ > Choose pane commands, launch settings and focus. Each entry in a window's `panes` list describes one pane. A string is a command; `null` leaves a blank shell pane. A mapping provides launch and command settings. ```yaml title="panes.yaml" session_name: panes-example windows: - window_name: work layout: even-horizontal panes: - null - shell: /bin/sh focus: true shell_command: - printf ready - printf second ``` The second pane launches `/bin/sh`, receives both commands in order and becomes the active pane. A command list inside one pane does not create extra panes. ## Overrides - `start_directory` overrides the inherited working directory. - `shell` overrides the window's launch command. - `environment` supplies the pane's launch environment map. - `shell_command_before` adds setup after session and window setup. - `enter`, `sleep_before` and `sleep_after` supply command defaults. - `suppress_history` overrides the inherited history policy. Set focus explicitly when automation depends on which pane is selected. Use returned pane IDs for later operations instead of assuming that creation order is a stable tmux ID. Read [commands](https://libtmux.org/en/csharp/latest/workspace/configuration/commands/) for Enter and delay behavior and [environment](https://libtmux.org/en/csharp/latest/workspace/configuration/environment/) for variable handling. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Workspace commands Source: https://libtmux.org/en/csharp/latest/workspace/configuration/commands/ > Order pane setup and command delivery, Enter handling and delays. `shell_command_before` adds setup for every affected pane. Setup is ordered from session to window to pane, followed by that pane's `shell_command` entries. ```yaml title="commands.yaml" session_name: commands-example shell_command_before: - printf session-setup windows: - window_name: shell shell_command_before: - printf window-setup panes: - shell_command_before: - printf pane-setup shell_command: - cmd: printf ready sleep_after: 0.01 - cmd: printf waiting enter: false sleep_after: 0 ``` The final command is typed without Enter. Delays are measured in seconds and pause delivery; they do not verify that an application is ready or that an earlier shell command succeeded. ## Enter and timing Pane-level `enter`, `sleep_before` and `sleep_after` establish defaults. Command mappings can change those defaults. An override carries to following commands in that pane until another override. Set an explicit value when later commands need to restore Enter or remove a delay. ## History and readiness History suppression prefixes sent commands with a space. The shell still needs its own setting to ignore leading-space commands, such as Bash's `HISTCONTROL=ignorespace` or zsh's `HIST_IGNORE_SPACE`. Prompt readiness delays initial input while a shell draws its prompt. It is separate from application readiness and command completion. Use a checked [before script](https://libtmux.org/en/csharp/latest/workspace/configuration/hooks/) for bootstrap work whose exit status must stop the load on failure. See [environment](https://libtmux.org/en/csharp/latest/workspace/configuration/environment/) before putting variable expressions in commands. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Workspace environment Source: https://libtmux.org/en/csharp/latest/workspace/configuration/environment/ > Configure the loader process and the variables available to pane commands. The CLI's process environment controls discovery and optional runtimes. Configuration `environment` maps provide variables to the workspace's shells. ```yaml title="environment.yaml" session_name: environment-example environment: DOC_SESSION: session windows: - window_name: shell environment: DOC_WINDOW: window panes: - environment: DOC_PANE: pane shell_command: 'printf "ENV=%s|%s|%s\n" "$DOC_SESSION" "$DOC_WINDOW" "$DOC_PANE"' - shell_command: 'printf "ENV=%s|%s|%s\n" "$DOC_SESSION" "$DOC_WINDOW" "$DOC_PANE"' ``` A pane map selects its launch environment in place of the window map. Session variables still apply. Repeat a window variable in the pane map when that pane needs it too. Avoid putting credentials in example files or diagnostic output. ## Variable expressions The loader expands defined variables in configuration values before delivery. An expression can therefore use the invoking process's value before the pane shell reads it. Use explicit configuration variables and inspect resulting commands when moving a workspace between environments. ## Loader settings | Variable | Use | | --- | --- | | `TMUXP_CONFIGDIR` | Preferred existing directory for saved workspaces | | `XDG_CONFIG_HOME` | Base for the `tmuxp` configuration directory | | `EDITOR` | Editor used by `edit` | | `TMUX_WORKSPACE_PYTHON` | Optional interpreter for [`shell`]() and supported extensions | | `NO_COLOR` | Disable terminal color when nonempty | These are process settings, not workspace YAML keys. Read [discovery](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/), [editing](https://libtmux.org/en/csharp/latest/workspace/cli/edit/) and [shell inspection](https://libtmux.org/en/csharp/latest/workspace/cli/shell/) for their task-specific behavior. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Files and directories Source: https://libtmux.org/en/csharp/latest/workspace/configuration/directories/ > Resolve saved workspace files and the working directories used by panes. Use an explicit file path when debugging workspace discovery. A directory such as `.` selects a project configuration; a saved name selects a global workspace. See [finding workspaces](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/) for that lookup order. ## Set a starting directory ```yaml title="directories.yaml" session_name: directories-example start_directory: ./ windows: - window_name: shell start_directory: ./ panes: - start_directory: ./ shell_command: pwd ``` An explicit relative session directory starts from the configuration file's directory. Child directories resolve through their parent configuration. Use absolute paths when a workspace deliberately points outside its project. Quote home shortcuts in YAML, such as `"~/src/project"`; an unquoted `~` is a null value. An omitted directory lets the loader and tmux use their invocation context. The explicit relative directory in this example selects the file's project context. ## Verify the running pane A saved path can be absent on another machine. Inspect the real pane directory after loading rather than relying on successful YAML parsing. tmux can fall back to a home directory when a requested path does not exist. Bootstrap paths and process working directories have separate rules. See [before scripts](https://libtmux.org/en/csharp/latest/workspace/configuration/hooks/) before using one to create directories. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Window layouts Source: https://libtmux.org/en/csharp/latest/workspace/configuration/layouts/ > Arrange panes with tmux layout names or a saved layout. Choose a layout for each window. `even-horizontal` gives panes equal widths: ```yaml title="layouts.yaml" session_name: layouts-example windows: - window_name: work layout: even-horizontal panes: [null, null, null] ``` Other common tmux names include `even-vertical`, `main-horizontal`, `main-vertical` and `tiled`. Full names avoid version-dependent abbreviation ambiguity. Available names follow the selected tmux daemon. ## Saved layouts and terminal size A captured layout describes pane geometry. Loading validates its syntax and pane capacity, then tmux applies it to the actual window size. Resizing can change the final dimensions. Use a named layout when exact saved geometry is unnecessary. Set window and pane `focus` explicitly when the active target matters. Layout arrangement and active-pane selection are different settings. [Capture](https://libtmux.org/en/csharp/latest/workspace/cli/freeze/) can save a running layout; inspect it before [reloading](https://libtmux.org/en/csharp/latest/workspace/guides/export-session/) on a smaller terminal. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Bootstrap scripts and extensions Source: https://libtmux.org/en/csharp/latest/workspace/configuration/hooks/ > Run a checked bootstrap process before workspace commands. Use `before_script` when setup must finish successfully before configured windows are built. The command is split into an executable and arguments; shell operators require an explicit shell. ```yaml title="hooks.yaml" session_name: hooks-example before_script: /bin/sh -c 'printf bootstrap-ready' windows: - window_name: shell panes: [null] ``` The CLI checks the child process status. A failure stops that workspace's build. The result describes retained effects; an earlier input or borrowed session can still exist. A pane's `shell_command` only sends input and does not provide this process-status guarantee. ## Paths and output A relative script path beginning with `.` is resolved from the workspace file. The script's working directory uses the configured session directory when present, otherwise the invocation directory. The script runs before workspace pane commands. Reusing an existing session does not replay its bootstrap. Machine output captures or streams child output through the CLI protocol. Read [output](https://libtmux.org/en/csharp/latest/workspace/reference/output/) before parsing bootstrap records. ## Prompt readiness The `pane_readiness` setting under `workspace_builder_options` accepts `auto`, `always` or `never`. It controls a bounded wait before initial pane input. It does not wait for a server process to accept connections. Commands can still be delivered when the prompt wait expires. ## Optional extensions Nonempty `plugins` or `workspace_builder` values select the optional Python extension runtime. Set `TMUX_WORKSPACE_PYTHON` to an interpreter with a compatible tmuxp 1.74 installation. Ordinary documents use the native builder. Extensions run executable code and can make changes outside the CLI's own tracked operations. Inspect reported effects and errors before retrying them. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Examples Source: https://libtmux.org/en/csharp/latest/workspace/examples/ > Workspace configurations and complete command walkthroughs. These examples use the workspace command. For programs using the builder library, read the [internal API examples](https://libtmux.org/en/csharp/latest/workspace/internals/examples/). - [Workspace gallery](https://libtmux.org/en/csharp/latest/workspace/examples/gallery/): Configurations for pane layouts, commands and environment, with prerequisites. - [Load a workspace](https://libtmux.org/en/csharp/latest/workspace/guides/installation/): Run the installation and loading walkthrough on a private socket. - [Capture and reload](https://libtmux.org/en/csharp/latest/workspace/guides/export-session/): Export a live session and use the result as a workspace. --- # Examples Source: https://libtmux.org/en/csharp/latest/examples/ > Programs for sending input, capturing output, and building workspaces. Use these programs to send input, capture output, and build a workspace. Each example page includes its source and test coverage. Check those details before adapting an excerpt into a standalone program. ## Source and verification Port repositories use the following checks for their source examples. This site reads or copies those examples; a successful site build alone does not execute them: `sync_snippets.py --check` checks excerpts from tested `[Example]` methods. `ReadmeExampleTests` also compiles and executes blocks marked `csharp run`. See [Testing with libtmux](https://libtmux.org/en/csharp/latest/guides/testing-with-libtmux/) for the fixture each of those test suites runs against, and each example page for the exact file a given snippet was quoted from. - [Attach and send keys](https://libtmux.org/en/csharp/latest/examples/attach-and-send-keys/): Find a session, send a command, and read its output. - [Capture pane output](https://libtmux.org/en/csharp/latest/examples/capture-pane-output/): Read a pane's screen and wait for output to appear. - [Build a workspace from a file](https://libtmux.org/en/csharp/latest/examples/workspace-from-file/): Create a session, windows, and panes from configuration. --- # Attach and send keys Source: https://libtmux.org/en/csharp/latest/examples/attach-and-send-keys/ > Get a session handle, send a command to a pane, and capture output. Get a session handle, send a command to a pane, and capture output. These examples use libtmux from your program; to attach your terminal interactively, see [Attaching to tmux](https://libtmux.org/en/csharp/latest/guides/attaching-to-tmux/). The examples include setup, error handling, and cleanup. [Source and verification](https://libtmux.org/en/csharp/latest/examples/attach-and-send-keys/#where-this-comes-from) identifies their files and checks. ```csharp file="examples/LibTmux.Examples/Snippets/OneShot.cs" using System.Runtime.Versioning; namespace LibTmux.Examples.Snippets; /// The default mode: one command, one client, one materialized object. [UnsupportedOSPlatform("windows")] public static class OneShot { /// Connects, builds a hierarchy, and types into the pane it made. [Example("Connect, build a session and window, and type into a pane")] public static async Task ConnectAndBuild() { #region ConnectAndBuild // Requires a tmux server already listening on this socket: // ConnectAsync() discovers one, it never starts one. With nothing // running yet, call Server.CreateOwnedAsync() instead. Server server = await Server.ConnectAsync(); Session session = await server.CreateSessionAsync(new NewSessionRequest { Name = "build" }); Window window = await session.CreateWindowAsync(new NewWindowRequest { Name = "tests" }); Pane pane = (await window.GetPanesAsync())[0]; await pane.SendTextAsync("dotnet test"); #endregion } /// Creates a window and prints what tmux answered about it. [Example("One command, one materialized window")] public static async Task CreateWindow(Session session, CancellationToken ct) { #region CreateWindow Window window = await session.CreateWindowAsync(new NewWindowRequest { Name = "build" }, ct); Console.WriteLine($"{window.Id} {window.Index}:{window.Name}"); #endregion } } ``` ## Finding an existing session instead For a script that runs repeatedly, look up a session before creating it. [Attaching to tmux](https://libtmux.org/en/csharp/latest/guides/attaching-to-tmux/#finding-a-session-instead-of-always-creating-one) shows that pattern, and [Filtering and querying, in practice](https://libtmux.org/en/csharp/latest/guides/querying-and-filtering/) covers absent and ambiguous matches. ## Where this comes from **Source:** [`examples/LibTmux.Examples/Snippets/OneShot.cs`]() **In this page:** read whole from the file **Checked by:** its `ConnectAndBuild` region is mirrored into README.md and checked by `sync_snippets.py --check`; the mirrored `csharp run` block is additionally compiled and run by `ReadmeExampleTests` ### Source inclusion A `file="..."` fence reads the named source during the site build. Hand-quoted excerpts are copies; their source files and regions are listed above. --- # C# MCP examples Source: https://libtmux.org/en/csharp/latest/mcp/examples/ > Run complete C# clients that discover sessions and execute a command in an owned tmux server. Each example includes its project file, complete program, pinned tool installation, run command, and expected output. The programs create private tmux servers and attempt cleanup after successful and failed requests. ## List sessions [List sessions through MCP](https://libtmux.org/en/csharp/latest/mcp/examples/inspect-sessions/) uses an inspection-only connection. It checks the advertised tools, reads `tmux://capabilities`, and verifies the session name and window count in structured content. ## Run a command [Run a command through MCP](https://libtmux.org/en/csharp/latest/mcp/examples/run-command/) discovers the pane ID, submits a bounded shell command, and checks its exit status separately from the MCP result. It also checks whether the captured output is complete. For an existing server, follow the [connection guide](https://libtmux.org/en/csharp/latest/mcp/guides/connect-client/) and keep its ownership separate from the private servers in these examples. See [Waits and captured output](https://libtmux.org/en/csharp/latest/mcp/topics/waits-and-output/) before adding retries or cancellation to a client that controls long-running processes. - [List sessions through MCP](https://libtmux.org/en/csharp/latest/mcp/examples/inspect-sessions/): Verify tool discovery, read the capability resource, and check structured session metadata. - [Run a command through MCP](https://libtmux.org/en/csharp/latest/mcp/examples/run-command/): Discover a pane, check shell completion and output, and clean up the owned server. --- # Capture pane output Source: https://libtmux.org/en/csharp/latest/examples/capture-pane-output/ > Run a complete program that captures a pane and waits for a complete output line. A pane runs asynchronously: sending a command does not mean its output is already on screen. Capture repeatedly until the expected line appears, with a deadline so a failed command cannot leave the program waiting forever. This complete program creates a private tmux server, captures its output, and cleans up. Follow the [setup and run instructions](https://libtmux.org/en/csharp/latest/examples/capture-pane-output/#setup-and-run) below. You need tmux and a Unix environment; no existing tmux session is required. ## Read what's on screen The program sends `printf` with a leading newline, then waits for the complete line `libtmux capture ready`. The newline keeps a late shell prompt off that line. Matching the whole line avoids mistaking the echoed command for its output. ```csharp title="Program.cs" using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using LibTmux; if (OperatingSystem.IsWindows()) throw new PlatformNotSupportedException("Run this example on Linux or macOS"); string directory = Path.Combine( "/tmp/libtmux-dotnet-dev", Guid.NewGuid().ToString("N")); Directory.CreateDirectory(directory); try { using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10)); CancellationToken token = timeout.Token; await using OwnedServerScope owned = await Server.CreateOwnedAsync( new ServerConnectionOptions { SocketPath = Path.Combine(directory, "tmux.sock"), ConfigurationFile = "/dev/null", ChildEnvironment = new Dictionary { ["TMUX"] = null, ["TMUX_PANE"] = null, ["ENV"] = null, ["BASH_ENV"] = null, }, }, token); Session session = await owned.Value.CreateSessionAsync( new NewSessionRequest { Name = "capture", Command = "/bin/sh" }, token); Pane pane = (await session.GetPanesAsync(token))[0]; await pane.SendTextAsync( "printf '\\nlibtmux capture ready\\n'", cancellationToken: token); var elapsed = Stopwatch.StartNew(); bool captured = false; while (elapsed.Elapsed < TimeSpan.FromSeconds(5)) { var lines = await pane.CaptureAsync(cancellationToken: token); if (lines.Contains("libtmux capture ready")) { Console.WriteLine("libtmux capture ready"); captured = true; break; } await Task.Delay(25, token); } if (!captured) throw new TimeoutException("Output did not arrive within five seconds"); } finally { Directory.Delete(directory, recursive: true); } ``` ## Wait for output or completion The program above checks the captured screen for up to five seconds. The short pause between checks limits polling; the observed output determines when the loop finishes. A tmux capture is a view of the screen and scrollback, so it can miss output that has already scrolled away. Use a stream or a completion signal for long-running commands when that distinction matters. [Capturing output](https://libtmux.org/en/csharp/latest/guides/capturing-output/) covers capture options, while [Sending keys](https://libtmux.org/en/csharp/latest/guides/sending-keys/#the-race-you-cant-see-from-the-call-site) explains why sending and waiting are separate operations. ## Setup and run Use an empty directory. The commands pin the library revision used to verify the program. Save the program and project file using the displayed names. Use the .NET 10 SDK. The project disables implicit imports, so every required import appears in the program. ```xml title="Capture.csproj" Exe net10.0 disable enable false ``` ```console $ git clone https://github.com/libtmux/libtmux-dotnet libtmux-source && git -C libtmux-source checkout 320dc64f4b8b7815842471327a5e6b84a1499bf8 && dotnet build Capture.csproj --maxcpucount:1 && dotnet run --project Capture.csproj --no-build ``` ## Where this comes from This complete program was run against the library revision pinned above. The displayed code is checked against the bytes from that run. --- # List sessions through MCP Source: https://libtmux.org/en/csharp/latest/mcp/examples/inspect-sessions/ > Start an inspection client, verify its tool selection, and read structured session metadata. This program starts a private tmux server, creates a session, and launches `libtmux-mcp` as a child process. It checks the offered tools and reads [`list_sessions`](https://libtmux.org/en/csharp/latest/mcp/tools/list_sessions/) through the official C# MCP client. The program stops its owned server when the request succeeds or fails. ## Run the example Use the .NET 10 SDK and tmux 3.2a or newer on Linux, macOS, or WSL. The project pins the library and tool to the same published alpha release. The package source is [libtmux-dotnet at the documented release](https://github.com/libtmux/libtmux-dotnet/tree/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc). Create an empty directory: ```console $ mkdir inspect-mcp-sessions ``` ```console $ cd inspect-mcp-sessions ``` Install the MCP executable into that directory: ```console $ dotnet tool install \ --tool-path .tools \ --version 0.0.0-alpha.20 \ LibTmux.Mcp ``` Save the project file: ```xml title="McpExample.csproj" Exe net10.0 enable enable ``` ### Client program Save this as `Program.cs`: ```csharp title="Program.cs" using System.Text.Json; using LibTmux; using ModelContextProtocol.Client; using ModelContextProtocol.Protocol; if (OperatingSystem.IsWindows()) { throw new PlatformNotSupportedException("Use Linux, macOS, or WSL with tmux."); } using CancellationTokenSource deadline = new(TimeSpan.FromSeconds(30)); CancellationToken token = deadline.Token; DirectoryInfo directory = Directory.CreateTempSubdirectory("libtmux-mcp-"); string socket = Path.Combine(directory.FullName, "tmux.sock"); Console.Error.WriteLine($"Private socket: {socket}"); OwnedServerScope? owned = null; McpClient? client = null; List failures = []; bool stopped = false; try { ServerConnectionOptions options = new() { SocketPath = socket, ConfigurationFile = "/dev/null", }; owned = await Server.CreateOwnedAsync(options, token); await owned.Value.CreateSessionAsync( new NewSessionRequest { Name = "docs-demo", Command = "/bin/cat" }, token); Dictionary environment = StdioClientTransportOptions.GetDefaultEnvironmentVariables(); environment["DOTNET_ROOT"] = Environment.GetEnvironmentVariable("DOTNET_ROOT"); environment["LIBTMUX_SOCKET_PATH"] = socket; environment["LIBTMUX_TOOLSETS"] = "inspect"; StdioClientTransport transport = new(new StdioClientTransportOptions { Name = "tmux", Command = Path.GetFullPath(".tools/libtmux-mcp"), InheritEnvironmentVariables = false, EnvironmentVariables = environment, ShutdownTimeout = TimeSpan.FromSeconds(5), }); client = await McpClient.CreateAsync(transport, cancellationToken: token); var tools = await client.ListToolsAsync(cancellationToken: token); if (!tools.Any(tool => tool.Name == "list_sessions") || tools.Any(tool => tool.Name == "run_shell_command")) { throw new InvalidOperationException("Unexpected tool selection."); } ReadResourceResult resource = await client.ReadResourceAsync( "tmux://capabilities", cancellationToken: token); TextResourceContents text = (TextResourceContents)resource.Contents.Single(); using JsonDocument capabilities = JsonDocument.Parse(text.Text); string?[] selection = capabilities.RootElement.GetProperty("toolsets") .EnumerateArray().Select(value => value.GetString()).ToArray(); if (!selection.SequenceEqual(new[] { "inspect" })) { throw new InvalidOperationException("Unexpected capability report."); } Console.WriteLine("Tool selection: inspect"); CallToolResult result = await client.CallToolAsync( "list_sessions", cancellationToken: token); if (result.IsError == true || result.StructuredContent is not JsonElement data) { throw new InvalidOperationException(JsonSerializer.Serialize(result)); } JsonElement session = data.EnumerateArray().Single(); string? name = session.GetProperty("name").GetString(); int windows = session.GetProperty("windowCount").GetInt32(); if (name != "docs-demo" || windows != 1) { throw new InvalidOperationException("Unexpected session metadata."); } Console.WriteLine($"Session: {name} ({windows} window)"); } catch (Exception error) { failures.Add(error); } if (client is not null) { try { await client.DisposeAsync(); } catch (Exception error) { failures.Add(new IOException("MCP client cleanup failed.", error)); } } if (owned is not null) { try { await owned.DisposeAsync(); stopped = true; } catch (Exception error) { failures.Add(new IOException("Owned server cleanup failed.", error)); } } if (stopped) { try { directory.Delete(recursive: true); } catch (Exception error) { failures.Add(new IOException("Temporary directory cleanup failed.", error)); } } else { Console.Error.WriteLine($"Retained directory: {directory.FullName}"); } if (failures.Count != 0) { throw new AggregateException(failures); } Console.WriteLine("Owned server stopped."); ``` Run it from the directory containing both files and `.tools`: ```console $ dotnet run --project McpExample.csproj --no-launch-profile ``` The program prints its private socket path to stderr. Its stdout is: ```text Tool selection: inspect Session: docs-demo (1 window) Owned server stopped. ``` ## Read the result The client connects and discovers tools before making a request. It verifies that `list_sessions` is offered and `run_shell_command` is absent, then checks the frozen selection reported by `tmux://capabilities`. A successful protocol exchange can still contain a tool error. Check [`IsError`](https://csharp.sdk.modelcontextprotocol.io/v2/api/ModelContextProtocol.Protocol.CallToolResult.html#ModelContextProtocol_Protocol_CallToolResult_IsError) before reading [`StructuredContent`](https://csharp.sdk.modelcontextprotocol.io/v2/api/ModelContextProtocol.Protocol.CallToolResult.html#ModelContextProtocol_Protocol_CallToolResult_StructuredContent). Here, structured content is an array of session records. The example checks the created session's name and window count. It reads metadata without capturing terminal output or sending input through MCP. The result shape follows the negotiated protocol. For versions before 2026-07-28, the SDK server [wraps the array in a `result` property](https://github.com/modelcontextprotocol/csharp-sdk/blob/6fa3825973949a9c4f0cd8af344e15a8db09dc35/src/ModelContextProtocol.Core/Server/AIFunctionMcpServerTool.cs#L528-L535). Use the tool's advertised output schema when writing a different client. The client passes the SDK's ordinary launch environment plus its explicit socket and tool selection. It does not inherit an interactive shell's `TMUX`, `TMUX_PANE`, or other `LIBTMUX_*` settings. `DOTNET_ROOT` is carried over when the runtime installation needs it. ## Shutdown Startup and requests share a 30-second deadline. Closing the MCP client gives its child process five seconds to exit before the SDK terminates it. Closing the owned server uses a separate cleanup deadline, so an expired request token does not skip daemon cleanup. The program attempts both cleanups and reports their failures alongside any request error. It removes the temporary directory only after owned-server cleanup succeeds. If ownership was not established or server cleanup fails, it prints the retained directory for inspection. The [connection guide](https://libtmux.org/en/csharp/latest/mcp/guides/) covers connecting to an existing server. The [tool reference](https://libtmux.org/en/csharp/latest/mcp/tools/list_sessions/) describes the session fields, and the [owned-server implementation](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux/Server.Lifecycle.cs) defines daemon ownership and cleanup. --- # Run a command through MCP Source: https://libtmux.org/en/csharp/latest/mcp/examples/run-command/ > Discover a pane, run a bounded shell command, and check its exit status and captured output. This program creates a private shell pane and discovers its ID through [`list_panes`](https://libtmux.org/en/csharp/latest/mcp/tools/list_panes/). It calls [`run_shell_command`](https://libtmux.org/en/csharp/latest/mcp/tools/run_shell_command/), checks the shell exit status, and verifies that the captured output contains the expected line. The program owns the tmux server it creates and attempts cleanup after both successful and failed requests. It does not select a pane from your existing sessions. ## Run the example Use the .NET 10 SDK and tmux 3.2a or newer on Linux, macOS, or WSL. The library and tool use the same [published source revision](https://github.com/libtmux/libtmux-dotnet/tree/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc). Create an empty directory: ```console $ mkdir run-mcp-command ``` ```console $ cd run-mcp-command ``` Install the MCP executable into that directory: ```console $ dotnet tool install \ --tool-path .tools \ --version 0.0.0-alpha.20 \ LibTmux.Mcp ``` Save the project file: ```xml title="McpExample.csproj" Exe net10.0 enable enable ``` ### Client program Save this as `Program.cs`: ```csharp title="Program.cs" using System.Text.Json; using LibTmux; using ModelContextProtocol.Client; using ModelContextProtocol.Protocol; if (OperatingSystem.IsWindows()) { throw new PlatformNotSupportedException("Use Linux, macOS, or WSL with tmux."); } using CancellationTokenSource deadline = new(TimeSpan.FromSeconds(30)); CancellationToken token = deadline.Token; DirectoryInfo directory = Directory.CreateTempSubdirectory("libtmux-mcp-"); string socket = Path.Combine(directory.FullName, "tmux.sock"); Console.Error.WriteLine($"Private socket: {socket}"); OwnedServerScope? owned = null; McpClient? client = null; List failures = []; bool stopped = false; try { ServerConnectionOptions options = new() { SocketPath = socket, ConfigurationFile = "/dev/null", }; owned = await Server.CreateOwnedAsync(options, token); await owned.Value.CreateSessionAsync( new NewSessionRequest { Name = "docs-demo", Command = "/bin/sh" }, token); Dictionary environment = StdioClientTransportOptions.GetDefaultEnvironmentVariables(); environment["DOTNET_ROOT"] = Environment.GetEnvironmentVariable("DOTNET_ROOT"); environment["LIBTMUX_SOCKET_PATH"] = socket; environment["LIBTMUX_TOOLSETS"] = "inspect,execute"; environment["LIBTMUX_MCP_WAIT_MAX_SECONDS"] = "5"; StdioClientTransport transport = new(new StdioClientTransportOptions { Name = "tmux", Command = Path.GetFullPath(".tools/libtmux-mcp"), InheritEnvironmentVariables = false, EnvironmentVariables = environment, ShutdownTimeout = TimeSpan.FromSeconds(5), }); client = await McpClient.CreateAsync(transport, cancellationToken: token); var tools = await client.ListToolsAsync(cancellationToken: token); if (!tools.Any(tool => tool.Name == "run_shell_command")) { throw new InvalidOperationException("Command execution is not offered."); } JsonElement panes = ReadResult(await client.CallToolAsync( "list_panes", cancellationToken: token)); string pane = panes.EnumerateArray().Single() .GetProperty("paneId").GetString() ?? throw new InvalidOperationException("The pane has no ID."); JsonElement result = ReadResult(await client.CallToolAsync( "run_shell_command", new Dictionary { ["paneId"] = pane, ["command"] = "printf 'MCP command ready\\n'", ["timeoutSeconds"] = 5, }, cancellationToken: token)); if (result.GetProperty("timedOut").GetBoolean() || result.GetProperty("paneExited").GetBoolean() || !result.GetProperty("started").GetBoolean()) { throw new InvalidOperationException($"Command did not finish: {result}"); } int status = result.GetProperty("exitStatus").GetInt32(); if (status != 0) { throw new InvalidOperationException($"Shell exit status: {status}"); } JsonElement output = result.GetProperty("output"); bool found = output.GetProperty("lines").EnumerateArray() .Any(line => line.GetString() == "MCP command ready"); if (!found || output.GetProperty("truncated").GetBoolean() || result.GetProperty("linesMissed").GetBoolean() || result.GetProperty("anchorLost").GetBoolean()) { throw new InvalidOperationException($"Incomplete command output: {result}"); } Console.WriteLine($"Command exit status: {status}"); Console.WriteLine("Captured marker: MCP command ready"); } catch (Exception error) { failures.Add(error); } if (client is not null) { try { await client.DisposeAsync(); } catch (Exception error) { failures.Add(new IOException("MCP client cleanup failed.", error)); } } if (owned is not null) { try { await owned.DisposeAsync(); stopped = true; } catch (Exception error) { failures.Add(new IOException("Owned server cleanup failed.", error)); } } if (stopped) { try { directory.Delete(recursive: true); } catch (Exception error) { failures.Add(new IOException("Temporary directory cleanup failed.", error)); } } else { Console.Error.WriteLine($"Retained directory: {directory.FullName}"); } if (failures.Count != 0) { throw new AggregateException(failures); } Console.WriteLine("Owned server stopped."); static JsonElement ReadResult(CallToolResult result) { if (result.IsError == true || result.StructuredContent is not JsonElement data) { throw new InvalidOperationException(JsonSerializer.Serialize(result)); } return data; } ``` Run the program from the directory containing these files and `.tools`: ```console $ dotnet run --project McpExample.csproj --no-launch-profile ``` It prints the private socket path to stderr. Its stdout is: ```text Command exit status: 0 Captured marker: MCP command ready Owned server stopped. ``` ## Completion and output The client offers `inspect` and `execute`. It discovers the actual pane ID instead of assuming that the first pane has a particular number. The command wait is limited to five seconds; startup and MCP requests share a separate 30-second deadline. Check the tool result before reading the shell result. The [`ReadResult`](https://libtmux.org/en/csharp/latest/mcp/examples/run-command/#client-program) helper in this example rejects `isError` and missing structured content. The program then checks completion, shell status, and capture completeness separately. `linesMissed`, `anchorLost`, or a truncated capture means output may be missing even if the command exited successfully. The command runs in a subshell. A `cd` or `export` inside one call does not persist into another call. Combine dependent shell operations in one command when they need to share a directory or environment. ## Failures and cleanup A timeout with `started: false` means the command wrapper was not seen to begin; inspect whether the pane is at an empty, ready shell prompt. A timeout after startup can leave the command running. `paneExited` instead reports that the pane's program ended before returning a shell status. For this private example, cleanup stops the owned server and any remaining pane command. In an application that borrows an existing pane, cancelling the wait does not stop the command. Inspect that pane before deciding to retry or send more input. MCP shutdown and owned-server shutdown are attempted independently, and the program reports cleanup failures alongside request failures. It deletes its temporary directory only after owned-server cleanup succeeds. The [session inspection example](https://libtmux.org/en/csharp/latest/mcp/examples/inspect-sessions/#shutdown) explains that ownership pattern, and [Waits and captured output](https://libtmux.org/en/csharp/latest/mcp/topics/waits-and-output/) covers observation, cancellation, and response budgets. --- # Workspace examples Source: https://libtmux.org/en/csharp/latest/workspace/examples/gallery/ > Start from complete configurations for pane layout, commands and environment. Each configuration below is a complete workspace document. Save it to a file and load it on the private socket from the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/). ## Two blank panes ```yaml title="gallery-blank.yaml" session_name: gallery-blank windows: - window_name: work layout: even-horizontal panes: [null, null] ``` Blank panes open their shells without application-specific prerequisites. Change the [layout](https://libtmux.org/en/csharp/latest/workspace/configuration/layouts/) to arrange them vertically. ## Setup before pane commands ```yaml title="gallery-commands.yaml" session_name: gallery-commands shell_command_before: - printf setup windows: - window_name: shell panes: - shell_command: - printf first - printf second ``` Both commands run in one pane after its inherited setup. Read [command ordering](https://libtmux.org/en/csharp/latest/workspace/configuration/commands/) before adding delays or commands that should remain unsubmitted. ## More complete examples - [Session options and environment](https://libtmux.org/en/csharp/latest/workspace/configuration/session/). - [Explicit window index and synchronized input](https://libtmux.org/en/csharp/latest/workspace/configuration/windows/). - [Pane launch shell and focus](https://libtmux.org/en/csharp/latest/workspace/configuration/panes/). - [Inherited directories](https://libtmux.org/en/csharp/latest/workspace/configuration/directories/). - [Environment overrides](https://libtmux.org/en/csharp/latest/workspace/configuration/environment/). - [Checked bootstrap process](https://libtmux.org/en/csharp/latest/workspace/configuration/hooks/). Use the [workspace library](https://libtmux.org/en/csharp/latest/workspace/internals/) when application code needs to construct sessions directly. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Guides Source: https://libtmux.org/en/csharp/latest/workspace/guides/ > Install the workspace command, find configurations and automate tmux sessions. Choose a task below. The [CLI reference](https://libtmux.org/en/csharp/latest/workspace/cli/) documents commands and options; [Internals](https://libtmux.org/en/csharp/latest/workspace/internals/) covers the workspace builder library. - [Install and load](https://libtmux.org/en/csharp/latest/workspace/guides/installation/): Install the command and load a workspace on a private socket. - [Find workspace files](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/): Discover, search and edit configurations. - [Automate workspace loading](https://libtmux.org/en/csharp/latest/workspace/guides/automation/): Use machine output and exit codes in scripts. - [Export a session](https://libtmux.org/en/csharp/latest/workspace/guides/export-session/): Capture a running session and load it again. - [Troubleshooting](https://libtmux.org/en/csharp/latest/workspace/guides/troubleshooting/): Diagnose installation, configuration and execution problems. --- # Guides Source: https://libtmux.org/en/csharp/latest/guides/ > Task-oriented walkthroughs that sit between the concepts and each port's own API reference. Use these guides to connect to tmux, send input, capture output, query objects, and test your program. [Concepts](https://libtmux.org/en/csharp/latest/concepts/) explains the object model and transport choices. [Examples](https://libtmux.org/en/csharp/latest/examples/) provides complete programs with setup and cleanup. - [Getting started](https://libtmux.org/en/csharp/latest/guides/getting-started/): Install tmux and run a complete example. - [Attaching to tmux](https://libtmux.org/en/csharp/latest/guides/attaching-to-tmux/): Select a socket and find or create a session. - [Sending keys](https://libtmux.org/en/csharp/latest/guides/sending-keys/): Send literal text, named keys, and Enter. - [Capturing output](https://libtmux.org/en/csharp/latest/guides/capturing-output/): Read the screen or scrollback and wait for a result. - [Filtering and querying](https://libtmux.org/en/csharp/latest/guides/querying-and-filtering/): Find objects and handle missing or ambiguous matches. - [Testing](https://libtmux.org/en/csharp/latest/guides/testing-with-libtmux/): Use isolated tmux servers and manage test cleanup. --- # C# MCP guides Source: https://libtmux.org/en/csharp/latest/mcp/guides/ > Install the MCP executable, choose its tmux server, and verify the client's connection. Let the MCP client launch `libtmux-mcp` and exchange protocol messages over stdin and stdout. The [connection guide](https://libtmux.org/en/csharp/latest/mcp/guides/connect-client/) covers installation, an existing tmux server, and the launcher's default dedicated server. ## Install the tool [`LibTmux.Mcp`]() is a framework-dependent .NET tool targeting .NET 8 and .NET 10. Follow the [pinned installation steps](https://libtmux.org/en/csharp/latest/mcp/guides/connect-client/#install-the-tool). The [complete client example](https://libtmux.org/en/csharp/latest/mcp/examples/inspect-sessions/) installs the executable into its own directory and includes the client project files. ## Connect a client Choose the socket and [tool selection](https://libtmux.org/en/csharp/latest/mcp/topics/tool-selection/) in the startup environment, then inspect `tmux://capabilities` and the offered tools. Use `manage` for topology changes and `execute` for terminal input and command execution. Reconnect after changing the configuration. ## Diagnose startup The client's server log contains stderr diagnostics. The [startup checks](https://libtmux.org/en/csharp/latest/mcp/guides/connect-client/#diagnose-startup) cover executable lookup, runtime installation, conflicting socket settings, and invalid tool names. Keep stdout available for MCP messages. - [Connect a client](https://libtmux.org/en/csharp/latest/mcp/guides/connect-client/): Install the pinned tool, choose a socket, and check startup and shutdown. --- # Getting started Source: https://libtmux.org/en/csharp/latest/guides/getting-started/ > Run a complete program with this language library. Use [`LibTmux`]() to create sessions, send input and read pane output from C#. The [complete capture program](https://libtmux.org/en/csharp/latest/examples/capture-pane-output/) includes imports, its entry point, project files, dependency setup and a run command. ## Run the smallest thing that proves it works Open that example in an empty directory and save the files using their displayed names. Its setup pins the library revision that was used to execute the program. It needs tmux on `PATH` and the native tools named on the example page. The program creates a private server, sends a command, waits for the complete line `libtmux capture ready`, then cleans up. A timeout or command failure is reported. It does not need an existing tmux session. ## What just happened [`Pane.CaptureAsync`]() reads visible pane lines. The complete program passes a cancellation token, compares whole lines and bounds its waits with a [`CancellationTokenSource`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource?view=net-10.0). Its [`OwnedServerScope`]() owns the private server and is disposed with `await using`. ## Connect to an existing server Use the [complete attach program](https://libtmux.org/en/csharp/latest/guides/attaching-to-tmux/) to select an existing socket and find the `work` session. That example leaves tmux running; its launcher owns setup and cleanup for trying it safely. ## Where to go next [Sending keys](https://libtmux.org/en/csharp/latest/guides/sending-keys/) explains input, and [Capturing output](https://libtmux.org/en/csharp/latest/guides/capturing-output/) explains completion. [Querying and filtering](https://libtmux.org/en/csharp/latest/guides/querying-and-filtering/) selects a target. --- # Attaching to tmux Source: https://libtmux.org/en/csharp/latest/guides/attaching-to-tmux/ > Connect to an existing tmux server and find a session with C#. Connect a [`Server`]() to an explicit socket and find the existing `work` session. The program prints its name and leaves the tmux server running. It reports an error if the connection fails or the session is absent. This controls tmux from your program. 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 `Program.cs`. `LIBTMUX_SOCKET_PATH` selects the existing server. The launcher below supplies a private socket for trying the example. ```csharp title="Program.cs" using System; using System.Threading; using System.Threading.Tasks; using LibTmux; string socket = Environment.GetEnvironmentVariable("LIBTMUX_SOCKET_PATH") ?? throw new InvalidOperationException("Set LIBTMUX_SOCKET_PATH to an existing socket"); using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)); Server server = await Server.ConnectAsync( new ServerConnectionOptions { SocketPath = socket }, timeout.Token); if (!await server.HasSessionAsync("work", cancellationToken: timeout.Token)) throw new InvalidOperationException("The work session does not exist"); Console.WriteLine("work"); ``` ## Setup and run Use an empty directory on Linux with Git and tmux 3.2a or newer installed. This example was checked with .NET SDK 10.0.302. Save this file beside the program using the displayed filename. ```xml title="Connect.csproj" Exe net10.0 disable enable false ``` 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-dotnet-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' ``` Fetch the verified library revision, build, and run: ```console $ git clone https://github.com/libtmux/libtmux-dotnet libtmux-source && git -C libtmux-source checkout 320dc64f4b8b7815842471327a5e6b84a1499bf8 && dotnet build Connect.csproj --maxcpucount:1 && sh run.sh dotnet run --project Connect.csproj --no-build ``` The program prints `work`. To use an existing server of your own, set `LIBTMUX_SOCKET_PATH` to its socket and run the program without the launcher. That launcher is responsible for the demonstration server's lifetime. ## Find or create a session The example only looks up a session. If your application creates a session after an unsuccessful lookup, another client may create the same name between those operations. Handle the creation error instead of assuming the lookup reserves the name. For a complete program that starts and owns its server, see [Capture pane output](https://libtmux.org/en/csharp/latest/examples/capture-pane-output/). Continue with [Sending keys](https://libtmux.org/en/csharp/latest/guides/sending-keys/) once you have a pane handle. --- # Sending keys Source: https://libtmux.org/en/csharp/latest/guides/sending-keys/ > Send text and named keys, then wait for the result. [`Pane.SendTextAsync`]() sends text; [`Pane.EnterAsync`]() submits the line. Pass a cancellation token to both operations. The complete program performs these steps separately and waits for its output before treating the task as done. ## Run the complete program [Capture pane output](https://libtmux.org/en/csharp/latest/examples/capture-pane-output/) supplies the full C# program, imports, project setup and run command. It starts a private server, sends a command, checks a complete output line and cleans up. ## Literal text, key names, and whether Enter follows Choose the method and options for the input you mean to send. Literal text still goes to an application: a shell interprets its quoting, expansions and commands. Key-name handling and shell interpretation are separate concerns. ## The race you can't see from the call site A successful send means tmux accepted input. The pane's program may still be starting or processing that input. Wait for the state the next operation needs. Terminal echo alone does not prove command completion. [`Pane.CaptureAsync`]() reads visible pane lines. The complete program passes a cancellation token, compares whole lines and bounds its waits with a [`CancellationTokenSource`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource?view=net-10.0). Its [`OwnedServerScope`]() owns the private server and is disposed with `await using`. ## Where to go next [Capturing output](https://libtmux.org/en/csharp/latest/guides/capturing-output/) covers the output side. [Attaching to tmux](https://libtmux.org/en/csharp/latest/guides/attaching-to-tmux/) connects to a server you already own. --- # Capturing output Source: https://libtmux.org/en/csharp/latest/guides/capturing-output/ > Read pane output with an explicit completion condition. [`Pane.CaptureAsync`]() reads visible pane lines. The complete program passes a cancellation token, compares whole lines and bounds its waits with a [`CancellationTokenSource`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource?view=net-10.0). Its [`OwnedServerScope`]() owns the private server and is disposed with `await using`. ## Run the complete program [Capture pane output](https://libtmux.org/en/csharp/latest/examples/capture-pane-output/) includes the full C# program, all imports, project files and a run command. The program matches `libtmux capture ready` as a complete line, so the echoed command cannot satisfy the check. It creates and cleans up its own tmux server. ## Visible pane vs. scrollback A capture reads terminal state. Lines that have scrolled beyond retained history are unavailable, and repeated captures can miss intermediate output. Choose the range your task needs and use a stream or completion signal when every output event matters. ## Wait for the expected text Use a deadline and a specific output predicate. The example's short polling pause limits work between checks; it is the observed line that determines completion. [Sending keys](https://libtmux.org/en/csharp/latest/guides/sending-keys/) explains why returning from the input call is not a completion signal. ## Wait for a completion signal A program can also signal a dedicated tmux channel. Use the same server endpoint for the sender and waiter and a new channel name per task. [Waiting and retrying](https://libtmux.org/en/csharp/latest/topics/waiting-and-retry/) documents this port's waiting APIs and failure handling. --- # Querying and filtering Source: https://libtmux.org/en/csharp/latest/guides/querying-and-filtering/ > Choose a target and handle missing or ambiguous results. [`Server.HasSessionAsync`]() checks whether a session exists. It does not return a selected session object. The complete program checks `work`, reports its absence and leaves the borrowed server running. Use collection filtering when you need handles or must detect several matching objects. ## Require exactly one match [Attaching to tmux](https://libtmux.org/en/csharp/latest/guides/attaching-to-tmux/) provides the complete C# program and its setup. It searches an existing server for `work`, prints the name and reports an absent session. Its launcher checks that the server remains running. For a more general predicate, decide whether zero or several results are valid before indexing a collection. Keep lookup and command failures visible: another client can change the server between a read and the operation using its result. ## Declarative filters [Filtering and queries](https://libtmux.org/en/csharp/latest/concepts/queries/) describes this port's query APIs, accepted fields and result-count contracts. Use that contract when storing a query in configuration. ## Case-insensitive matching Choose case handling explicitly when your query needs it. The attach program uses exact case because the intended session is named `work`. ## Push the filter into tmux, or read once and filter locally A tmux-side filter reduces returned rows; a captured collection can answer several local queries from one read. Neither reserves the result. Check unexpectedly empty format values before assuming that an object does not exist. --- # Testing with libtmux Source: https://libtmux.org/en/csharp/latest/guides/testing-with-libtmux/ > Use an isolated server and check cleanup failures. [`LibTmux.Testing`]() is a separate package. [`TmuxTestFactory`]() creates a temporary hierarchy whose scope is disposed with `await using`. Use a bounded predicate wait for state assertions. The complete capture program shows ownership with [`Server.CreateOwnedAsync`]() and a cancellation token in a standalone executable. ## Run a complete example [Capture pane output](https://libtmux.org/en/csharp/latest/examples/capture-pane-output/) includes a complete .NET executable, imports, dependency setup and cleanup. Its output check fails when the expected line does not arrive before the deadline. Start with that program when adapting the pattern to your own test runner. ## Keep server ownership explicit Give each test a private socket and a known tmux configuration. Stop the server the test creates, including when startup or an assertion fails. Preserve the original failure and report cleanup errors so a leaked server remains visible. A connection to an existing server has a different lifetime. The [attach program](https://libtmux.org/en/csharp/latest/guides/attaching-to-tmux/) leaves that server running and lets its launcher own cleanup. ## Wait for the state you assert Wait for the actual output or completion condition with a deadline. [Sending keys](https://libtmux.org/en/csharp/latest/guides/sending-keys/) returning successfully does not establish that the application finished. [Capturing output](https://libtmux.org/en/csharp/latest/guides/capturing-output/) explains the difference between a screen snapshot and a stream of output. --- # Connect an MCP client Source: https://libtmux.org/en/csharp/latest/mcp/guides/connect-client/ > Install the .NET tool, select its tmux endpoint, and verify discovery and ownership. Configure your MCP client to launch `libtmux-mcp`. The executable selects one tmux socket and its tools at startup, then serves MCP over stdin and stdout. Use Linux, macOS, or WSL with tmux 3.2a or newer and a compatible .NET runtime. The examples here use the [published package](https://www.nuget.org/packages/LibTmux.Mcp/0.0.0-alpha.20) and its [source contract](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Mcp/README.md). ## Install the tool Install the pinned alpha release with the .NET SDK: ```console $ dotnet tool install \ --global \ --version 0.0.0-alpha.20 \ LibTmux.Mcp ``` The package targets .NET 8 and .NET 10. It installs the `libtmux-mcp` executable; `dotnet add package` is not the installation method for this tool. The client's launch environment must include the .NET tools directory on `PATH`, normally [`$HOME/.dotnet/tools`](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-tool-install#global-tools) on a POSIX host. For a project-local installation and a complete C# client, use [List sessions through MCP](https://libtmux.org/en/csharp/latest/mcp/examples/inspect-sessions/). ## Connect to an existing server This client configuration selects the existing socket named `docs-agent` and enables inspection tools: ```json { "mcpServers": { "tmux": { "command": "libtmux-mcp", "env": { "LIBTMUX_SOCKET": "docs-agent", "LIBTMUX_TOOLSETS": "inspect" } } } } ``` Use the name of the server you intend to inspect. A socket name corresponds to tmux's `-L` option. `LIBTMUX_SOCKET_PATH` instead selects one absolute socket path, corresponding to `-S`. Set only one of these variables. The selection is not taken from an inherited `TMUX` value. `TMUX_PANE` can identify the calling pane when the client runs inside the selected server; discovery and mutation tools use that context to avoid inappropriate input to the caller. Explicitly selecting a socket still requires checking that it is the server you intend to control. Ask the connected client to list tools, read `tmux://capabilities`, and call [`list_sessions`](https://libtmux.org/en/csharp/latest/mcp/tools/list_sessions/). Check the reported socket and session names before sending input. The capability resource records the startup selection; use [`get_server_info`](https://libtmux.org/en/csharp/latest/mcp/tools/get_server_info/) and the hierarchy tools for current state. ## Use the dedicated server Omit both socket variables to select the dedicated `libtmux-mcp` socket. When that endpoint is absent, the launcher can create it using its bundled minimal tmux configuration. A newly created dedicated endpoint defaults to all four toolsets. Select `inspect` explicitly when that is all the client needs. An existing or explicitly selected endpoint defaults to `inspect`, `manage`, and `execute`; teardown requires an explicit selection. An explicit `LIBTMUX_TMUX_CONFIG` must be an absolute, nonempty path. Using your own configuration also affects the launcher's ownership classification and default tool selection. Read the capability report instead of inferring ownership from the socket's name. On shutdown, the MCP process stops only a dedicated daemon whose launch marker still matches that process. It leaves borrowed and replaced daemons running. Closing an MCP client does not promise to stop work already running in a borrowed pane. ## Diagnose startup Read stderr in the client's server log. Keep stdout exclusively for protocol messages; a shell startup message on stdout can break the connection. - If `libtmux-mcp` is not found, check the client's `PATH` or configure the installed executable's absolute path. - If the tool cannot locate .NET, set `DOTNET_ROOT` to the runtime installation used by that client. Desktop launchers may not inherit a version manager's shell setup. - Use `LIBTMUX_TMUX` to select a particular tmux executable. It is resolved when the MCP server starts. - Set either `LIBTMUX_SOCKET` or `LIBTMUX_SOCKET_PATH`, and use an absolute path for the latter. The executable takes no positional socket argument. - Check toolset and tool names against [Tool selection](https://libtmux.org/en/csharp/latest/mcp/topics/tool-selection/). Unknown names and malformed comma-separated lists stop startup. - Remove `LIBTMUX_SAFETY` if it is present. This release rejects the retired variable instead of treating it as an additional policy. Restart the MCP connection after changing its environment. Changing a terminal's environment does not reconfigure a server process already running inside another client. The [startup implementation](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Mcp/Policy/McpStartup.cs) defines socket selection and ownership. The [tool-selection implementation](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Mcp/Policy/CapabilitySelection.cs) defines registration and filter precedence. --- # Install and load a workspace Source: https://libtmux.org/en/csharp/latest/workspace/guides/installation/ > Build the workspace command and load a session on a private tmux socket. Build the documented `tmux-workspace` revision, then load a small session on a private socket. Use a Unix shell with tmux 3.2a or newer on `PATH`. ## Build the command Fetch the documented source revision, then build from its repository root. Keep the exported `PATH` in this shell for the rest of the walkthrough. ```console $ git clone --filter=blob:none https://github.com/libtmux/libtmux-dotnet.git ``` ```console $ cd libtmux-dotnet ``` ```console $ git fetch --depth=1 origin f77fe776ba67a04abb20ddbbc26cf4a000d63b74 ``` ```console $ git checkout --detach FETCH_HEAD ``` Use the .NET 10 SDK to build the command: ```console $ dotnet build src/LibTmux.Workspace.Cli/LibTmux.Workspace.Cli.csproj --configuration Release ``` ```console $ WORKSPACE_BIN="$(mktemp -d)" ``` ```console $ ln -s "$PWD/src/LibTmux.Workspace.Cli/bin/Release/net10.0/LibTmux.Workspace.Cli" "$WORKSPACE_BIN/tmux-workspace" ``` ```console $ export PATH="$WORKSPACE_BIN:$PATH" ``` Keep the build directory and the matching .NET runtime available when using this launcher. ```console $ tmux-workspace --help ``` ## Create the input Keep this shell open. Create a temporary working directory on a filesystem that supports Unix sockets, then enter it: ```console $ WORKSPACE_TMP="$(mktemp -d)" ``` ```console $ cd "$WORKSPACE_TMP" ``` Save this as `workspace.yaml`: ```yaml title="workspace.yaml" session_name: workspace-guide windows: - window_name: editor layout: even-horizontal panes: [null, null] ``` ## Load and inspect ```console $ tmux-workspace load \ -S "$WORKSPACE_TMP/tmux.sock" \ -f /dev/null \ -d \ --json \ workspace.yaml ``` `-d` leaves the session detached. Inspect its panes using the same socket: ```console $ tmux -S "$WORKSPACE_TMP/tmux.sock" list-panes -t '=workspace-guide:editor' ``` Attach interactively with `tmux -S "$WORKSPACE_TMP/tmux.sock" attach-session -t '=workspace-guide'`. Detach with your tmux detach binding before continuing. ## Capture and clean up ```console $ tmux-workspace freeze -S "$WORKSPACE_TMP/tmux.sock" --json workspace-guide ``` Try [export and reload](https://libtmux.org/en/csharp/latest/workspace/guides/export-session/) before cleanup. Capture cannot recover original scripts, command history or application state. Remove only the session created by this walkthrough when finished: ```console $ tmux -S "$WORKSPACE_TMP/tmux.sock" kill-session -t '=workspace-guide' ``` The configuration remains in the temporary directory. Keep the session running when following guides that continue this example. ## Continue [Configuration](https://libtmux.org/en/csharp/latest/workspace/configuration/) describes execution fields; [discovery](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/) finds saved files. Read the [load reference](https://libtmux.org/en/csharp/latest/workspace/cli/load/) and [automation](https://libtmux.org/en/csharp/latest/workspace/guides/automation/) for attachment, output and failure handling. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Find saved workspaces Source: https://libtmux.org/en/csharp/latest/workspace/guides/discovery/ > Resolve explicit files, project directories and saved workspace names. Use an explicit path, such as [`./workspace.yaml`](https://libtmux.org/en/csharp/latest/workspace/guides/installation/#create-the-input), to select one document. Pass a project directory such as `.` to use its [`.tmuxp.yaml`](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/#list-available-files), [`.tmuxp.yml`](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/#list-available-files) or [`.tmuxp.json`](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/#list-available-files) configuration. A bare saved name uses the global workspace directory. ## List available files ```console $ tmux-workspace ls --json ``` Discovery includes project configurations in the current directory and its parents, plus saved global workspaces. The first existing global directory wins, in this order: 1. `TMUXP_CONFIGDIR`. 2. `$XDG_CONFIG_HOME/tmuxp`, with [`~/.config`](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/#list-available-files) as the XDG default. 3. [`~/.tmuxp`](https://libtmux.org/en/csharp/latest/workspace/guides/discovery/#list-available-files). An existing empty directory remains selected. A missing directory does not override an existing fallback merely because its environment variable is set. ## Search by content ```console $ tmux-workspace search --json window:editor ``` Use [search](https://libtmux.org/en/csharp/latest/workspace/cli/search/) for field prefixes and pattern rules. Use [edit](https://libtmux.org/en/csharp/latest/workspace/cli/edit/) to open a discovered workspace, or [load](https://libtmux.org/en/csharp/latest/workspace/cli/load/) with an explicit path when a name is ambiguous. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Automate workspace operations Source: https://libtmux.org/en/csharp/latest/workspace/guides/automation/ > Run detached commands with explicit inputs and machine-readable results. Give automation an explicit file, endpoint and attachment choice. Continue the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/) with this detached operation: ```console $ tmux-workspace load \ -S "$WORKSPACE_TMP/tmux.sock" \ -d \ --json \ workspace.yaml ``` Check the process exit status, parse its JSON result, then inspect any reported partial effects. A failed later input does not imply that earlier sessions were removed. Keep stderr separate from the result stream. ## Follow progress Use NDJSON when the caller needs records while a load is running: ```console $ tmux-workspace load \ -S "$WORKSPACE_TMP/tmux.sock" \ -d \ --ndjson \ workspace.yaml ``` Parse one complete JSON value per line. Treat a closed stream or missing final result as incomplete work. Do not infer success from an earlier creation event. ## Make retries deliberate Use a unique session name for independent jobs. Reusing a name follows the loader's existing-session policy; it is not a request to reset that session. Capture IDs and retained effects from the result before deciding what to clean up or retry. Remove only sessions the job owns. Read [output](https://libtmux.org/en/csharp/latest/workspace/reference/output/) and [errors](https://libtmux.org/en/csharp/latest/workspace/reference/exit-codes/) for the command's machine interface. A pane's process can outlive the CLI and can fail after successful command delivery. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Export and reload a session Source: https://libtmux.org/en/csharp/latest/workspace/guides/export-session/ > Capture a running session, inspect the document and load a second copy. Capture the session created by the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/) to a new YAML file: ```console $ tmux-workspace freeze \ -S "$WORKSPACE_TMP/tmux.sock" \ --json \ --workspace-format yaml \ --save-to workspace-export.yaml \ workspace-guide ``` Review the saved commands, directories and layout. Capture reads current tmux state; it cannot recover original arguments, shell history, scripts, comments or application state. A captured command may need editing before replay. ## Load a second copy Use a fresh session name on the same private server: ```console $ tmux-workspace load \ -S "$WORKSPACE_TMP/tmux.sock" \ -d \ -s workspace-replayed \ --json \ workspace-export.yaml ``` Inspect the second copy's panes: ```console $ tmux -S "$WORKSPACE_TMP/tmux.sock" list-panes -t '=workspace-replayed' ``` Remove that copy when finished: ```console $ tmux -S "$WORKSPACE_TMP/tmux.sock" kill-session -t '=workspace-replayed' ``` [Capture](https://libtmux.org/en/csharp/latest/workspace/cli/freeze/) explains destination handling. [Conversion](https://libtmux.org/en/csharp/latest/workspace/cli/convert/) changes file encoding without proving the document can be loaded. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Troubleshoot a workspace Source: https://libtmux.org/en/csharp/latest/workspace/guides/troubleshooting/ > Find the failed stage before retrying a workspace operation. Start with the error message and exit status. A partially completed load can leave sessions or windows running; inspect its result before retrying or cleaning up. ## Confirm the command and input ```console $ tmux-workspace debug-info --json ``` Check the executable version, selected tmux binary and workspace directories. Use an explicit file path to bypass saved-name lookup. Verify the socket matches the one used for inspection and capture. ## Common failures | Symptom | Next check | | --- | --- | | Workspace not found | Explicit path, file extension and global discovery directory | | Unsupported field | CLI configuration fields and the reported field path | | tmux unavailable | Executable path, permissions and selected socket | | Existing session mismatch | Running window names and the requested document | | Layout rejected | Layout name, pane capacity and the selected tmux version | | File already exists | Select a new output path or authorize replacement with `--force` | | Script failed | Child status, captured output and working directory | | Interactive context required | Use `load -d` for automation; provide a terminal for interactive work | ## Record a load Continue the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/) and append diagnostic records to a local file: ```console $ tmux-workspace --log-level debug load \ -S "$WORKSPACE_TMP/tmux.sock" \ -d \ --json \ --log-file workspace-load.log \ workspace.yaml ``` Logs may include script output and local paths. Inspect them before sharing a bug report. Include the command, versions, minimal configuration, exit status and relevant result; remove private values. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Inspect a workspace through MCP Source: https://libtmux.org/en/csharp/latest/workspace/guides/inspect-with-mcp/ > Connect the development C# MCP server to a session loaded by its native workspace CLI. Inspect the session you loaded with the C# workspace CLI by pointing its MCP server at the same tmux socket. The loaded windows and panes are ordinary tmux objects; discovery returns their existing IDs. **This guide uses development `workspace-cli` source.** Continue the [installation walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/#load-and-inspect) through its detached load, keeping that shell and `WORKSPACE_TMP` available. Leave the `workspace-guide` session running. Build both executables from the same native repository checkout; released package instructions may describe different MCP contracts. ## Build the MCP server Run from the native repository root with the installation walkthrough's toolchain and dependencies. ```console $ dotnet build \ --configuration Release \ --framework net10.0 \ -m:2 \ src/LibTmux.Mcp/LibTmux.Mcp.csproj ``` Use the repository's SDK and a compatible .NET 10 runtime. Keep the complete build output beside the DLL, including its runtime and dependency metadata. ## Select the same socket Configure an MCP client to launch the following command with the shown environment. The client owns the process's standard input and output for JSON-RPC messages. ```console $ LIBTMUX_TOOLSETS=inspect \ LIBTMUX_SOCKET_PATH="$WORKSPACE_TMP/tmux.sock" \ dotnet src/LibTmux.Mcp/bin/Release/net10.0/LibTmux.Mcp.dll ``` In a client's configuration file, use absolute executable or script paths and expand `WORKSPACE_TMP` to its actual value. Configuration files do not perform shell variable expansion. Retain the environment used to build and run the native executable. For a workspace loaded with `-L NAME`, set `LIBTMUX_SOCKET=NAME` instead of `LIBTMUX_SOCKET_PATH`. Do not set both. If you selected a tmux executable with `LIBTMUX_TMUX`, supply that same setting to the MCP process. ## Inspect and wait 1. Discover tools with `tools/list` and read the `tmux://capabilities` resource. Confirm that its resolved endpoint matches the loaded socket. 2. Call [list_sessions][mcp-source], then [list_windows][mcp-source] with `session: "workspace-guide"`, and [list_panes][mcp-source]. Retain the returned session, window and pane IDs. 3. Select one returned pane ID for capture or a bounded text wait. Use the argument names below; discover the full schema before adding options. | Tool | Arguments | | --- | --- | | [capture_pane][mcp-source] | `"paneId"`, `"maxLines"` | | [wait_for_text][mcp-source] | `"paneId"`, regex `"patterns"`, `"timeoutSeconds"` in seconds | Set `"timeoutSeconds"` to `10` for a ten-second wait. A pending wait permits other inspection calls on the same connection. To check that behavior, start a wait for text absent from the pane, then request [list_panes][mcp-source] before its deadline. Client cancellation uses `notifications/cancelled` with the outstanding request ID; the connection remains usable for inspection. Capture returns a bounded `"lines"` array inside `"content"` with trailing empty rows removed; interior blank lines remain. [snapshot_pane][mcp-source] adds cursor and viewport state. The first [capture_since][mcp-source] call establishes an opaque cursor without returning content; pass that cursor to subsequent calls. If discovery does not show `workspace-guide`, compare the resolved socket in capabilities with the CLI's `-S` path. A different socket selects a different daemon even when session names match. ## Close the connection Close the MCP connection's standard input to stop the server and release pending work. This separately loaded workspace remains running. When you finish the walkthrough, remove only its session on the same socket: ```console $ tmux \ -S "$WORKSPACE_TMP/tmux.sock" \ kill-session \ -t '=workspace-guide' ``` The configuration remains in the temporary directory until you remove it. See the verified [native workspace workflow][workspace-source] and [development MCP reference][mcp-source] for this source contract. The site's released MCP pages retain their version-pinned contracts. [workspace-source]: https://github.com/libtmux/libtmux-dotnet/blob/95df228cfbe33cd3672bebb2d9a1c4b7f02f58f2/src/LibTmux.Workspace.Cli/README.md [mcp-source]: https://github.com/libtmux/libtmux-dotnet/blob/95df228cfbe33cd3672bebb2d9a1c4b7f02f58f2/docs/mcp/tools.md --- # C# workspace internals Source: https://libtmux.org/en/csharp/latest/workspace/internals/ > Architecture and development interfaces of the C# workspace builder. Build and inspect tmux sessions from application code with the workspace library. To load files from a terminal, start with the [native CLI walkthrough](https://libtmux.org/en/csharp/latest/workspace/guides/installation/). ## Builder pipeline [`WorkspaceFile.Parse`]() validates the YAML. [`WorkspaceBuilder.BuildAsync`]() creates the session through a supplied core [`Server`]() and returns its materialized objects. The caller supplies file reading, cancellation, command-line handling, attachment, and server lifetime. ## Read the implementation - [Guides](https://libtmux.org/en/csharp/latest/workspace/internals/guides/) show builder setup and application code. - [Topics](https://libtmux.org/en/csharp/latest/workspace/internals/topics/) explain configuration, behavior, and failures. - [Examples](https://libtmux.org/en/csharp/latest/workspace/internals/examples/) exercise the builder through the language API. - [API](https://libtmux.org/en/csharp/latest/workspace/reference/) links the configuration and construction interfaces. ## Implementation scope [`LibTmux.Workspace`]() reads a YAML file and builds its session through LibTmux. It returns the session, materialized windows, and any layouts that tmux rejected while leaving their windows usable. Use it from a launcher or another .NET application that already controls a tmux server. The package adds YAML parsing separately from the core client. ## Package and runtime The package targets .NET 8 and .NET 10 and uses YamlDotNet. tmux must run on the host. Pin the prerelease selected by your package manager because public contracts can change between alpha versions. The parser rejects unknown fields. The caller reads the file and selects the server; parsing does not search configuration directories or load extensions. [Package documentation](https://github.com/libtmux/libtmux-dotnet/blob/6656a563ec9e07ab52e0c3ac96f7704fc94cc0c0/src/LibTmux.Workspace/README.md) --- # C# workspace builder behavior Source: https://libtmux.org/en/csharp/latest/workspace/internals/topics/ > Internal configuration, application, and failure contracts of the C# workspace builder. [`WorkspaceFile.Parse`]() produces immutable configuration before building begins. It rejects duplicate or unknown keys, wrong value shapes, multiple YAML documents, and inputs over 1 MiB. Missing session names and empty window lists are rejected before any session is created. ## Supported fields The package supports session names, working directories, scalar options, windows, panes, layouts, focus, and scalar or ordered shell commands. Working directory values remain unchanged after parsing. Call [`WorkspaceFile.Resolve`]() with the document's directory to resolve relative paths before planning. Neither parsing nor resolution contacts tmux or checks directory existence. The default plan refuses an existing session. [`WorkspacePlanOptions`]() can instead select [`Reuse`](), [`Append`](), or [`Replace`](). Reuse returns the inspected session unchanged; append adds windows; replace targets the inspected session while preserving its daemon. These choices do not reconcile arbitrary live state with the declaration. ## Pane readiness The default [`WorkspaceReadiness.Immediate`]() sends commands without waiting for shell readiness or completion. Choose [`Cooperative`]() only when the pane's startup can acknowledge that it accepts input. Each application supplies a fresh `LIBTMUX_WORKSPACE_READY` value to each pane. Startup signals that channel with tmux's `wait-for -S` command. A signal sent before the wait is preserved. The builder closes its waits and stops input to a pane whose readiness timeout expires. This is an explicit startup contract. The builder does not infer readiness from a cursor or prompt, and a startup signal does not acknowledge completion of a later workspace command. ## Construction and failures Inspect [`WorkspacePlan.Actions`]() before calling [`ApplyAsync`](). Planning records creation, input, readiness, host-script, final-capture, and conditional-cleanup actions. Application rechecks the observed daemon and session before running them. Planning observes an interval rather than a transaction; concurrent changes can invalidate its preconditions. Rejected layouts appear in [`WorkspaceResult.Unsupported`](); their windows remain available. Other tmux failures raise [`WorkspaceBuildException`](), whose `PartialResult` identifies materialized state when available. The action journal includes failures, uncertain outcomes, and actions never started. Cancellation during application raises [`WorkspaceOperationCanceledException`]() with the same partial state and journals. `CompensateOnFailure` requests cleanup of resources proven to have been created by that application, under a separate cleanup timeout. Its journal retains cleanup failures. Neither cancellation nor a thrown exception proves rollback; inspect the result and live state before retrying. [Validation and build behavior](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Workspace/README.md) --- # Use the C# workspace builder Source: https://libtmux.org/en/csharp/latest/workspace/internals/guides/ > Parse a workspace, build it on an owned server, and handle partial failures. Use [`WorkspaceFile.Parse`]() to read workspace YAML and [`WorkspaceBuilder.BuildAsync`]() to create its session, windows, and panes. Parsing needs no running tmux server; building requires tmux on a Unix host. Start with the [complete workspace example](https://libtmux.org/en/csharp/latest/workspace/internals/examples/). It includes the program, project file, dependency checkout, and run command for the .NET 10 SDK. The example creates a private server and removes it when the owned scope ends. ## Create an isolated workspace Parse the YAML before opening the server. Create an owned scope with [`Server.CreateOwnedAsync`](), passing a [`ServerConnectionOptions`]() object with the fresh socket name and configuration file. Pass the scope's server to [`WorkspaceBuilder`](), then await [`BuildAsync`]() with a cancellation token. Use `await using` so the scope is disposed even when building throws. The returned [`WorkspaceResult`]() identifies the session and its windows. Inspect [`Unsupported`]() for layouts that tmux rejected after creating their windows. Keep the owned scope alive while your application uses the workspace; disposing it removes its server and the sessions on that server. ## Read a file and handle errors Read the YAML file as text and pass it to [`WorkspaceFile.Parse`](). Resolve relative working directories yourself if they should be based on that file's location. For an existing application server, pass its handle to [`WorkspaceBuilder`]() instead of creating an owned scope. A failed build can leave a partial session. Inspect [`WorkspaceBuildException.PartialResult`]() and decide what to remove; the builder does not roll back changes automatically. The [builder source](https://github.com/libtmux/libtmux-dotnet/blob/320dc64f4b8b7815842471327a5e6b84a1499bf8/src/LibTmux.Workspace/WorkspaceBuilder.cs) describes the build result and partial-failure behavior. See [owned server lifetime](https://github.com/libtmux/libtmux-dotnet/blob/320dc64f4b8b7815842471327a5e6b84a1499bf8/src/LibTmux/Server.Lifecycle.cs) for scope cleanup. --- # C# workspace builder examples Source: https://libtmux.org/en/csharp/latest/workspace/internals/examples/ > Internal examples for building and inspecting workspaces through the C# API. Build a two-window workspace, print its size, and remove its private tmux server. Use a POSIX host with tmux on `PATH` and the .NET 10 SDK. ## Create the project In a new directory, fetch the source revision used by this documentation: ```console $ mkdir dotnet-workspace-example $ cd dotnet-workspace-example $ git init -q libtmux-source $ git -C libtmux-source remote add origin https://github.com/libtmux/libtmux-dotnet.git $ git -C libtmux-source fetch --depth=1 origin 320dc64f4b8b7815842471327a5e6b84a1499bf8 $ git -C libtmux-source checkout --detach FETCH_HEAD ``` Save the following project file. The project reference builds the workspace package and its core dependency from that checkout. ```xml title="WorkspaceExample.csproj" Exe net10.0 disable enable false ``` ## Build and inspect Save this complete program as `Program.cs` beside the project file: ```csharp title="Program.cs" using System; using System.Threading; using System.Threading.Tasks; using LibTmux; using LibTmux.Workspace; internal static class Program { private static async Task Main() { if (OperatingSystem.IsWindows()) throw new PlatformNotSupportedException("This example requires POSIX tmux."); using var deadline = new CancellationTokenSource(TimeSpan.FromSeconds(30)); WorkspaceFile workspace = WorkspaceFile.Parse(""" session_name: built options: default-shell: /bin/sh windows: - window_name: editor panes: - shell_command: echo editing - shell_command: echo watching - window_name: server panes: - shell_command: echo serving """); await using var owned = await Server.CreateOwnedAsync( new ServerConnectionOptions { SocketName = $"workspace-{Guid.NewGuid():N}", ConfigurationFile = "/dev/null", }, deadline.Token); WorkspaceResult result = await new WorkspaceBuilder(owned.Value) .BuildAsync(workspace, deadline.Token); Console.WriteLine($"{result.Session.Name}: {result.Windows.Count} windows"); foreach (string unsupported in result.Unsupported) Console.WriteLine(unsupported); } } ``` Build and run it from the example directory: ```console $ dotnet run --project WorkspaceExample.csproj --configuration Release ``` The program prints `built: 2 windows`. The owned scope removes the server on success or failure. Its unique socket and empty tmux configuration keep the example separate from an existing server. The deadline bounds construction; owned-scope cleanup uses its own lifetime. [`BuildAsync`]() returns after creating the workspace and sending its commands. That does not establish completion of programs running in the panes. A build failure can leave partial results; the owned server scope removes them here. [Workspace API source](https://github.com/libtmux/libtmux-dotnet/tree/320dc64f4b8b7815842471327a5e6b84a1499bf8/src/LibTmux.Workspace) --- # C# workspace builder API Source: https://libtmux.org/en/csharp/latest/workspace/reference/ > Internal reference for the C# workspace builder and configuration APIs. The [`LibTmux.Workspace`]() namespace provides configuration objects and a builder that uses a caller-supplied LibTmux [`Server`](). ## Configuration [`WorkspaceFile`](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacefile/) parses YAML and holds the session description. [`WorkspaceWindow`]() and [`WorkspacePane`]() hold nested configuration. [`WorkspaceFormatException`]() identifies unsupported or invalid configuration. ## Builder options [`WorkspaceBuilder`](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacebuilder/) accepts the server to use. [`PlanAsync`]() validates the declaration and observes that endpoint; its returned [`WorkspacePlan`](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceplan/) lists the actions to review before [`ApplyAsync`]() executes them. Enumerating those actions performs no I/O. Application rechecks the observed daemon and session. [`WorkspacePlanOptions`](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceplanoptions/) controls existing-session conflicts, readiness, host scripts, and cleanup. The defaults refuse an existing session and send pane input immediately. [`BuildAsync`]() combines planning and application with those defaults. Choose [`WorkspaceReadiness.Cooperative`](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacereadiness/) when pane startup can signal its assigned channel. Configure a positive `ReadinessTimeout`; a timeout prevents command delivery to that pane. [Topics](https://libtmux.org/en/csharp/latest/workspace/topics/) explains the startup contract and its limits. ## Results and failures [`WorkspaceResult`](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceresult/) contains the session, created windows, rejected final layouts, and action journals. Reusing an existing session creates no windows. A rejected final layout does not discard its window. [`WorkspaceBuildException`](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacebuildexception/) keeps a `PartialResult` when state could be materialized before failure. It can be null when no such result could be read. `Journal` records action outcomes; `CompensationJournal` records attempted cleanup. Inspect live tmux state before retrying; a missing result does not prove that no command reached tmux. Cancellation during application raises [`WorkspaceOperationCanceledException`](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceoperationcanceledexception/) with the caller's token, partial state, and journals. Cancellation does not imply rollback. `CompensateOnFailure` requests bounded cleanup only of resources proven to belong to that application. [Result contract](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Workspace/WorkspaceResult.cs); [Failure contract](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Workspace/WorkspaceBuildException.cs). ## API declarations - [LibTmux.Workspace.WorkspaceAction](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceaction/) - [LibTmux.Workspace.WorkspaceActionKind](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceactionkind/) - [LibTmux.Workspace.WorkspaceActionOutcome](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceactionoutcome/) - [LibTmux.Workspace.WorkspaceActionState](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceactionstate/) - [LibTmux.Workspace.WorkspaceBuilder](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacebuilder/) - [LibTmux.Workspace.WorkspaceBuildException](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacebuildexception/) - [LibTmux.Workspace.WorkspaceCommand](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacecommand/) - [LibTmux.Workspace.WorkspaceExistingSession](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceexistingsession/) - [LibTmux.Workspace.WorkspaceFile](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacefile/) - [LibTmux.Workspace.WorkspaceFormatException](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceformatexception/) - [LibTmux.Workspace.WorkspaceHostCommand](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacehostcommand/) - [LibTmux.Workspace.WorkspaceHostResult](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacehostresult/) - [LibTmux.Workspace.WorkspaceOperationCanceledException](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceoperationcanceledexception/) - [LibTmux.Workspace.WorkspacePane](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacepane/) - [LibTmux.Workspace.WorkspacePlan](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceplan/) - [LibTmux.Workspace.WorkspacePlanOptions](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceplanoptions/) - [LibTmux.Workspace.WorkspaceReadiness](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacereadiness/) - [LibTmux.Workspace.WorkspaceResult](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceresult/) - [LibTmux.Workspace.WorkspaceServerStartup](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspaceserverstartup/) - [LibTmux.Workspace.WorkspaceWindow](https://libtmux.org/en/csharp/latest/workspace/reference/libtmux-workspace-workspacewindow/) --- # Workspace reference generation Source: https://libtmux.org/en/csharp/latest/workspace/internals/documentation/ > Generate command references from the parser and verify task examples against the CLI. The executable's parser owns its command names, arguments and options. Keep reference generation tied to those definitions. ## Command metadata System.CommandLine owns the command definitions. `--generate reference` exports metadata; `--generate man` writes the manual. See [shell completion](https://libtmux.org/en/csharp/latest/workspace/cli/completion/) for end-user setup. A generated parser reference describes syntax; task examples also need to exercise the underlying services and their cleanup. ## Site integration Record the CLI's own source revision independently from the core library reference. Keep commands, configuration and examples specific to that source. Use the same content selection for HTML, search, Markdown and machine exports. Verify guides against a private tmux server, with cleanup limited to the objects the test owns. Check failure cases as well as successful construction. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Third-party notices Source: https://libtmux.org/en/csharp/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. --- # Exit codes and errors Source: https://libtmux.org/en/csharp/latest/workspace/reference/exit-codes/ > Use process status and structured error codes to handle workspace failures. Check the process status before treating a result as complete. A failed load can report retained effects; a later failure does not undo an earlier input. | Exit status | Meaning | | --- | --- | | `0` | Command completed; an explicitly declined prompt can also finish without changes | | `1` | Workspace validation or operation failure | | `2` | Invalid arguments or execution context | | `130` | Interrupted operation | Child commands such as `edit` can propagate another nonzero child status. Status `70` reports an internal error. ## Machine errors With `--json` or `--ndjson`, diagnostics identify a `code` and readable `message`. Use the code for program decisions and keep the message for users. | Code | Condition | | --- | --- | | `workspace_not_found` | Requested workspace was not found | | `invalid_workspace` | Document shape or value is invalid | | `unsupported_key` | An execution field is unsupported | | `session_not_found` | The selected session does not exist | | `session_mismatch` | Existing session does not match the requested document | | `tmux_unavailable` | tmux cannot be found or used | | `tmux_failed` | A tmux operation failed | | `script_failed` | A bootstrap process failed | | `destination_exists` | A file would be replaced without authorization | | `usage` | Arguments or execution context are invalid | | `interrupted` | A signal stopped the operation | Additional codes describe implementation failures such as a closed output stream, unavailable runtime or log-file failure. Keep unknown codes visible instead of assuming they mean success. See [troubleshooting](https://libtmux.org/en/csharp/latest/workspace/guides/troubleshooting/) for collecting a useful report. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Output formats Source: https://libtmux.org/en/csharp/latest/workspace/reference/output/ > Read JSON results, NDJSON events and diagnostics from the workspace command. Every command accepts `--json` and `--ndjson`. JSON writes one document to stdout. NDJSON writes one JSON record per line and takes precedence if both flags are present. Machine output contains no terminal styling. ## Choose a stream ```console $ tmux-workspace ls --json ``` The shape depends on the operation: listing and search describe workspace records; conversion and import can return the translated document; loading describes completed work and failures. Saving a document returns information about that save. The file's YAML/JSON encoding is controlled separately by `--workspace-format`. Use [automation](https://libtmux.org/en/csharp/latest/workspace/guides/automation/) for a detached load and streamed progress. Read stdout as results and stderr as diagnostics. Check the exit status even when stdout contains valid data. ## Partial work and interrupted streams Load results can contain completed inputs, created IDs and retained effects. Treat a failed operation as partial until its result tells you what remains. A creation event alone does not establish that the workspace finished. An output failure or interruption can leave a final record unwritten or incomplete. A consumer must handle EOF and parse errors. Preserve the exit status and inspect the private server before retrying mutations. ## Child output and logging Machine calls encode captured child text so it cannot be confused with result records. The optional [inspection shell](https://libtmux.org/en/csharp/latest/workspace/cli/shell/) reports its child status along with captured output. A nonzero editor status is propagated. NDJSON can carry child-output records while a command is running. Read the terminal result and child status after those records. `load --log-file PATH` appends diagnostics to a separate file. `--log-level` selects advisory detail. A later log-file failure reports a diagnostic and preserves the operation's result; the log can end with an incomplete record. ## Human output `--color auto|always|never` selects styling; nonempty `NO_COLOR` disables color. Human progress uses the terminal. `--no-progress` disables drawing without hiding errors. Redirected or machine output avoids the progress display. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # Runtime and configuration support Source: https://libtmux.org/en/csharp/latest/workspace/reference/compatibility/ > Runtime requirements and configuration boundaries for the C# workspace command. `tmux-workspace` is the .NET command for loading and capturing tmux workspaces. The [installation guide](https://libtmux.org/en/csharp/latest/workspace/guides/installation/) builds the documented source revision and runs a session on a private socket. The walkthroughs require tmux 3.2a or newer. ## Runtime and execution The CLI has .NET 8 and .NET 10 builds. Keep the selected runtime available, or install the packaged .NET tool. Native services handle loading, capture, discovery, search, conversion, import and editing. Plugins, custom builders and `shell` use an optional interpreter with tmuxp 1.74.0. Set `TMUX_WORKSPACE_PYTHON` to select it. Use detached loading for extension workspaces when terminal handoff is unavailable. [`LibTmux.Workspace`]() is a separate library API. Its parser and builder contract does not define every configuration feature accepted by the CLI. ## Configuration and failure handling Read [configuration](https://libtmux.org/en/csharp/latest/workspace/configuration/) for the CLI's fields. Unsupported execution fields fail visibly; generic [conversion](https://libtmux.org/en/csharp/latest/workspace/cli/convert/) preserves document values without proving that they can be executed. Use [machine output](https://libtmux.org/en/csharp/latest/workspace/reference/output/) for automation and check both the process status and any retained effects. Capture reads live tmux state; it cannot recover original command arguments, scripts, comments or application state. [Examples](https://libtmux.org/en/csharp/latest/workspace/examples/gallery/) provide complete starter documents. Their pane commands can need additional applications and directories when adapted. Use [library internals](https://libtmux.org/en/csharp/latest/workspace/internals/) for the programmatic builder. [CLI source](https://github.com/libtmux/libtmux-dotnet/blob/f77fe776ba67a04abb20ddbbc26cf4a000d63b74/src/LibTmux.Workspace.Cli/README.md). --- # C# MCP topics Source: https://libtmux.org/en/csharp/latest/mcp/topics/ > Choose callable tools, interpret bounded results, and understand pane observation and cancellation. The server selects one tmux endpoint and freezes its offered tools at startup. Read `tmux://capabilities` to inspect that endpoint's provenance and the effective tool selection. ## Select tools [Tool selection](https://libtmux.org/en/csharp/latest/mcp/topics/tool-selection/) explains the four groups, exact-name inclusions, exclusions, and the difference between an unset and an empty selection. A socket limits the tmux objects the process addresses; it does not restrict the operating-system authority of commands running in panes. ## Observe a command [Waits and captured output](https://libtmux.org/en/csharp/latest/mcp/topics/waits-and-output/) distinguishes command completion from terminal text changes. It covers `run_shell_command`, `wait_for_text`, incremental captures, response budgets, and cancellation. An expired wait can leave a command running. ## Resources and prompts The [capability resource](https://libtmux.org/en/csharp/latest/mcp/topics/tool-selection/#inspect-the-connection) reports startup configuration. Read live hierarchy and terminal state through tools. The server offers no workflow prompts or dynamic resource templates. - [Tool selection](https://libtmux.org/en/csharp/latest/mcp/topics/tool-selection/): Combine toolsets, exact names, and exclusions; inspect the frozen capability report. - [Waits and captured output](https://libtmux.org/en/csharp/latest/mcp/topics/waits-and-output/): Read command results, follow a pane, and handle deadlines, truncation, and lost events. --- # Topics Source: https://libtmux.org/en/csharp/latest/topics/ > Object traversal, cleanup, pane I/O, configuration, and failure handling. Use these pages for object traversal, cleanup, pane I/O, configuration, and failure handling. [Concepts](https://libtmux.org/en/csharp/latest/concepts/) introduces the shared object model. The concept guides also cover [control mode vs one-shot](https://libtmux.org/en/csharp/latest/concepts/transports/), [filtering and queries](https://libtmux.org/en/csharp/latest/concepts/queries/), and [workspaces](https://libtmux.org/en/csharp/latest/concepts/workspaces/). Choose a topic for more detailed behavior. Use your port's API reference for signatures and defaults. Each topic explains the behavior behind those calls. - [Architecture](https://libtmux.org/en/csharp/latest/topics/architecture/): Locate operations and field definitions in the library source. - [Traversal](https://libtmux.org/en/csharp/latest/topics/traversal/): Navigate related objects, test membership, and compare identity. - [Ownership and cleanup](https://libtmux.org/en/csharp/latest/topics/context-managers/): Manage cleanup on block exit and identify objects that need a kill. - [Pane interaction](https://libtmux.org/en/csharp/latest/topics/pane-interaction/): Choose input modes, capture ranges, and completion waits. - [Options and hooks](https://libtmux.org/en/csharp/latest/topics/options-and-hooks/): Configure tmux and register event commands at a supported scope. - [Format-token fields](https://libtmux.org/en/csharp/latest/topics/format-tokens/): Read typed state and handle absent fields. - [Waiting and retrying](https://libtmux.org/en/csharp/latest/topics/waiting-and-retry/): Wait on a condition or a named tmux signal. - [Environment](https://libtmux.org/en/csharp/latest/topics/environment/): Locate objects from process variables and configure new panes. - [Socket and servers](https://libtmux.org/en/csharp/latest/topics/socket-and-servers/): Select a server, check liveness, and detect a replacement daemon. - [Errors and exceptions](https://libtmux.org/en/csharp/latest/topics/errors-and-exceptions/): Handle command failures and decide whether a mutation can be retried. --- # Architecture Source: https://libtmux.org/en/csharp/latest/topics/architecture/ > Locate operations, distinguish snapshots from live commands, and find their implementation. A server handle selects a tmux server. Object IDs select sessions, windows, and panes within it. For the object hierarchy and stable IDs, start with [Server, session, window, pane](https://libtmux.org/en/csharp/latest/concepts/server-session-window-pane/). ## Calling operations Session, window, and pane handles carry their ID and server context. Call an operation on the object you want to change. The examples below send input and kill that pane. ```csharp await pane.SendTextAsync("echo hi"); await pane.KillAsync(); ``` ## Reading tmux fields Object IDs become tmux targets (`-t`). Format variables (`#{...}`) provide the state returned by tmux. Typed properties read a dictionary captured from tmux. A property throws [`IncompleteSnapshotException`]() when the capture did not request its field. This differs from a captured field whose value is absent. ## Source layout [`src/LibTmux/`]() splits each entity into partial-class files by concern. For example, [`src/LibTmux/Pane.cs`](), [`src/LibTmux/Pane.Capture.cs`](), [`src/LibTmux/Pane.Input.cs`](), [`src/LibTmux/Pane.Relations.cs`](), [`src/LibTmux/Pane.Scopes.cs`](), and [`src/LibTmux/Pane.Topology.cs`]() contribute to one [`Pane`]() type. `Options` and `Hooks` views are reached through the object's properties. --- # Traversal Source: https://libtmux.org/en/csharp/latest/topics/traversal/ > Moving up and down the server/session/window/pane tree, and the two questions that come up once you have more than one object. Use relationships to move between sessions, windows, and panes. [Server, session, window, pane](https://libtmux.org/en/csharp/latest/concepts/server-session-window-pane/) explains the hierarchy and snapshot model. This page covers relationship calls, collection membership, and object identity. ## Down the hierarchy List children through the parent object or a captured snapshot. Whether a read issues another tmux command depends on the API, independently of whether the call is async; see [Server, session, window, pane](https://libtmux.org/en/csharp/latest/concepts/server-session-window-pane/). Use [`Server.GetSessionsAsync`](), [`Session.GetWindowsAsync`](), and [`Window.GetPanesAsync`]() to read each level of the hierarchy. ## All panes in a session Use a session-wide pane collection when the task spans several windows, such as finding a command or capturing output from every pane. A window linked to multiple sessions still refers to the same tmux panes. Check whether the API reads live state or traverses a captured graph before reusing its result. [`LibTmux.Session.Panes`]() reads the session's captured relations. It does not issue a tmux command; an incomplete capture may lack the required relation. ## Up the hierarchy Parent lookups may read captured data or query tmux again. Check the method's read and failure semantics; [Server, session, window, pane](https://libtmux.org/en/csharp/latest/concepts/server-session-window-pane/) introduces that distinction: Read the [`Pane.Window`]() and [`Window.Session`]() properties. [`.Window`](), [`.Session`](), [`.ActiveWindow`](), and `.ActivePane` read captured state synchronously. They throw [`IncompleteSnapshotException`]() when the capture lacks the required context. ## One walk, down and back up List a session's windows, then look up a parent and compare its identity with the starting object: ```csharp Session session = (await server.GetSessionsAsync())[0]; Window window = (await session.GetWindowsAsync())[0]; Session back = window.Session; // property, read from the captured snapshot back.Equals(session); ``` ## The active child The active window and pane identify where untargeted input goes. Use their accessors or inspect the active flags in a captured snapshot: Read the [`Session.ActiveWindow`]() and [`Window.ActivePane`]() properties. [Format-token fields](https://libtmux.org/en/csharp/latest/topics/format-tokens/) describes the underlying `window_active` and `pane_active` fields. ## Is it in that collection? Checking membership generally goes through whatever your language uses for collection membership, since most of these calls already return an ordinary array, slice, or list: Use standard collection membership operations with the object identity comparison described below. ## Is this the same object? Compare IDs to determine whether two handles refer to the same tmux object on the same server. Check what handle equality includes before using it as an identity test: [`Pane.Equals`]() compares a generation counter and the pane ID. --- # Ownership and cleanup Source: https://libtmux.org/en/csharp/latest/topics/context-managers/ > Scope-based cleanup for tmux objects, and when your program must kill them explicitly. A tmux session, window, or pane normally remains until you kill it. Scope-based cleanup can kill it when your code leaves a block, including after an exception. See [Workspaces](https://libtmux.org/en/csharp/latest/concepts/workspaces/) for a temporary layout example. ## Owned sessions and windows C#'s [`OwnedSessionScope`]() and [`OwnedWindowScope`]() wrap the created object and implement [`IAsyncDisposable`](). The [`Session`]() and [`Window`]() handles themselves are not disposable: ```csharp await using OwnedSessionScope session = await server.CreateOwnedSessionAsync(); await using OwnedWindowScope window = await session.Value.CreateOwnedWindowAsync(); await window.Value.SendTextAsync("echo hello"); // window, then session, killed on the way out ``` For tests that need an owned pane, [`TmuxTestFactory.CreateHierarchyAsync()`]() returns a [`TemporaryHierarchyScope`]() containing a private server, session, window, and pane. Disposing it kills the server. ## Testing cleanup Use explicit cleanup for objects whose handles have no disposal hook. For an entire disposable test server, prefer your port's test fixture or server guard; see [Testing with libtmux](https://libtmux.org/en/csharp/latest/guides/testing-with-libtmux/). --- # Pane interaction Source: https://libtmux.org/en/csharp/latest/topics/pane-interaction/ > Input defaults, screen capture, and waiting for a command to finish. Send input to a pane and capture its screen to interact with a running program. [Attach and send keys](https://libtmux.org/en/csharp/latest/examples/attach-and-send-keys/) provides examples. [Sending keys](https://libtmux.org/en/csharp/latest/guides/sending-keys/) and [Capturing output](https://libtmux.org/en/csharp/latest/guides/capturing-output/) are task guides; this page covers input defaults, capture ranges, and completion handling. ## Typing into a pane Two questions come up every time you send something to a pane: should tmux press Enter afterward, and should tmux interpret what you sent as key names ([`Enter`](), `C-c`) rather than literal characters? Choose both explicitly when a command depends on them. **Type without Enter:** [`SendKeysAsync(new SendKeysRequest(text, enter: false))`]() **Type + Enter (default):** [`SendTextAsync(text)`]() (defaults `enter: true`) **How "literal" is chosen:** [`SendKeysRequest.Literal`]() field; [`SendTextAsync`]() hardcodes it ### Examples Text and Enter can be separate tmux commands. If the second operation fails, the text may already be in the pane. Check the current state before retrying; repeating the whole request can duplicate input. Send a command line and press Enter: ```csharp await pane.SendKeysAsync(new SendKeysRequest("echo hi", enter: false)); await pane.SendTextAsync("echo hi"); // defaults enter: true ``` ## Reading a pane back Capture reads the pane's visible screen by default. Request scrollback when you need earlier output. A capture is a snapshot of terminal contents, including any input echoed by the application. ```csharp await pane.CaptureAsync(); ``` ## Waiting for something to finish A send call completes when input reaches tmux. It does not wait for the shell command to finish. Wait for expected output or a completion signal. Use [`TmuxWaitChannel`]() when the command can signal a named tmux `wait-for` channel. Use a cancellation token to bound the wait. [Capture pane output](https://libtmux.org/en/csharp/latest/examples/capture-pane-output/) shows capture and waiting examples. [Waiting and retrying](https://libtmux.org/en/csharp/latest/topics/waiting-and-retry/) explains completion conditions and timeouts.
tmux manual and source The tmux manual defines [key-name and literal input](https://github.com/tmux/tmux/blob/94796f6b1182507efac8a272fc309a79e22e58a5/tmux.1#L4457) and [screen and history capture](https://github.com/tmux/tmux/blob/94796f6b1182507efac8a272fc309a79e22e58a5/tmux.1#L2798). A send operation delivers input; it does not establish the program's exit status.
--- # Options and hooks Source: https://libtmux.org/en/csharp/latest/topics/options-and-hooks/ > Read and update tmux options, and register commands for tmux events. Use options to change tmux behavior, such as `automatic-rename` or the status-line format. Use hooks to run commands on events such as `session-renamed` or `after-split-window`. Choose the scope supported by the option or hook. ## Reading and writing options Read, set, or unset an option at its supported scope. Distinguish a local override from the effective value inherited from a parent scope. **Read all (this scope):** [`pane.Options.GetAllAsync()`]() **Read effective/inherited:** [`pane.Options.GetAsync(new GetOptionRequest(name, includeInherited: true))`](): an explicit opt-in flag, mapped straight to tmux's own `-A` **Set:** [`pane.Options.SetAsync(new SetOptionRequest(name, value))`]() **Unset:** [`pane.Options.UnsetAsync(...)`]() ### Examples After a successful write completes, read the option to obtain its updated value. The following examples set, read, and unset an option: ```csharp await pane.Options.SetAsync(new SetOptionRequest("automatic-rename", "off")); await pane.Options.GetAllAsync(); await pane.Options.UnsetAsync("automatic-rename"); ``` ## Hooks **Set:** [`pane.Hooks.SetAsync(new SetHookRequest(event, command))`]() **Unset:** [`pane.Hooks.UnsetAsync(...)`]() **List:** [`pane.Hooks.GetAllAsync()`]() **Run now, without the event:** [`pane.Hooks.RunAsync(...)`]() ### Examples tmux stores hook commands in indexed arrays, such as `after-new-window[0]`. Set and list a session hook. The next section explains window and pane scope limitations: ```csharp await session.Hooks.SetAsync(new SetHookRequest("session-renamed", "display-message 'renamed'")); await session.Hooks.GetAllAsync(); ``` ## Supported hook scopes tmux stores hooks globally or per session. Accepted `set-hook -w` or `-p` flags do not imply a separate window or pane hook table, and `show-hooks` does not provide a corresponding listing. Check the event's supported scope if a hook is accepted but never fires. Options have window and pane tables of their own. The hook-scope limitation does not apply to ordinary options. ## tmux version compatibility Check the library's supported tmux versions before using a version-specific option or hook.
tmux manual and source The tmux manual defines [option scopes and inherited reads](https://github.com/tmux/tmux/blob/94796f6b1182507efac8a272fc309a79e22e58a5/tmux.1#L4725). Unsetting a local value restores inheritance. Hook programs run in tmux when their event occurs; see the [hook implementation](https://github.com/tmux/tmux/blob/94796f6b1182507efac8a272fc309a79e22e58a5/cmd-set-option.c).
--- # Format-token fields Source: https://libtmux.org/en/csharp/latest/topics/format-tokens/ > The typed fields every object exposes, mirroring tmux's own format tokens, and why a field is sometimes absent. Object fields expose values from tmux's [FORMATS](https://man.openbsd.org/tmux.1#FORMATS), such as `pane_id`, `window_zoomed_flag`, and `session_name`. The available fields depend on the accessor, object scope, tmux version, and data requested by the read. A token needs the right **scope** and **tmux version**. For example, a pane token needs a pane context, and a token added after your tmux release may be absent. Check the accessor's result before using a field that can be missing, as described below. ## Handling an absent field A nullable value represents an absent value. A field that was not captured can instead raise [`IncompleteSnapshotException`](). These examples read optional fields, including `pane_dead_signal` on tmux 3.3 or newer: Missing values differ from incomplete captures. [`Pane.Title`]() is nullable because tmux may report no title. [`Pane.Height`](), `.Width`, and `.Index` throw [`IncompleteSnapshotException`]() when the read that produced the handle did not request those fields. A handle resolved by ID alone may therefore lack enough data to answer: ```csharp string? title = pane.Title; // nullable: the ordinary absence case int height = pane.Height; // throws IncompleteSnapshotException instead, // if this Pane wasn't captured with a full listing ``` ## Field availability Field accessors retain the scope and version requirements of tmux tokens. Version gates describe tmux behavior: `pane_dead_signal` and `pane_dead_time` arrived in tmux 3.3, and a cluster of pane-geometry and floating-pane tokens (`pane_floating_flag`, `pane_pb_progress`, `pane_x`, `pane_y`, `pane_z`, `pane_zoomed_flag`, `bracket_paste_flag`, `synchronized_output_flag`, among others) arrived together in 3.7. ## Fields promoted from the active child tmux's format engine includes active-child fields when listing a parent. A `list-sessions -F` row can include `window_id` and `pane_id` for the active window and pane. Check the port reference for typed access to those fields, or use the explicit relationships described in [Traversal](https://libtmux.org/en/csharp/latest/topics/traversal/). A pane context can include parent window and session fields. A session cannot identify one attached client when several clients may be attached, so client tokens such as `client_name` require a client context. --- # Waiting and retrying Source: https://libtmux.org/en/csharp/latest/topics/waiting-and-retry/ > Polling a condition instead of guessing a sleep, and tmux's own wait-for signal channel as the alternative to polling. After sending input or starting a process, wait for the state your next step requires. [Pane interaction](https://libtmux.org/en/csharp/latest/topics/pane-interaction/#waiting-for-something-to-finish) covers waiting for screen text. This page covers arbitrary conditions and tmux's named `wait-for` signal channels. ## Polling a condition Polling checks a condition repeatedly until it succeeds or a deadline expires. Set a deadline and choose an interval that limits unnecessary tmux commands. **Helper:** [`LibTmux.Testing.TmuxWait.UntilAsync(probe, timeout, interval)`]() **Where it lives:** the separate [`LibTmux.Testing`]() package ### Examples ```csharp await LibTmux.Testing.TmuxWait.UntilAsync( async ct => (await session.GetWindowsAsync(ct)).Any(w => w.Name == "build"), TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(50)); ``` ## tmux's own wait-for channel Use `tmux wait-for -S ` to signal and `tmux wait-for ` to block until signalled. This avoids repeated screen captures when the command can announce its own completion: [`Server.OpenWaitChannel`]() returns a [`TmuxWaitChannel`](). Keep it in an `await using` scope and call [`WaitAsync`]() with a budget. Select the signal mode to signal the channel. ```csharp await using TmuxWaitChannel channel = server.OpenWaitChannel("built"); bool signalled = await channel.WaitAsync(TimeSpan.FromSeconds(5)); ``` tmux remembers a signal sent before a waiter starts. The next wait on that channel returns immediately, so completion is not lost when the command finishes first. A raw `wait-for` client can exit zero when the server dies, as well as when the channel is signalled. Verify server liveness when a lost server must be treated as a failed task. Use a channel name specific to the task. A remembered signal can otherwise satisfy an unrelated later wait.
tmux manual and source The tmux manual describes [completion channels](https://github.com/tmux/tmux/blob/94796f6b1182507efac8a272fc309a79e22e58a5/tmux.1#L8715). The [channel implementation](https://github.com/tmux/tmux/blob/94796f6b1182507efac8a272fc309a79e22e58a5/cmd-wait-for.c#L388) retains an early signal until a waiter consumes it. Use a fresh channel name for each operation.
--- # Environment Source: https://libtmux.org/en/csharp/latest/topics/environment/ > Locate tmux objects from process variables and manage the environment inherited by new panes. tmux exposes two environment APIs. Process variables such as `TMUX` and `TMUX_PANE` let code inside a pane identify its server and pane. The server also stores variables through `set-environment` and `show-environment` for new processes to inherit. Like the tables in [Options and hooks](https://libtmux.org/en/csharp/latest/topics/options-and-hooks/), this persistent store has explicit scopes. ## Locating yourself from inside a pane Inside a pane, `TMUX` contains `,,`, and `TMUX_PANE` contains the pane ID, such as `%1`. Use these variables to locate the current tmux objects. Select the object your operation needs: **Server:** [`Server.FromEnvironment(env)`]() **Session:** [`Session.FromEnvironmentAsync()`]() **Window:** [`Window.FromEnvironmentAsync()`]() **Pane:** [`Pane.FromEnvironmentAsync()`]() ### Examples ```csharp Server server = Server.FromEnvironment(null); Session session = await Session.FromEnvironmentAsync(); Window window = await Window.FromEnvironmentAsync(); Pane pane = await Pane.FromEnvironmentAsync(); ``` Environment lookup requires valid tmux targeting variables. If your process can run outside tmux, handle that case before using the result. Handle [`TmuxObjectNotFoundException`]() when the environment cannot identify an object. ## tmux's own environment variable store Like [Options and hooks](https://libtmux.org/en/csharp/latest/topics/options-and-hooks/), tmux's persistent environment store has global and per-session scopes. It is read with `show-environment` and updated with `set-environment`. Newly spawned processes inherit it; existing processes retain their own environments. **Set:** [`server.Environment.SetAsync(name, value)`](), [`session.Environment.SetAsync(...)`]() **Read all:** [`server.Environment.GetAllAsync()`]() **Unset:** [`server.Environment.UnsetAsync(name)`](), [`.RemoveAsync(name)`]() ### Examples ```csharp await server.Environment.SetAsync("EDITOR", "vim"); await session.Environment.SetAsync("EDITOR", "hx"); await session.Environment.GetAllAsync(); ``` `set-environment` writes a value. Its `-u` flag removes the entry, while `-r` marks the variable for exclusion from new processes, including values tmux inherited at startup. The listing retains an excluded variable as `-NAME`. Use `.UnsetAsync` for `-u`, or [`.RemoveAsync`]() for `-r`. --- # Socket and servers Source: https://libtmux.org/en/csharp/latest/topics/socket-and-servers/ > Select a server socket, check liveness, and detect a replacement daemon. A tmux server is selected by its Unix-domain socket. Use different sockets for independent servers, such as a development session and an isolated test server. Choose the default socket, a named socket (`-L`), or an explicit path (`-S`). ## Naming a server `new ServerConnectionOptions()` selects the default socket. Supply `socketName` for a named socket or `socketPath` for an explicit path. ```csharp using LibTmux; Server named = await Server.ConnectAsync(new ServerConnectionOptions(socketName: "work")); ``` Choose either a socket name or a socket path. tmux uses `TMUX_TMPDIR` to resolve the directory for default and named sockets. [`ServerConnectionOptions(socketNameFactory: ...)`]() accepts a callable that generates socket names. Use a unique name for each isolated test server. ## Is the server actually there? A server handle does not prove that the target server is running. Use a liveness check when your program needs to distinguish a live server from an unavailable socket: [`Server.IsAliveAsync`]() returns `Task`. ```csharp if (await server.IsAliveAsync()) { await server.GetSessionsAsync(); } ``` ## Killing a server, and telling two apart Killing a server ends all its sessions. Use this only for a server your program owns; for narrower cleanup, kill the session or pane you created. Call [`await server.KillAsync()`]() and handle a cleanup failure before returning. A restarted server can reuse a socket path while having different state. Do not treat a matching path as proof that a cached object still exists. --- # Tool selection Source: https://libtmux.org/en/csharp/latest/mcp/topics/tool-selection/ > Choose the C# MCP server's callable operations and interpret its startup capability report. The server registers its callable tools once at startup. Select groups with `LIBTMUX_TOOLSETS`, add individual tools with `LIBTMUX_TOOLS`, and remove tools with `LIBTMUX_EXCLUDE_TOOLS`. Reconnect the client after changing a selection. ## Choose groups The groups are unordered. Selecting one does not imply the others. | Toolset | Use it for | | --- | --- | | `inspect` | Session, window, and pane discovery; terminal reads and text waits. | | `manage` | Topology, layout, naming, options, hooks, and environment changes. | | `execute` | Sending input and running commands. | | `teardown` | Removing sessions, windows, panes, or the server. | For an inspection client, set `LIBTMUX_TOOLSETS` to `inspect`. The [complete client example](https://libtmux.org/en/csharp/latest/mcp/examples/inspect-sessions/) verifies both an included tool and an absent execution tool through discovery. When the variable is absent, defaults depend on the chosen endpoint. A newly created dedicated daemon with the launcher's minimal configuration can receive all four groups. Existing and explicitly configured endpoints omit teardown unless you request it. Read `tmux://capabilities` to see which default applied. An entirely empty `LIBTMUX_TOOLSETS` value selects no groups. This is useful when adding only particular tools. A nonempty list cannot contain empty segments: `inspect,`, `,inspect`, and `inspect,,manage` are startup errors. Names are case-sensitive; surrounding whitespace on a valid token is trimmed. ## Add and exclude exact names This environment configuration offers only the two named hierarchy tools: ```json { "LIBTMUX_TOOLSETS": "", "LIBTMUX_TOOLS": "list_sessions,list_windows" } ``` This selection enables inspection while removing environment reads: ```json { "LIBTMUX_TOOLSETS": "inspect", "LIBTMUX_EXCLUDE_TOOLS": "show_environment" } ``` Inclusions add tools after groups are selected. Exclusions apply last, even when a tool was explicitly included. Unknown toolset or tool names stop startup. Unlike `LIBTMUX_TOOLSETS`, an explicitly empty `LIBTMUX_TOOLS` or `LIBTMUX_EXCLUDE_TOOLS` value is invalid; omit an unused variable. Tool selection changes both discovery and dispatch. A tool removed from the effective selection cannot be called by guessing its name. The [tool reference](https://libtmux.org/en/csharp/latest/mcp/tools/) lists the full catalog, which can be broader than the set offered by a particular connection. ## Read several facts [`call_read_tools_batch`](https://libtmux.org/en/csharp/latest/mcp/tools/call_read_tools_batch/) executes a bounded list of typed inspection operations serially. Each operation names a tool and supplies that tool's normal arguments. `onError` chooses whether the batch stops at the first failure or continues. Select the batch tool and the operations you intend to call, through a toolset or by exact name. Those operations also appear as individual tools. This configuration offers the batch and `list_sessions`: ```json { "LIBTMUX_TOOLSETS": "", "LIBTMUX_TOOLS": "call_read_tools_batch,list_sessions" } ``` The server omits the batch when no nested operation is selected. Exclusions remove operations from its schema and dispatch as well. Inspect the batch's `nestedAuthority` capability field for the allowed operations. The pinned [selection implementation](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L251-L281) applies the same selection to individual tools and nested operations. Check the status and nested MCP result for each completed row. A successful outer request does not imply that every nested operation succeeded. A batch can also omit nested payloads to fit its aggregate result bound; its result reports that omission. Operations are separate reads, so a hierarchy can change between them. ## Inspect the connection Read `tmux://capabilities` after connecting. It includes the frozen socket selection, ownership provenance, effective toolsets and tools, and pane observation policy. Each tool has a capability record describing its process reach, tmux effects, output classes, and nested operations. The same per-tool record appears in discovery under `_meta["com.git-pull.libtmux-mcp/capability"]`. Use current hierarchy tools for live session and pane state; the resource describes startup configuration. There are no dynamic resource templates or workflow prompts. ## Execution authority Tool filters shape the interface. They do not provide an operating-system sandbox. Commands execute with the tmux user's filesystem, process, network, and credential access. Selecting a socket confines which tmux objects a call can address, not what a process inside those objects can do. Inspection tools can expose secrets in terminal text or environment values. Captured terminal content can include instructions written by another process; receiving it through a tool does not make those instructions trusted. MCP annotations describe tools for clients and consent interfaces. They do not enforce a separate authorization policy. See the pinned [selection parser](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Mcp/Policy/CapabilitySelection.cs), [capability resource](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Mcp/Resources/CapabilityResource.cs), and [protocol behavior](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/docs/mcp/README.md) for the behavior documented here. --- # Errors and exceptions Source: https://libtmux.org/en/csharp/latest/topics/errors-and-exceptions/ > Handle command failures, inspect delivery status, and decide when a retry is safe. A command can fail because tmux rejects it, or because the transport stops before returning a reply. Inspect the reported error and delivery state before retrying a mutation: tmux may already have received it. For lookup failures caused by zero or multiple matches, see [Filtering and queries](https://libtmux.org/en/csharp/latest/concepts/queries/#the-cardinality-contract-side-by-side). ## A failed command, as a value Failures raise subclasses of [`LibTmuxException`](), including [`TmuxCommandException`](), [`TmuxTransportException`](), and [`TmuxObjectNotFoundException`](). ## Is it safe to retry? Retry a mutation automatically only when you know it was not dispatched, or when repeating it is safe for your operation. A timeout, cancellation, or dropped connection can occur after tmux has acted. These APIs expose delivery information: [`LibTmuxException.Dispatch`]() reports a [`TmuxDispatchState`](): [`NotDispatched`](), [`Dispatched`](), or [`Unknown`](). Treat the default, [`Unknown`](), as potentially dispatched. ```csharp try { await session.CreateWindowAsync(new NewWindowRequest(name: "build")); } catch (LibTmuxException error) when (error.Dispatch == TmuxDispatchState.NotDispatched) { // safe to retry } ``` Treat unknown delivery as potentially executed. [`NotDispatched`]() identifies a request that did not reach tmux. For subprocess calls that complete normally, inspect the exit status. If a call is interrupted or times out without a delivery state, check tmux's resulting state before repeating a mutation. --- # Waits and captured output Source: https://libtmux.org/en/csharp/latest/mcp/topics/waits-and-output/ > Choose command completion or text observation, handle bounded captures, and cancel the right operation. Use a command's exit status to determine whether it finished successfully. Use terminal text observation when the process was started elsewhere or a long-running service needs to report readiness. A text match does not prove that a command exited. ## Command results [`run_shell_command`](https://libtmux.org/en/csharp/latest/mcp/tools/run_shell_command/) sends a command to a selected pane and waits for a tmux completion signal. Check the MCP result's `isError` before interpreting its structured result, then read `exitStatus`, `timedOut`, and `output`. An unsuccessful shell exit and a tool failure are different results. The shell can finish with a nonzero exit status while the MCP exchange succeeds. If the wait times out or is cancelled, the command may still be running. Inspect the pane before retrying or sending more input; a second submission can start duplicate work. `started: false` means the command wrapper was not seen to begin, usually because the pane was not at an empty shell prompt. `paneExited` reports that the pane's program ended before returning a status. Neither case provides a successful shell exit. The [complete command example](https://libtmux.org/en/csharp/latest/mcp/examples/run-command/) checks these fields along with captured output. The command must target a pane that can accept the intended shell input. Input refuses modal targets rather than leaving a human's copy mode for them. `run_shell_command` also refuses a configured synchronized-input cohort larger than one pane. These checks observe current state; they are not atomic transactions with later tmux input delivery. ## Wait for text [`wait_for_text`](https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_text/) reads the pane and observes control-mode notifications for changes. Notifications wake the wait; returned text comes from a capture of tmux's rendered pane, not the raw event stream. Layout and window-close events can also trigger a fresh read. Control startup failure or stream loss ends the wait by default. Set `LIBTMUX_MCP_ALLOW_POLLING_FALLBACK=true` only when repeated pane captures are acceptable. Fallback waits 60 milliseconds between reads and remains bounded by the original deadline and cancellation token. The capability resource reports the configured policy, and an activated fallback reports `pollingFallback: true` in the wait result. `eventsDropped` reports lost session notifications while the wait held its observer. That count can include other panes in the session. The server reads the current pane again, but a fresh capture cannot reconstruct intermediate output that is no longer available. A match establishes what the capture contained, not a complete terminal transcript. Polling fallback applies to pane text waits. `run_shell_command` and [`wait_for_channel`](https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_channel/) use tmux rendezvous signals independently of that setting. ## Follow a pane Use [`capture_pane`](https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/) for a bounded text capture or [`snapshot_pane`](https://libtmux.org/en/csharp/latest/mcp/tools/snapshot_pane/) when pane metadata and content should be returned together. Use [`capture_since`](https://libtmux.org/en/csharp/latest/mcp/tools/capture_since/) to read subsequent output across several requests. The first `capture_since` call omits a cursor and establishes a position. Keep its returned opaque cursor and supply it on the next call for that same pane. Cursors are authenticated and bound to the socket, daemon generation, and pane. They cannot move between panes or servers, and restarting the MCP process expires them. Omit an expired cursor to establish a new baseline. Inspect the content's truncation and dropped-line or dropped-byte fields. A successful capture can be incomplete. Narrow the requested history or increase a relevant limit when the missing text matters to the task. ## Response limits Startup policy bounds waits and returned data: | Variable | Default | Accepted range | | --- | --- | --- | | `LIBTMUX_MCP_WAIT_MAX_SECONDS` | 30 seconds | 1–600 seconds | | `LIBTMUX_MCP_MAX_LINES` | 500 lines | 10–100,000 lines | | `LIBTMUX_MCP_MAX_BYTES` | 128,000 bytes | 4,000–4,000,000 bytes | Numeric values outside those ranges are clamped. Invalid values fall back to the default and produce a stderr diagnostic. These are ceilings or defaults; individual tool arguments and schemas can impose tighter bounds. The byte budget covers serialized results, including text, structured content, and metadata. It is not a raw terminal-text byte count. JSON escaping and duplicate representations can increase the serialized size. Content tools truncate within the budget and report the loss. A result that still cannot fit becomes a bounded error explaining how to narrow the call or adjust the ceiling. ## Cancellation A plain pending MCP request is cancelled with `notifications/cancelled` for its JSON-RPC request ID. A client-side timeout alone does not establish that the server received that notification. Check the client's cancellation behavior when prompt observer cleanup matters. When using the protocol's task support, cancel the task with `tasks/cancel` and its task ID. Cancelling the request that created a task does not cancel the task's work. Task-status polling is separate from polling pane contents. Wait cleanup releases the control observer. Cancelling the wait does not terminate a shell command already running in the pane. The server does not provide a separate detached command-job registry. These rules come from the pinned [protocol guide](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/docs/mcp/README.md) and [server policy](https://github.com/libtmux/libtmux-dotnet/blob/ec8b6ab2a4f65e23664f43fba538ba200d4ae8bc/src/LibTmux.Mcp/Policy/ServerPolicy.cs). --- # C# MCP tools Source: https://libtmux.org/en/csharp/latest/mcp/tools/ > Tools, resources, and prompts advertised by the C# MCP server. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Use the wire name shown here when calling a tool. The C# server advertises 45 tools with the reference configuration below. Your client’s list follows the policy configured for its server. Read the [setup guide](https://libtmux.org/en/csharp/latest/mcp/guides/) before choosing tool access. The [language API reference](https://libtmux.org/en/csharp/latest/mcp/reference/) covers embedding and implementation types. [Download the protocol catalog as JSON](https://libtmux.org/en/csharp/latest/mcp/tools.json). Reference configuration * `LIBTMUX_TOOLSETS` `inspect,manage,execute,teardown` Protocol version: `2025-11-25`. ## Tools * [`call_read_tools_batch`](https://libtmux.org/en/csharp/latest/mcp/tools/call_read_tools_batch/) Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Execute up to 16 declared inspect operations serially; inner operations receive no separate approval. * [`capture_pane`](https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/) Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Read the text a pane is showing, and optionally its scrollback. The newest lines are always kept; anything dropped to fit the budget is reported. To watch a pane across several turns, use capture_since instead — it returns only what is new. * [`capture_since`](https://libtmux.org/en/csharp/latest/mcp/tools/capture_since/) Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Read only what a pane has printed since the last call. Pass back the cursor each time. Use this to watch a long-running process across turns: the tenth read costs what the first did, where re-capturing the pane would return everything again. Call with no cursor to start watching from now. * [`clear_pane_scrollback`](https://libtmux.org/en/csharp/latest/mcp/tools/clear_pane_scrollback/) Delete tmux state; accepts no command payload. Delete a pane's scrollback history, keeping what the screen shows. Deleted history cannot be read back. * [`create_session`](https://libtmux.org/en/csharp/latest/mcp/tools/create_session/) Start a pane's configured process; accepts no command payload. Create a detached tmux session and return its ids. Give a width and height when nothing will attach to it: a session with no client keeps tmux's default 80x24, which truncates wide output. * [`create_window`](https://libtmux.org/en/csharp/latest/mcp/tools/create_window/) Start a pane's configured process; accepts no command payload. Create a window in a tmux session and return its ids. * [`find_pane_by_position`](https://libtmux.org/en/csharp/latest/mcp/tools/find_pane_by_position/) Inspect tmux metadata; accepts no client-supplied executable input. Find the pane sitting at an index within a window. Answers nothing rather than failing when no pane is at that position. * [`get_pane_info`](https://libtmux.org/en/csharp/latest/mcp/tools/get_pane_info/) Inspect tmux metadata; accepts no client-supplied executable input. Read one pane's size, title, running command, working directory, process ID, history size and limit, and whether it is active, dead, zoomed, in a mode or the pane this server runs in. This is metadata only; to read what the pane shows, use capture_pane or snapshot_pane. * [`get_server_info`](https://libtmux.org/en/csharp/latest/mcp/tools/get_server_info/) Inspect tmux metadata; accepts no client-supplied executable input. Read the tmux server's version and how many sessions, windows and panes it holds. Use to confirm a socket is alive and which tmux is running it. * [`get_session_info`](https://libtmux.org/en/csharp/latest/mcp/tools/get_session_info/) Inspect tmux metadata; accepts no client-supplied executable input. Read one session's name, ID, window count and whether a client is attached, without listing every session. Give the session, or a window ID to read the session that holds it. * [`get_tmux_variables`](https://libtmux.org/en/csharp/latest/mcp/tools/get_tmux_variables/) Read configured tmux commands; accepts no client-supplied executable input. Returned values may contain executable configuration. Expand named tmux format variables for a pane, such as session_name or window_width. Use it for fields nothing else answers; get_pane_info already returns the common ones, and show_option reads configuration rather than live state. * [`get_window_info`](https://libtmux.org/en/csharp/latest/mcp/tools/get_window_info/) Inspect tmux metadata; accepts no client-supplied executable input. Read one window's name, index, size, layout, pane count and whether it is its session's current window, without listing every window. Give the window ID, or a pane ID to read the window that holds it. * [`kill_pane`](https://libtmux.org/en/csharp/latest/mcp/tools/kill_pane/) Delete tmux state; accepts no command payload. Close a pane and end its program. Refuses the pane this server runs in; to remove a whole window, use kill_window. * [`kill_session`](https://libtmux.org/en/csharp/latest/mcp/tools/kill_session/) Delete tmux state; accepts no command payload. Close a session with all its windows and panes. Refuses the session this server runs in. * [`kill_window`](https://libtmux.org/en/csharp/latest/mcp/tools/kill_window/) Delete tmux state; accepts no command payload. Close a window and every pane in it. Refuses the window this server runs in. * [`list_panes`](https://libtmux.org/en/csharp/latest/mcp/tools/list_panes/) Inspect tmux metadata; accepts no client-supplied executable input. List tmux panes, optionally within one session or window. Filter for isCaller=true to answer 'which pane am I in?', which finds one only when this server drives the caller's own socket — get_server_info says whose socket that is. This reads sizes and running commands, not terminal text — for that use search_panes. * [`list_sessions`](https://libtmux.org/en/csharp/latest/mcp/tools/list_sessions/) Inspect tmux metadata; accepts no client-supplied executable input. List the tmux sessions. This reads names and sizes, not terminal text — to find what a pane is showing, use search_panes. * [`list_windows`](https://libtmux.org/en/csharp/latest/mcp/tools/list_windows/) Inspect tmux metadata; accepts no client-supplied executable input. List tmux windows, optionally within one session. This reads names and layouts, not terminal text — to find what a pane is showing, use search_panes. * [`move_window`](https://libtmux.org/en/csharp/latest/mcp/tools/move_window/) Change tmux state; no client-supplied executable input. Move a window to another index, or into another session. With replaceExisting it takes an index that is already occupied by killing the window there, which needs the teardown toolset. * [`paste_text`](https://libtmux.org/en/csharp/latest/mcp/tools/paste_text/) Send input to a pane's program; a shell that receives it runs it with your user's permissions. Paste a block of text into exactly one pane through a tmux buffer. Use for multi-line text, or anything an editor would mangle if typed — bracketed paste stops auto-indent. Set enter to append a newline to that same private buffer. It refuses a target in a human-owned mode and never fans out to synchronized siblings. The temporary buffer is deleted afterwards; if cleanup fails, the result identifies what remains. * [`rename_session`](https://libtmux.org/en/csharp/latest/mcp/tools/rename_session/) Change tmux state; no client-supplied executable input. Rename a tmux session. Its id does not change, so anything holding one still works. * [`rename_window`](https://libtmux.org/en/csharp/latest/mcp/tools/rename_window/) Change tmux state; no client-supplied executable input. Rename a tmux window. Its id does not change. * [`resize_pane`](https://libtmux.org/en/csharp/latest/mcp/tools/resize_pane/) Change tmux state; no client-supplied executable input. Resize a pane, or zoom it to fill its window. Widening a pane before reading it is the fix for output that comes back wrapped across rows. * [`resize_window`](https://libtmux.org/en/csharp/latest/mcp/tools/resize_window/) Change tmux state; no client-supplied executable input. Resize a window to a width and height in cells; its panes resize with it. To resize one pane, use resize_pane. * [`respawn_pane`](https://libtmux.org/en/csharp/latest/mcp/tools/respawn_pane/) Start a pane's configured process; accepts no command payload. Only restarts a pane whose command has ALREADY EXITED. killExistingProcess overrides that and kills what is running first — an editor holding unsaved changes, a build part way through. It reruns the command the pane was created with rather than running something new. * [`run_shell_command`](https://libtmux.org/en/csharp/latest/mcp/tools/run_shell_command/) Run a shell command in a pane with your user's permissions. Run a shell command in one pane, wait for it to finish, and report its singular real exit status and output. This is the tool for 'run X and tell me if it worked'. It reaches only the pane you name: the command travels through a tmux buffer, which synchronize-panes does not fan out, so the exit status is one pane's. Use send_keys when you want a synchronized cohort to receive input. Do NOT send keys and then poll a capture in a loop — this waits deterministically and costs one call. The command runs in a subshell, so cd and export do not persist. It refuses the named pane in a human-owned mode. Check linesMissed and anchorLost. A timed-out command MAY STILL BE RUNNING; inspect it and do not retry it — unless started is false, which means it never ran because something other than an idle shell was reading that pane's input. * [`search_panes`](https://libtmux.org/en/csharp/latest/mcp/tools/search_panes/) Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Find which panes are showing text matching a regular expression. This is the tool for 'which pane has the error', 'where is the build running', or any question about what a pane CONTAINS — the list tools only see names and sizes. * [`select_layout`](https://libtmux.org/en/csharp/latest/mcp/tools/select_layout/) Change tmux state; no client-supplied executable input. Arrange a window's panes with a named layout — even-horizontal, even-vertical, main-horizontal, main-vertical, tiled — or a layout string read from list_windows. * [`select_pane`](https://libtmux.org/en/csharp/latest/mcp/tools/select_pane/) Change tmux state; no client-supplied executable input. Make a pane the active one in its window. This changes what a watching human sees; targeting a pane by id does not require selecting it first. * [`select_window`](https://libtmux.org/en/csharp/latest/mcp/tools/select_window/) Change tmux state; no client-supplied executable input. Make a window the current one in its session. * [`send_keys`](https://libtmux.org/en/csharp/latest/mcp/tools/send_keys/) Send input to a pane's program; a shell that receives it runs it with your user's permissions. Send raw keystrokes to a pane and return immediately. Use for driving an interactive program — a key in vim, a menu choice, Ctrl-C. Set literal=false to send named keys such as C-c, Escape or F5. It refuses the named pane in a human-owned mode and, when source input expands, every synchronized input cohort peer. To run a shell command and learn whether it worked, use run_shell_command instead; this reports nothing about what happens next. Tracks what it sends — including edits such as backspace, Ctrl-U or Ctrl-C — so wait_for_text can tell this pane's echo apart from real output for a short time afterward. * [`send_keys_batch`](https://libtmux.org/en/csharp/latest/mcp/tools/send_keys_batch/) Send input to a pane's program; a shell that receives it runs it with your user's permissions. Send several keystrokes to one pane in order, in a single call. Use for a short interactive sequence — open a file, move, type, save — instead of one call per key. Each operation refuses the named pane in a human-owned mode and, when source input expands, every synchronized input cohort peer. A batch has at most 64 steps and 64 KiB of UTF-8 text. Each delay is 0-2000 ms and all delays together must fit the server wait ceiling. * [`set_history_limit`](https://libtmux.org/en/csharp/latest/mcp/tools/set_history_limit/) Change tmux state; no client-supplied executable input. Set how many scrollback lines tmux keeps. This is a SESSION option, so it covers every window in the session rather than one pane, and the session must be named because the call can destroy data. Raise it before starting something that prints a lot: no capture can return lines tmux has already discarded. LOWERING it discards the excess from every pane immediately, and the result says how many lines went; raising the limit again does not bring them back. * [`set_mouse_enabled`](https://libtmux.org/en/csharp/latest/mcp/tools/set_mouse_enabled/) Change tmux state; no client-supplied executable input. Turn tmux mouse support on or off. This sets the global option, so it applies to every session on this server and changes what a human watching can do with their mouse. * [`set_pane_title`](https://libtmux.org/en/csharp/latest/mcp/tools/set_pane_title/) Change tmux state; no client-supplied executable input. Set a pane's title. Useful for labelling panes you created so a human watching can tell which is which. * [`set_synchronize_panes`](https://libtmux.org/en/csharp/latest/mcp/tools/set_synchronize_panes/) Change tmux state; no client-supplied executable input. Turn synchronize-panes on or off for a window. Input typed into one of its panes then reaches the synchronized input cohort: every pane whose effective synchronize-panes setting is on. A pane without a setting of its own follows the window; one with its own setting stays included or excluded either way. * [`show_environment`](https://libtmux.org/en/csharp/latest/mcp/tools/show_environment/) Read the tmux environment; accepts no client-supplied executable input. A listing answers names without values, and a named variable is still withheld when the name reads as a credential. Read what a NEW pane will inherit, at the server or session level — not what an already-running shell has. * [`show_hooks`](https://libtmux.org/en/csharp/latest/mcp/tools/show_hooks/) Read configured tmux commands; accepts no client-supplied executable input. Returned values may contain executable configuration. Read the hooks tmux will run on its own events. Read-only on purpose: a hook written here would outlive this conversation and keep firing with nobody left who knows why. Put hooks you want to keep in your tmux config file. * [`show_option`](https://libtmux.org/en/csharp/latest/mcp/tools/show_option/) Read configured tmux commands; accepts no client-supplied executable input. Returned values may contain executable configuration. Read tmux options at the server, session, window or pane level. Values set at a wider scope are included and marked inherited, because that is where nearly all tmux configuration lives. Omit the name to list them all. Reading history-limit before a long tail tells you how much output the pane can hold before it starts dropping lines. * [`signal_channel`](https://libtmux.org/en/csharp/latest/mcp/tools/signal_channel/) Change tmux state; no client-supplied executable input. Signal a tmux wait-for channel, releasing whatever waits on it. The channel latches: signalling before anyone waits still satisfies the next wait, so a handoff cannot be lost to a race. * [`snapshot_pane`](https://libtmux.org/en/csharp/latest/mcp/tools/snapshot_pane/) Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Read a pane's visible content together with its cursor position, size and running command, in one call. Prefer this over capture_pane plus list_panes: it is one round trip and the cursor is guaranteed to describe the text returned with it. * [`split_window`](https://libtmux.org/en/csharp/latest/mcp/tools/split_window/) Start a pane's configured process; accepts no command payload. Split a pane and return the NEW pane's id. Use that id for what you put in it — pane ids stay valid across layout changes, where window names and indexes do not. * [`swap_pane`](https://libtmux.org/en/csharp/latest/mcp/tools/swap_pane/) Change tmux state; no client-supplied executable input. Swap two panes' positions; each keeps its program, its content and its ID. * [`wait_for_channel`](https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_channel/) Change tmux state; no client-supplied executable input. Block until something signals a tmux wait-for channel with 'tmux wait-for -S \'. Use when you composed a shell command that signals it. For an ordinary command whose completion you want, run_shell_command already does this and also reports the exit status. * [`wait_for_text`](https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_text/) Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Wait until a pane prints something matching one of these patterns, then return. Use for output you did NOT start — a server's ready line, another process's progress, a person typing. A matching pattern already on screen returns PresentAtEntry. For a command you are running yourself, run_shell_command is better: it reports the real exit status instead of guessing from text. Never poll capture_pane in a loop; this call does the waiting. Control observation is required by default; pollingFallback reports activation when the operator permits fallback. Text this server itself typed is discounted while deciding what is new, for a few seconds after it is sent or submitted, so its own echo cannot be the match — except on a pane whose program has not yet configured its terminal; wait for a first prompt before typing into a freshly created pane. ## Resources * `tmux://capabilities` The startup-frozen tmux connection and effective MCP tool capabilities. ## Resource templates This server does not advertise resource templates in this configuration. ## Prompts This server does not advertise prompts in this configuration. Source revision: [libtmux/libtmux-dotnet@cf34b255c896d19a97e7d7fabea58609c916012d](https://github.com/libtmux/libtmux-dotnet/tree/cf34b255c896d19a97e7d7fabea58609c916012d). --- # call_read_tools_batch Source: https://libtmux.org/en/csharp/latest/mcp/tools/call_read_tools_batch/ > Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Execute up to 16 declared inspect operations serially; inner operations receive no separate approval. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Execute up to 16 declared inspect operations serially; inner operations receive no separate approval. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/call_read_tools_batch.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L586) ## Arguments * `onError` optional · string Stop after the first failed operation, or continue serially. Default: `"stop"`. * `operations` required · array Between 1 and 16 declared inspect calls, executed serially without separate approval for each inner operation. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "onError": { "default": "stop", "description": "Stop after the first failed operation, or continue serially.", "enum": [ "continue", "stop" ], "type": "string" }, "operations": { "description": "Between 1 and 16 declared inspect calls, executed serially without separate approval for each inner operation.", "items": { "oneOf": [ { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "includeHistory": { "default": false, "description": "Include scrollback.", "type": "boolean" }, "joinWrappedLines": { "default": false, "description": "Rejoin tmux-wrapped lines.", "type": "boolean" }, "maxLines": { "default": null, "description": "Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] } }, "type": "object" }, "tool": { "const": "capture_pane" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "cursor": { "default": null, "description": "The opaque cursor returned by the previous call. Omit to start from what is on screen now.", "type": [ "string", "null" ] }, "maxLines": { "default": null, "description": "Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] } }, "type": "object" }, "tool": { "const": "capture_since" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "position": { "description": "The zero-based pane index.", "maximum": 2147483647, "minimum": -2147483648, "type": "integer" }, "windowId": { "description": "The window id.", "type": "string" } }, "required": [ "windowId", "position" ], "type": "object" }, "tool": { "const": "find_pane_by_position" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "paneId": { "description": "A pane id.", "type": "string" } }, "required": [ "paneId" ], "type": "object" }, "tool": { "const": "get_pane_info" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": {}, "type": "object" }, "tool": { "const": "get_server_info" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "session": { "description": "A session id or name.", "type": "string" } }, "required": [ "session" ], "type": "object" }, "tool": { "const": "get_session_info" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "names": { "description": "Variable names such as session_name, without #{...}. Between 1 and 64 names, each at most 64 letters, digits and underscores.", "items": { "type": "string" }, "type": "array" }, "paneId": { "default": null, "description": "A pane id used as the lookup context. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] } }, "required": [ "names" ], "type": "object" }, "tool": { "const": "get_tmux_variables" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "windowId": { "description": "A window id.", "type": "string" } }, "required": [ "windowId" ], "type": "object" }, "tool": { "const": "get_window_info" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "session": { "default": null, "description": "A session id or name. Omit for every session.", "type": [ "string", "null" ] }, "windowId": { "default": null, "description": "A window id. Omit for every window.", "type": [ "string", "null" ] } }, "type": "object" }, "tool": { "const": "list_panes" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": {}, "type": "object" }, "tool": { "const": "list_sessions" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "session": { "default": null, "description": "A session id or name. Omit for every session.", "type": [ "string", "null" ] } }, "type": "object" }, "tool": { "const": "list_windows" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "ignoreCase": { "default": true, "description": "Ignore case.", "type": "boolean" }, "includeHistory": { "default": false, "description": "Search scrollback too.", "type": "boolean" }, "maxMatchesPerPane": { "default": 20, "description": "Maximum matches per pane.", "maximum": 2147483647, "minimum": -2147483648, "type": "integer" }, "pattern": { "description": "A linear-time regular expression, at most 999 UTF-8 bytes. .NET syntax without lookarounds, backreferences or atomic groups.", "type": "string" }, "session": { "default": null, "description": "A session id or name. Omit for every session.", "type": [ "string", "null" ] } }, "required": [ "pattern" ], "type": "object" }, "tool": { "const": "search_panes" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "name": { "default": null, "description": "One variable name, which answers its value. Omit for every name with hasValue instead of values.", "type": [ "string", "null" ] }, "session": { "default": null, "description": "A session id or name. Omit for the server environment.", "type": [ "string", "null" ] } }, "type": "object" }, "tool": { "const": "show_environment" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "paneId": { "default": null, "description": "The pane whose scope is read. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "scope": { "default": "Session", "description": "Server, Session, Window, or Pane.", "enum": [ "Server", "Session", "Window", "Pane" ], "type": "string" } }, "type": "object" }, "tool": { "const": "show_hooks" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "name": { "description": "The option name.", "type": "string" }, "paneId": { "default": null, "description": "The pane whose scope is read. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "scope": { "default": "Pane", "description": "Server, Session, Window, or Pane.", "enum": [ "Server", "Session", "Window", "Pane" ], "type": "string" } }, "required": [ "name" ], "type": "object" }, "tool": { "const": "show_option" } }, "required": [ "tool" ], "type": "object" }, { "additionalProperties": false, "properties": { "arguments": { "additionalProperties": false, "properties": { "maxLines": { "default": null, "description": "Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] } }, "type": "object" }, "tool": { "const": "snapshot_pane" } }, "required": [ "tool" ], "type": "object" } ] }, "maxItems": 16, "minItems": 1, "type": "array" } }, "required": [ "operations" ], "type": "object" } ``` Output schema ```json { "properties": { "failed": { "type": "integer" }, "onError": { "type": "string" }, "results": { "items": { "properties": { "error": { "type": [ "string", "null" ] }, "index": { "type": "integer" }, "result": true, "resultTruncated": { "type": "boolean" }, "success": { "type": "boolean" }, "tool": { "type": "string" } }, "required": [ "index", "tool", "success", "error", "result", "resultTruncated" ], "type": "object" }, "type": "array" }, "stoppedAt": { "type": [ "integer", "null" ] }, "succeeded": { "type": "integer" }, "truncated": { "type": "boolean" }, "truncatedBytes": { "type": "integer" } }, "required": [ "results", "succeeded", "failed", "stoppedAt", "truncated", "truncatedBytes", "onError" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Call read tools batch" } ``` --- # capture_pane Source: https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/ > Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Read the text a pane is showing, and optionally its scrollback. The newest lines are always kept; anything dropped to fit the budget is reported. To watch a pane across several turns, use capture_since instead — it returns only what is new. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Read the text a pane is showing, and optionally its scrollback. The newest lines are always kept; anything dropped to fit the budget is reported. To watch a pane across several turns, use [capture_since](https://libtmux.org/en/csharp/latest/mcp/tools/capture_since/) instead — it returns only what is new. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L576) ## Arguments * `includeHistory` optional · boolean Include scrollback. Default: `false`. * `joinWrappedLines` optional · boolean Rejoin tmux-wrapped lines. Default: `false`. * `maxLines` optional · integer | null Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another. Default: `null`. * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "includeHistory": { "default": false, "description": "Include scrollback.", "type": "boolean" }, "joinWrappedLines": { "default": false, "description": "Rejoin tmux-wrapped lines.", "type": "boolean" }, "maxLines": { "default": null, "description": "Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "content": { "properties": { "droppedBytes": { "type": "integer" }, "droppedLines": { "type": "integer" }, "lines": { "items": { "type": "string" }, "type": "array" }, "truncated": { "type": "boolean" } }, "required": [ "lines", "truncated", "droppedLines", "droppedBytes" ], "type": "object" }, "paneId": { "type": "string" } }, "required": [ "paneId", "content" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Capture pane" } ``` --- # capture_since Source: https://libtmux.org/en/csharp/latest/mcp/tools/capture_since/ > Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Read only what a pane has printed since the last call. Pass back the cursor each time. Use this to watch a long-running process across turns: the tenth read costs what the first did, where re-capturing the pane would return everything again. Call with no cursor to start watching from now. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Read only what a pane has printed since the last call. Pass back the cursor each time. Use this to watch a long-running process across turns: the tenth read costs what the first did, where re-capturing the pane would return everything again. Call with no cursor to start watching from now. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/capture_since.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L577) ## Arguments * `cursor` optional · string | null The opaque cursor returned by the previous call. Omit to start from what is on screen now. Default: `null`. * `maxLines` optional · integer | null Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another. Default: `null`. * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "cursor": { "default": null, "description": "The opaque cursor returned by the previous call. Omit to start from what is on screen now.", "type": [ "string", "null" ] }, "maxLines": { "default": null, "description": "Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "anchorLost": { "type": "boolean" }, "content": { "properties": { "droppedBytes": { "type": "integer" }, "droppedLines": { "type": "integer" }, "lines": { "items": { "type": "string" }, "type": "array" }, "truncated": { "type": "boolean" } }, "required": [ "lines", "truncated", "droppedLines", "droppedBytes" ], "type": "object" }, "cursor": { "type": "string" }, "linesMissed": { "type": "boolean" }, "paneId": { "type": "string" } }, "required": [ "paneId", "content", "cursor", "linesMissed", "anchorLost" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Capture since" } ``` --- # clear_pane_scrollback Source: https://libtmux.org/en/csharp/latest/mcp/tools/clear_pane_scrollback/ > Delete tmux state; accepts no command payload. Delete a pane's scrollback history, keeping what the screen shows. Deleted history cannot be read back. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Delete tmux state; accepts no command payload. Delete a pane’s scrollback history, keeping what the screen shows. Deleted history cannot be read back. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/clear_pane_scrollback.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L613) ## Arguments * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Clear pane scrollback" } ``` --- # create_session Source: https://libtmux.org/en/csharp/latest/mcp/tools/create_session/ > Start a pane's configured process; accepts no command payload. Create a detached tmux session and return its ids. Give a width and height when nothing will attach to it: a session with no client keeps tmux's default 80x24, which truncates wide output. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Start a pane’s configured process; accepts no command payload. Create a detached tmux session and return its ids. Give a width and height when nothing will attach to it: a session with no client keeps tmux’s default 80x24, which truncates wide output. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/create_session.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L603) ## Arguments * `height` optional · integer | null Rows. Omit for tmux's default of 24. Default: `null`. * `name` optional · string | null The session name. Omit and tmux names it with a number. Default: `null`. * `startDirectory` optional · string | null The literal starting directory. Omit for the MCP server's own working directory. Default: `null`. * `width` optional · integer | null Columns. Omit for tmux's default of 80. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "height": { "default": null, "description": "Rows. Omit for tmux's default of 24.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "name": { "default": null, "description": "The session name. Omit and tmux names it with a number.", "type": [ "string", "null" ] }, "startDirectory": { "default": null, "description": "The literal starting directory. Omit for the MCP server's own working directory.", "type": [ "string", "null" ] }, "width": { "default": null, "description": "Columns. Omit for tmux's default of 80.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Create session" } ``` --- # create_window Source: https://libtmux.org/en/csharp/latest/mcp/tools/create_window/ > Start a pane's configured process; accepts no command payload. Create a window in a tmux session and return its ids. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Start a pane’s configured process; accepts no command payload. Create a window in a tmux session and return its ids. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/create_window.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L604) ## Arguments * `name` optional · string | null The window name. Omit and tmux names it after the program it runs. Default: `null`. * `session` optional · string | null A session id or name. Omit for the first session. Default: `null`. * `startDirectory` optional · string | null The literal starting directory. Omit for the MCP server's own working directory. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "name": { "default": null, "description": "The window name. Omit and tmux names it after the program it runs.", "type": [ "string", "null" ] }, "session": { "default": null, "description": "A session id or name. Omit for the first session.", "type": [ "string", "null" ] }, "startDirectory": { "default": null, "description": "The literal starting directory. Omit for the MCP server's own working directory.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Create window" } ``` --- # find_pane_by_position Source: https://libtmux.org/en/csharp/latest/mcp/tools/find_pane_by_position/ > Inspect tmux metadata; accepts no client-supplied executable input. Find the pane sitting at an index within a window. Answers nothing rather than failing when no pane is at that position. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Inspect tmux metadata; accepts no client-supplied executable input. Find the pane sitting at an index within a window. Answers nothing rather than failing when no pane is at that position. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/find_pane_by_position.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L580) ## Arguments * `position` required · integer The zero-based pane index. * `windowId` required · string The window id. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "position": { "description": "The zero-based pane index.", "maximum": 2147483647, "minimum": -2147483648, "type": "integer" }, "windowId": { "description": "The window id.", "type": "string" } }, "required": [ "windowId", "position" ], "type": "object" } ``` Output schema ```json { "properties": { "active": { "type": "boolean" }, "currentCommand": { "type": [ "string", "null" ] }, "currentPath": { "type": [ "string", "null" ] }, "dead": { "type": "boolean" }, "height": { "type": "integer" }, "historyLimit": { "type": [ "integer", "null" ] }, "historySize": { "type": [ "integer", "null" ] }, "index": { "type": "integer" }, "inMode": { "type": "boolean" }, "isCaller": { "type": "boolean" }, "paneId": { "type": "string" }, "pid": { "type": [ "integer", "null" ] }, "sessionId": { "type": "string" }, "title": { "type": [ "string", "null" ] }, "width": { "type": "integer" }, "windowId": { "type": "string" }, "zoomed": { "type": "boolean" } }, "required": [ "paneId", "windowId", "sessionId", "index", "width", "height", "title", "active", "dead", "zoomed", "inMode", "currentCommand", "currentPath", "pid", "historySize", "historyLimit", "isCaller" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Find pane by position" } ``` --- # get_pane_info Source: https://libtmux.org/en/csharp/latest/mcp/tools/get_pane_info/ > Inspect tmux metadata; accepts no client-supplied executable input. Read one pane's size, title, running command, working directory, process ID, history size and limit, and whether it is active, dead, zoomed, in a mode or the pane this server runs in. This is metadata only; to read what the pane shows, use capture_pane or snapshot_pane. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Inspect tmux metadata; accepts no client-supplied executable input. Read one pane’s size, title, running command, working directory, process ID, history size and limit, and whether it is active, dead, zoomed, in a mode or the pane this server runs in. This is metadata only; to read what the pane shows, use [capture_pane](https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/) or [snapshot_pane](https://libtmux.org/en/csharp/latest/mcp/tools/snapshot_pane/). [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/get_pane_info.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L575) ## Arguments * `paneId` required · string A pane id. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "paneId": { "description": "A pane id.", "type": "string" } }, "required": [ "paneId" ], "type": "object" } ``` Output schema ```json { "properties": { "active": { "type": "boolean" }, "currentCommand": { "type": [ "string", "null" ] }, "currentPath": { "type": [ "string", "null" ] }, "dead": { "type": "boolean" }, "height": { "type": "integer" }, "historyLimit": { "type": [ "integer", "null" ] }, "historySize": { "type": [ "integer", "null" ] }, "index": { "type": "integer" }, "inMode": { "type": "boolean" }, "isCaller": { "type": "boolean" }, "paneId": { "type": "string" }, "pid": { "type": [ "integer", "null" ] }, "sessionId": { "type": "string" }, "title": { "type": [ "string", "null" ] }, "width": { "type": "integer" }, "windowId": { "type": "string" }, "zoomed": { "type": "boolean" } }, "required": [ "paneId", "windowId", "sessionId", "index", "width", "height", "title", "active", "dead", "zoomed", "inMode", "currentCommand", "currentPath", "pid", "historySize", "historyLimit", "isCaller" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Get pane info" } ``` --- # get_server_info Source: https://libtmux.org/en/csharp/latest/mcp/tools/get_server_info/ > Inspect tmux metadata; accepts no client-supplied executable input. Read the tmux server's version and how many sessions, windows and panes it holds. Use to confirm a socket is alive and which tmux is running it. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Inspect tmux metadata; accepts no client-supplied executable input. Read the tmux server’s version and how many sessions, windows and panes it holds. Use to confirm a socket is alive and which tmux is running it. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/get_server_info.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L572) ## Arguments This tool has no top-level named arguments. Consult its schema below. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": {}, "type": "object" } ``` Output schema ```json { "properties": { "callerPaneId": { "type": [ "string", "null" ] }, "callerPaneSocket": { "type": [ "string", "null" ] }, "paneCount": { "type": "integer" }, "sessionCount": { "type": "integer" }, "socketName": { "type": [ "string", "null" ] }, "socketPath": { "type": [ "string", "null" ] }, "version": { "type": [ "string", "null" ] }, "windowCount": { "type": "integer" } }, "required": [ "socketName", "socketPath", "version", "sessionCount", "windowCount", "paneCount", "callerPaneId", "callerPaneSocket" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Get server info" } ``` --- # get_session_info Source: https://libtmux.org/en/csharp/latest/mcp/tools/get_session_info/ > Inspect tmux metadata; accepts no client-supplied executable input. Read one session's name, ID, window count and whether a client is attached, without listing every session. Give the session, or a window ID to read the session that holds it. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Inspect tmux metadata; accepts no client-supplied executable input. Read one session’s name, ID, window count and whether a client is attached, without listing every session. Give the session, or a window ID to read the session that holds it. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/get_session_info.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L573) ## Arguments * `session` required · string A session id or name. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "session": { "description": "A session id or name.", "type": "string" } }, "required": [ "session" ], "type": "object" } ``` Output schema ```json { "properties": { "attached": { "type": "boolean" }, "name": { "type": "string" }, "sessionId": { "type": "string" }, "windowCount": { "type": [ "integer", "null" ] } }, "required": [ "sessionId", "name", "attached", "windowCount" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Get session info" } ``` --- # get_tmux_variables Source: https://libtmux.org/en/csharp/latest/mcp/tools/get_tmux_variables/ > Read configured tmux commands; accepts no client-supplied executable input. Returned values may contain executable configuration. Expand named tmux format variables for a pane, such as session_name or window_width. Use it for fields nothing else answers; get_pane_info already returns the common ones, and show_option reads configuration rather than live state. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read configured tmux commands; accepts no client-supplied executable input. Returned values may contain executable configuration. Expand named tmux format variables for a pane, such as session_name or window_width. Use it for fields nothing else answers; [get_pane_info](https://libtmux.org/en/csharp/latest/mcp/tools/get_pane_info/) already returns the common ones, and [show_option](https://libtmux.org/en/csharp/latest/mcp/tools/show_option/) reads configuration rather than live state. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/get_tmux_variables.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L582) ## Arguments * `names` required · array Variable names such as session_name, without #{...}. Between 1 and 64 names, each at most 64 letters, digits and underscores. * `paneId` optional · string | null A pane id used as the lookup context. Omit for this server's own pane, or else the one the first session shows. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "names": { "description": "Variable names such as session_name, without #{...}. Between 1 and 64 names, each at most 64 letters, digits and underscores.", "items": { "type": "string" }, "type": "array" }, "paneId": { "default": null, "description": "A pane id used as the lookup context. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] } }, "required": [ "names" ], "type": "object" } ``` Output schema ```json { "additionalProperties": { "type": "string" }, "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Get tmux variables" } ``` --- # get_window_info Source: https://libtmux.org/en/csharp/latest/mcp/tools/get_window_info/ > Inspect tmux metadata; accepts no client-supplied executable input. Read one window's name, index, size, layout, pane count and whether it is its session's current window, without listing every window. Give the window ID, or a pane ID to read the window that holds it. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Inspect tmux metadata; accepts no client-supplied executable input. Read one window’s name, index, size, layout, pane count and whether it is its session’s current window, without listing every window. Give the window ID, or a pane ID to read the window that holds it. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/get_window_info.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L574) ## Arguments * `windowId` required · string A window id. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "windowId": { "description": "A window id.", "type": "string" } }, "required": [ "windowId" ], "type": "object" } ``` Output schema ```json { "properties": { "active": { "type": "boolean" }, "height": { "type": "integer" }, "index": { "type": "integer" }, "layout": { "type": [ "string", "null" ] }, "name": { "type": "string" }, "paneCount": { "type": [ "integer", "null" ] }, "sessionId": { "type": "string" }, "width": { "type": "integer" }, "windowId": { "type": "string" } }, "required": [ "windowId", "sessionId", "index", "name", "width", "height", "active", "paneCount", "layout" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Get window info" } ``` --- # kill_pane Source: https://libtmux.org/en/csharp/latest/mcp/tools/kill_pane/ > Delete tmux state; accepts no command payload. Close a pane and end its program. Refuses the pane this server runs in; to remove a whole window, use kill_window. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Delete tmux state; accepts no command payload. Close a pane and end its program. Refuses the pane this server runs in; to remove a whole window, use [kill_window](https://libtmux.org/en/csharp/latest/mcp/tools/kill_window/). [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/kill_pane.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L614) ## Arguments * `paneId` required · string The pane id to kill. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "paneId": { "description": "The pane id to kill.", "type": "string" } }, "required": [ "paneId" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Kill pane" } ``` --- # kill_session Source: https://libtmux.org/en/csharp/latest/mcp/tools/kill_session/ > Delete tmux state; accepts no command payload. Close a session with all its windows and panes. Refuses the session this server runs in. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Delete tmux state; accepts no command payload. Close a session with all its windows and panes. Refuses the session this server runs in. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/kill_session.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L616) ## Arguments * `session` required · string The session id or name to kill. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "session": { "description": "The session id or name to kill.", "type": "string" } }, "required": [ "session" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Kill session" } ``` --- # kill_window Source: https://libtmux.org/en/csharp/latest/mcp/tools/kill_window/ > Delete tmux state; accepts no command payload. Close a window and every pane in it. Refuses the window this server runs in. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Delete tmux state; accepts no command payload. Close a window and every pane in it. Refuses the window this server runs in. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/kill_window.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L615) ## Arguments * `windowId` required · string The window id to kill. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "windowId": { "description": "The window id to kill.", "type": "string" } }, "required": [ "windowId" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Kill window" } ``` --- # list_panes Source: https://libtmux.org/en/csharp/latest/mcp/tools/list_panes/ > Inspect tmux metadata; accepts no client-supplied executable input. List tmux panes, optionally within one session or window. Filter for isCaller=true to answer 'which pane am I in?', which finds one only when this server drives the caller's own socket — get_server_info says whose socket that is. This reads sizes and running commands, not terminal text — for that use search_panes. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Inspect tmux metadata; accepts no client-supplied executable input. List tmux panes, optionally within one session or window. Filter for isCaller=true to answer ‘which pane am I in?’, which finds one only when this server drives the caller’s own socket — [get_server_info](https://libtmux.org/en/csharp/latest/mcp/tools/get_server_info/) says whose socket that is. This reads sizes and running commands, not terminal text — for that use [search_panes](https://libtmux.org/en/csharp/latest/mcp/tools/search_panes/). [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/list_panes.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L571) ## Arguments * `session` optional · string | null A session id or name. Omit for every session. Default: `null`. * `windowId` optional · string | null A window id. Omit for every window. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "session": { "default": null, "description": "A session id or name. Omit for every session.", "type": [ "string", "null" ] }, "windowId": { "default": null, "description": "A window id. Omit for every window.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "result": { "items": { "properties": { "active": { "type": "boolean" }, "currentCommand": { "type": [ "string", "null" ] }, "currentPath": { "type": [ "string", "null" ] }, "dead": { "type": "boolean" }, "height": { "type": "integer" }, "historyLimit": { "type": [ "integer", "null" ] }, "historySize": { "type": [ "integer", "null" ] }, "index": { "type": "integer" }, "inMode": { "type": "boolean" }, "isCaller": { "type": "boolean" }, "paneId": { "type": "string" }, "pid": { "type": [ "integer", "null" ] }, "sessionId": { "type": "string" }, "title": { "type": [ "string", "null" ] }, "width": { "type": "integer" }, "windowId": { "type": "string" }, "zoomed": { "type": "boolean" } }, "required": [ "paneId", "windowId", "sessionId", "index", "width", "height", "title", "active", "dead", "zoomed", "inMode", "currentCommand", "currentPath", "pid", "historySize", "historyLimit", "isCaller" ], "type": "object" }, "type": "array" } }, "required": [ "result" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "List panes" } ``` --- # list_sessions Source: https://libtmux.org/en/csharp/latest/mcp/tools/list_sessions/ > Inspect tmux metadata; accepts no client-supplied executable input. List the tmux sessions. This reads names and sizes, not terminal text — to find what a pane is showing, use search_panes. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Inspect tmux metadata; accepts no client-supplied executable input. List the tmux sessions. This reads names and sizes, not terminal text — to find what a pane is showing, use [search_panes](https://libtmux.org/en/csharp/latest/mcp/tools/search_panes/). [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/list_sessions.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L569) ## Arguments This tool has no top-level named arguments. Consult its schema below. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": {}, "type": "object" } ``` Output schema ```json { "properties": { "result": { "items": { "properties": { "attached": { "type": "boolean" }, "name": { "type": "string" }, "sessionId": { "type": "string" }, "windowCount": { "type": [ "integer", "null" ] } }, "required": [ "sessionId", "name", "attached", "windowCount" ], "type": "object" }, "type": "array" } }, "required": [ "result" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "List sessions" } ``` --- # list_windows Source: https://libtmux.org/en/csharp/latest/mcp/tools/list_windows/ > Inspect tmux metadata; accepts no client-supplied executable input. List tmux windows, optionally within one session. This reads names and layouts, not terminal text — to find what a pane is showing, use search_panes. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Inspect tmux metadata; accepts no client-supplied executable input. List tmux windows, optionally within one session. This reads names and layouts, not terminal text — to find what a pane is showing, use [search_panes](https://libtmux.org/en/csharp/latest/mcp/tools/search_panes/). [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/list_windows.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L570) ## Arguments * `session` optional · string | null A session id or name. Omit for every session. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "session": { "default": null, "description": "A session id or name. Omit for every session.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "result": { "items": { "properties": { "active": { "type": "boolean" }, "height": { "type": "integer" }, "index": { "type": "integer" }, "layout": { "type": [ "string", "null" ] }, "name": { "type": "string" }, "paneCount": { "type": [ "integer", "null" ] }, "sessionId": { "type": "string" }, "width": { "type": "integer" }, "windowId": { "type": "string" } }, "required": [ "windowId", "sessionId", "index", "name", "width", "height", "active", "paneCount", "layout" ], "type": "object" }, "type": "array" } }, "required": [ "result" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "List windows" } ``` --- # move_window Source: https://libtmux.org/en/csharp/latest/mcp/tools/move_window/ > Change tmux state; no client-supplied executable input. Move a window to another index, or into another session. With replaceExisting it takes an index that is already occupied by killing the window there, which needs the teardown toolset. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Move a window to another index, or into another session. With replaceExisting it takes an index that is already occupied by killing the window there, which needs the teardown toolset. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/move_window.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L595) ## Arguments * `destination` optional · string The destination window index. Omit for the next free index, as an empty one does. Default: `""`. * `replaceExisting` optional · boolean Kill the window already at that index and take its place. Needs the same authority as kill_window, because that is what it does to it. Default: `false`. * `session` optional · string | null The destination session id or name. Omit to stay in the window's session. Default: `null`. * `windowId` required · string The window id to move. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "destination": { "default": "", "description": "The destination window index. Omit for the next free index, as an empty one does.", "type": "string" }, "replaceExisting": { "default": false, "description": "Kill the window already at that index and take its place. Needs the same authority as kill_window, because that is what it does to it.", "type": "boolean" }, "session": { "default": null, "description": "The destination session id or name. Omit to stay in the window's session.", "type": [ "string", "null" ] }, "windowId": { "description": "The window id to move.", "type": "string" } }, "required": [ "windowId" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Move window" } ``` --- # paste_text Source: https://libtmux.org/en/csharp/latest/mcp/tools/paste_text/ > Send input to a pane's program; a shell that receives it runs it with your user's permissions. Paste a block of text into exactly one pane through a tmux buffer. Use for multi-line text, or anything an editor would mangle if typed — bracketed paste stops auto-indent. Set enter to append a newline to that same private buffer. It refuses a target in a human-owned mode and never fans out to synchronized siblings. The temporary buffer is deleted afterwards; if cleanup fails, the result identifies what remains. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Send input to a pane’s program; a shell that receives it runs it with your user’s permissions. Paste a block of text into exactly one pane through a tmux buffer. Use for multi-line text, or anything an editor would mangle if typed — bracketed paste stops auto-indent. Set enter to append a newline to that same private buffer. It refuses a target in a human-owned mode and never fans out to synchronized siblings. The temporary buffer is deleted afterwards; if cleanup fails, the result identifies what remains. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/paste_text.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L610) ## Arguments * `bracketed` optional · boolean Use bracketed paste. Default: `true`. * `enter` optional · boolean Append Enter to the same paste buffer. Default: `false`. * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `text` required · string The text to paste. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "bracketed": { "default": true, "description": "Use bracketed paste.", "type": "boolean" }, "enter": { "default": false, "description": "Append Enter to the same paste buffer.", "type": "boolean" }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "text": { "description": "The text to paste.", "type": "string" } }, "required": [ "text" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Paste text" } ``` --- # rename_session Source: https://libtmux.org/en/csharp/latest/mcp/tools/rename_session/ > Change tmux state; no client-supplied executable input. Rename a tmux session. Its id does not change, so anything holding one still works. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Rename a tmux session. Its id does not change, so anything holding one still works. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/rename_session.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L588) ## Arguments * `name` required · string The new session name. * `session` optional · string | null A session id or name. Omit for the first session. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "name": { "description": "The new session name.", "type": "string" }, "session": { "default": null, "description": "A session id or name. Omit for the first session.", "type": [ "string", "null" ] } }, "required": [ "name" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Rename session" } ``` --- # rename_window Source: https://libtmux.org/en/csharp/latest/mcp/tools/rename_window/ > Change tmux state; no client-supplied executable input. Rename a tmux window. Its id does not change. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Rename a tmux window. Its id does not change. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/rename_window.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L589) ## Arguments * `name` required · string The new window name. * `windowId` optional · string | null A window id. Omit for this server's own window, or else the one the first session shows. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "name": { "description": "The new window name.", "type": "string" }, "windowId": { "default": null, "description": "A window id. Omit for this server's own window, or else the one the first session shows.", "type": [ "string", "null" ] } }, "required": [ "name" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Rename window" } ``` --- # resize_pane Source: https://libtmux.org/en/csharp/latest/mcp/tools/resize_pane/ > Change tmux state; no client-supplied executable input. Resize a pane, or zoom it to fill its window. Widening a pane before reading it is the fix for output that comes back wrapped across rows. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Resize a pane, or zoom it to fill its window. Widening a pane before reading it is the fix for output that comes back wrapped across rows. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/resize_pane.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L594) ## Arguments * `height` optional · integer | null Rows. Omit to keep the current height. Default: `null`. * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `width` optional · integer | null Columns. Omit to keep the current width. Default: `null`. * `zoom` optional · boolean Zoom the pane. Default: `false`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "height": { "default": null, "description": "Rows. Omit to keep the current height.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "width": { "default": null, "description": "Columns. Omit to keep the current width.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "zoom": { "default": false, "description": "Zoom the pane.", "type": "boolean" } }, "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Resize pane" } ``` --- # resize_window Source: https://libtmux.org/en/csharp/latest/mcp/tools/resize_window/ > Change tmux state; no client-supplied executable input. Resize a window to a width and height in cells; its panes resize with it. To resize one pane, use resize_pane. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Resize a window to a width and height in cells; its panes resize with it. To resize one pane, use [resize_pane](https://libtmux.org/en/csharp/latest/mcp/tools/resize_pane/). [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/resize_window.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L593) ## Arguments * `height` optional · integer | null Rows. Omit to keep the current height. Default: `null`. * `width` optional · integer | null Columns. Omit to keep the current width. Default: `null`. * `windowId` optional · string | null A window id. Omit for this server's own window, or else the one the first session shows. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "height": { "default": null, "description": "Rows. Omit to keep the current height.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "width": { "default": null, "description": "Columns. Omit to keep the current width.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "windowId": { "default": null, "description": "A window id. Omit for this server's own window, or else the one the first session shows.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Resize window" } ``` --- # respawn_pane Source: https://libtmux.org/en/csharp/latest/mcp/tools/respawn_pane/ > Start a pane's configured process; accepts no command payload. Only restarts a pane whose command has ALREADY EXITED. killExistingProcess overrides that and kills what is running first — an editor holding unsaved changes, a build part way through. It reruns the command the pane was created with rather than running something new. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Start a pane’s configured process; accepts no command payload. Only restarts a pane whose command has ALREADY EXITED. killExistingProcess overrides that and kills what is running first — an editor holding unsaved changes, a build part way through. It reruns the command the pane was created with rather than running something new. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/respawn_pane.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L606) ## Arguments * `killExistingProcess` optional · boolean Kill the existing pane process first. Default: `false`. * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `startDirectory` optional · string | null The literal starting directory. Omit for the directory the pane started in before. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "killExistingProcess": { "default": false, "description": "Kill the existing pane process first.", "type": "boolean" }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "startDirectory": { "default": null, "description": "The literal starting directory. Omit for the directory the pane started in before.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Respawn pane" } ``` --- # run_shell_command Source: https://libtmux.org/en/csharp/latest/mcp/tools/run_shell_command/ > Run a shell command in a pane with your user's permissions. Run a shell command in one pane, wait for it to finish, and report its singular real exit status and output. This is the tool for 'run X and tell me if it worked'. It reaches only the pane you name: the command travels through a tmux buffer, which synchronize-panes does not fan out, so the exit status is one pane's. Use send_keys when you want a synchronized cohort to receive input. Do NOT send keys and then poll a capture in a loop — this waits deterministically and costs one call. The command runs in a subshell, so cd and export do not persist. It refuses the named pane in a human-owned mode. Check linesMissed and anchorLost. A timed-out command MAY STILL BE RUNNING; inspect it and do not retry it — unless started is false, which means it never ran because something other than an idle shell was reading that pane's input. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Run a shell command in a pane with your user’s permissions. Run a shell command in one pane, wait for it to finish, and report its singular real exit status and output. This is the tool for ‘run X and tell me if it worked’. It reaches only the pane you name: the command travels through a tmux buffer, which synchronize-panes does not fan out, so the exit status is one pane’s. Use [send_keys](https://libtmux.org/en/csharp/latest/mcp/tools/send_keys/) when you want a synchronized cohort to receive input. Do NOT send keys and then poll a capture in a loop — this waits deterministically and costs one call. The command runs in a subshell, so cd and export do not persist. It refuses the named pane in a human-owned mode. Check linesMissed and anchorLost. A timed-out command MAY STILL BE RUNNING; inspect it and do not retry it — unless started is false, which means it never ran because something other than an idle shell was reading that pane’s input. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/run_shell_command.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L607) ## Arguments * `command` required · string The shell command. * `maxLines` optional · integer | null Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another. Default: `null`. * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `suppressHistory` optional · boolean Keep the command out of shell history on a best-effort basis. Default: `false`. * `timeoutSeconds` optional · number | null Seconds to wait, lowered to the server's ceiling. Omit to wait the whole ceiling, 30 unless LIBTMUX_MCP_WAIT_MAX_SECONDS sets another. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "command": { "description": "The shell command.", "type": "string" }, "maxLines": { "default": null, "description": "Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "suppressHistory": { "default": false, "description": "Keep the command out of shell history on a best-effort basis.", "type": "boolean" }, "timeoutSeconds": { "default": null, "description": "Seconds to wait, lowered to the server's ceiling. Omit to wait the whole ceiling, 30 unless LIBTMUX_MCP_WAIT_MAX_SECONDS sets another.", "type": [ "number", "null" ] } }, "required": [ "command" ], "type": "object" } ``` Output schema ```json { "properties": { "anchorLost": { "default": false, "type": "boolean" }, "effectiveTimeoutSeconds": { "type": "number" }, "elapsedSeconds": { "type": "number" }, "exitStatus": { "type": [ "integer", "null" ] }, "linesMissed": { "default": false, "type": "boolean" }, "output": { "properties": { "droppedBytes": { "type": "integer" }, "droppedLines": { "type": "integer" }, "lines": { "items": { "type": "string" }, "type": "array" }, "truncated": { "type": "boolean" } }, "required": [ "lines", "truncated", "droppedLines", "droppedBytes" ], "type": "object" }, "paneExited": { "default": false, "type": "boolean" }, "paneId": { "type": "string" }, "started": { "default": true, "type": "boolean" }, "timedOut": { "type": "boolean" } }, "required": [ "paneId", "exitStatus", "timedOut", "output", "elapsedSeconds", "effectiveTimeoutSeconds" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Run shell command" } ``` --- # search_panes Source: https://libtmux.org/en/csharp/latest/mcp/tools/search_panes/ > Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Find which panes are showing text matching a regular expression. This is the tool for 'which pane has the error', 'where is the build running', or any question about what a pane CONTAINS — the list tools only see names and sizes. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Find which panes are showing text matching a regular expression. This is the tool for ‘which pane has the error’, ‘where is the build running’, or any question about what a pane CONTAINS — the list tools only see names and sizes. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/search_panes.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L579) ## Arguments * `ignoreCase` optional · boolean Ignore case. Default: `true`. * `includeHistory` optional · boolean Search scrollback too. Default: `false`. * `maxMatchesPerPane` optional · integer Maximum matches per pane. Default: `20`. * `pattern` required · string A linear-time regular expression, at most 999 UTF-8 bytes. .NET syntax without lookarounds, backreferences or atomic groups. * `session` optional · string | null A session id or name. Omit for every session. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "ignoreCase": { "default": true, "description": "Ignore case.", "type": "boolean" }, "includeHistory": { "default": false, "description": "Search scrollback too.", "type": "boolean" }, "maxMatchesPerPane": { "default": 20, "description": "Maximum matches per pane.", "maximum": 2147483647, "minimum": -2147483648, "type": "integer" }, "pattern": { "description": "A linear-time regular expression, at most 999 UTF-8 bytes. .NET syntax without lookarounds, backreferences or atomic groups.", "type": "string" }, "session": { "default": null, "description": "A session id or name. Omit for every session.", "type": [ "string", "null" ] } }, "required": [ "pattern" ], "type": "object" } ``` Output schema ```json { "properties": { "panes": { "items": { "properties": { "matches": { "items": { "properties": { "row": { "type": "integer" }, "text": { "type": "string" } }, "required": [ "row", "text" ], "type": "object" }, "type": "array" }, "paneId": { "type": "string" }, "sessionId": { "type": "string" }, "windowId": { "type": "string" } }, "required": [ "paneId", "windowId", "sessionId", "matches" ], "type": "object" }, "type": "array" }, "panesSearched": { "type": "integer" }, "pattern": { "type": "string" }, "truncated": { "type": "boolean" } }, "required": [ "pattern", "panesSearched", "panes", "truncated" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Search panes" } ``` --- # select_layout Source: https://libtmux.org/en/csharp/latest/mcp/tools/select_layout/ > Change tmux state; no client-supplied executable input. Arrange a window's panes with a named layout — even-horizontal, even-vertical, main-horizontal, main-vertical, tiled — or a layout string read from list_windows. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Arrange a window’s panes with a named layout — even-horizontal, even-vertical, main-horizontal, main-vertical, tiled — or a layout string read from [list_windows](https://libtmux.org/en/csharp/latest/mcp/tools/list_windows/). [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/select_layout.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L592) ## Arguments * `layout` optional · string | null A supported layout name or layout string. Omit to reapply the window's last preset layout, if it has had one. Default: `null`. * `windowId` optional · string | null A window id. Omit for this server's own window, or else the one the first session shows. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "layout": { "default": null, "description": "A supported layout name or layout string. Omit to reapply the window's last preset layout, if it has had one.", "type": [ "string", "null" ] }, "windowId": { "default": null, "description": "A window id. Omit for this server's own window, or else the one the first session shows.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Select layout" } ``` --- # select_pane Source: https://libtmux.org/en/csharp/latest/mcp/tools/select_pane/ > Change tmux state; no client-supplied executable input. Make a pane the active one in its window. This changes what a watching human sees; targeting a pane by id does not require selecting it first. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Make a pane the active one in its window. This changes what a watching human sees; targeting a pane by id does not require selecting it first. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/select_pane.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L591) ## Arguments * `paneId` required · string A pane id. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "paneId": { "description": "A pane id.", "type": "string" } }, "required": [ "paneId" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Select pane" } ``` --- # select_window Source: https://libtmux.org/en/csharp/latest/mcp/tools/select_window/ > Change tmux state; no client-supplied executable input. Make a window the current one in its session. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Make a window the current one in its session. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/select_window.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L590) ## Arguments * `windowId` required · string A window id. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "windowId": { "description": "A window id.", "type": "string" } }, "required": [ "windowId" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Select window" } ``` --- # send_keys Source: https://libtmux.org/en/csharp/latest/mcp/tools/send_keys/ > Send input to a pane's program; a shell that receives it runs it with your user's permissions. Send raw keystrokes to a pane and return immediately. Use for driving an interactive program — a key in vim, a menu choice, Ctrl-C. Set literal=false to send named keys such as C-c, Escape or F5. It refuses the named pane in a human-owned mode and, when source input expands, every synchronized input cohort peer. To run a shell command and learn whether it worked, use run_shell_command instead; this reports nothing about what happens next. Tracks what it sends — including edits such as backspace, Ctrl-U or Ctrl-C — so wait_for_text can tell this pane's echo apart from real output for a short time afterward. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Send input to a pane’s program; a shell that receives it runs it with your user’s permissions. Send raw keystrokes to a pane and return immediately. Use for driving an interactive program — a key in vim, a menu choice, Ctrl-C. Set literal=false to send named keys such as C-c, Escape or F5. It refuses the named pane in a human-owned mode and, when source input expands, every synchronized input cohort peer. To run a shell command and learn whether it worked, use [run_shell_command](https://libtmux.org/en/csharp/latest/mcp/tools/run_shell_command/) instead; this reports nothing about what happens next. Tracks what it sends — including edits such as backspace, Ctrl-U or Ctrl-C — so [wait_for_text](https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_text/) can tell this pane’s echo apart from real output for a short time afterward. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/send_keys.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L608) ## Arguments * `enter` optional · boolean Press Enter after the keys. Default: `false`. * `keys` required · string Text or a tmux key name. * `literal` optional · boolean Treat keys as literal text. Default: `true`. * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `suppressHistory` optional · boolean Keep text out of shell history on a best-effort basis. Default: `false`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "enter": { "default": false, "description": "Press Enter after the keys.", "type": "boolean" }, "keys": { "description": "Text or a tmux key name.", "type": "string" }, "literal": { "default": true, "description": "Treat keys as literal text.", "type": "boolean" }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "suppressHistory": { "default": false, "description": "Keep text out of shell history on a best-effort basis.", "type": "boolean" } }, "required": [ "keys" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "type": "string" }, "targetPaneIds": { "items": { "type": "string" }, "type": "array" } }, "required": [ "changed", "paneId", "targetPaneIds" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Send keys" } ``` --- # send_keys_batch Source: https://libtmux.org/en/csharp/latest/mcp/tools/send_keys_batch/ > Send input to a pane's program; a shell that receives it runs it with your user's permissions. Send several keystrokes to one pane in order, in a single call. Use for a short interactive sequence — open a file, move, type, save — instead of one call per key. Each operation refuses the named pane in a human-owned mode and, when source input expands, every synchronized input cohort peer. A batch has at most 64 steps and 64 KiB of UTF-8 text. Each delay is 0-2000 ms and all delays together must fit the server wait ceiling. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Send input to a pane’s program; a shell that receives it runs it with your user’s permissions. Send several keystrokes to one pane in order, in a single call. Use for a short interactive sequence — open a file, move, type, save — instead of one call per key. Each operation refuses the named pane in a human-owned mode and, when source input expands, every synchronized input cohort peer. A batch has at most 64 steps and 64 KiB of UTF-8 text. Each delay is 0-2000 ms and all delays together must fit the server wait ceiling. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/send_keys_batch.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L609) ## Arguments * `onError` optional · string Stop after the first failed operation, or continue serially. Default: `"stop"`. * `operations` required · array Between 1 and 64 bounded pane-input operations, executed serially. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "onError": { "default": "stop", "description": "Stop after the first failed operation, or continue serially.", "enum": [ "continue", "stop" ], "type": "string" }, "operations": { "description": "Between 1 and 64 bounded pane-input operations, executed serially.", "items": { "additionalProperties": false, "properties": { "delayMilliseconds": { "default": null, "maximum": 2000, "minimum": 0, "type": [ "integer", "null" ] }, "enter": { "default": false, "type": "boolean" }, "keys": { "type": "string" }, "literal": { "default": true, "type": "boolean" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "suppressHistory": { "default": false, "type": "boolean" } }, "required": [ "keys" ], "type": "object" }, "maxItems": 64, "minItems": 1, "type": "array" } }, "required": [ "operations" ], "type": "object" } ``` Output schema ```json { "properties": { "failed": { "type": "integer" }, "onError": { "type": "string" }, "results": { "items": { "properties": { "error": { "type": [ "string", "null" ] }, "index": { "type": "integer" }, "paneId": { "type": [ "string", "null" ] }, "success": { "type": "boolean" }, "targetPaneIds": { "items": { "type": "string" }, "type": "array" } }, "required": [ "index", "paneId", "success", "error", "targetPaneIds" ], "type": "object" }, "type": "array" }, "stoppedAt": { "type": [ "integer", "null" ] }, "succeeded": { "type": "integer" } }, "required": [ "results", "succeeded", "failed", "stoppedAt", "onError" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Send keys batch" } ``` --- # set_history_limit Source: https://libtmux.org/en/csharp/latest/mcp/tools/set_history_limit/ > Change tmux state; no client-supplied executable input. Set how many scrollback lines tmux keeps. This is a SESSION option, so it covers every window in the session rather than one pane, and the session must be named because the call can destroy data. Raise it before starting something that prints a lot: no capture can return lines tmux has already discarded. LOWERING it discards the excess from every pane immediately, and the result says how many lines went; raising the limit again does not bring them back. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Set how many scrollback lines tmux keeps. This is a SESSION option, so it covers every window in the session rather than one pane, and the session must be named because the call can destroy data. Raise it before starting something that prints a lot: no capture can return lines tmux has already discarded. LOWERING it discards the excess from every pane immediately, and the result says how many lines went; raising the limit again does not bring them back. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/set_history_limit.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L601) ## Arguments * `lines` required · integer The scrollback line limit. * `session` required · string A session id such as $0, or its name. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "lines": { "description": "The scrollback line limit.", "maximum": 2147483647, "minimum": -2147483648, "type": "integer" }, "session": { "description": "A session id such as $0, or its name.", "type": "string" } }, "required": [ "lines", "session" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Set history limit" } ``` --- # set_mouse_enabled Source: https://libtmux.org/en/csharp/latest/mcp/tools/set_mouse_enabled/ > Change tmux state; no client-supplied executable input. Turn tmux mouse support on or off. This sets the global option, so it applies to every session on this server and changes what a human watching can do with their mouse. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Turn tmux mouse support on or off. This sets the global option, so it applies to every session on this server and changes what a human watching can do with their mouse. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/set_mouse_enabled.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L600) ## Arguments * `enabled` required · boolean Whether mouse support is enabled globally. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "enabled": { "description": "Whether mouse support is enabled globally.", "type": "boolean" } }, "required": [ "enabled" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Set mouse enabled" } ``` --- # set_pane_title Source: https://libtmux.org/en/csharp/latest/mcp/tools/set_pane_title/ > Change tmux state; no client-supplied executable input. Set a pane's title. Useful for labelling panes you created so a human watching can tell which is which. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Set a pane’s title. Useful for labelling panes you created so a human watching can tell which is which. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/set_pane_title.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L597) ## Arguments * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `title` required · string The literal pane title. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "title": { "description": "The literal pane title.", "type": "string" } }, "required": [ "title" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Set pane title" } ``` --- # set_synchronize_panes Source: https://libtmux.org/en/csharp/latest/mcp/tools/set_synchronize_panes/ > Change tmux state; no client-supplied executable input. Turn synchronize-panes on or off for a window. Input typed into one of its panes then reaches the synchronized input cohort: every pane whose effective synchronize-panes setting is on. A pane without a setting of its own follows the window; one with its own setting stays included or excluded either way. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Turn synchronize-panes on or off for a window. Input typed into one of its panes then reaches the synchronized input cohort: every pane whose effective synchronize-panes setting is on. A pane without a setting of its own follows the window; one with its own setting stays included or excluded either way. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/set_synchronize_panes.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L611) ## Arguments * `enabled` required · boolean Whether to set this window's inherited synchronize-panes default. Pane overrides can still include or exclude individual panes. * `windowId` optional · string | null A window id. Omit for this server's own window, or else the one the first session shows. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "enabled": { "description": "Whether to set this window's inherited synchronize-panes default. Pane overrides can still include or exclude individual panes.", "type": "boolean" }, "windowId": { "default": null, "description": "A window id. Omit for this server's own window, or else the one the first session shows.", "type": [ "string", "null" ] } }, "required": [ "enabled" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Set synchronize panes" } ``` --- # show_environment Source: https://libtmux.org/en/csharp/latest/mcp/tools/show_environment/ > Read the tmux environment; accepts no client-supplied executable input. A listing answers names without values, and a named variable is still withheld when the name reads as a credential. Read what a NEW pane will inherit, at the server or session level — not what an already-running shell has. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read the tmux environment; accepts no client-supplied executable input. A listing answers names without values, and a named variable is still withheld when the name reads as a credential. Read what a NEW pane will inherit, at the server or session level — not what an already-running shell has. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/show_environment.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L584) ## Arguments * `name` optional · string | null One variable name, which answers its value. Omit for every name with hasValue instead of values. Default: `null`. * `session` optional · string | null A session id or name. Omit for the server environment. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "name": { "default": null, "description": "One variable name, which answers its value. Omit for every name with hasValue instead of values.", "type": [ "string", "null" ] }, "session": { "default": null, "description": "A session id or name. Omit for the server environment.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "result": { "items": { "properties": { "hasValue": { "type": "boolean" }, "isRemoved": { "type": "boolean" }, "name": { "type": "string" }, "value": { "type": [ "string", "null" ] }, "withheld": { "type": "boolean" } }, "required": [ "name", "value", "isRemoved", "hasValue", "withheld" ], "type": "object" }, "type": "array" } }, "required": [ "result" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Show environment" } ``` --- # show_hooks Source: https://libtmux.org/en/csharp/latest/mcp/tools/show_hooks/ > Read configured tmux commands; accepts no client-supplied executable input. Returned values may contain executable configuration. Read the hooks tmux will run on its own events. Read-only on purpose: a hook written here would outlive this conversation and keep firing with nobody left who knows why. Put hooks you want to keep in your tmux config file. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read configured tmux commands; accepts no client-supplied executable input. Returned values may contain executable configuration. Read the hooks tmux will run on its own events. Read-only on purpose: a hook written here would outlive this conversation and keep firing with nobody left who knows why. Put hooks you want to keep in your tmux config file. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/show_hooks.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L585) ## Arguments * `paneId` optional · string | null The pane whose scope is read. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `scope` optional · string Server, Session, Window, or Pane. Default: `"Session"`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "paneId": { "default": null, "description": "The pane whose scope is read. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "scope": { "default": "Session", "description": "Server, Session, Window, or Pane.", "enum": [ "Server", "Session", "Window", "Pane" ], "type": "string" } }, "type": "object" } ``` Output schema ```json { "properties": { "result": { "items": { "properties": { "command": { "type": "string" }, "index": { "type": "integer" }, "name": { "type": "string" }, "scope": { "enum": [ "Server", "Session", "Window", "Pane" ], "type": "string" } }, "required": [ "name", "index", "command", "scope" ], "type": "object" }, "type": "array" } }, "required": [ "result" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Show hooks" } ``` --- # show_option Source: https://libtmux.org/en/csharp/latest/mcp/tools/show_option/ > Read configured tmux commands; accepts no client-supplied executable input. Returned values may contain executable configuration. Read tmux options at the server, session, window or pane level. Values set at a wider scope are included and marked inherited, because that is where nearly all tmux configuration lives. Omit the name to list them all. Reading history-limit before a long tail tells you how much output the pane can hold before it starts dropping lines. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read configured tmux commands; accepts no client-supplied executable input. Returned values may contain executable configuration. Read tmux options at the server, session, window or pane level. Values set at a wider scope are included and marked inherited, because that is where nearly all tmux configuration lives. Omit the name to list them all. Reading history-limit before a long tail tells you how much output the pane can hold before it starts dropping lines. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/show_option.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L583) ## Arguments * `name` required · string The option name. * `paneId` optional · string | null The pane whose scope is read. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `scope` optional · string Server, Session, Window, or Pane. Default: `"Pane"`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "name": { "description": "The option name.", "type": "string" }, "paneId": { "default": null, "description": "The pane whose scope is read. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "scope": { "default": "Pane", "description": "Server, Session, Window, or Pane.", "enum": [ "Server", "Session", "Window", "Pane" ], "type": "string" } }, "required": [ "name" ], "type": "object" } ``` Output schema ```json { "properties": { "result": { "items": { "properties": { "inherited": { "type": "boolean" }, "name": { "type": "string" }, "scope": { "enum": [ "Server", "Session", "Window", "Pane" ], "type": "string" }, "value": { "type": [ "string", "null" ] } }, "required": [ "name", "value", "scope", "inherited" ], "type": "object" }, "type": "array" } }, "required": [ "result" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Show option" } ``` --- # signal_channel Source: https://libtmux.org/en/csharp/latest/mcp/tools/signal_channel/ > Change tmux state; no client-supplied executable input. Signal a tmux wait-for channel, releasing whatever waits on it. The channel latches: signalling before anyone waits still satisfies the next wait, so a handoff cannot be lost to a race. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Signal a tmux wait-for channel, releasing whatever waits on it. The channel latches: signalling before anyone waits still satisfies the next wait, so a handoff cannot be lost to a race. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/signal_channel.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L599) ## Arguments * `channel` required · string The tmux wait-for channel. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "channel": { "description": "The tmux wait-for channel.", "type": "string" } }, "required": [ "channel" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Signal channel" } ``` --- # snapshot_pane Source: https://libtmux.org/en/csharp/latest/mcp/tools/snapshot_pane/ > Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Read a pane's visible content together with its cursor position, size and running command, in one call. Prefer this over capture_pane plus list_panes: it is one round trip and the cursor is guaranteed to describe the text returned with it. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Read a pane’s visible content together with its cursor position, size and running command, in one call. Prefer this over [capture_pane](https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/) plus [list_panes](https://libtmux.org/en/csharp/latest/mcp/tools/list_panes/): it is one round trip and the cursor is guaranteed to describe the text returned with it. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/snapshot_pane.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L578) ## Arguments * `maxLines` optional · integer | null Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another. Default: `null`. * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "maxLines": { "default": null, "description": "Maximum returned lines, newest kept. Omit for the server default, 500 unless LIBTMUX_MCP_MAX_LINES sets another.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "alternateScreen": { "type": "boolean" }, "content": { "properties": { "droppedBytes": { "type": "integer" }, "droppedLines": { "type": "integer" }, "lines": { "items": { "type": "string" }, "type": "array" }, "truncated": { "type": "boolean" } }, "required": [ "lines", "truncated", "droppedLines", "droppedBytes" ], "type": "object" }, "cursorX": { "type": [ "integer", "null" ] }, "cursorY": { "type": [ "integer", "null" ] }, "pane": { "properties": { "active": { "type": "boolean" }, "currentCommand": { "type": [ "string", "null" ] }, "currentPath": { "type": [ "string", "null" ] }, "dead": { "type": "boolean" }, "height": { "type": "integer" }, "historyLimit": { "type": [ "integer", "null" ] }, "historySize": { "type": [ "integer", "null" ] }, "index": { "type": "integer" }, "inMode": { "type": "boolean" }, "isCaller": { "type": "boolean" }, "paneId": { "type": "string" }, "pid": { "type": [ "integer", "null" ] }, "sessionId": { "type": "string" }, "title": { "type": [ "string", "null" ] }, "width": { "type": "integer" }, "windowId": { "type": "string" }, "zoomed": { "type": "boolean" } }, "required": [ "paneId", "windowId", "sessionId", "index", "width", "height", "title", "active", "dead", "zoomed", "inMode", "currentCommand", "currentPath", "pid", "historySize", "historyLimit", "isCaller" ], "type": "object" } }, "required": [ "pane", "content", "cursorX", "cursorY", "alternateScreen" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Snapshot pane" } ``` --- # split_window Source: https://libtmux.org/en/csharp/latest/mcp/tools/split_window/ > Start a pane's configured process; accepts no command payload. Split a pane and return the NEW pane's id. Use that id for what you put in it — pane ids stay valid across layout changes, where window names and indexes do not. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Start a pane’s configured process; accepts no command payload. Split a pane and return the NEW pane’s id. Use that id for what you put in it — pane ids stay valid across layout changes, where window names and indexes do not. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/split_window.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L605) ## Arguments * `direction` optional · string Below, Above, Left, or Right. Default: `"Below"`. * `paneId` optional · string | null The pane to split. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `percentage` optional · integer | null Percentage of the space for the new pane. Omit for half. Default: `null`. * `startDirectory` optional · string | null The literal starting directory. Omit for the MCP server's own working directory. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "direction": { "default": "Below", "description": "Below, Above, Left, or Right.", "enum": [ "Above", "Below", "Left", "Right" ], "type": "string" }, "paneId": { "default": null, "description": "The pane to split. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "percentage": { "default": null, "description": "Percentage of the space for the new pane. Omit for half.", "maximum": 2147483647, "minimum": -2147483648, "type": [ "integer", "null" ] }, "startDirectory": { "default": null, "description": "The literal starting directory. Omit for the MCP server's own working directory.", "type": [ "string", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Split window" } ``` --- # swap_pane Source: https://libtmux.org/en/csharp/latest/mcp/tools/swap_pane/ > Change tmux state; no client-supplied executable input. Swap two panes' positions; each keeps its program, its content and its ID. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Swap two panes’ positions; each keeps its program, its content and its ID. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/swap_pane.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L596) ## Arguments * `detach` optional · boolean Leave the swapped pane unselected. Default: `false`. * `keepZoom` optional · boolean Keep zoom state. Default: `false`. * `paneId` required · string The pane id to swap. * `targetPaneId` required · string The other pane id. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "detach": { "default": false, "description": "Leave the swapped pane unselected.", "type": "boolean" }, "keepZoom": { "default": false, "description": "Keep zoom state.", "type": "boolean" }, "paneId": { "description": "The pane id to swap.", "type": "string" }, "targetPaneId": { "description": "The other pane id.", "type": "string" } }, "required": [ "paneId", "targetPaneId" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "paneId": { "default": null, "type": [ "string", "null" ] }, "sessionId": { "default": null, "type": [ "string", "null" ] }, "windowId": { "default": null, "type": [ "string", "null" ] } }, "required": [ "changed" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Swap pane" } ``` --- # wait_for_channel Source: https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_channel/ > Change tmux state; no client-supplied executable input. Block until something signals a tmux wait-for channel with 'tmux wait-for -S '. Use when you composed a shell command that signals it. For an ordinary command whose completion you want, run_shell_command already does this and also reports the exit status. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Change tmux state; no client-supplied executable input. Block until something signals a tmux wait-for channel with ‘tmux wait-for -S ’. Use when you composed a shell command that signals it. For an ordinary command whose completion you want, [run_shell_command](https://libtmux.org/en/csharp/latest/mcp/tools/run_shell_command/) already does this and also reports the exit status. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_channel.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L598) ## Arguments * `channel` required · string The tmux wait-for channel. * `timeoutSeconds` optional · number | null Seconds to wait, lowered to the server's ceiling. Omit to wait the whole ceiling, 30 unless LIBTMUX_MCP_WAIT_MAX_SECONDS sets another. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "channel": { "description": "The tmux wait-for channel.", "type": "string" }, "timeoutSeconds": { "default": null, "description": "Seconds to wait, lowered to the server's ceiling. Omit to wait the whole ceiling, 30 unless LIBTMUX_MCP_WAIT_MAX_SECONDS sets another.", "type": [ "number", "null" ] } }, "required": [ "channel" ], "type": "object" } ``` Output schema ```json { "properties": { "changed": { "type": "string" }, "channel": { "type": "string" }, "effectiveTimeoutSeconds": { "type": "number" }, "elapsedSeconds": { "type": "number" }, "signalled": { "type": "boolean" } }, "required": [ "changed", "channel", "signalled", "elapsedSeconds", "effectiveTimeoutSeconds" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Wait for channel" } ``` --- # wait_for_text Source: https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_text/ > Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Wait until a pane prints something matching one of these patterns, then return. Use for output you did NOT start — a server's ready line, another process's progress, a person typing. A matching pattern already on screen returns PresentAtEntry. For a command you are running yourself, run_shell_command is better: it reports the real exit status instead of guessing from text. Never poll capture_pane in a loop; this call does the waiting. Control observation is required by default; pollingFallback reports activation when the operator permits fallback. Text this server itself typed is discounted while deciding what is new, for a few seconds after it is sent or submitted, so its own echo cannot be the match — except on a pane whose program has not yet configured its terminal; wait for a first prompt before typing into a freshly created pane. MCP is in development Server behavior and tool contracts may change. Tool availability depends on the server configuration. Read pane output; accepts no client-supplied executable input. Returned content may be sensitive or untrusted. Wait until a pane prints something matching one of these patterns, then return. Use for output you did NOT start — a server’s ready line, another process’s progress, a person typing. A matching pattern already on screen returns PresentAtEntry. For a command you are running yourself, [run_shell_command](https://libtmux.org/en/csharp/latest/mcp/tools/run_shell_command/) is better: it reports the real exit status instead of guessing from text. Never poll [capture_pane](https://libtmux.org/en/csharp/latest/mcp/tools/capture_pane/) in a loop; this call does the waiting. Control observation is required by default; pollingFallback reports activation when the operator permits fallback. Text this server itself typed is discounted while deciding what is new, for a few seconds after it is sent or submitted, so its own echo cannot be the match — except on a pane whose program has not yet configured its terminal; wait for a first prompt before typing into a freshly created pane. [All C# tools](https://libtmux.org/en/csharp/latest/mcp/tools/) · [JSON](https://libtmux.org/en/csharp/latest/mcp/tools/wait_for_text.json) · [Source](https://github.com/libtmux/libtmux-dotnet/blob/cf34b255c896d19a97e7d7fabea58609c916012d/src/LibTmux.Mcp/Policy/CapabilityModel.cs#L581) ## Arguments * `ignoreCase` optional · boolean Ignore case. Default: `true`. * `paneId` optional · string | null A pane id. Omit for this server's own pane, or else the one the first session shows. Default: `null`. * `patterns` optional · array | null Linear-time regular expressions that end the wait successfully: .NET syntax without lookarounds, backreferences or atomic groups. Output arriving after this call counts unless the pattern is already present, which returns PresentAtEntry. Omit to return on any new output. Across both pattern lists: at most 32 entries and 16384 UTF-8 bytes; each entry is at most 999 UTF-8 bytes. Default: `null`. * `stopPatterns` optional · array | null Linear-time regular expressions that stop the wait, in the same subset as patterns. Omit for none. Across both pattern lists: at most 32 entries and 16384 UTF-8 bytes; each entry is at most 999 UTF-8 bytes. Default: `null`. * `timeoutSeconds` optional · number | null Seconds to wait, lowered to the server's ceiling. Omit to wait the whole ceiling, 30 unless LIBTMUX_MCP_WAIT_MAX_SECONDS sets another. Default: `null`. ## Schemas The schema defines required fields, nested values, defaults, and validation constraints. Input schema ```json { "additionalProperties": false, "properties": { "ignoreCase": { "default": true, "description": "Ignore case.", "type": "boolean" }, "paneId": { "default": null, "description": "A pane id. Omit for this server's own pane, or else the one the first session shows.", "type": [ "string", "null" ] }, "patterns": { "default": null, "description": "Linear-time regular expressions that end the wait successfully: .NET syntax without lookarounds, backreferences or atomic groups. Output arriving after this call counts unless the pattern is already present, which returns PresentAtEntry. Omit to return on any new output. Across both pattern lists: at most 32 entries and 16384 UTF-8 bytes; each entry is at most 999 UTF-8 bytes.", "items": { "type": [ "string", "null" ] }, "type": [ "array", "null" ] }, "stopPatterns": { "default": null, "description": "Linear-time regular expressions that stop the wait, in the same subset as patterns. Omit for none. Across both pattern lists: at most 32 entries and 16384 UTF-8 bytes; each entry is at most 999 UTF-8 bytes.", "items": { "type": [ "string", "null" ] }, "type": [ "array", "null" ] }, "timeoutSeconds": { "default": null, "description": "Seconds to wait, lowered to the server's ceiling. Omit to wait the whole ceiling, 30 unless LIBTMUX_MCP_WAIT_MAX_SECONDS sets another.", "type": [ "number", "null" ] } }, "type": "object" } ``` Output schema ```json { "properties": { "anchorLost": { "type": "boolean" }, "effectiveTimeoutSeconds": { "type": "number" }, "elapsedSeconds": { "type": "number" }, "eventsDropped": { "type": "integer" }, "linesMissed": { "type": "boolean" }, "matchedPattern": { "type": [ "string", "null" ] }, "outcome": { "enum": [ "Matched", "AnyOutput", "Stopped", "Timeout", "PaneDied", "PresentAtEntry" ], "type": "string" }, "paneId": { "type": "string" }, "pollingFallback": { "type": "boolean" }, "tail": { "properties": { "droppedBytes": { "type": "integer" }, "droppedLines": { "type": "integer" }, "lines": { "items": { "type": "string" }, "type": "array" }, "truncated": { "type": "boolean" } }, "required": [ "lines", "truncated", "droppedLines", "droppedBytes" ], "type": "object" } }, "required": [ "paneId", "outcome", "matchedPattern", "tail", "elapsedSeconds", "effectiveTimeoutSeconds" ], "type": "object" } ``` Tool annotations ```json { "destructiveHint": true, "idempotentHint": false, "openWorldHint": true, "readOnlyHint": false, "title": "Wait for text" } ```