#!/usr/bin/env bash # Attach a browser (via ttyd) to a single tmux window by linking it into a # private temporary session. Unlike grouped sessions, link-window leaves no # permanent group label on the source session, and each browser tab gets an # independent view (own active window, own status setting). # Usage: tmux-web-attach.sh [window-index] set -euo pipefail sess="${1:-}" win="${2:-}" if [ -z "$sess" ]; then echo "missing session. open this page from the kanban Live Agents panel." sleep 2 exit 1 fi # Only accept existing session names; never interpret arbitrary input. if ! tmux list-sessions -F '#{session_name}' 2>/dev/null | grep -Fxq -- "$sess"; then echo "unknown session: $sess" sleep 2 exit 1 fi # Default to the session's active window; validate the index either way. if [ -z "$win" ]; then win="$(tmux display-message -p -t "$sess" '#{window_index}')" fi if ! tmux list-windows -t "$sess" -F '#{window_index}' | grep -Fxq -- "$win"; then echo "unknown window: $sess:$win" sleep 2 exit 1 fi src="$sess:$win" tmp="web-$$-$RANDOM" tmux new-session -d -s "$tmp" -x 220 -y 60 tmux set-option -t "$tmp" status off # mouse on (session-scoped, local clients unaffected): wheel / touch scrolling # from the browser enters copy-mode and scrolls history naturally, no prefix keys. tmux set-option -t "$tmp" mouse on # Replace the placeholder window with a link to the target window (-k kills the placeholder). first="$(tmux display-message -p -t "$tmp" '#{window_index}')" tmux link-window -k -s "$src" -t "$tmp:$first" # A tmux window has a single size shared by every viewer. With the global # "latest" policy a bigger local client cuts the browser view off, so pin this # window to "smallest" while a web viewer is attached: the browser always sees # the full content; a larger local client sees dotted padding instead. tmux set-window-option -t "$src" window-size smallest cleanup() { tmux set-window-option -u -t "$src" window-size 2>/dev/null || true tmux kill-session -t "$tmp" 2>/dev/null || true } trap cleanup EXIT HUP TERM INT # destroy-unattached must be set only after attaching (it kills detached sessions instantly). tmux attach -t "$tmp" \; set-option destroy-unattached on