How to send an escape sequence to the terminal when switching window/pane?

27 views
Skip to first unread message

Pier Giuseppe Fogli

unread,
Mar 24, 2026, 10:03:33 AMMar 24
to tmux-...@googlegroups.com
Dear tmuxers,
I use iTerm2 to connect through SSH to remote hosts where I launch tmux sessions.
I'd like to update the local iTerm2 status bar (there's an iTerm2 escape extension for doing this)
whenever I switch pane/window on the remote tmux session, so that the status bar reflects
the information of the current active pane/window, for example CWD, numbers of jobs in background,
etc....
I can send the iTerm2 escape sequence through tmux passthrough mechanism and it works.
I'm figuring out how to trigger the same behavior at pane/window switching.

Is there a way to do this?

Thank you.

Nicholas Marriott

unread,
Mar 24, 2026, 10:07:29 AMMar 24
to Pier Giuseppe Fogli, tmux-...@googlegroups.com
There are a few possibilities:

1) If you do "tmux lsc -F '#{client_tty}'" it will give you a list of attached client tty devices, you could write the escape sequence (without passthrough) directly to whichever of those is iTerm2 (maybe all of them).

2) You could put the passthrough sequence in your shell prompt, so it will update as soon as the shell prints a new prompt.

3) Use `set-titles`/`set-titles-string` to have tmux set the iTerm2 title, then configure iTerm2 to use that instead of whatever it is setting with the custom escape sequence.


--
You received this message because you are subscribed to the Google Groups "tmux-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tmux-users+...@googlegroups.com.
To view this discussion, visit https://groups.google.com/d/msgid/tmux-users/CALOCt5oNCuo5-XPFP6t94zDkiUFc4kJJSeQyXoUZpbvHs_PTJw%40mail.gmail.com.

M Kelly

unread,
Mar 25, 2026, 7:43:37 AMMar 25
to tmux-users
Hi,

Not sure (I don't use iTerm2), but maybe a hook for pane-focus (if you have focus events enabled) could work ?

set-hook -g 'pane-focus-in'   .....

thx,
-m

pgf

unread,
Apr 1, 2026, 9:41:09 AM (9 days ago) Apr 1
to tmux-users
#{client_tty} is what I needed, thanks.

I'm new to tmux and I'm experimenting with shell/terminal integration through shell functions and tmux hooks.

Some more background.
On the local host I configured iTerm2 with the "Compact" theme, which does not display the window title bar.
Then I set up the iTerm2 status bar with a couple of "Interpolated string" components set to "\(user.left_title) [Spring] \(user.right_title)".

On the remote host:
1. I defined a shell function iterm2_update_status in .bashrc in order to trigger the iTerm2 status bar update through the bash variable PROMPT_COMMAND.

if [[ -n "$SSH_TTY" ]]; then
  _loc="🌍"
else
  _loc="🖥️ "
fi

# cache to avoid useless updates
ITERM2_LAST_LEFT=""
ITERM2_LAST_RIGHT=""

iterm2_update_status() {
  # Left title
  local left="${_loc}CWD: ${PWD/$HOME/\~}"

  # Right title: conda env and/or number of loaded modules
  local right=""
  [[ -n "${CONDA_DEFAULT_ENV}" ]] && right+="conda: ${CONDA_DEFAULT_ENV} "
  [[ -n "${LOADEDMODULES}" ]] && right+="mods: $(echo ${LOADEDMODULES//:/" "} | wc -w) "

  # number of jobs in background
  local njobs
  njobs=$(jobs -p 2>/dev/null | wc -l)
  (( ${njobs} > 0 )) && right+="jobs: ${njobs}"

  # final trim
  right="${right%" "}"

  # Update only when left OR right title change
  [[ "${left}" == "${ITERM2_LAST_LEFT}" && "${right}" == "${ITERM2_LAST_RIGHT}" ]] && return
  ITERM2_LAST_LEFT="${left}"
  ITERM2_LAST_RIGHT="${right}"

  # Encode for iTerm2
  local left_encoded right_encoded
  left_encoded=$(echo -n "${left}" | base64 -w0)
  right_encoded=$(echo -n "${right}" | base64 -w0)

  # Send OSC to the remote iTerm2, through tmux passthrough DCS if needed
  if [[ -n "${TMUX}" ]]; then
    local dcs
    dcs="\033Ptmux;\033\033]1337;SetUserVar=left_title=${left_encoded}\a\033\033]1337;SetUserVar=right_title=${right_encoded}\a\033\\"
    printf "%b" "${dcs}"
    # Save the DCS to current pane status_bar variable
    pane_id=$(tmux display-message -p '#{client_session}:#{window_id}.#{pane_id}')
    tmux set-option -pq -t "${pane_id}" @status_bar "${dcs}"
  else
    local osc
    osc="\033]1337;SetUserVar=left_title=${left_encoded}\a\033]1337;SetUserVar=right_title=${right_encoded}\a"
    printf "%b" "${osc}"
  fi
}

if [ "${REMOTE_TERM}" == "iTerm2" ]; then
  PROMPT_COMMAND="${PROMPT_COMMAND};iterm2_update_status"
fi


2. Finally, I set up the following hooks in the remote .tmux.conf:

# Hooks to update the remote iTerm2 status bar whenever a pane/window switch occurs
set-hook -g after-select-window 'run-shell "printf '\''%b'\'' \"\$(tmux show-option -pqv -t #{pane_id} @status_bar)\" > #{client_tty}"'
set-hook -g after-select-pane 'run-shell "printf '\''%b'\'' \"\$(tmux show-option -pqv -t #{pane_id} @status_bar)\" > #{client_tty}"'
set-hook -g pane-focus-in 'run-shell "printf '\''%b'\'' \"\$(tmux show-option -pqv -t #{pane_id} @status_bar)\" > #{client_tty}"'

Now the local iTerm2 status bar is updated whenever I switch pane or window in the remote tmux session.

pgf
screenshot.png
Reply all
Reply to author
Forward
0 new messages