Last active
June 17, 2026 05:03
-
-
Save scarrillo/1668e3213a6066c9bda680a3e27be231 to your computer and use it in GitHub Desktop.
Ghostty Tmux Claude Notifications
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Sends an OSC 777 notification to the parent Ghostty terminal via tmux passthrough. | |
| # Walks up the process tree to find the TTY since hooks have no controlling terminal. | |
| # | |
| # Based on: https://github.com/recursechat/agent-workflow/blob/main/ghostty-tab-notifications.md | |
| # | |
| # Expanded on by: https://github.com/scarrillo && Claude | |
| # - Tmux support | |
| # - Requires: tmux `set -g allow-passthrough on` | |
| # - You can set and reload Tmux without interrupting your active sessions. | |
| # - This Gist: https://gist.github.com/scarrillo/1668e3213a6066c9bda680a3e27be231 | |
| # | |
| # Claude Code hook config (~/.claude/settings.json): | |
| # Use separate matchers per notification type to pass emoji + message as $1. | |
| # "Notification": [ | |
| # { "matcher": "permission_prompt", "hooks": [{ "type": "command", "command": "~/.claude/hooks/ghostty-notify.sh 'π Needs permission'" }] }, | |
| # { "matcher": "idle_prompt", "hooks": [{ "type": "command", "command": "~/.claude/hooks/ghostty-notify.sh 'π΄ Waiting for input'" }] }, | |
| # { "matcher": "auth_success", "hooks": [{ "type": "command", "command": "~/.claude/hooks/ghostty-notify.sh 'β Auth successful'" }] }, | |
| # { "matcher": "elicitation_dialog", "hooks": [{ "type": "command", "command": "~/.claude/hooks/ghostty-notify.sh 'π¬ Asking a question'" }] } | |
| # ] | |
| MSG="${1:-π€ needs you.}" | |
| # Walk up process tree to find an ancestor with a real TTY | |
| PID=$$ | |
| TTY="" | |
| while [ "$PID" != "1" ] && [ -n "$PID" ]; do | |
| T=$(ps -o tty= -p "$PID" 2>/dev/null | tr -d ' ') | |
| if [ -n "$T" ] && [ "$T" != "??" ] && [ -e "/dev/$T" ]; then | |
| TTY="/dev/$T" | |
| break | |
| fi | |
| PID=$(ps -o ppid= -p "$PID" 2>/dev/null | tr -d ' ') | |
| done | |
| if [ -z "$TTY" ]; then | |
| exit 0 | |
| fi | |
| # Build subtitle from tmux context | |
| SUBTITLE=$(tmux display-message -p '#{window_name}: #{b:pane_current_path}' 2>/dev/null) | |
| # Set window title and send notification in one write to avoid Claude Code overwriting title | |
| if [ -n "$SUBTITLE" ]; then | |
| printf '\ePtmux;\e\e]0;%s\007\e\\\ePtmux;\e\e]777;notify;Claude;%s\007\e\\' "$SUBTITLE" "$MSG" > "$TTY" | |
| else | |
| printf '\ePtmux;\e\e]777;notify;Claude;%s\007\e\\' "$MSG" > "$TTY" | |
| fi | |
| exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment