5.6 KiB
| title | aliases | tags | sources | created | updated | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| WezTerm Mouse Bindings |
|
|
|
2026-04-17 | 2026-04-17 |
Overview
WezTerm mouse bindings are fully configurable via Lua. By default, terminal applications can capture mouse events — WezTerm hands them through unless you intervene with a modifier key.
Mouse Reporting Bypass
When an app enables mouse tracking, WezTerm passes all mouse events to it rather than matching bindings. To force your bindings to fire anyway, hold SHIFT (default bypass modifier).
- Change the bypass key via
config.bypass_mouse_reporting_modifiers - Use
mouse_reporting = truein a binding entry to target app-captured state (generally avoid this)
Default Mouse Assignments
| Event | Modifiers | Action |
|---|---|---|
| Single Left Down | NONE |
SelectTextAtMouseCursor("Cell") |
| Double Left Down | NONE |
SelectTextAtMouseCursor("Word") |
| Triple Left Down | NONE |
SelectTextAtMouseCursor("Line") |
| Single Left Down | SHIFT |
ExtendSelectionToMouseCursor("Cell") |
| Single Left Down | ALT |
SelectTextAtMouseCursor("Block") |
| Single Left Up | NONE |
CompleteSelectionOrOpenLinkAtMouseCursor(...) |
| Single Left Up | SHIFT |
CompleteSelectionOrOpenLinkAtMouseCursor(...) |
| Single Left Drag | NONE |
ExtendSelectionToMouseCursor("Cell") |
| Single Left Drag | ALT |
ExtendSelectionToMouseCursor("Block") |
| Double Left Drag | NONE |
ExtendSelectionToMouseCursor("Word") |
| Triple Left Drag | NONE |
ExtendSelectionToMouseCursor("Line") |
| Single Middle Down | NONE |
PasteFrom("PrimarySelection") |
| Single Left Drag | SUPER / CTRL+SHIFT |
StartWindowDrag |
Run wezterm show-keys to inspect the effective bindings at runtime.
Disable all defaults with:
config.disable_default_mouse_bindings = true
Configuring Custom Mouse Bindings
local wezterm = require 'wezterm'
local act = wezterm.action
config.mouse_bindings = {
-- Right click sends a string
{
event = { Down = { streak = 1, button = 'Right' } },
mods = 'NONE',
action = act.SendString 'woot',
},
-- CTRL-Click opens hyperlinks
{
event = { Up = { streak = 1, button = 'Left' } },
mods = 'CTRL',
action = act.OpenLinkAtMouseCursor,
},
-- Disable Down event to prevent leaking to app (see gotcha below)
{
event = { Down = { streak = 1, button = 'Left' } },
mods = 'CTRL',
action = act.Nop,
},
}
Binding Entry Fields
| Field | Required | Description |
|---|---|---|
event |
yes | Down, Up, or Drag + streak + button |
mods |
yes | Modifier keys (same syntax as key bindings) |
action |
yes | KeyAssignment action to perform |
mouse_reporting |
no | Match only when app mouse reporting is active (default false) |
alt_screen |
no | 'Any' (default), true, or false — match only in/out of alt screen |
Event Lua Representation
-- Triple Left Down
event = { Down = { streak = 3, button = "Left" } }
-- Double Left Up
event = { Up = { streak = 2, button = "Left" } }
-- Single Left Drag
event = { Drag = { streak = 1, button = "Left" } }
Arbitrary click streaks are supported — streak = 4 for quadruple-click, etc.
Mouse Wheel Bindings
Wheel events use WheelUp / WheelDown as the button value:
-- CTRL+Scroll to resize font
{
event = { Down = { streak = 1, button = { WheelUp = 1 } } },
mods = 'CTRL',
action = act.IncreaseFontSize,
},
{
event = { Down = { streak = 1, button = { WheelDown = 1 } } },
mods = 'CTRL',
action = act.DecreaseFontSize,
},
streak and amount are fixed at 1 for wheel events in pattern matching. Use window:current_event inside a callback to get the actual delta.
Note: default scroll bindings use alt_screen = false — wheel maps to arrow keys in alt screen mode instead.
Gotcha: Binding Only the 'Up' Event
If you bind Up but not Down, the Down event is still forwarded to the running app (e.g. tmux, vim). This causes the app to see a Down without a matching Up — leading to stuck selection state or other glitches.
Fix: always pair an Up binding with a Down = act.Nop to suppress the Down event:
-- Good: suppress Down so app never sees it
{ event = { Up = { streak = 1, button = 'Left' } }, mods = 'CTRL', action = act.OpenLinkAtMouseCursor },
{ event = { Down = { streak = 1, button = 'Left' } }, mods = 'CTRL', action = act.Nop },
Key Takeaways
- Default bindings cover selection (cell/word/line/block), clipboard, link-open, and window drag
- Apps can capture mouse events; hold
SHIFT(or configured bypass mod) to force your bindings - Custom bindings go in
config.mouse_bindingsas a Lua table - Every entry needs
event,mods, andaction;mouse_reportingandalt_screenare optional filters - Wheel events use
{ WheelUp = 1 }/{ WheelDown = 1 }as the button value - Always pair an
Upbinding with aDown = act.Nopto avoid leaking events to apps wezterm show-keysshows the live effective binding table
Related
- wiki/dotfiles/wezterm-key-bindings — keyboard equivalent, same
modssyntax - wiki/dotfiles/wezterm-key-tables — modal layers that also affect input routing
- wiki/dotfiles/wezterm-keyboard-concepts — how WezTerm handles input at the OS level
- wiki/dotfiles/wezterm-config — config file structure and live reload