Configuration
wtmux reads ~/.wtmux.conf (or ~/.tmux.conf as fallback). It supports a subset of tmux configuration syntax.
Note: After editing the config, run
wtmux reload-configorsource-filefrom the command prompt to re-read it without restarting the server.
See the Default Bindings reference for every built-in prefix, root, mouse, custom-table, and copy-mode binding and the exact override precedence.
Declarative DSC configuration
wtmux also ships a DSC v3 command resource for declarative global option management. The resource type is Shmuelie.WTmux/Options; it invokes wtmux dsc get, wtmux dsc test, and wtmux dsc set with JSON over standard input, so the same option names and values accepted by wtmux set-option -g are used in WinGet Configuration or DSC v3.
Example configuration.dsc.yaml:
$schema: https://aka.ms/configuration-dsc-schema/0.2
properties:
resources:
- resource: Shmuelie.WTmux/Options
id: wtmux-options
directives:
description: Configure wtmux global options
settings:
options:
prefix: C-a
mouse: 'on'
status-position: bottom
history-limit: 50000
The DSC resource talks to the per-user wtmux server and starts it if needed. test is idempotent: it reports _inDesiredState: true when the running server already has the desired option values and false when applying set would change them.
Example
# Change prefix key to Ctrl+A
set -g prefix C-a
# Default shell with arguments
set -g default-shell pwsh
set -g default-shell-arg -NoLogo
# Window numbering starts at 1
set -g base-index 1
# Add a command alias
set -g command-alias sp=split-window -h
# Enable mouse support
set -g mouse on
# Terminal settings
set -g default-terminal "screen-256color"
set -g history-limit 50000
set -g set-titles on
set -g set-titles-string '#S:#I:#W'
set -g clock-mode-style 24
set -g clock-mode-colour green
set -g automatic-rename on
set -g destroy-unattached off
set -g display-time 4000
# Activity, bell, and silence monitoring
set -g monitor-activity on
set -g monitor-bell on
set -g monitor-silence 60
set -g activity-action other
set -g bell-action any
set -g silence-action other
set -g visual-activity on
set -g visual-bell both
set -g visual-silence on
# Environment for new panes
set-environment -g WT_SESSION_MODE dev
set-environment -g -u NO_COLOR
# Status bar customization
set -g status-position bottom
set -g status-interval 5
set -g status-left '#{prefix_highlight} [#S] '
set -g status-right '%a %Y-%m-%d %H:%M'
set -g status-style fg=white,bg=black
set -g window-status-current-format ' #I:#W#F '
set -g window-status-format ' #I:#W#F '
# Custom key bindings
bind | split-window -h # Vertical split with |
bind - split-window # Horizontal split with -
bind h select-pane -L # Vim-style pane navigation
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
bind H resize-pane -L 5 # Vim-style pane resize (5 cells)
bind J resize-pane -D 5
bind K resize-pane -U 5
bind L resize-pane -R 5
unbind % # Remove default binding
# Include another config file
source-file ~/.wtmux.local.conf
# Run a PowerShell script during config loading
run 'Write-Output "set -g status-right $(Get-Date -Format HH:mm)"'
# Conditionally apply config based on a shell command's exit status
if-shell 'if (Get-Command git -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }' 'set -g status-left " git "'
Terminal title
set -g set-titles on lets wtmux update the host terminal window title while attached. It is disabled by default; when disabled, wtmux leaves the host title unchanged except for restoring the original title on detach.
set -g set-titles-string <format> controls the title text. The default is #S:#I:#W (session name, window index, and window name). The format uses the same variables and time escapes as the status bar, including #P/#{pane_index}, #T/#{pane_title}, #H/#{host}, and #{host_short}. Runtime changes through wtmux set-option -g set-titles ... or wtmux set-option -g set-titles-string ... repaint attached clients and update the title immediately.
Mouse support
set -g mouse on enables mouse support (it is disabled by default). When enabled:
- Scroll wheel scrolls the active pane's scrollback. Scrolling up automatically enters copy mode so you can browse history; scrolling down returns toward the live view. When the active pane is running a full-screen application such as
lessthat requested application cursor keys, entered the alternate screen, or hid the cursor for full-screen input, but did not request mouse tracking, wheel input is translated to that application's Up/Down cursor keys instead. - Left-click selects the pane under the cursor.
- Right-click pastes the most recent paste buffer into the pane under the cursor.
- Left-button drag over a pane enters copy mode, selects text from the press cell to the current cell, and releasing copies the selection to the paste buffer and clipboard.
- Drag a pane border, or a cell immediately beside it, to resize the split.
- Mouse events are passed through to full-screen applications that request mouse tracking (for example editors), so their own mouse handling keeps working.
With mouse support off, the scroll wheel is handled by your host terminal (for example, Windows Terminal scrolls its own window).
Session cleanup
set -g destroy-unattached on destroys a session when its last attached client detaches, switches away, or disconnects because the terminal tab/process exits. It is disabled by default (off), so unattached sessions persist as before. The option is runtime-settable globally with wtmux set-option -g destroy-unattached on|off or per session with wtmux set-option [-t target] destroy-unattached on|off.
Detached sessions created before any client attaches are not destroyed immediately; cleanup only happens after an attached-client count transitions from at least one to zero. This avoids racing new-session -d creation with a later attach.
Mouse bindings
Mouse actions are bindable with bind -n <mouse-key> <command>, using tmux-style named mouse keys. The event name combines an action, an optional button number (1 = left, 2 = middle, 3 = right), and a location (Pane or Status):
# Rebind the wheel, left-click, and right-click (built-in defaults under `mouse on`)
bind -n WheelUpPane copy-mode
bind -n MouseDown1Pane select-pane
bind -n MouseDown3Pane paste-buffer
# Middle-click a pane to open a new window
bind -n MouseDown2Pane new-window
# Remove a default mouse binding
unbind -n WheelUpPane
Recognized actions are WheelUp, WheelDown, MouseDown<n>, MouseUp<n>, MouseDrag<n>, and MouseDragEnd<n>. When mouse on is set, WheelUpPane/WheelDownPane (scrollback), MouseDown1Pane (select pane), and MouseDown3Pane (paste buffer) have built-in defaults that a bind/unbind -n overrides. An explicit wheel binding or unbind also takes precedence over alternate-screen wheel-to-arrow translation.
Root key bindings
bind -n <key> <command> also binds a keyboard key to fire without the prefix (tmux's root table), alongside the normal prefix bindings created by bind <key> <command>. -n is an alias for -T root; ordinary bind commands target the prefix table:
bind -n C-o new-window # Ctrl+O opens a new window without the prefix
bind -T root C-p previous-window
Root key bindings match raw input bytes before the prefix, so bind control or special keys (e.g. C-o) rather than plain letters — a letter binding would also fire when that byte appears inside an escape sequence (such as arrow keys) or pasted text.
Custom key tables
Use bind -T <table> and unbind -T <table> to define named key tables. A binding can enter one with switch-client -T <table>:
bind n switch-client -T navigation
bind -T navigation h select-pane -L
bind -T navigation j select-pane -D
bind -T navigation k select-pane -U
bind -T navigation l select-pane -R
unbind -T navigation q
After prefix n, the next key is looked up in navigation. Custom tables are one-shot: the next key is consumed and the client returns to root whether the key matches or not. A matched binding runs through the normal runtime command path; it may use another switch-client -T to continue a longer sequence. Switching to an undefined or invalid table reports an error.
For this initial key-table slice, switch-client -T must be the only command on its command line. Combining it with ; and server commands is rejected; ordinary all-server command sequences continue to run server-side with their existing ordering and stop-on-error behavior.
This is partial advanced-binding support. Repeatable bind -r behavior, binding notes (bind -N), list-keys, and send-prefix are not implemented.
Configuration options
See the Configuration Options reference for every supported option, accepted values, defaults, and runtime scope.
Conditional Configuration
wtmux evaluates run-shell and if-shell directives while loading the config file.
run-shell
run-shell 'shell-command'
run 'shell-command' # short alias
Runs shell-command (via pwsh/powershell, falling back to cmd) and feeds
each line of its standard output back to the parser as a wtmux command. Only
set / setw, bind, and unbind commands are recognized in the output.
if-shell
if-shell [-b] shell-command then-command [else-command]
if [-b] shell-command then-command [else-command] # short alias
Runs shell-command. If it exits with status 0, then-command is executed as
a wtmux command; otherwise the optional else-command runs. then-command and
else-command are ordinary config commands (usually quoted) and may be any
supported directive, including a nested if-shell or source-file.
# Apply a different prefix when running under an SSH session
if-shell 'if ($env:SSH_CONNECTION) { exit 0 } else { exit 1 }' \
'set -g prefix C-a' 'set -g prefix C-b'
Supported semantics and notes:
- The exit status of the shell command determines the branch (
0= success →then-command; non-zero, or a command that fails to launch →else-command). -b(run the command in the background) is accepted for tmux compatibility, but the command is always evaluated synchronously at config load time.- Commands are run with a 5-second timeout; a command that times out or cannot be launched is treated as a failure.
Environment
Use set-environment to configure environment variables for panes created after
the server loads the config:
set-environment [-g] NAME VALUE
set-environment [-g] -u NAME
show-environment [-g]
Config-time environment changes are global. Runtime set-environment without
-g applies to the current session; with -g, it updates the global
environment. Configured values override inherited variables, and -u removes a
variable from the child process environment. wtmux still sets WTMUX and
WTMUX_PANE for each pane.
Format Variables
Status formats (status-left, status-right, window-status-format, window-status-current-format) support tmux-style # variables, #{...} expressions, % time escapes, and inline #[...] style directives.
| Variable | Description |
|---|---|
#S / #{session_name} |
Session name |
#I / #{window_index} |
Window index |
#W / #{window_name} |
Window name |
#F / #{window_flags} |
Window flags (* current, - last, # activity, ! bell, ~ silence, Z zoomed) |
#P / #{pane_index} |
Pane index |
#H / #{host} / #{hostname} |
Hostname |
#{host_short} |
Hostname before the first dot |
#T / #{pane_title} |
Pane title |
#{pane_pid} |
Pane process ID |
#{pane_current_path} |
Pane working directory, initialized from the launch directory and updated when the shell emits OSC 7 (file://...) or OSC 9;9 cwd reports |
#{session_windows} |
Number of windows in the session |
#{window_activity} |
Last window output time as a Unix timestamp |
#{client_prefix} |
1 while the prefix key is active; otherwise 0 |
#{synchronize_panes} / #{pane_synchronized} |
1 when synchronize-panes is enabled for the active window; otherwise 0 |
#{@name} |
Value of the @name user option, or empty when unset (see User options) |
#{prefix_highlight} |
Prefix key indicator supplied by the built-in prefix-highlight plugin |
Format Expressions
| Expression | Description |
|---|---|
#{?condition,yes,no} |
Conditional text. condition may be a variable or nested expression and is true when it expands to a non-empty value other than 0, false, no, or off. |
#{==:left,right} |
Expands to 1 when the expanded values are equal; otherwise 0. |
#{!=:left,right} |
Expands to 1 when the expanded values differ; otherwise 0. |
#{m:pattern,string} |
Expands to 1 when string matches pattern. * and ? use glob matching; patterns without wildcards use substring matching. |
#{s/old/new/:value} |
Replaces old with new in the expanded value. The delimiter after s can be any character. |
#{=<N>:value} |
Trims the expanded value to N visible columns. |
#{p<N>:value} |
Pads the expanded value with spaces to at least N visible columns. |
#{t:value} |
Formats an expanded timestamp value such as #{t:window_activity}. Unix seconds and parseable date/time strings are accepted. |
#{W:body} |
Expands body once for each window in the current session, with window variables (#I, #W, #F, #{window_activity}) scoped to that window. |
#{P:body} |
Expands body once for each pane in the current window, with pane variables (#P, #T, #{pane_pid}, #{pane_current_path}) scoped to that pane. |
Use \, for a literal comma inside conditional or operator arguments. Nested #{...} expressions are supported inside arguments, branches, and loop bodies. Session loop expressions (#{S:...}) are reserved but not populated by the status renderer yet.
Inline Styles
Use #[...] inside a status format to change the style for following text:
set -g status-left '#[fg=green,bold]#S#[default] '
set -g status-right '#[fg=colour220,bg=black] %H:%M #[default]'
Supported style entries are fg=<color>, bg=<color>, bold, dim, reverse, underline, default, and none. #[default] and #[none] reset back to the base status-style/status-fg/status-bg. Inline style escape sequences do not count toward status-line width or truncation.
Time Formats
| Format | Description | Example |
|---|---|---|
%H |
Hour (24h) | 14 |
%I |
Hour (12h) | 02 |
%M |
Minute | 35 |
%S |
Second | 09 |
%R |
HH:MM | 14:35 |
%T |
HH:MM:SS | 14:35:09 |
%p |
AM/PM | PM |
%P |
am/pm | pm |
%a |
Day abbreviation | Mon |
%A |
Day full name | Monday |
%d |
Day of month | 07 |
%e |
Day (space-padded) | 7 |
%b / %h |
Month abbreviation | Jan |
%B |
Month full name | January |
%m |
Month number | 01 |
%Y |
Year | 2026 |
%j |
Day of year | 042 |
%k |
Hour (space-padded 24h) | 14 |
%l |
Hour (space-padded 12h) | 2 |
Colors
Named colors: red, green, blue, yellow, cyan, magenta, white, black, default
256-color palette: colour0 through colour255 (or color0 through color255). Numeric palette indexes are also accepted.