From ha-nova
Reviews Home Assistant automations, scripts, and helpers for errors, best-practice violations, and conflicts. Handles discovery and reading internally.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ha-nova:reviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Read-only quality review for automations, scripts, and helpers:
Read-only quality review for automations, scripts, and helpers:
Read-only analysis. Exception: after explicit user confirmation, one Quick-Fix service call may be executed to correct an acute state problem detected during review.
POST, PUT, PATCH, or DELETE config writes through the relay.ha-nova:write.ha-nova:helper.Preflight: ha-nova relay health (once per session, skip if already verified). If this fails: ha-nova setup.
Relay CLI: ha-nova relay
ha-nova relay ws --data-file <payload-file> — canonical WebSocket pathha-nova relay core --method <METHOD> --path <PATH> --body-file <payload-file> — canonical REST pathha-nova relay ... --jq-file <filter-file> — canonical complex filter pathha-nova relay ... --out <result-file> — canonical large-output pathIf user provides an exact automation/script entity_id (e.g., automation.main_lights), skip search and go directly to config read.
For helpers, resolve the family first:
input_boolean, input_number, input_text, input_select, input_datetime, input_button, counter, timer, scheduleutility_meter, derivative, integration, min_max, threshold, tod, statistics, group, history_stats, templateentry_idIf the target config is not already in the thread context, resolve it yourself:
prefix, domain, area, or label, build a shortlist first using skills/ha-nova/bulk-patterns.md.
config/entity_registry/list_for_display for direct prefix / domain resolutionconfig/entity_registry/list and config/area_registry/list only when richer area/label evidence is requiredsearch/related with item_type:"area" before any registry-first fallbackautomation, script, entity, device, ...), not as a flat array.data.automation.data.script.data.entity is only a fallback seed for automation/script derivation when the target-family arrays are absentarea_id only as supplemental evidence when it is actually populatedentity_id, then sort deterministically and persist the matched shortlistrelated-config; if the marker must live in command transcript output, emit a line like COLLISION_EVIDENCE=<reason>ei=entity_id, en=name/alias):
Skip this step when step 1 already produced a resolved current review set.
Create <payload-file> with {"type":"config/entity_registry/list_for_display"}.
Then run:
ha-nova relay ws --data-file <payload-file> --jq-file <filter-file>
Write <filter-file> with:
.data.entities[] | select(.ei | startswith("automation.")) | "\(.ei) | \(.en // "unnamed")"
Filter the resulting text with the client's native search/filter tool, not shell-specific pipelines.
For scripts: select(.ei | startswith("script.")).
For helpers: (.ei | split(".")[0]) as $domain | select(["input_boolean","input_number","input_text","input_select","input_datetime","input_button","counter","timer","schedule"] | index($domain)).ha-nova relay ws --data-file <payload-file> --out <entries-file>
ha-nova relay ws --data-file <payload-file> --out <registry-file>
with:
{"type":"config_entries/get"}{"type":"config/entity_registry/list"}
Resolve the target by one of:entry_idtitle within the supported helper domainsentity_id by matching entity-registry config_entry_id
Build the canonical metadata item:entry_iddomaintitlestatelinked_entities[]unique_id (config key) — the entity_id slug and config key differ for UI-created items (see relay-api.md → ID Types):
Create <payload-file> with the final config/entity_registry/get request in one write step, then run:
ha-nova relay ws --data-file <payload-file> --out <registry-file>
ha-nova relay jq -r --file <registry-file> '.data.unique_id'
The jq filter quoting above is a POSIX example. On Windows/PowerShell pass the same filter with native argument quoting.
Use that saved-result + -r form for the scalar. Do not create a separate jq file for .data.unique_id, do not strip quotes with shell substitutions afterward, and do not write placeholder payload templates that are rewritten later with perl -0pi, sed -i, or similar commands.
For scripts: use "entity_id":"script.<slug>".
Skip this step for config-entry helpers — entry_id is already the canonical identity.# Automation:
ha-nova relay core --method GET --path /api/config/automation/config/<unique_id> --jq-file <config-filter-file> --out <target-file>
# Script:
ha-nova relay core --method GET --path /api/config/script/config/<unique_id> --jq-file <config-filter-file> --out <target-file>
# Helper (storage-based family, WS list + filter):
ha-nova relay ws --data-file <payload-file> --jq-file <helper-filter-file> --out <target-file>
Preferred: copy skills/ha-nova/config-body-filter.jq to <config-filter-file> and use that copied file directly.
If the canonical file is unavailable (flat-copy installs), recreate it with exactly:
if .ok then .data.body else error("relay error: \(.error.message // "unknown")") end
When writing this jq file, paste that jq program body exactly as shown. Do not add extra shell-escape backslashes around the jq interpolation or run a probe variant first.
POSIX shell example only:
cat <<'EOF' > "$config_filter_file"
if .ok then .data.body else error("relay error: \(.error.message // "unknown")") end
EOF
On Windows/PowerShell, use the native file-writing equivalent or copy the canonical file while preserving the exact jq file body. The jq file body must contain exactly that one jq expression and nothing else. Do not add extra single quotes inside the error string. If you print the file for confirmation, do not compare it against a shell-escaped string, do not store the jq program in a shell variable, and do not wrap it in an if [ "$line" != ... ] guard. If the printed contents differ, overwrite the same config_filter_file with the exact canonical line before the first config read; do not create probe variants or alternate filenames, and do not patch the file afterward with in-place rewrite commands.
Write <helper-filter-file> with:
if .ok then [.data[] | select(.name | test("<search_term>";"i"))] else error("relay error: \(.error.message // "unknown")") end
For config-entry helpers, persist the canonical metadata item from step 3 to <target-file> instead of attempting {type}/list.
Then read the file with the native file-reading tool for complete, untruncated access.light.main_light, climate.main_zone — NOT the automation/script entity itself). Read its current state (for Quick-Fix detection at end of review):
ha-nova relay core --method GET --path /api/states/<controlled_entity_id> --jq-file <state-filter-file> --out <state-file>
Write <state-filter-file> with:
if .ok then .data.body else empty end
Skip this step when the current review set contains more than one target.
If no controlled entity found in actions, or state read fails: continue review — Quick-Fix will be skipped.
For standalone config-entry helper review, skip this step entirely. There is no config body with actions to analyze for a primary controlled entity.If config is already in the thread context (e.g., user pasted YAML):
Do NOT invoke ha-nova:entity-discovery or ha-nova:read as separate skills — handle everything within this review flow.
After target resolution:
== 1: stay in normal single-target review mode> 1: enter aggregate multi-target review mode automaticallyMulti-target rules:
Bulk mode rules:
skills/ha-nova/bulk-patterns.md for selector semantics, stable ordering, and workset limitsunique_id, config, state, and related-item evidence per target inside the current workset only; no prefetch for the remaining matched targetsmatched N / audited M / remaining R and wait for an explicit follow-up request before continuingBefore analyzing, consult these sources:
Local reference (always):
docs/reference/ha-template-reference.md — valid Jinja2 functions, constants, filtersOfficial HA docs (fetch selectively based on config content — do NOT fetch all for every review):
Only fetch pages relevant to the triggers, actions, and templates found in the config. Cross-check against documented gotchas and constraints — this catches issues beyond the hardcoded checks below.
Verify-before-flag rule: Before reporting ANY issue:
Do NOT flag valid HA builtins or documented behavior as errors.
Analyze config against the review catalog plus any additional issues found in the official docs. Report only violations found.
Traverse all variables: mappings in the config, not just the top-level block. Include root variables: on the automation/script plus local variables: actions inside choose, if / then / else, default, repeat, and nested sequence blocks.
Rule Catalog
skills/review/checks.md before evaluating findings.skills/review/SKILL.md is the stable review entrypoint; skills/review/checks.md is the full rule catalog.Apply the catalog:
skills/review/checks.md and follow its ## Application section — the family-by-domain matrix, the per-check evidence boundaries (R-17..R-25, M-05), and the live-helper evidence rules live there.Find other automations/scripts that control the same entities.
For updates, this same scan is also run pre-write as an advisory impact preview (see ha-nova:write Phase 2 Step 3c, Pre-Write Impact, and the ha-nova:helper update flows). The post-write run here stays mandatory and authoritative against the persisted config.
Branch by target family:
linked_entities[] from the canonical metadata item; do not attempt action extractionlinked_entities[] from the canonical metadata itemsearch/related:
ha-nova relay ws --data-file <payload-file>
write/helper deliberately use a tighter budget of max 3 related configs). Resolve unique_id first for automation/script targets (see Target Resolution step 5), then:
# Automation:
ha-nova relay core --method GET --path /api/config/automation/config/<unique_id> --jq-file <config-filter-file> --out <related-file>
# Script:
ha-nova relay core --method GET --path /api/config/script/config/<unique_id> --jq-file <config-filter-file> --out <related-file>
When the user reports runtime issues ("automation didn't fire", "wrong behavior last night"):
skills/read/SKILL.md → Trace Debuggingha-nova trace latest/list/get --json; they are enough for run selection, result status, timestamp, item binding, and most review findings.path, result, changed_variables, or error, and avoid large jq projections as the standard path.item_id in every trace matches the target's unique_id before attributing results. see skills/ha-nova/SKILL.md → Claim-Evidence Binding.🔴 Condition blocked — condition was never met in last 3 runs). Localize at runtime per skills/ha-nova/output-rules.md.For each related automation/script, apply the 3-step conflict test:
Step 3a — Action Polarity:
Step 3b — Trigger Temporal Relationship:
Step 3c — Guard Conditions:
sleep_mode: on vs off) → no conflict, skipUse the known safe/problem patterns from skills/review/checks.md when deciding whether a related automation pair is truly benign or a real conflict.
Skip this step entirely in bulk mode.
After completing Steps 1-3, check if the current entity state (from the earlier <state-file> read) shows an acute, fixable problem.
Qualifies as Quick-Fix:
on when automation should have turned it off, climate mode wrong)unavailable cover that needs cover.stop_cover)input_select stuck on wrong option)Does NOT qualify:
If qualified:
ha-nova:service-call; see context skill → Active Preview Confirmation; no token needed for ordinary service calls)On confirmation: Execute via Relay:
ha-nova relay core --method POST --path /api/services/{domain}/{service} --body-file <payload-file>
Then verify state changed:
ha-nova relay core --method GET --path /api/states/{entity_id}
Report result (new state or failure).
Skip this step in bulk mode and for helper reviews.
Run this step only when at least one complexity gate matches:
repeat: present, or choose: with 3+ branchestime_pattern) combined with actuator control such as switch, light, cover, climate, or valveAsk only non-binding "what happens if...?" questions that go beyond the fixed checklist:
queued / parallel behavior under rapid repeat triggersRules:
Skip this step in bulk mode.
Derive candidate suggestions only from verified evidence already present in the current review context:
Do not invent intent or removal justification from appearance alone.
Design-intent gate for remove/simplify ideas:
After the gate, rank confident suggestions by intervention depth:
Rules:
Apply skills/ha-nova/output-rules.md to all user-facing output.
Review output is sectioned, not card-framed; only a Section 8 quick-fix proposal renders as the service-call action preview when it proposes a call.
Exception: if a maintainer-provided release-validation or machine-check prompt explicitly pins exact section titles or machine markers, follow that override exactly so automated validation can compare the fixed headings. This exception does not allow internal check codes in normal user-facing prose.
For resolved targets == 1, keep this 8-section output in the same order every time:
Section 1 — Review target:
Section 2 — Findings:
🔴|🟠|🟡 Short descriptive titleWhy: ...Fix: ...Section 3 — Collision check:
Section 4 — Conflicts:
Section 5 — Questions to consider:
Section 6 — Suggestions:
Section 7 — Summary:
Section 8 — Instant help:
For resolved targets > 1, return exactly these 6 sections:
Section 1 — Scope:
Section 2 — Summary:
Section 3 — High-Risk Findings:
Section 4 — Repeated Patterns:
Section 5 — Items Checked:
Section 6 — Collisions by Cluster:
Preview before write: nothing is saved until the user confirms the shown preview.
Confirmation binds to the displayed preview and expires on any change to target, payload, endpoint, or scope (context skill → Active Preview Confirmation).
Pre-preview phrases ("do it", "go ahead", "implement the plan") authorize drafting and preview only — never the write itself.
Delete and destructive operations require the typed token confirm:<token> verbatim; "yes" or any natural-language reply is invalid.
Never guess entity, service, or config IDs — resolve them or ask.
Home Assistant is reached exclusively through ha-nova relay.
For any HA write this skill does not cover, STOP and invoke ha-nova:fallback first — never probe unfamiliar write endpoints.
Read-only analysis: no config writes through the relay (see Scope for the single Quick-Fix exception).
The Quick-Fix service call requires confirmation bound to its exact preview; bulk mode disables it entirely.
ha-nova relaywrite/helper use max 3 by design)npx claudepluginhub markusleben/ha-nova --plugin ha-novaCreate and manage Home Assistant YAML configuration files including automations, scripts, templates, blueprints, Lovelace dashboards, and file organization. Use when working with Home Assistant configuration files (.yaml, .yml) or discussing HA automations, scripts, sensors, or dashboards.
Teaches Home Assistant automation patterns using native triggers, helpers, and conditions instead of Jinja2 templates. Covers safe refactoring, Blueprints, Zigbee automations, and dashboard cards.
Creates, updates, and deletes Home Assistant automations and scripts via HA NOVA Relay. Includes entity resolution, safety checks, and preview before applying changes.