After a bit of searching I didn’t find any obvious solution to the problem of: I want a process running in a tmux pane to send a desktop notification, and when I click that notification I’m taken directly to the source pane.

Here are a couple scripts that will achieve it (courtesy of opencode and the new codex-5.3 model).

It’s tailored to my setup:

  • macos
  • Kitty terminal emulator
  • tmux running locally

Example invocation:


./tmux-notify-return.sh <title> <message>

It’s probably a little brittle, but I think it will address a pain point I’ve been facing with a flurry of agents running across different tmux windows and panes.

Here are the scripts:

tmux-return.sh

What it does: click-handler script run by Notification Center; activates Kitty, switches the correct tmux client/window/pane, and retries briefly to avoid focus races.


#!/usr/bin/env bash

set -euo pipefail

if [[ $# -lt 4 || $# -gt 5 ]]; then

echo "Usage: $0 <client\_tty> <socket\_path> <target\_win> <target\_pane> [target\_pane\_id]" >&2

exit 2

fi

client\_tty="$1"

socket\_path="$2"

target\_win="$3"

target\_pane="$4"

target\_pane\_id="${5:-}"

TMUX\_BIN="/opt/homebrew/bin/tmux"

OSA\_BIN="/usr/bin/osascript"

"$OSA\_BIN" -e 'tell application id "net.kovidgoyal.kitty" to activate'

for \_ in 1 2 3 4 5 6 7 8 9 10; do

"$TMUX\_BIN" -S "$socket\_path" switch-client -c "$client\_tty" -t "$target\_win" || true

"$TMUX\_BIN" -S "$socket\_path" select-window -t "$target\_win" || true

if [[ -n "$target\_pane\_id" ]]; then

"$TMUX\_BIN" -S "$socket\_path" select-pane -t "$target\_pane\_id" || true

else

"$TMUX\_BIN" -S "$socket\_path" select-pane -t "$target\_pane" || true

fi

if [[ -n "$target\_pane\_id" ]]; then

current\_pane="$($TMUX\_BIN -S "$socket\_path" display-message -p -c "$client\_tty" '#{pane\_id}' 2>/dev/null || true)"

[[ "$current\_pane" == "$target\_pane\_id" ]] && exit 0

else

current\_pane="$($TMUX\_BIN -S "$socket\_path" display-message -p -c "$client\_tty" '#{session\_name}:#{window\_index}.#{pane\_index}' 2>/dev/null || true)"

[[ "$current\_pane" == "$target\_pane" ]] && exit 0

fi

sleep 0.1

done

exit 1

tmux-notify-return.sh

What it does: captures the tmux pane running this command (TMUX_PANE), then sends a clickable notification whose click runs tmux-return.sh back to that captured pane.


#!/usr/bin/env bash

set -euo pipefail

# Send a clickable macOS notification that returns you to the tmux pane

# where this command was run.

TMUX\_BIN="/opt/homebrew/bin/tmux"

NOTIFIER\_BIN="/opt/homebrew/bin/terminal-notifier"

RETURN\_SCRIPT="/path/to/tmux-return.sh"

if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then

echo "Usage: $0 [title] [message]"

echo "  title   Notification title (default: Return to tmux pane)"

echo "  message Notification body  (default: Click to jump back in Kitty)"

exit 0

fi

title="${1:-Return to tmux pane}"

message="${2:-Click to jump back in Kitty}"

if [[ ! -x "$TMUX\_BIN" ]]; then

echo "tmux not found at $TMUX\_BIN" >&2

exit 1

fi

if [[ ! -x "$NOTIFIER\_BIN" ]]; then

echo "terminal-notifier not found at $NOTIFIER\_BIN" >&2

exit 1

fi

if [[ ! -x "$RETURN\_SCRIPT" ]]; then

echo "return script not executable: $RETURN\_SCRIPT" >&2

exit 1

fi

# Capture the pane that is actually running this process when possible.

# In tmux shells, TMUX\_PANE is stable even if the user navigates away later.

source\_pane="${TMUX\_PANE:-}"

if [[ -n "$source\_pane" ]]; then

target\_win="$($TMUX\_BIN display-message -p -t "$source\_pane" '#S:#I')"

target\_pane="$($TMUX\_BIN display-message -p -t "$source\_pane" '#S:#I.#P')"

target\_pane\_id="$($TMUX\_BIN display-message -p -t "$source\_pane" '#{pane\_id}')"

else

target\_win="$($TMUX\_BIN display-message -p '#S:#I')"

target\_pane="$($TMUX\_BIN display-message -p '#S:#I.#P')"

target\_pane\_id="$($TMUX\_BIN display-message -p '#{pane\_id}')"

fi

client\_tty="$($TMUX\_BIN display-message -p '#{client\_tty}')"

socket\_path="$($TMUX\_BIN display-message -p '#{socket\_path}')"

if [[ -z "$client\_tty" || -z "$socket\_path" || -z "$target\_win" || -z "$target\_pane" || -z "$target\_pane\_id" ]]; then

echo "failed to capture tmux target metadata" >&2

exit 1

fi

printf -v q\_client '%q' "$client\_tty"

printf -v q\_socket '%q' "$socket\_path"

printf -v q\_win '%q' "$target\_win"

printf -v q\_pane '%q' "$target\_pane"

printf -v q\_pane\_id '%q' "$target\_pane\_id"

exec\_cmd="$RETURN\_SCRIPT $q\_client $q\_socket $q\_win $q\_pane $q\_pane\_id"

"$NOTIFIER\_BIN" \

-title "$title" \

-subtitle "$target\_pane" \

-message "$message" \

-execute "$exec\_cmd"