psmux reads its config on startup from the first file found (in order):
~/.psmux.conf~/.psmuxrc~/.tmux.conf~/.config/psmux/psmux.conf
Config syntax is tmux-compatible. Most .tmux.conf lines work as-is.
You can also specify a custom config file path with the -f flag:
# Use a specific config file instead of default search
psmux -f ~/.config/psmux/custom.conf
# Use an empty config (no settings loaded)
psmux -f NULThis sets the PSMUX_CONFIG_FILE environment variable internally, which the server checks before searching the default locations.
Create ~/.psmux.conf:
# Change prefix key to Ctrl+a
set -g prefix C-a
# Enable mouse
set -g mouse on
# Window numbering base (default is 1)
set -g base-index 1
# Customize status bar
set -g status-left "[#S] "
set -g status-right "%H:%M %d-%b-%y"
set -g status-style "bg=green,fg=black"
# Cursor style: block, underline, or bar
set -g cursor-style bar
set -g cursor-blink on
# Scrollback history
set -g history-limit 5000
# Prediction dimming (disable for apps like Neovim)
set -g prediction-dimming off
# Key bindings
bind-key -T prefix h split-window -h
bind-key -T prefix v split-window -vpsmux launches PowerShell 7 (pwsh) by default. You can change this:
# Use cmd.exe
set -g default-shell cmd
# Use PowerShell 5 (Windows built-in)
set -g default-shell powershell
# Use PowerShell 7 (explicit path)
set -g default-shell "C:/Program Files/PowerShell/7/pwsh.exe"
# Use Git Bash
set -g default-shell "C:/Program Files/Git/bin/bash.exe"
# Use Nushell
set -g default-shell nu
# Use Windows Subsystem for Linux (via wsl.exe)
set -g default-shell wslYou can also launch a window with a specific command without changing the default:
psmux new-window -- cmd /K echo hello
psmux new-session -s py -- python
psmux split-window -- "C:/Program Files/Git/bin/bash.exe"| Option | Type | Default | Description |
|---|---|---|---|
prefix |
Key | C-b |
Prefix key |
prefix2 |
Key | none |
Secondary prefix key (optional) |
base-index |
Int | 0 |
First window number |
pane-base-index |
Int | 0 |
First pane number |
escape-time |
Int | 500 |
Escape delay (ms) |
repeat-time |
Int | 500 |
Repeat key timeout (ms) |
history-limit |
Int | 2000 |
Scrollback lines per pane |
display-time |
Int | 750 |
Message display time (ms) |
display-panes-time |
Int | 1000 |
Pane overlay time (ms) |
status-interval |
Int | 15 |
Status refresh (seconds) |
mouse |
Bool | on |
Mouse support |
scroll-enter-copy-mode |
Bool | on |
Enter copy mode on mouse scroll (set off to disable) |
pwsh-mouse-selection |
Bool | off |
Windows 11 PowerShell-style word/line selection (double/triple-click) |
status |
Bool/Int | on |
Show status bar (number = line count) |
status-position |
Str | bottom |
top or bottom |
status-justify |
Str | left |
left, centre, right, absolute-centre |
status-left-length |
Int | 10 |
Max width of status-left |
status-right-length |
Int | 40 |
Max width of status-right |
focus-events |
Bool | off |
Pass focus events to apps |
mode-keys |
Str | emacs |
vi or emacs |
renumber-windows |
Bool | off |
Auto-renumber windows on close |
automatic-rename |
Bool | on |
Rename windows from foreground process |
monitor-activity |
Bool | off |
Flag windows with new output |
monitor-silence |
Int | 0 |
Seconds before silence flag (0=off) |
visual-activity |
Bool | off |
Visual indicator for activity |
synchronize-panes |
Bool | off |
Send input to all panes |
remain-on-exit |
Bool | off |
Keep panes after process exits |
aggressive-resize |
Bool | off |
Resize to smallest client |
window-size |
Str | latest |
largest, smallest, manual, latest |
destroy-unattached |
Bool | off |
Exit server when no clients attached |
exit-empty |
Bool | on |
Exit server when all windows closed |
set-titles |
Bool | off |
Update terminal title |
set-titles-string |
Str | Terminal title format | |
default-shell |
Str | pwsh |
Shell to launch |
default-command |
Str | Alias for default-shell | |
word-separators |
Str | " -_@" |
Copy-mode word delimiters |
activity-action |
Str | other |
Action on window activity: any, none, current, other |
silence-action |
Str | other |
Action on window silence: any, none, current, other |
bell-action |
Str | any |
Bell action: controls audible bell forwarding and status bar flag (any, none, current, other) |
visual-bell |
Bool | off |
Visual bell indicator |
allow-passthrough |
Str | off |
Allow terminal passthrough sequences (on/off/all) |
allow-rename |
Bool | on |
Allow programs to set window title via escape sequences |
allow-set-title |
Bool | off |
Allow programs to set pane title via OSC 0/2 escape sequences (see pane-titles.md) |
allow-predictions |
Bool | off |
Preserve PSReadLine prediction settings (see below) |
default-terminal |
Str | Terminal type string (sets TERM env var in panes) |
|
update-environment |
Str | (tmux defaults) | Space-separated list of env vars to refresh on client attach |
warm |
Bool | on |
Pre-spawn shells for instant window/pane creation (see warm-sessions.md) |
copy-command |
Str | Shell command for clipboard pipe | |
set-clipboard |
Str | on |
Clipboard interaction (on/off/external) |
main-pane-width |
Int | 0 |
Main pane width in main-vertical layout |
main-pane-height |
Int | 0 |
Main pane height in main-horizontal layout |
| Option | Type | Default | Description |
|---|---|---|---|
status-left |
Str | [#S] |
Left status bar content |
status-right |
Str | Right status bar content | |
status-style |
Str | bg=green,fg=black |
Status bar style |
status-left-style |
Str | Left status style | |
status-right-style |
Str | Right status style | |
message-style |
Str | bg=yellow,fg=black |
Message style |
message-command-style |
Str | bg=black,fg=yellow |
Command prompt style |
mode-style |
Str | bg=yellow,fg=black |
Copy-mode highlight |
pane-border-style |
Str | Inactive border style | |
pane-active-border-style |
Str | fg=green |
Active border style |
pane-border-format |
Str | Pane border format string (e.g. #{pane_index}: #{pane_title}) |
|
pane-border-status |
Str | Pane border status position (top/bottom/off) |
|
window-status-format |
Str | #I:#W#F |
Inactive tab format |
window-status-current-format |
Str | #I:#W#F |
Active tab format |
window-status-separator |
Str | " " |
Tab separator |
window-status-style |
Str | Inactive tab style | |
window-status-current-style |
Str | Active tab style | |
window-status-activity-style |
Str | reverse |
Activity tab style |
window-status-bell-style |
Str | reverse |
Bell tab style |
window-status-last-style |
Str | Last-active tab style |
psmux supports a multi-line status bar using the status-format[] array. Set the status option to a number to control how many lines the status bar displays:
# Enable a 2-line status bar
set -g status 2
# Configure each line (0-indexed)
set -g status-format[0] "#[align=left]#S #[align=right]%H:%M"
set -g status-format[1] "#[align=left]#{W:#I:#W }"The first line (status-format[0]) replaces the default status bar content. Additional lines stack below (or above, depending on status-position).
Show pane information on the border between panes:
# Enable pane border labels at the top of each pane
set -g pane-border-status top
# Customize what the label shows
set -g pane-border-format " #{pane_index}: #{pane_title} [#{pane_current_command}] "
# Disable pane border labels
set -g pane-border-status offUse select-pane -T "title" to set a pane title that appears in the border label. Clear a title with select-pane -T "". The default pane title is the hostname, matching tmux convention.
Note: PowerShell 7 automatically sets the pane title to the current working directory on every prompt via OSC escape sequences. If you see a file path in your pane border labels instead of the hostname, see pane-titles.md for details and options to control this.
When a program inside a pane emits BEL (\x07), psmux forwards the bell character to your host terminal so you hear the audible beep. The bell-action option controls when this happens and when the status bar tab gets a bell flag (!):
# Forward bell from any window (default)
set -g bell-action any
# Forward bell only from the active window
set -g bell-action current
# Forward bell only from non-active windows
set -g bell-action other
# Mute bell completely (no sound, no status bar flag)
set -g bell-action noneThe window-status-bell-style option controls how the tab looks when flagged:
set -g window-status-bell-style "fg=red,bold"PowerShell example to test:
# These should all produce an audible beep inside psmux:
Write-Host "`a"
[Console]::Beep()
[char]7Mouse support is enabled by default. You can customize how the mouse interacts with psmux:
# Disable mouse entirely (no click, scroll, or drag)
set -g mouse off
# Disable entering copy mode on mouse scroll
set -g scroll-enter-copy-mode off
# Enable Windows 11 PowerShell-style word/line selection
# Double-click selects a word, triple-click selects a line
set -g pwsh-mouse-selection onWhen scroll-enter-copy-mode is off, scrolling in a pane does not enter copy mode and instead passes scroll events directly to the running application.
psmux supports tmux-style command chaining with the ; operator. Multiple commands on a single line are executed sequentially:
# Split and move focus in one binding
bind-key M-s split-window -h \; select-pane -L
# Create a development layout
bind-key D split-window -v -p 30 \; split-window -h \; select-pane -t 0In config files, escape the semicolon with \; so it is not treated as a comment delimiter.
psmux distinguishes between lowercase and uppercase letters in key bindings, matching tmux behavior:
# These are two different bindings:
bind-key t clock-mode # Prefix + t (lowercase)
bind-key T choose-tree # Prefix + Shift+T (uppercase)
# Uppercase bindings for plugin managers
bind-key I run-shell '~/.psmux/plugins/ppm/scripts/install_plugins.ps1'
bind-key U run-shell '~/.psmux/plugins/ppm/scripts/update_plugins.ps1'Multi-character key names like Space, Enter, Tab, and Escape are fully supported in prefix configuration:
set -g prefix C-Space
unbind-key C-b
bind-key C-Space send-prefix| Option | Type | Default | Description |
|---|---|---|---|
prediction-dimming |
Bool | off |
Dim predictive/speculative text |
cursor-style |
Str | Cursor shape: block, underline, or bar |
|
cursor-blink |
Bool | off |
Cursor blinking |
env-shim |
Bool | on |
Inject Unix-compatible env function in PowerShell panes |
claude-code-fix-tty |
Bool | on |
Patch Node.js process.stdout.isTTY for Claude Code |
claude-code-force-interactive |
Bool | on |
Set CLAUDE_CODE_FORCE_INTERACTIVE=1 in panes |
Style format: "fg=colour,bg=colour,bold,dim,underscore,italics,reverse,strikethrough"
Colours: default, black, red, green, yellow, blue, magenta, cyan, white, colour0–colour255, #RRGGBB
# Default session name used when not explicitly provided
$env:PSMUX_DEFAULT_SESSION = "work"
# Enable prediction dimming (off by default; dims predictive/speculative text)
$env:PSMUX_DIM_PREDICTIONS = "1"
# Disable warm pane pre-spawning (same as set -g warm off)
$env:PSMUX_NO_WARM = "1"
# Override the config file path (same effect as -f flag)
$env:PSMUX_CONFIG_FILE = "C:\Users\me\.psmux-alt.conf"
# These are set INSIDE psmux panes (tmux-compatible):
# TMUX - socket path and server info
# TMUX_PANE - current pane ID (%0, %1, etc.)Use set-environment to set env vars that are inherited by newly created panes:
# Set a global env var (inherited by all new panes)
psmux set-environment -g EDITOR vim
# Set a session-scoped env var
psmux set-environment MY_VAR value
# Unset an env var
psmux set-environment -gu MY_VAR
# Show all environment variables
psmux show-environment
psmux show-environment -gEnvironment variables set this way are injected at the process level when new panes spawn, so they are completely invisible (no commands echoed in the shell).
By default, psmux disables PSReadLine inline predictions (the grayed-out autocompletion/intellisense suggestions that appear as you type) to avoid additional unexpected bugs caused by the interaction between predictions and ConPTY. This means PredictionSource defaults to None inside psmux, even if your profile sets it to HistoryAndPlugin (#150).
If enough people test predictions and the community supports enabling them by default, this will be changed in a future release.
To preserve your prediction/autocompletion settings, enable allow-predictions:
set -g allow-predictions onWith this enabled:
- If your profile sets
PredictionSource, psmux respects your choice - If your profile does not set it, psmux restores the system default (typically
HistoryAndPlugin)
Prediction dimming is off by default. If you want psmux to dim predictive/speculative text (e.g. shell autosuggestions), you can enable it in ~/.psmux.conf:
set -g prediction-dimming onYou can also enable it for the current shell only:
$env:PSMUX_DIM_PREDICTIONS = "1"
psmuxTo make it persistent for new shells:
setx PSMUX_DIM_PREDICTIONS 1You can reload your config file without restarting psmux. From the command prompt (Prefix + :), run:
source-file ~/.psmux.confOr from outside psmux:
psmux source-file ~/.psmux.confThis re-executes every line in the config file, applying any changes to options, key bindings, hooks, and styles immediately.
By default, windows and panes are numbered starting from 0. You can change the starting index for both:
# Start window numbering at 1
set -g base-index 1
# Start pane numbering at 1
set -g pane-base-index 1The pane-base-index setting affects:
- Display Panes overlay (
Prefix + q): The numbers shown on each pane start from your configured base index - Pane targets: When referencing panes by number (e.g.
select-pane -t 1), numbering follows your base index - Format variables:
#{pane_index}reflects the base index setting - Status bar and border labels: Pane numbers in format strings use the configured base
A common setup for both windows and panes to start at 1:
set -g base-index 1
set -g pane-base-index 1Press Prefix + q to show numbered overlays on each pane. While the overlay is visible, press any displayed number key to jump to that pane. The overlay auto-dismisses after display-panes-time milliseconds (default: 1000ms).
# Show pane numbers for 3 seconds
set -g display-panes-time 3000The numbers shown respect your pane-base-index setting. For example, with pane-base-index 1, three panes show as 1, 2, 3 instead of 0, 1, 2.
You can also trigger this overlay from the command line:
psmux display-panesWhen splitting panes, you can control the size and starting directory of the new pane:
# Split vertically, new pane takes 30% of the space
split-window -v -p 30
# Split horizontally, new pane takes 70% of the space
split-window -h -p 70
# Split and start in a specific directory
split-window -v -c "C:\Projects\myapp"
# Split and start in the current pane's directory
split-window -h -c "#{pane_current_path}"
# Split and run a specific command
split-window -v -- pythonThese flags also work when creating new windows:
# New window with a specific name
new-window -n "logs"
# New window in a specific directory
new-window -c "C:\Projects"
# New window running a specific command with a name
new-window -n "build" -- cargo build --watchWhen you set a window name with -n, the automatic-rename flag is turned off for that window so psmux does not overwrite your chosen name with the foreground process name. To re-enable automatic renaming for that window:
set-option -w automatic-rename onControl what happens when clients disconnect or all windows close:
# Exit the server when no clients are attached (default: off)
set -g destroy-unattached on
# Exit the server when the last window/session closes (default: on)
set -g exit-empty onWith destroy-unattached on, the server process terminates as soon as the last client detaches. This is useful for single-use sessions.
With exit-empty off, the server stays alive even after all sessions are closed, allowing new sessions to be created without restarting.
When a process inside a pane exits, the pane normally closes. To keep the pane visible after its process exits:
set -g remain-on-exit onA pane with a dead process shows its last output and can be respawned:
# Restart the default shell in the pane
psmux respawn-pane
# Kill any remaining process and restart
psmux respawn-pane -k
# Respawn in a different directory
psmux respawn-pane -c "C:\Projects"
# Respawn with a specific command
psmux respawn-pane -- python app.pyThis is useful for monitoring: if a long-running process crashes, you can see its final output and restart it without losing the pane layout.
You can set environment variables at the session or global level that get inherited by all new panes:
# Set a global env var (all new panes in all sessions inherit this)
psmux set-environment -g EDITOR vim
# Set a session-scoped env var
psmux set-environment MY_VAR value
# Unset a global env var
psmux set-environment -gu MY_VAR
# View all environment variables
psmux show-environment
psmux show-environment -gYou can also pass environment variables when creating a new session:
# Create a session with custom environment
psmux new-session -s work -e "PROJECT=myapp" -e "ENV=production"The status bar supports time format variables that update in real time:
# Show current time in the status bar (updates every second)
set -g status-right "%H:%M:%S %d-%b-%y"
# Common time format variables:
# %H Hour (24-hour, 00-23)
# %I Hour (12-hour, 01-12)
# %M Minute (00-59)
# %S Second (00-59)
# %p AM/PM
# %r Full time in 12-hour format (e.g. 02:30:45 PM)
# %R Hour:Minute in 24-hour format (e.g. 14:30)
# %d Day of month (01-31)
# %b Abbreviated month name (Jan, Feb, ...)
# %Y Full year (2025)
# %a Abbreviated weekday (Mon, Tue, ...)Time variables refresh based on the status-interval option (default: 15 seconds). For second-level precision, reduce the interval:
# Update status bar every second (for live clock)
set -g status-interval 1psmux supports PSReadLine's ListView prediction style, which shows a dropdown list of suggestions:
# In your PowerShell profile ($PROFILE)
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineOption -PredictionViewStyle ListViewFor this to work inside psmux, enable allow-predictions in your psmux config:
set -g allow-predictions onWithout allow-predictions on, psmux resets PSReadLine's prediction settings during initialization, which disables ListView mode.