← back to Terminal Status
integrations/dot.sh
96 lines
#!/usr/bin/env bash
# Shared compatibility entrypoint for the Claude and Codex color skills.
#
# 2026-09-16 (Steve: "fix script so this is checked for color"): CHECK-FOR-COLOR
# hardening. Two failure modes previously left a tab silently colorless with no
# reason: (1) the engine's ps-scan can run up to its internal ~90s ceiling under
# host load, so a caller appeared to HANG; (2) a paint from a tool/subagent shell
# exits nonzero (the CLAUDE_CODE_CHILD_SESSION refusal), a silent no-op. Now every
# paint runs under a HARD outer timeout and the result is CHECKED + reported with
# ONE clear line (painted / cleared / TIMED OUT / NOT painted) so the color state
# is never changed-or-failed silently. Exit code is preserved (0 = painted), so
# callers doing `rc=$?` are unaffected. The subagent-paint guard in
# terminal_status.py is intentionally UNTOUCHED; instead this wrapper now
# AUTO-RETRIES a refused bridge/child-session paint once with the force opt-in
# (see the auto-force block below) so leaked-flag real sessions paint without a
# manual --force. The engine's own headless/nested refusal still holds under
# force, so a truly terminal-less agent is still refused.
set -u
runtime="${1:?runtime required}"
color="${2:?color required}"
shift 2
engine="$HOME/Projects/terminal-status/terminal_status.py"
timeout_s="${TS_PAINT_TIMEOUT:-100}" # just above the engine's ~90s scan ceiling
tmo="$(command -v timeout || command -v gtimeout || true)"
run() { # run the engine, under a hard outer timeout when one is available
if [ -n "$tmo" ]; then "$tmo" "$timeout_s" python3 "$engine" "$@"
else python3 "$engine" "$@"; fi
}
mode="${1:-}"
# Mechanism-A footgun fix (TK-11936): --all intercept regardless of arg position.
# Before a1139e9, only ${1:-} was checked; with $@ forwarding, --all in any position
# reached the engine as a raw arg and silently broadcast the caller's label fleet-wide.
for _a in "$@"; do case "$_a" in --all) mode=--all; break;; esac; done
paint() { # one dispatch of the requested subcommand; called again on auto-force retry
case "$mode" in
--off) run clear ;;
--all) run set "$color" --all "$runtime" ;;
*) run set "$color" "$@" ;;
esac
}
# Auto-force retry (Steve 2026-09-16, "allow sub sessions to show color too"):
# a bridge / sub-session paint refuses because nothing local distinguishes it
# from a true background subagent whose paint would corrupt the parent's pane.
# Per Steve's decision, retry ONCE with the conscious force opt-in so a
# leaked-flag REAL session (CLAUDE_CODE_CHILD_SESSION set by the env-leak, memory
# iterm-relaunched-from-claude-leaks-child-session-env) paints automatically.
# Gated so it CANNOT recurse (force already set) and CANNOT fire on a timeout
# (124) or a non-child context; the engine's headless/nested refusal still holds
# even under force, so this only reaches sessions whose ancestry owns a tty.
if [ -n "${CLAUDE_CODE_CHILD_SESSION:-}" ] && [ -z "${CLAUDE_COLORDOTS_FORCE:-}" ]; then
# First attempt with stderr buffered — a bridge refusal here is expected and
# followed by the force retry, so we don't want its scary line on the console.
err="$(mktemp -t dotsh.XXXXXX)"
paint 2>"$err"
rc=$?
if [ "$rc" -ne 0 ] && [ "$rc" -ne 124 ]; then
export CLAUDE_COLORDOTS_FORCE=1
paint # retry: its own stderr streams normally so a real failure shows
rc=$?
else
cat "$err" >&2 # first attempt already succeeded/timed out — surface its output
fi
rm -f "$err"
else
paint
rc=$?
fi
# CHECK the paint result and SAY so — never a silent color change or failure.
case "$rc" in
0) if [ "$mode" = --off ]; then echo "dot: cleared"; else echo "dot: painted ${color}"; fi ;;
124) echo "dot: paint TIMED OUT after ${timeout_s}s (host load) — tab color UNCHANGED" >&2 ;;
*) echo "dot: NOT painted (engine rc=${rc}; refusal or error above) — tab color UNCHANGED" >&2 ;;
esac
# AUTO-PLACE into the colour column (Steve 2026-09-17: "I want all color continue" —
# as soon as a tab gets a new colour, arrange it into that colour's correct place).
# Fires ONLY on a successful colour paint (rc=0, not --off), for EVERY colour, via the
# dot-screen-router's own single-window band math (DSR_MOVE_WINDOW). Runs in the
# BACKGROUND so it never slows or blocks the paint, and best-effort (any failure is
# swallowed — placement is cosmetic). The router already tiles all NON-frontmost windows
# every pass; this covers the frontmost/active window the router deliberately skips, so a
# tab that just changed its own colour snaps into place immediately. Kill-switch:
# export TS_NO_AUTOPLACE=1 (also auto-skips if the router skill is absent).
_rt="$HOME/.claude/skills/dot-screen-router/router.sh"
if [ "$rc" = 0 ] && [ "$mode" != --off ] && [ -z "${TS_NO_AUTOPLACE:-}" ] && [ -f "$_rt" ]; then
( _wid="$(osascript -e 'tell application "iTerm2" to id of current window' 2>/dev/null)"
[ -n "$_wid" ] && DSR_MOVE_WINDOW="$_wid" bash "$_rt" >/dev/null 2>&1
) >/dev/null 2>&1 &
fi
exit "$rc"