From 2c829754c81d7a90837dd5a8493f9f3bcdd71b54 Mon Sep 17 00:00:00 2001 From: MuLinForest <5525477+MuLinForest@users.noreply.github.com> Date: Wed, 25 Mar 2026 19:28:09 +0800 Subject: [PATCH 1/4] feat(dashboard): use inotify for event-driven redraws on Linux Replace fixed-interval polling with inotifywait when available. Dashboard now redraws only when session files change, reducing CPU usage to near-zero during idle periods. Falls back to the original 2s polling loop on macOS or when inotify-tools is not installed. If inotifywait exits unexpectedly, also falls back to polling rather than silently terminating. Header shows "(event-driven)" vs "(every 2s)" to reflect active mode. Closes #9 Co-Authored-By: Claude Code --- statusline/dashboard.sh | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/statusline/dashboard.sh b/statusline/dashboard.sh index f63c731..6f54c5f 100755 --- a/statusline/dashboard.sh +++ b/statusline/dashboard.sh @@ -66,7 +66,11 @@ render() { ts=$(date '+%Y-%m-%d %H:%M:%S') now=$(date +%s) - printf '%b' "${C_TITLE}Claude Code Dashboard${R} ${ts} ${DIM}(every ${INTERVAL}s)${R}" + if [ "${_REFRESH_MODE:-polling}" = "inotify" ]; then + printf '%b' "${C_TITLE}Claude Code Dashboard${R} ${ts} ${DIM}(event-driven)${R}" + else + printf '%b' "${C_TITLE}Claude Code Dashboard${R} ${ts} ${DIM}(every ${INTERVAL}s)${R}" + fi printf '\n\n' # Column headers @@ -183,6 +187,17 @@ render() { mkdir -p "$SESSIONS_DIR" trap 'printf "\n"; exit 0' INT TERM +if command -v inotifywait > /dev/null 2>&1; then + _REFRESH_MODE="inotify" + render + while inotifywait -q -e modify,create,delete "$SESSIONS_DIR" 2>/dev/null; do + render + done + # inotifywait exited unexpectedly — fall back to polling + _REFRESH_MODE="polling" +fi + +# Polling loop (primary on macOS, fallback if inotifywait fails) while true; do render sleep "$INTERVAL" From f824f973ad47a78a6930051bfa8361c6acfdb341 Mon Sep 17 00:00:00 2001 From: MuLinForest <5525477+MuLinForest@users.noreply.github.com> Date: Wed, 25 Mar 2026 19:35:07 +0800 Subject: [PATCH 2/4] fix(dashboard): suppress .status file-not-found error in sh/dash read < file with 2>/dev/null does not suppress redirect errors in dash. Check file existence first to avoid spurious error output. Co-Authored-By: Claude Code --- statusline/dashboard.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/statusline/dashboard.sh b/statusline/dashboard.sh index 6f54c5f..c0bac8a 100755 --- a/statusline/dashboard.sh +++ b/statusline/dashboard.sh @@ -111,7 +111,7 @@ render() { # Determine display status: prefer event-driven .status file disp_status="" _status_epoch="" - read -r disp_status _status_epoch < "$SESSIONS_DIR/${pid}.status" 2>/dev/null || disp_status="" + [ -f "$SESSIONS_DIR/${pid}.status" ] && read -r disp_status _status_epoch < "$SESSIONS_DIR/${pid}.status" # Fallback: JSON field, then file age if [ -z "$disp_status" ]; then age=$(( now - epoch )) From 7733512cd8325ebdd103681a8b977dd6e51954c4 Mon Sep 17 00:00:00 2001 From: MuLinForest <5525477+MuLinForest@users.noreply.github.com> Date: Thu, 26 Mar 2026 10:58:20 +0800 Subject: [PATCH 3/4] fix(dashboard): exclude .hb.dat from inotify watch to prevent spurious redraws heartbeat.sh writes $PID.hb.dat every 2s, causing inotifywait to fire continuously and negating the event-driven benefit. Filter to only watch .status and .json files so redraws only happen on actual state changes. Co-authored-by: Claude Sonnet 4.6 --- statusline/dashboard.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/statusline/dashboard.sh b/statusline/dashboard.sh index c0bac8a..af0231e 100755 --- a/statusline/dashboard.sh +++ b/statusline/dashboard.sh @@ -190,7 +190,7 @@ trap 'printf "\n"; exit 0' INT TERM if command -v inotifywait > /dev/null 2>&1; then _REFRESH_MODE="inotify" render - while inotifywait -q -e modify,create,delete "$SESSIONS_DIR" 2>/dev/null; do + while inotifywait -q -e modify,create,delete --include '\.(status|json)$' "$SESSIONS_DIR" 2>/dev/null; do render done # inotifywait exited unexpectedly — fall back to polling From 8608042db3860c6a124d627fc6f3d4eadc801644 Mon Sep 17 00:00:00 2001 From: MuLinForest <5525477+MuLinForest@users.noreply.github.com> Date: Thu, 26 Mar 2026 19:51:02 +0800 Subject: [PATCH 4/4] fix(dashboard): suppress inotifywait event output to stdout inotifywait prints the event (e.g. "MODIFY 990079.json") to stdout on each trigger, which leaked into the terminal between renders. Redirect stdout to /dev/null since only the exit code is needed. Co-Authored-By: Claude Sonnet 4.6 --- statusline/dashboard.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/statusline/dashboard.sh b/statusline/dashboard.sh index af0231e..771c768 100755 --- a/statusline/dashboard.sh +++ b/statusline/dashboard.sh @@ -190,7 +190,7 @@ trap 'printf "\n"; exit 0' INT TERM if command -v inotifywait > /dev/null 2>&1; then _REFRESH_MODE="inotify" render - while inotifywait -q -e modify,create,delete --include '\.(status|json)$' "$SESSIONS_DIR" 2>/dev/null; do + while inotifywait -q -e modify,create,delete --include '\.(status|json)$' "$SESSIONS_DIR" > /dev/null 2>/dev/null; do render done # inotifywait exited unexpectedly — fall back to polling