plugins/claude-code-hermit/skills/heartbeat/SKILL.md
Executes the heartbeat checklist from HEARTBEAT.md. Reads the checklist, evaluates each item, and reports findings or acknowledges with HEARTBEAT_OK. Supports run/start/stop/status/edit subcommands.
npx skillsauth add gtapps/claude-code-hermit heartbeatInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Background health checker that periodically evaluates a checklist and surfaces anything that needs operator attention.
/claude-code-hermit:heartbeat run — execute one tick immediately
/claude-code-hermit:heartbeat start — start the recurring tick
/claude-code-hermit:heartbeat stop — stop the recurring tick
/claude-code-hermit:heartbeat status — show last result and schedule state
/claude-code-hermit:heartbeat edit — modify the checklist
This subcommand is the handler for HEARTBEAT_EVALUATE notifications emitted by the heartbeat Monitor. It's also runnable manually for ad-hoc ticks. The Monitor uses precheck --peek for polling; this handler re-runs precheck without --peek so the mutating tick (total_ticks increment, alert-state write) happens exactly once per noteworthy tick.
node ${CLAUDE_PLUGIN_ROOT}/scripts/heartbeat-precheck.js .claude-code-hermit
SKIP| → emit HEARTBEAT_SKIP (<reason>). No channel notification. No SHELL.md write. Stop.OK → emit HEARTBEAT_OK. Stop.AUTO_CLOSE → operator inactivity exceeded the threshold (12h of no operator action, or 10-min lull after a daily-auto-close queued at midnight). Run the auto-close sequence, then stop:
## Monitoring: [HH:MM] Heartbeat: auto-closed. (Step 2 replaces SHELL.md with a fresh template, so a later append would miss the archived report.)/claude-code-hermit:session-close --auto (skips summary-gathering, reflect, heartbeat-stop; passes Closed Via: auto to session-mgr; clears state/pending-close.json after archive succeeds).HEARTBEAT_AUTO_CLOSED. Stop. Do NOT run the EVALUATE flow — the session is being archived; generating stale-session alerts for a closing session would create phantom dedup entries.EVALUATE → continue to step 3.${CLAUDE_PLUGIN_ROOT}/skills/heartbeat/reference.md for the semantic key taxonomy, alert deduplication procedure, self-evaluation steps, and output format..claude-code-hermit/HEARTBEAT.md, config.json, state/runtime.json, .claude-code-hermit/sessions/SHELL.md. (fresh read — re-read the file(s) now; do not reuse a value cached in context from before compaction)session_state is waiting: skip. If in_progress:
## Progress Log entry timestamp from SHELL.md. Use session start time if none.heartbeat.stale_threshold (default "2h"): generate alert with key stale-session.session_state is waiting and heartbeat.waiting_timeout is set:
waiting_timeout with no channel activity: update runtime.json session_state to idle, update SHELL.md Status to idle, notify the operator.state/alert-state.json (procedure in reference.md).
Do NOT write total_ticks — it was already incremented by the precheck.total_ticks % 20 === 0 (read from updated state/alert-state.json): run self-evaluation (procedure in reference.md).Start the heartbeat as a persistent CC Monitor subprocess.
heartbeat.every from config (default: "2h"). Parse to seconds ("30m" → 1800, "2h" → 7200, etc).${CLAUDE_PLUGIN_ROOT}/scripts/heartbeat-monitor.sh (resolve at skill execution time — not available inside the subprocess).CronList → if an entry's prompt matches /claude-code-hermit:heartbeat run, CronDelete it. Idempotent.state/heartbeat-monitor.runtime.json if it exists. If it contains a task_id, TaskStop that task — ignore not-found errors (the monitor may have already exited). Then TaskList → TaskStop any remaining task with description heartbeat-monitor (fallback for orphans where the runtime file was never written). Clear any prior entry from state/heartbeat-monitor.runtime.json.description: heartbeat-monitor (reserved slot — operators must not reuse this description for ad-hoc /watch entries)command: bash <abs_script_path> <interval_seconds> $PWD/.claude-code-hermittimeout_ms: 86400000 (24h; re-armed daily by heartbeat-restart)persistent: truestate/heartbeat-monitor.runtime.json. Do NOT use state/monitors.runtime.json — that file is owned exclusively by /watch and is cleared on every session start.[HH:MM] Heartbeat: monitor started (interval: <every>).Safe to call from a routine — idempotent (legacy cron swept + existing Monitor stopped + state file rewritten).
state/heartbeat-monitor.runtime.json. If a task_id is present, TaskStop it. Fallback: TaskList → find by description heartbeat-monitor and TaskStop.state/heartbeat-monitor.runtime.json (write {}).CronList → CronDelete any entry whose prompt matches /claude-code-hermit:heartbeat run. Belt-and-suspenders.[HH:MM] Heartbeat: stopped.Report current heartbeat state by reading:
state/heartbeat-monitor.runtime.json — running yes/no, registered interval, task_id, started_atCronList filtered for /claude-code-hermit:heartbeat run — should be empty post-migration; if present, surface as "legacy CronCreate still active — run /heartbeat start to clean up"state/alert-state.json for total_ticks and last-tick metadataconfig.json for active hours windowReport: monitor running (yes/no), configured interval, active hours window, total ticks since last clear, legacy-cron warning if applicable.
Open .claude-code-hermit/HEARTBEAT.md for the operator to modify.
After evaluating the checklist, if SHELL.md status is idle:
NEXT-TASK.md pickup (both wait and discover): check sessions/NEXT-TASK.md. If found, act per escalation in config:
conservative: notify operator, set SHELL.md to waiting, set waiting_reason: "conservative_pickup" in runtime.json.balanced: start via /claude-code-hermit:session-start.autonomous: start via /claude-code-hermit:session-start. On completion, run the session skill's Work-done flow (§6) — never send a bare notification without it: a notified-but-in_progress session triggers stale-session alerts and delays archival.The following only when idle_behavior: "discover":
.claude/cost-log.jsonl. Alert if deadlines need attention.All time comparisons use timezone from config.json.
Morning/evening routines are handled by /claude-code-hermit:hermit-routines. Manage routines with /claude-code-hermit:hermit-settings routines.
development
Use when the user asks about cost structure or composition: which token types cost the most, how cache reads compare to output costs, which sessions are draining budget, or what cold starts add up to. This is the 'why is my bill high' skill. It audits where spend goes across token categories (cache_read, cache_write, output, input) and per-session attribution. Invoke for questions like 'cost breakdown', 'which sessions are expensive', 'what's driving spend', or 'cold start costs'. Not for week-over-week trend lines (use hermit-evolution) or simple total-spend summaries.
tools
Presence history & tracker-health report — current home/away state, reliability, recent arrival/departure transitions, and activity patterns for person/device_tracker entities. Use when the operator asks about presence history or when a presence-dependent automation (locks, alarm, vacuum, climate) misbehaves.
development
Evening house brief — end-of-day security check, device status, and energy snapshot. Runs as a daily routine at 22:30 or on demand.
tools
Browse and explain the hermit's Home Assistant automations — list by topic, filter by keyword with plain-language YAML explanations, or sort by last-fired. Read-only. Use when the operator asks "what automations do I have / what does this one do / which haven't fired."