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

46 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 AMApr 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

pgf

unread,
Apr 20, 2026, 12:04:09 PM (10 days ago) Apr 20
to tmux-users
One more question regarding the hook I mentioned in my previous post:

Il giorno mercoledì 1 aprile 2026 alle 15:41:09 UTC+2 pgf ha scritto:
set-hook -g pane-focus-in 'run-shell "printf '\''%b'\'' \"\$(tmux show-option -pqv -t #{pane_id} @status_bar)\" > #{client_tty}"'

Is there a way to obtain the same behavior without writing directly to the #{client_tty} pseudoterminal?
Is there any tmux command to send the content of the @status_bar variable through the passthrough mechanism?

Thanks.


Nicholas Marriott

unread,
Apr 20, 2026, 4:10:29 PM (10 days ago) Apr 20
to pgf, tmux-users
There is no way to make tmux write to the terminal aside of through either a pane sending output or a few other fixed mechanisms like set-titles.

I suppose you could maybe open an empty pane and use it to write the passthrough sequence, but what's wrong with writing to client_tty? That will be much more reliable so long as you are careful only to write sequences which are "invisible" to tmux (that is, do not affect the visible terminal state).


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

Pier Giuseppe Fogli

unread,
Apr 21, 2026, 2:09:44 AM (10 days ago) Apr 21
to tmux-users
Il lun 20 apr 2026, 22:10 Nicholas Marriott <nicholas...@gmail.com> ha scritto:
but what's wrong with writing to client_tty?

It works almost always, except when sudo-ing to a different user.
Where I work I need to switch user to work on a project account. Things  go like this: ssh to us...@remote.host -> sudo to switch to userB -> start a tmux session.
For some reason I don't fully understand tmux inherits the pseudoterminal of the original userA so #{client_tty} is not writeable by userB.

Reply all
Reply to author
Forward
0 new messages