Help us improve
Share bugs, ideas, or general feedback.
From ha-nova
Use when analyzing, reviewing, auditing, or checking Home Assistant automations, scripts, or helpers for errors, best-practice violations, and conflicts. Do not invoke `ha-nova:read` separately — this skill handles discovery and reading internally.
npx claudepluginhub markusleben/ha-nova --plugin ha-novaHow 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:
Use when creating, updating, or deleting Home Assistant automations or scripts through HA NOVA Relay. Self-contained — resolves entities and reviews internally.
Create 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.
Provides best practices for Home Assistant automations, helpers, scripts, and dashboards. Guides on avoiding templates, using native constructs, and safe refactoring.
Share bugs, ideas, or general feedback.
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.Relay CLI: ha-nova relay
ha-nova relay health (once per session, skip if already verified)relay ws --data-file <payload-file> — canonical WebSocket pathrelay core --method <METHOD> --path <PATH> --body-file <payload-file> — canonical REST pathrelay ... --jq-file <filter-file> — canonical complex filter pathrelay ... --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_statsentry_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 you must recreate it, write <config-filter-file> with:
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.Check Taxonomy (internal only):
{CATEGORY}-{NN} (example: H-09)Apply these families by domain:
linked_entities[], not from config actionssearch/related on up to 3 linked entitiesvariables: mapping. Never emit it for cross-action or cross-scope references, script fields, HA builtins, or {% set %} locals inside the same template.if plus at least one elif, entity-state-style branch guards, and a terminal bare else that contains a direct trigger.id comparison. Skip single if / else, trigger.id in elif, non-entity-state selector trees, else blocks with extra explicit guards, and choose + condition: trigger.trigger.id check into an explicit elif. Or refactor to choose + condition: trigger.Live helper evidence for H-09/H-10:
skills/review/checks.md → Helper Threshold Evidence/api/states/<helper_entity_id> only when the threshold reference is directstate, attributes.min, attributes.max, or attributes.step are missing or non-numeric, skip H-09/H-10Find other automations/scripts that control the same entities.
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>
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 Debuggingitem_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/SKILL.md → Output Localization.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 — no token needed, service calls are reversible)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:
Localize all headings to the user's language (see skills/ha-nova/SKILL.md → Output Localization).
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:
ha-nova relay