- tmux-web-attach.sh: attach browser to one window via link-window into a private temp session (no session-group pollution); window-size smallest while attached so the browser never gets cut off; mouse on for natural wheel/touch scrolling; status bar off; destroy-unattached cleanup - start-ttyd.sh: ttyd on 127.0.0.1:7681, base path /term, url-arg enabled, Tokyo Night theme, system mono stack, fontSize 14 - systemd user unit + install script registration - nginx: /term/ proxied with websocket upgrade, gated by auth_request to the kanban cookie check; unauthenticated -> 302 /login Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
61 lines
2.2 KiB
Bash
Executable File
61 lines
2.2 KiB
Bash
Executable File
#!/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 <session> [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
|