obsidian/wiki/dotfiles/wezterm-pane-to-lua.md
2026-04-17 13:03:50 +01:00

4.8 KiB

title aliases tags sources created updated
WezTerm: Passing Data from a Pane to Lua
wezterm-user-vars
wezterm-osc
wezterm-pane-data
wezterm
lua
terminal
osc
pane
shell-integration
raw/Passing Data from a pane to Lua - Wez's Terminal Emulator.md
2026-04-17 2026-04-17

Overview

WezTerm cannot directly inspect what's running inside a pane (especially remote/SSH panes). The PTY interface only provides input/output streams and screen size. Instead, you signal data into WezTerm via escape sequences or OS APIs.

Methods

1. User Vars (OSC 1337) — Most Powerful

Key/value pairs scoped to a terminal pane. Written by the shell, read-only from within the pane, readable by Lua.

Set a user var from shell:

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

Value must be base64 encoded.

Read in Lua:

pane:get_user_vars()           -- returns all vars as a table
tab.active_pane.user_vars.FOO  -- direct field access in event handlers

Events triggered on var change:

  • user-var-changed — act immediately on a set/change
  • update-status — refresh left/right status bar items
  • Tab bar / title events fire as well

Propagates across multiplexer clients. Works through tmux if you use tmux passthrough:

printf "\033Ptmux;\033\033]1337;SetUserVar=%s=%s\007\033\\" "$1" `echo -n "$2" | base64`

(Also requires set -g allow-passthrough on in tmux.conf.)

Shell alias pattern — set PROG on command run:

__wezterm_set_user_var() {
  if hash base64 2>/dev/null; then
    if [[ -z "${TMUX}" ]]; then
      printf "\033]1337;SetUserVar=%s=%s\007" "$1" `echo -n "$2" | base64`
    else
      printf "\033Ptmux;\033\033]1337;SetUserVar=%s=%s\007\033\\" "$1" `echo -n "$2" | base64`
    fi
  fi
}

function _run_prog() {
    __wezterm_set_user_var "PROG" "$1"
    trap '__wezterm_set_user_var PROG ""' EXIT
    command "$@"
}

alias vim="_run_prog vim"
alias nvim="_run_prog nvim"
alias tmux="_run_prog tmux"

Use PROG in tab title:

local wezterm = require 'wezterm'

wezterm.on('format-tab-title', function(tab)
  local prog = tab.active_pane.user_vars.PROG
  return tab.active_pane.title .. ' [' .. (prog or '') .. ']'
end)

return {}

2. OSC 0 / 1 / 2 — Window & Tab Title

OSC Effect Example
0 Clears Icon Name, sets Window Title \x1b]0;title\x1b\\
1 Sets Icon Name (used as Tab title if non-empty) \x1b]1;tab-title\x1b\\
2 Sets Window Title \x1b]2;window-title\x1b\\

Read back via pane:get_title() or PaneInformation.title.

Many distro shells emit OSC 2 before each command. WezTerm will substitute the foreground process title if no OSC title is set (local panes only).

3. OSC 7 — Current Working Directory

printf "\033]7;file://HOSTNAME/CURRENT/DIR\033\\"
# or:
wezterm set-working-directory

Read back via pane:get_current_working_dir() or PaneInformation.current_working_dir.

Wezterm shell integration auto-sets OSC 7 for bash/zsh.

4. Local Process State

Works only for local panes (no SSH/multiplexer):

  • pane:get_foreground_process_info() — process hierarchy info
  • wezterm.procinfo.get_info_for_pid(pid) — info for a given PID

Convenient since no shell config changes required, but:

  • Fails for remote panes
  • Less reliable on Windows for determining foreground process

Comparison

Method Remote/SSH Requires shell config Use case
User Vars (OSC 1337) Yes (aliases/integration) Arbitrary key/value signaling
OSC 0/1/2 Often automatic Tab/window titles
OSC 7 Shell integration CWD tracking
Local process info No Quick local introspection

Key Takeaways

  • User Vars are the most flexible mechanism — arbitrary key/value, works over SSH and tmux
  • Values must be base64 encoded when sending via OSC 1337
  • The user-var-changed event fires immediately; use it to react dynamically in Lua
  • OSC 7 is the standard way to track CWD; shell integration handles it automatically
  • Local process APIs are zero-config but only work locally
  • Install wezterm shell integration to get User Vars, OSC 7, and more out of the box

Sources