Overview
WezTerm is a GPU-accelerated cross-platform terminal emulator and multiplexer written in Rust and configured with Lua. It combines the features of a modern terminal emulator with a built-in terminal multiplexer similar to tmux, eliminating the need for a separate multiplexer. WezTerm supports true color, ligatures, image display, tabs, panes, workspaces, and SSH multiplexing.
WezTerm runs on Linux, macOS, Windows, and FreeBSD. Its Lua-based configuration enables dynamic and programmatic setup including keybinding customization, event handlers, color scheme switching, and workspace management. It supports the iTerm2 and Kitty image protocols, sixel graphics, and provides a built-in SSH client with domain multiplexing.
Installation
# macOS
brew install --cask wezterm
# Ubuntu/Debian
curl -fsSL https://apt.fury.io/wez/gpg.key | sudo gpg --yes --dearmor -o /usr/share/keyrings/wezterm-fury.gpg
echo 'deb [signed-by=/usr/share/keyrings/wezterm-fury.gpg] https://apt.fury.io/wez/ * *' | sudo tee /etc/apt/sources.list.d/wezterm.list
sudo apt update && sudo apt install wezterm
# Arch Linux
sudo pacman -S wezterm
# Fedora
sudo dnf install wezterm
# Flatpak
flatpak install flathub org.wezfurlong.wezterm
# Verify
wezterm --version
Key Bindings
Tab Management
| Shortcut | Action |
|---|
Ctrl+Shift+T | New tab |
Ctrl+Shift+W | Close tab |
Ctrl+Shift+Tab | Previous tab |
Ctrl+Tab | Next tab |
Ctrl+Shift+1-9 | Switch to tab N |
Ctrl+Shift+PageUp | Move tab left |
Ctrl+Shift+PageDown | Move tab right |
Pane Management
| Shortcut | Action |
|---|
Ctrl+Shift+% | Split horizontally |
Ctrl+Shift+" | Split vertically |
Ctrl+Shift+Arrow | Navigate panes |
Ctrl+Shift+Z | Toggle pane zoom |
Ctrl+Shift+X | Close pane |
Ctrl+Shift+LeftArrow | Adjust pane size left |
Ctrl+Shift+RightArrow | Adjust pane size right |
General
| Shortcut | Action |
|---|
Ctrl+Shift+C | Copy |
Ctrl+Shift+V | Paste |
Ctrl+Shift+F | Search |
Ctrl+Shift+Space | Quick select mode |
Ctrl+Shift+L | Debug overlay |
Ctrl+Shift+P | Command palette |
Ctrl+Shift+U | Unicode input |
Ctrl+= | Increase font size |
Ctrl+- | Decrease font size |
Ctrl+0 | Reset font size |
Configuration
-- ~/.wezterm.lua (or ~/.config/wezterm/wezterm.lua)
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
-- Font
config.font = wezterm.font('JetBrains Mono')
config.font_size = 13.0
config.harfbuzz_features = { 'calt=1', 'clig=1', 'liga=1' }
-- Appearance
config.color_scheme = 'Catppuccin Mocha'
config.window_background_opacity = 0.95
config.window_padding = {
left = 8,
right = 8,
top = 8,
bottom = 8,
}
config.hide_tab_bar_if_only_one_tab = true
config.use_fancy_tab_bar = false
config.tab_bar_at_bottom = true
-- Cursor
config.default_cursor_style = 'BlinkingBar'
config.cursor_blink_rate = 500
config.cursor_blink_ease_in = 'Constant'
config.cursor_blink_ease_out = 'Constant'
-- Window
config.initial_rows = 35
config.initial_cols = 120
config.window_decorations = 'RESIZE'
-- Scrollback
config.scrollback_lines = 10000
-- Performance
config.front_end = 'WebGpu'
config.max_fps = 120
-- Shell
config.default_prog = { '/bin/zsh' }
-- macOS specific
config.macos_forward_to_ime_modifier_mask = 'SHIFT|CTRL'
return config
Color Schemes
-- List available color schemes
-- wezterm ls-fonts --list-system
-- See: https://wezfurlong.org/wezterm/colorschemes/
config.color_scheme = 'Catppuccin Mocha'
-- Custom color scheme
config.colors = {
foreground = '#cdd6f4',
background = '#1e1e2e',
cursor_bg = '#f5e0dc',
cursor_fg = '#1e1e2e',
selection_bg = '#585b70',
selection_fg = '#cdd6f4',
ansi = {
'#45475a', '#f38ba8', '#a6e3a1', '#f9e2af',
'#89b4fa', '#f5c2e7', '#94e2d5', '#bac2de',
},
brights = {
'#585b70', '#f38ba8', '#a6e3a1', '#f9e2af',
'#89b4fa', '#f5c2e7', '#94e2d5', '#a6adc8',
},
tab_bar = {
background = '#11111b',
active_tab = { bg_color = '#1e1e2e', fg_color = '#cdd6f4' },
inactive_tab = { bg_color = '#181825', fg_color = '#6c7086' },
},
}
Key Binding Configuration
local act = wezterm.action
config.keys = {
-- Pane splits
{ key = '|', mods = 'CTRL|SHIFT', action = act.SplitHorizontal { domain = 'CurrentPaneDomain' } },
{ key = '-', mods = 'CTRL|SHIFT', action = act.SplitVertical { domain = 'CurrentPaneDomain' } },
-- Pane navigation
{ key = 'h', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Left' },
{ key = 'l', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Right' },
{ key = 'k', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Up' },
{ key = 'j', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Down' },
-- Resize panes
{ key = 'H', mods = 'CTRL|SHIFT|ALT', action = act.AdjustPaneSize { 'Left', 5 } },
{ key = 'L', mods = 'CTRL|SHIFT|ALT', action = act.AdjustPaneSize { 'Right', 5 } },
-- Toggle zoom
{ key = 'z', mods = 'CTRL|SHIFT', action = act.TogglePaneZoomState },
-- Workspaces
{ key = 'w', mods = 'CTRL|SHIFT', action = act.ShowLauncherArgs { flags = 'WORKSPACES' } },
-- Command palette
{ key = 'p', mods = 'CTRL|SHIFT', action = act.ActivateCommandPalette },
-- Quick select (URLs, hashes, etc.)
{ key = 'Space', mods = 'CTRL|SHIFT', action = act.QuickSelect },
}
Multiplexer Features
-- Workspaces (like tmux sessions)
config.keys = {
-- Switch workspace
{ key = 's', mods = 'CTRL|SHIFT', action = act.ShowLauncherArgs { flags = 'WORKSPACES' } },
-- Create new workspace
{ key = 'n', mods = 'CTRL|SHIFT|ALT', action = act.SwitchToWorkspace {
name = 'monitoring',
spawn = { args = { 'htop' } },
}},
}
SSH Multiplexing
-- SSH domains
config.ssh_domains = {
{
name = 'production',
remote_address = 'prod-server.example.com',
username = 'deploy',
multiplexing = 'WezTerm',
},
{
name = 'staging',
remote_address = 'staging.example.com',
username = 'deploy',
},
}
# Connect to SSH domain
wezterm connect production
# Direct SSH
wezterm ssh user@server
Advanced Usage
Event Handlers
-- Dynamic tab title
wezterm.on('format-tab-title', function(tab, tabs, panes, config, hover, max_width)
local title = tab.active_pane.title
if tab.is_active then
return { { Text = ' ' .. title .. ' ' } }
end
return { { Text = ' ' .. title .. ' ' } }
end)
-- Status bar
wezterm.on('update-right-status', function(window, pane)
local date = wezterm.strftime '%H:%M %Y-%m-%d'
window:set_right_status(wezterm.format {
{ Text = date .. ' ' },
})
end)
-- Background image on startup
wezterm.on('gui-startup', function(cmd)
local tab, pane, window = wezterm.mux.spawn_window(cmd or {})
window:gui_window():maximize()
end)
config.launch_menu = {
{ label = 'Bash', args = { 'bash' } },
{ label = 'Zsh', args = { 'zsh' } },
{ label = 'Htop', args = { 'htop' } },
{ label = 'Python', args = { 'python3' } },
{ label = 'SSH Production', args = { 'ssh', 'prod-server' } },
}
Quick Select Patterns
config.quick_select_patterns = {
-- Match git hashes
'[0-9a-f]{7,40}',
-- Match IP addresses
'\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}',
-- Match UUIDs
'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',
}
CLI Commands
# List available fonts
wezterm ls-fonts
# List color schemes
wezterm ls-fonts --list-system
# Connect to SSH domain
wezterm connect DOMAIN_NAME
# Start with specific config
wezterm --config-file /path/to/config.lua
# Show configuration
wezterm show-keys
Troubleshooting
| Issue | Solution |
|---|
| Fonts not rendering | Run wezterm ls-fonts; install missing fonts |
| Ligatures not working | Set harfbuzz_features in config; verify font supports ligatures |
| GPU rendering issues | Try config.front_end = 'OpenGL' or 'Software' |
| Slow on macOS | Set config.front_end = 'WebGpu'; update macOS |
| Panes not splitting | Check key binding conflicts; verify pane is focusable |
| SSH multiplexing fails | Ensure WezTerm is installed on remote; check SSH config |
| Colors wrong | Verify color_scheme name; check TERM environment variable |
| Config errors | Run wezterm --config-file config.lua to see Lua errors |