name: wezterm which: wezterm description: "Use for WezTerm config: Lua, panes, tabs, domains, key bindings, appearance. Use terminal-harness to drive interactive programs."
WezTerm Skill
WezTerm is a Rust-based GPU-accelerated terminal emulator with a built-in
multiplexer, cross-platform (Linux/macOS/Windows/FreeBSD/NetBSD).
Configuration uses Lua 5.4 in ~/.wezterm.lua or
~/.config/wezterm/wezterm.lua.
Config file discovery order: CLI --config-file > $WEZTERM_CONFIG_FILE >
Windows exe dir > $XDG_CONFIG_HOME/wezterm/wezterm.lua >
~/.config/wezterm/wezterm.lua > ~/.wezterm.lua
Auto-reload: enabled by default (automatically_reload_config = true).
Changes take effect without restart.
Basic Config
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
config.font = wezterm.font 'JetBrains Mono'
config.font_size = 11
config.color_scheme = 'nord'
config.enable_tab_bar = false
return config
Config File Location
| Priority | Path |
|---|---|
| 1 | --config-file CLI argument |
| 2 | $WEZTERM_CONFIG_FILE env var |
| 3 | Windows: exe directory (portable/thumb drive mode) |
| 4 | $XDG_CONFIG_HOME/wezterm/wezterm.lua |
| 5 | ~/.config/wezterm/wezterm.lua |
| 6 | ~/.wezterm.lua |
Key config options:
config.automatically_reload_config = true -- default
config.config_file = 'path/to/wezterm.lua' -- explicit path
Colors & Appearance
-- Use a built-in color scheme
config.color_scheme = 'nord' -- see wezterm.color.get_builtin_schemes()
-- Fully custom colors
config.colors = {
foreground = '#cccccc',
background = '#1e1e1e',
cursor_bg = '#ffffff',
cursor_border = '#ffffff',
cursor_fg = '#1e1e1e',
selection_bg = '#264f78',
tab_bar = { background = '#0d1117', active_tab = { bg_color = '#161b22', fg_color = '#cccccc' } },
ansi = { '#484848', '#cc4444', '#44cc44', '#cccc44', '#4444cc', '#cc44cc', '#44cccc', '#cccccc' },
brightness = { '#303030', '#e06060', '#60e060', '#e0e060', '#6060e0', '#e060e0', '#60e0e0', '#e0e0e0' },
}
Background layers (multiple can be combined):
-- Solid background color
config.background = { { source = 'solid_color', color = '#0d1117' } }
-- Vertical gradient
config.background = {
{ source = 'linear_gradient', orientation = 'Vertical', colors = { '#0d1117', '#161b22' } },
}
-- Radial gradient
config.background = {
{ source = 'radial_gradient', anchor = 'bottom', colors = { '#0d1117', '#161b22' } },
}
-- Background image
config.background = {
{ source = 'image', path = '/path/to/image.png', hscan = 'Flip', vscan = 'Tile' },
{ source = 'solid_color', color = '#0d1117', alpha = 0.7 }, -- overlay
}
Window chrome:
config.window_decorations = 'RESIZE' -- 'RESIZE' | 'MACOS_BORDERLESS' | 'NONE' | 'ALWAYS_FORCE_OPAQUE'
config.window_background_opacity = 0.95
config.window_padding = { left = 8, right = 8, top = 0, bottom = 0 }
config.hide_tab_bar_if_only_one_tab = true
config.use_fancy_tab_bar = false
config.tab_bar_at_bottom = false
Fonts
-- Single font
config.font = wezterm.font 'JetBrains Mono'
-- With fallback chain
config.font = wezterm.font_with_fallback { 'JetBrains Mono', 'Fira Code', 'Noto Sans' }
-- Font with size and line height
config.font_size = 12
config.line_height = 1.2
config.font_rules = {
{ italic = true, font = wezterm.font('JetBrains Mono', { italic = true }) },
{ weight = 'Bold', font = wezterm.font('JetBrains Mono', { weight = 'Bold' }) },
}
Harfbuzz shaping features:
config.font_rules = {
{
intensity = 'Bold',
font = wezterm.font('JetBrains Mono', { weight = 'Bold' }),
},
{
italic = true,
font = wezterm.font('JetBrains Mono', { italic = true }),
},
}
Key Bindings
config.keys = {
-- Basic keybinding
{ key = 't', mods = 'CTRL|SHIFT', action = wezterm.action.SpawnTab 'CurrentPaneDomain' },
-- With multiple modifiers
{ key = 'Enter', mods = 'ALT', action = wezterm.action.ToggleFullScreen },
-- Send string (type text)
{ key = 'w', mods = 'CTRL|SHIFT', action = wezterm.action.SpawnWindow },
-- Encode special keys
{ key = 'LeftArrow', mods = 'ALT', action = wezterm.action.EmitEvent 'noop' },
}
config.leader = { key = 'a', mods = 'CTRL' } -- chord: Ctrl-a then key
Modifier names: CTRL, SHIFT, ALT, SUPER (macOS Cmd), CMD, META,
SUPER
Key names: single chars, Enter, Escape, Space, Backspace, Tab,
F1–F12, LeftArrow, RightArrow, UpArrow, DownArrow, Home, End,
PageUp, PageDown, Insert, Delete
Key tables for mode switching:
config.key_tables = {
copy_mode = {
{ key = 'Escape', mods = 'NONE', action = wezterm.action.ActivateCopyMode 'Prev' },
{ key = 'q', mods = 'NONE', action = wezterm.action.ActivateCopyMode 'Close' },
{ key = 'g', mods = 'NONE', action = 'ScrollByPage', args = { -1 } },
{ key = 'G', mods = 'SHIFT', action = 'ScrollToBottom' },
{ key = 'j', mods = 'NONE', action = 'ScrollByLine', args = { 1 } },
{ key = 'k', mods = 'NONE', action = 'ScrollByLine', args = { -1 } },
{ key = 'v', mods = 'NONE', action = wezterm.action.CopyMode 'Select' },
{ key = 'V', mods = 'SHIFT', action = wezterm.action.CopyMode 'SelectLine' },
{ key = 'y', mods = 'NONE', action = wezterm.action.CopyTo 'Clipboard' },
{ key = '/', mods = 'NONE', action = wezterm.action.Search { Regex = '', mode = 'CopyMode' } },
},
}
Key Actions Reference
Pane Operations
wezterm.action.SplitHorizontal { domain = 'CurrentPaneDomain' }
wezterm.action.SplitVertical { domain = 'CurrentPaneDomain' }
wezterm.action.SplitPane { program = '/bin/bash', cwd = '/home', domain = 'CurrentPaneDomain' }
wezterm.action.CloseCurrentPane { confirm = true }
wezterm.action.AdjustPaneSize { direction = 'Down', amount = 3 }
wezterm.action.TogglePaneZoomState
wezterm.action.PaneSelect { mode = 'Swap' } -- 'Activate' | 'Swap' | 'ForceSelected' | 'Reset'
Tab Operations
wezterm.action.SpawnTab 'CurrentPaneDomain'
wezterm.action.SpawnTab { domain = 'CurrentPaneDomain', program = '/bin/bash', cwd = '/home' }
wezterm.action.CloseCurrentTab { confirm = true }
wezterm.action.ActivateTab 2
wezterm.action.MoveTab 3
wezterm.action.ShowTabNavigator
Window Operations
wezterm.action.SpawnWindow
wezterm.action.ActivateWindow 0
wezterm.action.SwitchToWorkspace { name = 'main', spawn = { 'wezterm', 'start' } }
wezterm.action.ToggleFullScreen
wezterm.action.Maximize
Navigation
wezterm.action.ActivatePaneDirection 'Down'
wezterm.action.ActivatePaneDirection 'Left'
wezterm.action.ActivatePaneDirection 'Right'
wezterm.action.ActivatePaneDirection 'Up'
wezterm.action.ActivatePaneByIndex 0 -- 0-indexed
wezterm.action.PaneSelect -- interactive
wezterm.action.PaneSelect { mode = 'Activate' }
Text Operations
wezterm.action.SendString 'hello'
wezterm.action.SendKey { key = 'Enter' }
wezterm.action.Paste 'Clipboard'
wezterm.action.CompleteSelection 'Clipboard'
wezterm.action.CopyTo 'Clipboard'
Copy Mode
wezterm.action.ActivateCopyMode 'CopyMode'
wezterm.action.CopyMode { preset = 'vim' } -- vim or emacs
wezterm.action.ScrollByPage -1
wezterm.action.ScrollByLine 5
wezterm.action.Search { Regex = 'pattern', mode = 'CopyMode' }
wezterm.action.QuickSelect
UI / Overlay
wezterm.action.ShowLauncher { titles = {}, cli_labels = {} }
wezterm.action.ShowDebugOverlay
wezterm.action.PromptInputLine {
description = 'Enter command',
action = wezterm.action_callback(function(window, pane, line)
if line then window:perform_action(wezterm.action.SendString(line), pane) end
end),
}
wezterm.action.InputSelector {
description = 'Select option',
choices = { { label = 'opt1', id = '1' } },
action = wezterm.action_callback(function(window, pane, id, label) end),
}
Multiple / Chaining
wezterm.action.Multiple {
wezterm.action.SplitHorizontal { domain = 'CurrentPaneDomain' },
wezterm.action.ActivatePaneDirection 'Right',
}
Other Actions
wezterm.action.EmitEvent 'my-event-name'
wezterm.action.ReloadConfiguration
wezterm.action.QuitApplication
wezterm.action.CharSelect { copy_on_select = true, }
Lua API Modules
wezterm module
wezterm.action(action_obj) -- perform an action
wezterm.action_callback(fn) -- callback(fn(window, pane, ...)) -> action
wezterm.config_builder() -- returns config table
wezterm.default_hyperlink_rules() -- returns hyperlink rules
wezterm.font(name, opts) -- font with optional weight/italic/slant
wezterm.font_with_fallback({'Font1', 'Font2'})
wezterm.format({ { Foreground = { Color = 'red' }, Text = 'hello' } })
wezterm.glob(pattern) -- glob expansion
wezterm.json_encode(val) -- JSON string
wezterm.json_parse(str) -- parse JSON
wezterm.log_error(msg)
wezterm.log_info(msg)
wezterm.log_warn(msg)
wezterm.nerdfonts -- table of icon names
wezterm.now() -- Unix timestamp
wezterm.on('event', fn) -- register event handler
wezterm.read_dir(dir) -- list directory entries
wezterm.reload_configuration()
wezterm.run_child_process(cmd) -- returns { stdout, stderr, exit_code }
wezterm.sleep_ms(ms)
wezterm.strftime(fmt, ts) -- format timestamp
Programmatic config reload:
wezterm.on('window-config-reloaded', function(window)
wezterm.log_info('config reloaded for ' .. window:panel():get_title())
end)
wezterm.color
wezterm.color.parse('#ff0000') -- returns { r=1, g=0, b=0, a=1 }
wezterm.color.from_hsla(180, 0.5, 0.5, 1.0) -- returns Color
wezterm.color.gradient({'#red', 'blue'}, 'horizontal', 10) -- interpolate colors
wezterm.color.get_builtin_schemes() -- list all built-in schemes
wezterm.color.load_scheme('nord') -- load scheme as color table
wezterm.color.extract_colors_from_image('/path/to/image.png') -- extract palette
wezterm.gui
wezterm.gui.get_appearance() -- 'Dark' | 'Light' | 'Unknown'
wezterm.gui.screens() -- list screens: { { width, height, xscale, yscale, name } }
wezterm.gui.enumerate_gpus() -- list available GPUs
wezterm.gui.default_keys() -- default keybindings as table
wezterm.gui.default_key_tables() -- default key tables (copy mode, etc.)
wezterm.gui.gui_windows() -- all GUI windows
Dark/light mode switching:
wezterm.on('update-status', function(window, pane)
local appearance = wezterm.gui.get_appearance()
local scheme = appearance == 'Dark' and 'nord' or 'nord-light'
window:configure_actions({
{ SetColorScheme = scheme },
})
end)
wezterm.mux
wezterm.mux.spawn_window({ domain = 'local', workspace = 'main', cwd = '/home' })
wezterm.mux.get_active_workspace() -- current workspace name
wezterm.mux.all_windows() -- all mux windows
wezterm.mux.rename_workspace(old_name, new_name)
wezterm.mux.set_active_workspace(name)
Window/Pane objects:
window:gui_window() -- GuiWindow
window:mux_window() -- MuxWindow
pane:split({ program = '/bin/bash', domain = 'CurrentPaneDomain' })
pane:send_text('text\n')
pane:paste()
pane:get_title()
pane:get_current_working_dir() -- returns Path or nil
pane:get_foreground_process_info() -- returns ProcessInfo { pid, name, cwd }
pane:get_text_from_region(0, 0, 100, 200) -- get text rectangle
pane:inject_output('text\n')
wezterm.plugin
wezterm.plugin.require('github.com/path/to/plugin') -- load plugin
wezterm.plugin.list() -- list loaded plugins
wezterm.plugin.update_all() -- update all plugins
Events
| Event | Callback |
|---|---|
gui-startup |
fn(window) |
gui-attached |
fn(window) |
mux-startup |
fn() |
format-tab-title |
fn(tab, tabs, panes, config, hover) |
format-window-title |
fn(window) |
update-status |
fn(window, pane) |
update-right-status |
fn(window, pane) |
window-config-reloaded |
fn(window) |
window-focus-changed |
fn(window, bool) |
window-resized |
fn(window, size) |
bell |
fn(window, pane) |
open-uri |
fn(uri, action) |
user-var-changed |
fn(pane, name, value) |
Example — dynamic tab titles:
wezterm.on('format-tab-title', function(tab, tabs, panes, config, hover)
return tab.tab_index + 1 .. ': ' .. tab.active_pane.title
end)
Example — status line:
wezterm.on('update-right-status', function(window, pane)
window:set_right_status(wezterm.format {
{ Text = wezterm.strftime('%H:%M:%S') },
})
end)
Multiplexing & Domains
config.unix_domains = { { name = 'unix', socket_dir = '/tmp/wezterm' } }
config.ssh_domains = {
{
name = 'prod-server',
host = 'example.com',
username = 'me',
port = 22,
-- or use SSH config: remote_addr = 'example.com'
ssh_option = 'value',
},
}
config.wsl_domains = { { name = 'WSL:Ubuntu', distribution = 'Ubuntu' } }
config.tls_domains = { { name = 'tls-server', host = 'example.com', port = 443 } }
Spawning in domains:
{ key = 'c', mods = 'CTRL|SHIFT', action = wezterm.action.SpawnCommandInDomain { domain = 'unix', program = '/bin/bash' } }
CLI Reference
Use terminal-harness for pane control, app input, and screen capture.
This section covers configuration-adjacent commands only.
# Launch GUI
wezterm start
wezterm start --config-file ~/.wezterm.lua
wezterm start --prefix-search 'ssh'
# SSH
wezterm ssh user@host
wezterm ssh user@host --domian-name prod
# Connect to domain
wezterm connect domain-name
# Titles
wezterm cli set-tab-title --pane-id 1 "My Tab"
wezterm cli set-window-title --window-id 0 "My Window"
wezterm cli rename-workspace --name main
# Utilities
wezterm show-keys --help # key sequence explorer
wezterm ls-fonts # list available fonts
wezterm imgcat /path/to/image.png # display image
wezterm serial /dev/ttyUSB0 115200
wezterm record --label "session" # record session
wezterm replay /path/to/recording # replay
CLI flags for wezterm start:
wezterm start --config-file FILE
wezterm start --cwd DIR
wezterm start --position X,Y
wezterm start --size WIDTH,HEIGHT
wezterm start --domain SOCKET_DIR
wezterm start --workspace NAME
Common Patterns
Dark/light mode colors:
local function get_colors()
local appearance = wezterm.gui.get_appearance()
local scheme = appearance == 'Dark' and 'nord' or 'nord-bright'
return wezterm.color.load_scheme(scheme)
end
wezterm.on('update-status', function(window, pane)
local colors = get_colors()
pane:set_config_overrides {
colors = { foreground = colors.foreground, background = colors.background },
}
end)
Gradient background with overlay:
config.background = {
{ source = 'linear_gradient', orientation = 'Vertical', colors = { '#0d1117', '#161b22' } },
{ source = 'solid_color', color = '#000000', width = '100%', opacity = 0.3, fill = 'Gradient' },
}
Workspace-aware status:
wezterm.on('format-window-title', function(window)
local workspace = wezterm.mux.get_active_workspace()
return workspace .. ' — ' .. window:gui_window().title
end)
Conditional action with callback:
wezterm.on('update-status', function(window, pane)
local has_jobs = #pane:get_foreground_process_info() > 0
window:perform_action(
has_jobs and wezterm.action.ShowTabNavigator()
or wezterm.action_callback(function() end),
pane
)
end)
URL Reference
| Topic | URL |
|---|---|
| Main docs | https://wezterm.org/ |
| Config overview | https://wezterm.org/config/ |
| Lua config options | https://wezterm.org/config/lua/config/ |
| Lua API reference | https://wezterm.org/config/lua/wezterm/ |
| Color module | https://wezterm.org/config/lua/wezterm.color/ |
| GUI module | https://wezterm.org/config/lua/wezterm.gui/ |
| Mux module | https://wezterm.org/config/lua/wezterm.mux/ |
| KeyAssignment actions | https://wezterm.org/config/lua/keyassignment/ |
| Window events | https://wezterm.org/config/lua/window-events/ |
| GUI events | https://wezterm.org/config/lua/gui-events/ |
| CLI reference | https://wezterm.org/cli/cli/ |
| Key binding config | https://wezterm.org/config/keys.html |
| Key tables | https://wezterm.org/config/key-tables.html |
| Default keys | https://wezterm.org/config/default-keys.html |
| Launching programs | https://wezterm.org/config/launch.html |
| Plugin system | https://wezterm.org/config/plugins.html |
| Mouse bindings | https://wezterm.org/config/mouse.html |
| Color schemes | https://wezterm.org/config/colors.html |