/hermit-health
Show alert state, pending task decisions, routine engagement, knowledge state, channel availability, plus fragile zones, long-waiting decisions, and recent learnings. Activates on messages like 'health check', 'how's the hermit', 'is anything broken', 'hermit health', 'system
Claude Code
$ npx -y skills add gtapps/hermitd --skill hermit-health --agent claude-code
Codex
$ npx skills add gtapps/hermitd --skill hermit-health -a codex -y
Cursor
$ npx skills add gtapps/hermitd --skill hermit-health -a cursor -y
Gemini CLI
$ npx skills add gtapps/hermitd --skill hermit-health -a gemini-cli -y
GitHub Copilot
$ npx skills add gtapps/hermitd --skill hermit-health -a github-copilot -y
OpenCode
$ npx skills add gtapps/hermitd --skill hermit-health -a opencode -y
Windsurf
$ npx skills add gtapps/hermitd --skill hermit-health -a windsurf -y
SKILL.md
hermit-health.SKILL.mdname: hermit-health
model: haiku
description: "Show alert state, pending task decisions, routine engagement, knowledge state, channel availability, plus fragile zones, long-waiting decisions, and recent learnings. Activates on messages like 'health check', 'how's the hermit', 'is anything broken', 'hermit health', 'system health', 'anything wrong', 'hermitd status', 'hermit brain', 'are routines running', 'what's stuck', 'any fragile zones', 'show me what's blocked', 'recent learnings', 'what have you learned lately', 'where are the weak spots', 'check knowledge', 'lint knowledge', 'knowledge health'."
Hermit Health
Synthesize a compact "state of the hermit" snapshot in two halves: infrastructure (active alerts, pending decisions, routine engagement, knowledge state, channel readiness) and analysis (fragile zones, long-waiting decisions, recent learnings). Everything is read directly in main — this skill is on-demand and runner-free.
Step 0 — Channel reply
If this skill was invoked from a channel-arrived message (the inbound prompt contains a `<channel source="...">` tag), reply via that channel's reply tool. Otherwise emit to conversation.
Scope
Read the following (gracefully skip any file that doesn't exist). The sources are independent — read them concurrently:
1. `.hermit/state/alert-state.json` — the `alerts` object, keyed by alert id (`checklist:*`, `custom:*`). Each entry has `text`, `count`, `first_seen`, `last_seen`, `suppressed`, `consecutive_clean`. 2. `.hermit/state/runtime.json` — `last_activity`, `session_id`. 3. `.hermit/state/reflection-state.json` — `last_reflection` timestamp, `counters` (including `judge_suppress_by_code` map and run/output fields), and run/output counters. 4. `.hermit/config.json` — `routines` array (id, schedule, enabled); `channels` object (each channel's `default_chat_id`). 5. `bun ${CLAUDE_PLUGIN_ROOT}/scripts/task.ts list .hermit --open --limit 20 --json` for open tasks and their pending decisions. Use `total` for the open count, describe only the returned sample, and report `omitted` rather than scanning more files. A proposal is a task with `kind: proposal`; authority, purpose and wait age come from its decision and record, never a separate queue. 7. Glob counts: `.hermit/raw/**` (excluding `.archive/`), `.hermit/compiled/**`, `.hermit/raw/.archive/**`. 8. `bun ${CLAUDE_PLUGIN_ROOT}/scripts/task-report.ts .hermit --limit 5` for normalized recent task records: titles, outcomes, waiting reasons and lessons. Never read frozen session archives or the old live shell document.
Analysis
**Alerts:** From `alert-state.json → alerts`, active means `suppressed` is not `true`; suppressed ones are digest-only and reported separately. Compute each entry's age from `first_seen`. Report the active count with the oldest entry's `text` and age, then the suppressed count with its oldest age. If no active entries: "No active alerts" (still name the suppressed count when there is one).
**Proposal queue:** Count proposals with `status: proposed` (pending operator review), `status: accepted` (in flight, not yet resolved), and `status: in_progress`. If all zero: "Queue empty."
**Routine engagement:** From `config.json.routines`, list each routine and its schedule. For the `reflect` routine, use `reflection-state.json → last_reflection` to show when it last ran; also append counter info from `reflection-state.json → counters`: apply the reflect-line rules below, then append the suppress-mix suffix if any `judge_suppress_by_code` code has a non-zero count: `suppress mix — no-evidence:N, covered-by-memory:N, no-sessions:N` (omit codes with count 0; omit the suffix entirely when all counts are 0 or the map is absent). For every routine, run `bun ${CLAUDE_PLUGIN_ROOT}/scripts/routines.ts health .hermit` once and take last run, fire count and skip reason from its rows.
**Reflect-line rules** (applied to the reflect routine bullet):
- If `counters` is absent: omit the counter clause entirely
- If `total_runs` is 0: show `no runs yet (since YYYY-MM-DD)` where the date is `counters.since`
- Otherwise: `N runs, N empty | output: N proposal tasks, N input decisions | since YYYY-MM-DD` where the date is `counters.since`; omit `| output: ...` if both `proposals_created` and `micro_proposals_queued` are 0
**Micro:** Count entries with `status: "pending"` in `pending decisions.json`. Omit this section entirely if count is zero.
**Knowledge:** Report glob counts for raw (excl. archive), compiled, and archived files. Omit if all three are zero and the directories are missing. If the operator explicitly asked to check or lint knowledge ("check knowledge", "lint knowledge", "knowledge health"), also run `bun ${CLAUDE_PLUGIN_ROOT}/scripts/knowledge-lint.ts .hermit` and list its `findings` by type (`file`, `age` in days, `detail`) beneath the counts, each type with its fix from [reference.md](reference.md). It is read-only.
**Channel availability:** From `config.json.channels`, for each configured channel, check whether `default_chat_id` is set — the same home field the outbound resolver uses. Report "ready" or "not yet paired (no chat id — send a message first)".
**Fragile zones:** From the last five normalized task records, identify repeated themes in cancelled outcomes and open waiting reasons. Combine these with proposal tags for dismissed or blocked proposals. Surface the top two or three themes with the actual outcomes; unconfirmed is not completed. If none recur, report "No fragile zones detected."
**Stale proposals:** From proposals, find those with `status: accepted` and `resolved_date` absent or `null`. Sort by `accepted_date` ascending (oldest first). Show up to 3. Compute days open = today minus `accepted_date`. If none: "No accepted proposals awaiting resolution."
**Recent learnings:** From `reflection-state.json`, read `queue` entries with `status: accepted` or `status: pending` and surface the most recent 3 question/observation fields. If
Read more
name: hermit-health model: haiku description: "Show alert state, pending task decisions, routine engagement, knowledge state, channel availability, plus fragile zones, long-waiting decisions, and recent learnings. Activates on messages like 'health check', 'how's the hermit', 'is anything broken', 'hermit health', 'system health', 'anything wrong', 'hermitd status', 'hermit brain', 'are routines running', 'what's stuck', 'any fragile zones', 'show me what's blocked', 'recent learnings', 'what have you learned lately', 'where are the weak spots', 'check knowledge', 'lint knowledge', 'knowledge health'."
Hermit Health
Synthesize a compact "state of the hermit" snapshot in two halves: infrastructure (active alerts, pending decisions, routine engagement, knowledge state, channel readiness) and analysis (fragile zones, long-waiting decisions, recent learnings). Everything is read directly in main — this skill is on-demand and runner-free.
Step 0 — Channel reply
If this skill was invoked from a channel-arrived message (the inbound prompt contains a `<channel source="...">` tag), reply via that channel's reply tool. Otherwise emit to conversation.
Scope
Read the following (gracefully skip any file that doesn't exist). The sources are independent — read them concurrently:
1. `.hermit/state/alert-state.json` — the `alerts` object, keyed by alert id (`checklist:*`, `custom:*`). Each entry has `text`, `count`, `first_seen`, `last_seen`, `suppressed`, `consecutive_clean`. 2. `.hermit/state/runtime.json` — `last_activity`, `session_id`. 3. `.hermit/state/reflection-state.json` — `last_reflection` timestamp, `counters` (including `judge_suppress_by_code` map and run/output fields), and run/output counters. 4. `.hermit/config.json` — `routines` array (id, schedule, enabled); `channels` object (each channel's `default_chat_id`). 5. `bun ${CLAUDE_PLUGIN_ROOT}/scripts/task.ts list .hermit --open --limit 20 --json` for open tasks and their pending decisions. Use `total` for the open count, describe only the returned sample, and report `omitted` rather than scanning more files. A proposal is a task with `kind: proposal`; authority, purpose and wait age come from its decision and record, never a separate queue. 7. Glob counts: `.hermit/raw/**` (excluding `.archive/`), `.hermit/compiled/**`, `.hermit/raw/.archive/**`. 8. `bun ${CLAUDE_PLUGIN_ROOT}/scripts/task-report.ts .hermit --limit 5` for normalized recent task records: titles, outcomes, waiting reasons and lessons. Never read frozen session archives or the old live shell document.
Analysis
**Alerts:** From `alert-state.json → alerts`, active means `suppressed` is not `true`; suppressed ones are digest-only and reported separately. Compute each entry's age from `first_seen`. Report the active count with the oldest entry's `text` and age, then the suppressed count with its oldest age. If no active entries: "No active alerts" (still name the suppressed count when there is one).
**Proposal queue:** Count proposals with `status: proposed` (pending operator review), `status: accepted` (in flight, not yet resolved), and `status: in_progress`. If all zero: "Queue empty."
**Routine engagement:** From `config.json.routines`, list each routine and its schedule. For the `reflect` routine, use `reflection-state.json → last_reflection` to show when it last ran; also append counter info from `reflection-state.json → counters`: apply the reflect-line rules below, then append the suppress-mix suffix if any `judge_suppress_by_code` code has a non-zero count: `suppress mix — no-evidence:N, covered-by-memory:N, no-sessions:N` (omit codes with count 0; omit the suffix entirely when all counts are 0 or the map is absent). For every routine, run `bun ${CLAUDE_PLUGIN_ROOT}/scripts/routines.ts health .hermit` once and take last run, fire count and skip reason from its rows.
**Reflect-line rules** (applied to the reflect routine bullet):
- If `counters` is absent: omit the counter clause entirely
- If `total_runs` is 0: show `no runs yet (since YYYY-MM-DD)` where the date is `counters.since`
- Otherwise: `N runs, N empty | output: N proposal tasks, N input decisions | since YYYY-MM-DD` where the date is `counters.since`; omit `| output: ...` if both `proposals_created` and `micro_proposals_queued` are 0
**Micro:** Count entries with `status: "pending"` in `pending decisions.json`. Omit this section entirely if count is zero.
**Knowledge:** Report glob counts for raw (excl. archive), compiled, and archived files. Omit if all three are zero and the directories are missing. If the operator explicitly asked to check or lint knowledge ("check knowledge", "lint knowledge", "knowledge health"), also run `bun ${CLAUDE_PLUGIN_ROOT}/scripts/knowledge-lint.ts .hermit` and list its `findings` by type (`file`, `age` in days, `detail`) beneath the counts, each type with its fix from [reference.md](reference.md). It is read-only.
**Channel availability:** From `config.json.channels`, for each configured channel, check whether `default_chat_id` is set — the same home field the outbound resolver uses. Report "ready" or "not yet paired (no chat id — send a message first)".
**Fragile zones:** From the last five normalized task records, identify repeated themes in cancelled outcomes and open waiting reasons. Combine these with proposal tags for dismissed or blocked proposals. Surface the top two or three themes with the actual outcomes; unconfirmed is not completed. If none recur, report "No fragile zones detected."
**Stale proposals:** From proposals, find those with `status: accepted` and `resolved_date` absent or `null`. Sort by `accepted_date` ascending (oldest first). Show up to 3. Compute days open = today minus `accepted_date`. If none: "No accepted proposals awaiting resolution."
**Recent learnings:** From `reflection-state.json`, read `queue` entries with `status: accepted` or `status: pending` and surface the most recent 3 question/observation fields. If
Run an always-on Claude Code agent on your own machine, for you or your team. Start and orchestrate sessions from chat in any project it can reach. Take over the same session in the Claude app or the CLI.
Other skills on hermitd.
More skills from other plugins.
browser-use
Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…
agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…
Questions about hermit-health.
- Which coding agents can use hermit-health?
- hermit-health installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

