← back to Terminal Status

verification/install/before/.claude/skills/lightgreendot/lightgreendot.sh

73 lines

#!/usr/bin/env bash
# /lightgreendot — mark a Claude session's iTerm2 tab LIGHT GREEN = "MONITORING with a SCHEDULED
# next-check / DEADLINE". A shade-variant of /greendot (Steve, 2026-09-04): plain green = working/
# monitoring with no specific wake time; LIGHT green = working/monitoring AND a wake is scheduled at
# a known time (a ScheduleWakeup / next-monitor). So Steve can glance and see "this one has a deadline".
# Pair with showing the next-check time 3x inline in the reply (memory: monitor-response-dot-and-3x-time).
#
# Mechanism identical to greendot.sh (resolve own pty by ancestry, write OSC straight to /dev/ttysNNN).
# Usage:
#   lightgreendot.sh "TK-NNNNN · monitoring · next 10:15"   # light-green tint + title (put the time!)
#   lightgreendot.sh --all
#   lightgreendot.sh --off
set -u

# HARD RAIL (2026-09-08): a subagent has no tab of its own — its ancestry resolves to the
# PARENT session's pty, so painting would corrupt Steve's live pane (the input-field bug). No-op.
if [ -n "${CLAUDE_CODE_CHILD_SESSION:-}" ]; then
  echo "/lightgreendot → subagent context — refusing to paint (would write to the parent session's live pane). no-op."
  exit 0
fi

# Teal green — "monitoring with a scheduled deadline". Distinct from plain green (0,200,83).
R=0; G=150; B=136
DOT="🟢"

paint() { # $1 = tty_path, $2 = label(optional), $3 = off(1=reset)
  local tp="$1" label="${2:-}" off="${3:-0}"
  [[ -w "$tp" ]] || return 1
  if [[ "$off" == "1" ]]; then
    { printf '\033]6;1;bg;*;default\007'; printf '\033]1337;SetBadgeFormat=\a'; } > "$tp" 2>/dev/null
    rm -f "${HOME}/.claude/tab-dots/$(basename "$tp").dot" 2>/dev/null
    return 0
  fi
  local title="$DOT ${label:-MONITORING}"
  {
    printf '\033]6;1;bg;red;brightness;%d\007'   "$R"
    printf '\033]6;1;bg;green;brightness;%d\007' "$G"
    printf '\033]6;1;bg;blue;brightness;%d\007'  "$B"
    printf '\033]1;%s\007' "$title"
    printf '\033]2;%s\007' "$title"
  } > "$tp" 2>/dev/null
  mkdir -p "${HOME}/.claude/tab-dots"
  printf '%s' "$title" > "${HOME}/.claude/tab-dots/$(basename "$tp").dot"
  printf '\033]1337;SetBadgeFormat=%s\a' "$(printf '%s' "$title" | base64 | tr -d '\n')" > "$tp" 2>/dev/null
}

if [[ "${1:-}" == "--all" ]]; then
  ttys="$(ps -axo tty=,command= 2>/dev/null | awk '$1 ~ /^ttys/ && $0 ~ /claude/ && $0 !~ /grep/ {print $1}' | sort -u)"
  [[ -z "$ttys" ]] && { echo "/lightgreendot --all → no live claude ttys"; exit 0; }
  n=0; for tt in $ttys; do paint "/dev/$tt" "MONITORING" 0 && { echo "  $tt → 🟢 MONITORING"; n=$((n+1)); }; done
  echo "/lightgreendot --all → marked ${n} tab(s) light green"; exit 0
fi

OFF=0; LABEL=""
[[ "${1:-}" == "--off" ]] && OFF=1 || LABEL="${1:-}"

tty_path=""; p=$$
for _ in 1 2 3 4 5 6 7 8 9 10; do
  line="$(ps -o ppid=,tty= -p "$p" 2>/dev/null)" || break
  set -- $line
  pp="${1:-}"; tt="${2:-}"
  [[ -z "$pp" ]] && break
  if [[ "$tt" == ttys* ]]; then tty_path="/dev/$tt"; break; fi
  p="$pp"
done
if [[ -z "$tty_path" ]]; then echo "/lightgreendot → could not resolve this session's tty"; exit 1; fi

if [[ "$OFF" == "1" ]]; then
  paint "$tty_path" "" 1 && echo "/lightgreendot --off → cleared tint on $tty_path"
else
  paint "$tty_path" "$LABEL" 0 && echo "/lightgreendot → $tty_path 🟢(light) ${LABEL:-MONITORING}  rgb(${R},${G},${B})"
fi