> ## 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.

# Multiplexer Events

> Events emitted by the WezTerm multiplexer layer

Multiplexer (mux) events are emitted by WezTerm's multiplexer layer, which manages terminal sessions, panes, tabs, and windows. These events allow you to customize multiplexer behavior and startup.

## mux-startup

**Since:** 20220624-141144-bd1b7c5d

Emitted once when the mux server starts up.

### Timing

* Fires before any default program is started
* Fires BEFORE `gui-startup` event
* If this event creates panes, they take precedence over default program configuration
* Fires in both local and remote (daemon) mode

### Event Signature

```lua theme={null}
wezterm.on('mux-startup', function()
  -- No parameters
end)
```

### Return Value

No return value expected. This is a fire-and-forget event.

### Examples

#### Basic Window Split

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

-- Called when the mux server starts
wezterm.on('mux-startup', function()
  local tab, pane, window = mux.spawn_window {}
  pane:split { direction = 'Top' }
end)

return {
  unix_domains = {
    { name = 'unix' },
  },
}
```

#### Multi-Pane Development Layout

```lua theme={null}
wezterm.on('mux-startup', function()
  -- Create main window with editor
  local tab, pane, window = mux.spawn_window {
    cwd = wezterm.home_dir .. '/projects',
  }
  
  -- Create horizontal split for terminal
  local bottom_pane = pane:split {
    direction = 'Bottom',
    size = 0.3,
  }
  
  -- Create vertical split in bottom for logs
  bottom_pane:split {
    direction = 'Right',
    size = 0.5,
  }
end)
```

#### Workspace Initialization

```lua theme={null}
wezterm.on('mux-startup', function()
  -- Create multiple workspaces
  local workspaces = {
    { name = 'main', cwd = wezterm.home_dir },
    { name = 'dev', cwd = wezterm.home_dir .. '/dev' },
    { name = 'ops', cwd = '/var/log' },
  }
  
  for _, ws in ipairs(workspaces) do
    mux.spawn_window {
      workspace = ws.name,
      cwd = ws.cwd,
    }
  end
  
  mux.set_active_workspace 'main'
end)
```

### Use Cases

* Setting up consistent terminal layouts
* Creating default workspaces
* Initializing multiplexer-only sessions (daemon mode)
* Pre-configuring pane arrangements before GUI attachment

## mux-is-process-stateful

**Since:** 20220101-133340-7edc5b5a

Emitted when the multiplexer needs to determine if a pane can be closed without prompting.

### Characteristics

* **Synchronous event** - Must return quickly to avoid blocking
* Called before closing a pane to check if confirmation is needed
* Allows custom logic beyond the default process name matching

### Event Signature

```lua theme={null}
wezterm.on('mux-is-process-stateful', function(proc)
  -- proc is a LocalProcessInfo object
  -- Return true, false, or nil
end)
```

<ParamField path="proc" type="LocalProcessInfo">
  Process information object containing details about the process tree in the pane.

  **Fields:**

  * `pid` - Process ID
  * `name` - Process name
  * `status` - Process status (e.g., "Sleep", "Running")
  * `argv` - Array of command-line arguments
  * `executable` - Full path to executable
  * `cwd` - Current working directory
  * `children` - Table of child processes (keyed by PID)
</ParamField>

### Return Values

<ResponseField name="true" type="boolean">
  Process is stateful - prompt user before closing
</ResponseField>

<ResponseField name="false" type="boolean">
  Process is not stateful - close without prompting
</ResponseField>

<ResponseField name="nil" type="nil">
  Use default behavior (check `skip_close_confirmation_for_processes_named` config)
</ResponseField>

### Examples

#### Log Process Tree

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

function log_proc(proc, indent)
  indent = indent or ''
  wezterm.log_info(
    indent
      .. 'pid='
      .. proc.pid
      .. ', name='
      .. proc.name
      .. ', status='
      .. proc.status
  )
  wezterm.log_info(indent .. 'argv=' .. table.concat(proc.argv, ' '))
  wezterm.log_info(
    indent .. 'executable=' .. proc.executable .. ', cwd=' .. proc.cwd
  )
  for pid, child in pairs(proc.children) do
    log_proc(child, indent .. '  ')
  end
end

wezterm.on('mux-is-process-stateful', function(proc)
  log_proc(proc)
  return nil -- Use default behavior
end)

return {}
```

**Example Output:**

```
INFO  config::lua > lua: pid=1913470, name=zsh, status=Sleep
INFO  config::lua > lua: argv=-zsh
INFO  config::lua > lua: executable=/usr/bin/zsh, cwd=/home/user
INFO  config::lua > lua:   pid=1913567, name=bash, status=Sleep
INFO  config::lua > lua:   argv=bash
INFO  config::lua > lua:   executable=/usr/bin/bash, cwd=/home/user
INFO  config::lua > lua:     pid=1913624, name=vim, status=Sleep
INFO  config::lua > lua:     argv=vim foo
INFO  config::lua > lua:     executable=/usr/bin/vim, cwd=/home/user
```

#### Custom Stateful Process Detection

```lua theme={null}
-- Check if any process in the tree is an editor
local function is_editor_running(proc)
  local editors = { 'vim', 'nvim', 'emacs', 'nano', 'code' }
  
  for _, editor in ipairs(editors) do
    if proc.name == editor then
      return true
    end
  end
  
  -- Check children recursively
  for _, child in pairs(proc.children) do
    if is_editor_running(child) then
      return true
    end
  end
  
  return false
end

wezterm.on('mux-is-process-stateful', function(proc)
  if is_editor_running(proc) then
    return true -- Always prompt when editor is running
  end
  return nil -- Use default for other processes
end)
```

#### Directory-Based Detection

```lua theme={null}
wezterm.on('mux-is-process-stateful', function(proc)
  -- Always prompt if working in important directories
  local protected_dirs = {
    '/etc',
    wezterm.home_dir .. '/important-project',
  }
  
  for _, dir in ipairs(protected_dirs) do
    if proc.cwd:find(dir, 1, true) == 1 then
      wezterm.log_info('Process in protected directory: ' .. proc.cwd)
      return true
    end
  end
  
  return nil
end)
```

#### Long-Running Process Detection

```lua theme={null}
-- Track process start times (simplified example)
local process_times = {}

wezterm.on('mux-is-process-stateful', function(proc)
  local now = os.time()
  
  if not process_times[proc.pid] then
    process_times[proc.pid] = now
  end
  
  local runtime = now - process_times[proc.pid]
  
  -- Prompt if process has been running for more than 1 hour
  if runtime > 3600 then
    wezterm.log_info(
      string.format('Long-running process detected: %s (%ds)',
        proc.name, runtime)
    )
    return true
  end
  
  return nil
end)
```

### Use Cases

* Custom logic for determining important processes
* Protecting specific workflows or directories
* Integration with project-specific tools
* Preventing accidental closure of development environments

## Event Ordering

When WezTerm starts, multiplexer events fire first:

```
1. mux-startup          ← Multiplexer initializes
2. gui-startup          ← GUI layer starts
3. gui-attached         ← GUI attaches to domain
```

For `wezterm connect DOMAIN`:

```
1. mux-startup          ← Mux starts (if new daemon)
2. gui-attached         ← GUI attaches to domain
                          (gui-startup does NOT fire)
```

## Common Patterns

### Daemon Mode Setup

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

wezterm.on('mux-startup', function()
  -- Setup for daemon/server mode
  local home = wezterm.home_dir
  
  -- Create a persistent development workspace
  local dev_tab, dev_pane, dev_window = mux.spawn_window {
    workspace = 'dev',
    cwd = home .. '/dev',
  }
  
  -- Bottom pane for build output
  local build_pane = dev_pane:split {
    direction = 'Bottom',
    size = 0.25,
  }
  
  -- Create monitoring workspace
  local mon_tab, mon_pane, mon_window = mux.spawn_window {
    workspace = 'monitoring',
    args = { 'htop' },
  }
  
  -- Default to dev workspace
  mux.set_active_workspace 'dev'
end)

return {
  unix_domains = {
    { name = 'unix' },
  },
}
```

### Combining mux-startup with gui-startup

```lua theme={null}
-- mux-startup: Create persistent structure
wezterm.on('mux-startup', function()
  -- This runs once when mux starts
  mux.spawn_window { workspace = 'persistent' }
end)

-- gui-startup: Configure GUI-specific settings
wezterm.on('gui-startup', function(cmd)
  -- This runs each time GUI starts
  local tab, pane, window = mux.spawn_window(cmd or {})
  window:gui_window():maximize()
end)
```

## See Also

* [gui-startup](/lua/events/gui-events#gui-startup) - GUI initialization event
* [MuxWindow object](/lua/objects/mux-window) - Multiplexer window API
* [MuxTab object](/lua/objects/mux-tab) - Multiplexer tab API
* [Pane object](/lua/objects/pane) - Pane API and information
