plugins/claude-code-dev-hermit/skills/dev-status/SKILL.md
One-shot read of branch state, dev-server monitor health, and worktree refs. Read-only — no gates, no fixes; surfaces issues with the recovery command the operator should run. Run any time you want to know "is the server up? what branch am I on? is anything stale?" without scanning three places.
npx skillsauth add gtapps/claude-code-hermit dev-statusInstall 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.
Three-line status read for the dev-hermit workflow. Read-only — this skill names commands the operator can run (/dev-down, git worktree prune) but never runs them itself.
Each section runs independently; if one fails to read, surface (read failed: <reason>) and continue. No FAIL gates.
Kick off all three sections concurrently — they read independent state. Compose output in section order (1, 2, 3) once all have settled. Latency dominates here; this is an interactive skill, not a validation flow.
Run in parallel:
git rev-parse --abbrev-ref HEAD → branch name. If output is HEAD, the tree is detached; substitute (detached HEAD at $(git rev-parse --short HEAD)).git status --porcelain → count M (staged or unstaged modifications, including MM/AM/etc — any line starting with M or whose second char is M), A (added), D (deleted), ?? (untracked). Combine into one summary: clean if no lines, otherwise DIRTY — <N> modified, <U> untracked (omit zero-count categories; never list deleted/added separately — fold them into "modified" for the one-line summary).git rev-list --left-right --count HEAD...@{u} 2>/dev/null → ahead/behind counts. Skip if exit is non-zero (no upstream).Compose:
<branch> (clean, in sync with <upstream>) — only show "in sync" line when ahead and behind are both 0.<branch> (clean, <N> ahead of <upstream>) / <N> behind <upstream> / <N> ahead, <M> behind <upstream>.<branch> (DIRTY — N modified, M untracked). Append divergence in parens if non-zero: <branch> (DIRTY — N modified, M untracked; X ahead of <upstream>).<branch> (clean) or <branch> (DIRTY — ...) — omit the upstream clause entirely.The registry-read → pid-extract → kill -0 → health-poll sequence mirrors dev-up Gate 1 (same JSON fields, same kill -0 probe, same health-poll.js invocation). The difference is read-only treatment: a stale pid surfaces the STALE message and does not clear the registry entry. If Gate 1's liveness or health logic changes, mirror it here.
.claude-code-hermit/state/monitors.runtime.json. If missing or malformed: output dev-up: (read failed: <reason>) and stop the section. Do not proceed to any further step.id == "dev-server". If absent: dev-up: not running. Stop the section — do not read config, do not probe.pid. Run kill -0 <pid> 2>/dev/null.
dev-up: registry has dev-server (pid <pid>) but process is not alive — STALE; /dev-down to clear. Stop the section immediately — do not extract started_at, do not read config, do not probe health.started_at (ISO 8601). Format as HH:MM in local time. If parse fails, omit the timestamp..claude-code-hermit/config.json → claude-code-dev-hermit.dev_health_url. If the read fails, behave as if the field is unset.dev_health_url configured: dev-up: running (pid <pid>, started <HH:MM>) — no health probe configured.dev_health_url set: invoke node "${CLAUDE_PLUGIN_ROOT}/scripts/lib/health-poll.js" "<url>" 5 (5-second timeout — /dev-status is interactive, but 3s false-positives on warming services like Spring/JVM/Next.js post-restart; 5s is the interactive sweet spot).
dev-up: running (pid <pid>, started <HH:MM>) — health <status> OK at <url>.{status, error, elapsedMs}: dev-up: running (pid <pid>, started <HH:MM>) — health probe failed at <url>: <error or "last status N">. Do not mark the dev-server stale on a health failure — the process is up; only the readiness check failed.git worktree list --porcelain. If exit is non-zero, output worktree: (read failed) and stop.worktree <path> line; secondary worktrees also have branch refs/heads/<name> (or detached); prunable worktrees have a prunable <reason> line.git rev-parse --show-toplevel). Exclude it from counts.active (no prunable) and prunable (has prunable).worktree: none.worktree: 1 active (<path> on <branch>). If the worktree is detached, use (<path> detached at <short-sha>).worktree: <N> active. Operator runs git worktree list for full detail — do not list every path.worktree: <P> PRUNABLE at <path> (<reason>) — git worktree prune (single prunable). For multiple: worktree: <P> PRUNABLE (sample: <path> — <reason>) — git worktree prune. If active also exist, append after the prunable summary: ; <A> active.Always exactly three lines following the title line. Indent with two spaces; align colons at column 13 (branch: / dev-up: / worktree: are all 7-9 chars + colon — pad to consistent column).
dev-status
branch: feature/PROJ-123-add-auth (3 ahead of origin/main)
dev-up: dev-server running (pid 12345, started 14:23) — health 200 OK at http://localhost:3000/api/health
worktree: 1 active (.claude/worktrees/implementer-456 on feature/PROJ-456)
Idle:
dev-status
branch: main (clean, in sync with origin/main)
dev-up: not running
worktree: none
Issues surface inline:
dev-status
branch: main (DIRTY — 3 modified, 1 untracked)
dev-up: registry has dev-server (pid 12345) but process is not alive — STALE; /dev-down to clear
worktree: 1 PRUNABLE at .claude/worktrees/implementer-456 (branch was deleted) — git worktree prune
git worktree prune, kill, /dev-down, or anything that mutates state. Name the recovery command in the output and let the operator run it.monitors.runtime.json does not block the branch read. A failed git worktree list does not block the dev-up read./dev-up Gate 3's job. Running lsof on every status read is noise.dev-log-errors monitor reporting. This skill is about the dev server, not the log watch — different question, different time-to-answer.git worktree list / /watch status / git status for the full view.git status --porcelain and git worktree list --porcelain parses live in this SKILL's prose rather than scripts/lib/ helpers (per the plugin's "helpers own non-trivial parsing" convention used by port-check.js, resolve-command.js, etc.). The exception is justified because each parse is ~5 lines, has no edge cases worth a helper's overhead, and is consumed only by this read-only skill. If a second skill ever needs the same parse, extract to scripts/lib/git-status.js / git-worktree.js then.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."