> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/wezterm/wezterm/llms.txt
> Use this file to discover all available pages before exploring further.

# Window Events

> Events emitted by windows and panes during their lifecycle

Window events are emitted throughout the lifecycle of WezTerm windows and panes. These events allow you to customize window behavior, format UI elements, and respond to user interactions.

## Formatting and UI Events

### format-tab-title

**Since:** 20210502-130208-bff6815d

Emitted when tab title text needs to be computed or recomputed.

#### Characteristics

* **Synchronous event** - Must return immediately to avoid blocking UI
* Cannot call asynchronous functions like `wezterm.run_child_process()`
* Called twice per tab: once for measurement, once for rendering
* Only the first registered handler is executed

#### Event Signature

```lua theme={null}
wezterm.on('format-tab-title', 
  function(tab, tabs, panes, config, hover, max_width)
    -- Return string or FormatItems table
  end
)
```

<ParamField path="tab" type="TabInformation">
  Information about the tab being formatted. Contains `tab_title`, `active_pane`, `is_active`, and more.
</ParamField>

<ParamField path="tabs" type="TabInformation[]">
  Array of all tabs in the window.
</ParamField>

<ParamField path="panes" type="PaneInformation[]">
  Array of all panes in the active tab.
</ParamField>

<ParamField path="config" type="table">
  Effective configuration for the window.
</ParamField>

<ParamField path="hover" type="boolean">
  True if mouse is hovering over this tab. False on first pass (measurement).
</ParamField>

<ParamField path="max_width" type="number">
  Maximum cells available for this tab. Set to `tab_max_width` on first pass.
</ParamField>

#### Return Values

<ResponseField name="string" type="string">
  Plain text for the tab title
</ResponseField>

<ResponseField name="FormatItems" type="table">
  Array of format items with text, colors, and attributes (same as `wezterm.format()`)
</ResponseField>

#### Examples

##### Basic Tab Title

```lua theme={null}
local wezterm = require 'wezterm'

function tab_title(tab_info)
  local title = tab_info.tab_title
  if title and #title > 0 then
    return title
  end
  return tab_info.active_pane.title
end

wezterm.on('format-tab-title',
  function(tab, tabs, panes, config, hover, max_width)
    local title = tab_title(tab)
    if tab.is_active then
      return {
        { Background = { Color = 'blue' } },
        { Text = ' ' .. title .. ' ' },
      }
    end
    return title
  end
)
```

##### Fancy Tab Bar with Icons

```lua theme={null}
local SOLID_LEFT_ARROW = wezterm.nerdfonts.pl_right_hard_divider
local SOLID_RIGHT_ARROW = wezterm.nerdfonts.pl_left_hard_divider

wezterm.on('format-tab-title',
  function(tab, tabs, panes, config, hover, max_width)
    local edge_background = '#0b0022'
    local background = '#1b1032'
    local foreground = '#808080'

    if tab.is_active then
      background = '#2b2042'
      foreground = '#c0c0c0'
    elseif hover then
      background = '#3b3052'
      foreground = '#909090'
    end

    local edge_foreground = background
    local title = tab.active_pane.title

    -- Ensure titles fit, leaving room for edges
    title = wezterm.truncate_right(title, max_width - 2)

    return {
      { Background = { Color = edge_background } },
      { Foreground = { Color = edge_foreground } },
      { Text = SOLID_LEFT_ARROW },
      { Background = { Color = background } },
      { Foreground = { Color = foreground } },
      { Text = title },
      { Background = { Color = edge_background } },
      { Foreground = { Color = edge_foreground } },
      { Text = SOLID_RIGHT_ARROW },
    }
  end
)
```

##### Tab Index and Count

```lua theme={null}
wezterm.on('format-tab-title',
  function(tab, tabs, panes, config, hover, max_width)
    local title = tab.active_pane.title
    local index = tab.tab_index + 1
    local count = #tabs
    
    return string.format('[%d/%d] %s', index, count, title)
  end
)
```

### format-window-title

**Since:** 20210314-114017-04b7cedd

Emitted when the window title needs to be formatted.

```lua theme={null}
wezterm.on('format-window-title', function(tab, pane, tabs, panes, config)
  local title = tab.active_pane.title
  local workspace = tab.active_pane.user_vars.WORKSPACE or 'default'
  return string.format('%s - %s', workspace, title)
end)
```

## Status Bar Events

### update-status

**Since:** 20220903-194523-3bb1ed61

Emitted periodically based on `status_update_interval` configuration.

#### Characteristics

* Asynchronous - can perform longer operations
* Only one instance runs at a time (coalesced if handler is slow)
* Won't schedule next call until `status_update_interval` ms after previous call completes

#### Event Signature

```lua theme={null}
wezterm.on('update-status', function(window, pane)
  -- Update status bars using window methods
end)
```

<ParamField path="window" type="Window">
  GUI window object with methods like `set_left_status()` and `set_right_status()`
</ParamField>

<ParamField path="pane" type="Pane">
  Active pane in the window
</ParamField>

#### Examples

##### Clock in Status Bar

```lua theme={null}
wezterm.on('update-status', function(window, pane)
  local date = wezterm.strftime '%Y-%m-%d %H:%M:%S'
  window:set_right_status(wezterm.format {
    { Attribute = { Intensity = 'Bold' } },
    { Text = date },
  })
end)
```

##### Workspace Indicator

```lua theme={null}
wezterm.on('update-status', function(window, pane)
  local workspace = window:active_workspace()
  local colors = {
    coding = '#00ff00',
    ops = '#ff0000',
    default = '#888888',
  }
  
  window:set_left_status(wezterm.format {
    { Background = { Color = colors[workspace] or colors.default } },
    { Foreground = { Color = '#000000' } },
    { Text = ' ' .. workspace .. ' ' },
  })
end)
```

##### Battery and System Info

```lua theme={null}
wezterm.on('update-status', function(window, pane)
  local battery = ''
  for _, b in ipairs(wezterm.battery_info()) do
    battery = string.format('%.0f%%', b.state_of_charge * 100)
  end
  
  local date = wezterm.strftime '%H:%M'
  
  window:set_right_status(wezterm.format {
    { Text = battery .. ' | ' .. date },
  })
end)
```

### update-right-status

Deprecated in favor of `update-status`. Use `update-status` instead.

## Interaction Events

### bell

**Since:** 20211204-082213-a66c61ee9

Emitted when ASCII BEL sequence is received by a pane.

#### Characteristics

* Fire-and-forget event
* Does not alter WezTerm's bell handling (supplements it)
* Pane may not be the active pane

```lua theme={null}
wezterm.on('bell', function(window, pane)
  wezterm.log_info('Bell in pane ' .. pane:pane_id())
  -- Could show notification, flash colors, etc.
end)
```

### open-uri

Emitted when a URI is activated (e.g., clicking a link).

#### Event Signature

```lua theme={null}
wezterm.on('open-uri', function(window, pane, uri)
  -- Return false to prevent default action
end)
```

<ParamField path="uri" type="string">
  The URI that was activated
</ParamField>

#### Return Value

<ResponseField name="false" type="boolean">
  Prevent default browser opening
</ResponseField>

<ResponseField name="nil" type="nil">
  Allow default handling
</ResponseField>

#### Examples

##### Custom mailto Handler

```lua theme={null}
wezterm.on('open-uri', function(window, pane, uri)
  local start, match_end = uri:find 'mailto:'
  if start == 1 then
    local recipient = uri:sub(match_end + 1)
    window:perform_action(
      wezterm.action.SpawnCommandInNewWindow {
        args = { 'mutt', recipient },
      },
      pane
    )
    return false -- Prevent browser opening
  end
  -- Allow default for other URIs
end)
```

##### JIRA Integration

```lua theme={null}
wezterm.on('open-uri', function(window, pane, uri)
  -- Handle jira:PROJ-123 format
  local issue = uri:match('^jira:(.+)$')
  if issue then
    local url = 'https://jira.company.com/browse/' .. issue
    wezterm.open_with(url)
    return false
  end
end)
```

### new-tab-button-click

**Since:** 20230326-111934-3666303c

Emitted when the `+` button in the tab bar is clicked.

```lua theme={null}
wezterm.on('new-tab-button-click',
  function(window, pane, button, default_action)
    -- button: "Left", "Right", or "Middle"
    -- default_action: KeyAssignment or nil
    
    if button == 'Right' then
      window:perform_action(
        wezterm.action.ShowLauncherArgs { flags = 'FUZZY|WORKSPACES' },
        pane
      )
      return false -- Prevent default
    end
    -- Allow default for left-click
  end
)
```

### augment-command-palette

**Since:** 20230712-072601-f4abf8fd

Emitted when Command Palette is shown. Add custom entries.

#### Characteristics

* Synchronous - no async operations allowed
* Returns array of command entries

```lua theme={null}
wezterm.on('augment-command-palette', function(window, pane)
  return {
    {
      brief = 'Rename tab',
      icon = 'md_rename_box',
      action = wezterm.action.PromptInputLine {
        description = 'Enter new name for tab',
        action = wezterm.action_callback(function(window, pane, line)
          if line then
            window:active_tab():set_title(line)
          end
        end),
      },
    },
    {
      brief = 'Select workspace',
      icon = 'md_briefcase',
      action = wezterm.action.ShowLauncherArgs {
        flags = 'FUZZY|WORKSPACES',
      },
    },
  }
end)
```

## Lifecycle Events

### window-resized

**Since:** 20210314-114017-04b7cedd

Emitted when window is resized or enters/exits fullscreen.

#### Characteristics

* Asynchronous with respect to resize operation
* Coalesced: max 1 executing + 1 buffered during live resize

```lua theme={null}
wezterm.on('window-resized', function(window, pane)
  local dims = window:get_dimensions()
  wezterm.log_info('Window resized to ' .. dims.pixel_width .. 'x' .. dims.pixel_height)
end)
```

##### Adaptive Padding in Fullscreen

```lua theme={null}
function recompute_padding(window)
  local window_dims = window:get_dimensions()
  local overrides = window:get_config_overrides() or {}

  if not window_dims.is_full_screen then
    if not overrides.window_padding then
      return -- No changes needed
    end
    overrides.window_padding = nil
  else
    -- Use middle third in fullscreen
    local third = math.floor(window_dims.pixel_width / 3)
    local new_padding = {
      left = third,
      right = third,
      top = 0,
      bottom = 0,
    }
    if overrides.window_padding
      and new_padding.left == overrides.window_padding.left then
      return -- Padding unchanged
    end
    overrides.window_padding = new_padding
  end
  window:set_config_overrides(overrides)
end

wezterm.on('window-resized', function(window, pane)
  recompute_padding(window)
end)

wezterm.on('window-config-reloaded', function(window)
  recompute_padding(window)
end)
```

### window-config-reloaded

**Since:** 20210314-114017-04b7cedd

Emitted when window configuration is reloaded.

#### Triggers

* Configuration file changes (when `automatically_reload_config` is enabled)
* `ReloadConfiguration` key action
* `window:set_config_overrides()` is called

#### Important

Calling `window:set_config_overrides()` inside this event triggers another event. Avoid loops by only calling when values actually change.

```lua theme={null}
wezterm.on('window-config-reloaded', function(window, pane)
  wezterm.log_info('Config reloaded for window ' .. window:window_id())
end)
```

### window-focus-changed

**Since:** 20221119-145034-49b9839f

Emitted when window focus state changes.

```lua theme={null}
wezterm.on('window-focus-changed', function(window, pane)
  if window:is_focused() then
    wezterm.log_info('Window gained focus')
  else
    wezterm.log_info('Window lost focus')
  end
end)
```

##### Dim Unfocused Windows

```lua theme={null}
wezterm.on('window-focus-changed', function(window, pane)
  local overrides = window:get_config_overrides() or {}
  
  if window:is_focused() then
    overrides.color_scheme = 'Tokyo Night'
  else
    overrides.color_scheme = 'Tokyo Night Storm'
  end
  
  window:set_config_overrides(overrides)
end)
```

### user-var-changed

**Since:** 20220903-194523-3bb1ed61

Emitted when a user variable is set via escape sequence.

#### Setting User Vars

From shell:

```bash theme={null}
printf "\033]1337;SetUserVar=%s=%s\007" foo `echo -n bar | base64`
```

#### Event Handler

```lua theme={null}
wezterm.on('user-var-changed', function(window, pane, name, value)
  wezterm.log_info('User var: ' .. name .. ' = ' .. value)
  
  if name == 'BUILD_STATUS' then
    local colors = {
      success = 'green',
      failure = 'red',
      running = 'yellow',
    }
    window:set_left_status(wezterm.format {
      { Background = { Color = colors[value] or 'gray' } },
      { Text = ' ' .. value .. ' ' },
    })
  end
end)
```

## Common Patterns

### Status Bar with Multiple Sections

```lua theme={null}
wezterm.on('update-status', function(window, pane)
  local workspace = window:active_workspace()
  local date = wezterm.strftime '%H:%M'
  local battery = ''
  
  for _, b in ipairs(wezterm.battery_info()) do
    battery = string.format('🔋%.0f%%', b.state_of_charge * 100)
  end
  
  window:set_left_status(workspace)
  window:set_right_status(battery .. ' | ' .. date)
end)
```

### Conditional UI Based on Pane

```lua theme={null}
wezterm.on('update-status', function(window, pane)
  local cwd = pane:get_current_working_dir()
  if cwd and cwd:find('/production') then
    window:set_left_status(wezterm.format {
      { Background = { Color = 'red' } },
      { Foreground = { Color = 'white' } },
      { Text = ' ⚠ PRODUCTION ⚠ ' },
    })
  else
    window:set_left_status('')
  end
end)
```

## See Also

* [Window object](/lua/objects/window) - Window manipulation methods
* [Pane object](/lua/objects/pane) - Pane information and control
* [Tab object](/lua/objects/tab) - Tab information and control
