Plugins
Windows Terminal Multiplexer ships with built-in plugins and supports third-party plugins that add format variables, key bindings, and behavior.
Built-in Plugins
- Prefix highlight (
#{prefix_highlight}) — Shows an inverse-video indicator when the prefix key is active. - Session save/restore — Save and restore window/pane layouts (a tmux-resurrect equivalent).
- Conditional format (
#{?client_prefix,yes,no}) — Conditional text based on terminal state.
PowerShell Config Scripts
The simplest way to extend the status bar is to run a PowerShell script from your config that outputs wtmux commands:
# In ~/.wtmux.conf
run 'Write-Output "set -g status-right $(Get-Date -Format HH:mm)"'
See Configuration for the full status bar and format variable reference.
Third-Party Plugins
Third-party plugins are out-of-process COM servers distributed as MSIX packages. wtmux discovers them automatically through the com.wtmux.plugin AppExtension contract — there is no folder to scan and no configuration to edit. Because plugins run in their own process and use source-generated COM interop, they are:
- Language-agnostic — write them in C#, C++, Rust, or any COM-capable language.
- Isolated — a plugin crash cannot take down wtmux.
- Safe to distribute — MSIX packages are signed and can be published to the Microsoft Store.
1. Implement IWtmuxComPlugin
A plugin implements the IWtmuxComPlugin interface ({3A2F8E01-7B4C-4D5A-9E1F-0A2B3C4D5E01}). Until a contract package is available, declare the interfaces in your project with the same GUIDs so COM activation lines up:
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)]
[Guid("3A2F8E01-7B4C-4D5A-9E1F-0A2B3C4D5E01")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public partial interface IWtmuxComPlugin
{
void GetName(out string name);
void Initialize(IWtmuxComPluginHost host);
void OnSessionCreated(string sessionName, int sessionId);
void OnSessionDestroyed(string sessionName, int sessionId);
void ExpandVariable(string variableName, string sessionName,
int windowIndex, string windowName, int paneIndex,
bool prefixActive, out string result);
void Shutdown();
}
[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)]
[Guid("3A2F8E01-7B4C-4D5A-9E1F-0A2B3C4D5E02")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public partial interface IWtmuxComPluginHost
{
void RegisterFormatVariable(string name);
void BindKey(byte key, string command);
void UnbindKey(byte key);
void SetOption(string option, string value);
void Log(string message);
}
The example below implements that interface — it registers a format variable and a key binding, then expands the variable when wtmux renders the status bar:
[GeneratedComClass]
public partial class MyPlugin : IWtmuxComPlugin
{
public void GetName(out string name) => name = "my-plugin";
public void Initialize(IWtmuxComPluginHost host)
{
host.RegisterFormatVariable("my_var");
host.BindKey((byte)'T', "new-window");
host.Log("My plugin loaded!");
}
public void ExpandVariable(string variableName, string sessionName,
int windowIndex, string windowName, int paneIndex,
bool prefixActive, out string result)
{
result = variableName == "my_var"
? (prefixActive ? "[PREFIX]" : "[NORMAL]")
: "";
}
public void OnSessionCreated(string sessionName, int sessionId) { }
public void OnSessionDestroyed(string sessionName, int sessionId) { }
public void Shutdown() { }
}
| Member | Called when |
|---|---|
GetName |
wtmux needs the plugin’s display name. |
Initialize |
The plugin is loaded — register variables and key bindings here. |
ExpandVariable |
A registered #{variable} is rendered; return empty for names you don’t handle. |
OnSessionCreated / OnSessionDestroyed |
A session starts or ends. |
Shutdown |
The plugin is being unloaded. |
2. Use the Host API
Initialize receives an IWtmuxComPluginHost for talking back to wtmux:
| Method | Purpose |
|---|---|
RegisterFormatVariable(name) |
Register a #{name} variable your plugin expands in the status bar. |
BindKey(key, command) |
Bind a key in the prefix key table to a wtmux command. |
UnbindKey(key) |
Remove a key binding. |
SetOption(option, value) |
Set a configuration option. |
Log(message) |
Write a debug message to the wtmux log. |
Variables you register are usable anywhere format strings are — for example in status-left / status-right (see Configuration).
3. Declare the Plugin in the MSIX Manifest
Package the plugin as an MSIX that registers its COM server and declares the com.wtmux.plugin AppExtension, exposing the class ID via a CLSID property:
<Extensions>
<!-- Register the COM server -->
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="MyPlugin.exe">
<com:Class Id="{YOUR-PLUGIN-CLSID}" />
</com:ExeServer>
</com:ComServer>
</com:Extension>
<!-- Declare as a wtmux plugin -->
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.wtmux.plugin"
DisplayName="My Plugin"
Description="Description of my plugin"
PublicFolder="Public">
<uap3:Properties>
<CLSID>{YOUR-PLUGIN-CLSID}</CLSID>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
</Extensions>
4. Package and Distribute
Build the plugin as an MSIX package, sign it, then install it by sideloading the package or publishing it to the Microsoft Store. wtmux picks up the plugin automatically the next time it starts.