Install
$ agentstack add skill-markusleben-ha-nova-helper ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
HA NOVA Helper
Scope
ha-nova:helper has two helper families:
- Storage-based family — full CRUD for:
input_boolean,input_number,input_text,input_select,input_datetime,input_button,counter,timer,schedule- Config-entry family — CRUD support for:
utility_meter,derivative,integration,min_max,threshold,tod,statistics,history_statsgroupthrough the live menu-driven flow; end-to-end support is verified for thesensorsubtype, and other subtypes must stay anchored to the live step schema instead of guessed fields
Not handled here:
- other config-entry helper families:
template,trend,random,filter,generic_thermostat,switch_as_x,generic_hygrostat- automations/scripts config mutations (use
ha-nova:write)
Bootstrap (once per session)
Verify relay CLI: ha-nova relay health If this fails: ha-nova setup
Relay Contract
Write payloads with the client's native file-writing tool, then use:
ha-nova relay ws --data-fileha-nova relay core --method --path --body-fileha-nova relay ... --outfor larger read/verify output--jq-filefor non-trivial filters; keep inline--jqfor short selectors only
Family-specific transport:
- Storage-based family: WS CRUD + WS list
- Config-entry family: WS
config_entries/get+ WS entity-registry joins for list/read; relay/coreconfig-entry flow, options-flow, and delete writes
Flow
Family 1: Storage-based helpers
Listing helpers
Use the compact entity registry (abbreviated keys: ei = entityid, en = name, ai = areaid).
Create ` with {"type":"config/entityregistry/listfor_display"}`, then run:
ha-nova relay ws --data-file --jq-file
Write `` with:
[.data.entities[] | (.ei | split(".")[0]) as $domain | select(["input_boolean","input_number","input_text","input_select","input_datetime","input_button","counter","timer","schedule"] | index($domain)) | {entity_id: .ei, name: .en, area_id: .ai}] | .[0:30]
If user filters by type, narrow the domain filter to that single storage-based domain.
Keyword search
ha-nova relay ws --data-file --jq-file
Write `` with:
[.data.entities[] | (.ei | split(".")[0]) as $domain | select(["input_boolean","input_number","input_text","input_select","input_datetime","input_button","counter","timer","schedule"] | index($domain)) | select((.ei + " " + (.en // "")) | test("KEYWORD";"i")) | {entity_id: .ei, name: .en, area_id: .ai}] | .[0:20]
If 0 results: try synonyms or shorter stems. Never dump entire domains.
Reading a single helper
- Determine type from entity_id domain prefix.
- Fetch full config via type-specific list:
``text ha-nova relay ws --data-file --jq-file ` Write with: `jq [.data[] | select(.name | test("KEYWORD";"i"))] ``
- No single-item read endpoint — always
{type}/list+ filter.
Creating a helper
- Validate intent against
skills/ha-nova/helper-schemas.mdfor required/optional fields. - Use-case defaults (create only, skip on update/delete):
- Infer use-case from helper name + type using general HA knowledge.
- Consult
skills/ha-nova/helper-schemas.md→ Suggested Defaults for principles and field name reminders. - If sensible defaults can be inferred: show max 4 as numbered list. Group related fields into one item.
``` Suggested defaults for "{name}" ({type}):
- min: 16, max: 30, step: 0.5
- unitofmeasurement: "°C"
- mode: slider
- icon: mdi:thermometer
Accept all, pick by number (e.g. "1 and 3"), or "skip". ```
- User accepts all, picks by number, or says "skip".
- Accepted → merge into payload BEFORE preview.
- No useful defaults inferable → silently skip.
- Preview the payload.
- Ask for natural confirmation.
- for unobserved
groupsubtypes, this first confirmation authorizes only the non-persisting menu-step submit, not the final subtype-specific payload
- Execute:
``text ha-nova relay ws --data-file ``
- Verify — list back and confirm new item exists.
- No domain reload needed — immediate effect.
- Run storage-family post-write review (see below).
Updating a helper
- Resolve target from
{type}/listbynameor internalid. - Extract
idfrom the list response (this is the{type}_idfor the update command). - Preview current vs proposed as a
## Changesdiff (seeskills/ha-nova/write-safety.md→ Pre-Write Diff). Then run a pre-write impact check —search/relatedon this helper entity (seeskills/review/SKILL.mdStep 2) — and surface affected automations/scripts as an advisory. Advisory only; never block. - Ask for natural confirmation.
- Execute:
``text ha-nova relay ws --data-file ``
- Verify by re-reading the same list item.
- Run storage-family post-write review (see below).
- Update-Revert: after the verified update, capture the snapshot and offer
revert— seeskills/ha-nova/write-safety.md→ Update-Revert. Storage-family restore rebuilds a schema-valid{type}/updatefrombefore_config(typed{type}_idfrom itsid+ writable fields only — never the raw list item, which lacks{type}_idand carries read-onlyid/entity_id);expected_afteris the post-update read-back.
Deleting a helper
- Resolve target from
{type}/list; extract itsid(the{type}_idused for the delete call — internal, not shown to the user). - Preview (see
skills/ha-nova/write-safety.md→ Output hygiene — no raw internal id):
- name
- type
- entity_id
- Token confirmation:
confirm:(strict: only exact token accepted; see context skill → Safety Baseline). - Execute:
``text ha-nova relay ws --data-file ``
- Verify absence from
{type}/list.
Family 2: Config-entry helpers
Canonical config-entry helper item:
entry_iddomaintitlestatelinked_entities[]supports_options
entry_id is the canonical identity for config-entry helper writes. If the user gives only a linked entity_id, resolve it back to config_entry_id through the full entity registry before continuing.
Supported domains
utility_meterderivativeintegrationmin_maxthresholdtodstatisticsgrouphistory_stats
Listing helpers
- Read all config entries:
``text ha-nova relay ws --data-file --out ` with {"type":"config_entries/get"}`.
- Read full entity registry:
``text ha-nova relay ws --data-file --out ` with {"type":"config/entity_registry/list"}`.
- Filter config entries to the nine supported domains.
- Join linked entities by matching
config_entry_id. - Present a compact table with:
- title
- domain
entry_id- state
supports_options- linked entities (compact comma-separated summary)
Keyword search
Search against:
- config-entry
title domain- linked
entity_id - linked original/display names when available
If multiple matches remain, present max 5 candidates and ask one blocking question.
Reading a single helper
- Resolve by one of:
entry_id- config-entry title
- linked
entity_id - if multiple candidates remain after resolution, stop and ask one blocking question
- never guess between duplicate titles or ambiguous linked-entity matches
- Re-read
config_entries/get. - Re-read full entity registry and attach
linked_entities[]. - If
supports_options: true, start an options flow:
``text ha-nova relay core --method POST --path /api/config/config_entries/options/flow --body-file ` with containing {"handler":"","showadvancedoptions":false}`.
- Treat the returned current step as the current editable options snapshot:
- record
step_id - summarize each exposed field from
description.suggested_valuewhen present - if an exposed field has no
description.suggested_value, mark its value as unavailable instead of guessing - ignore hidden fields that are not exposed in the current step
- If the options flow is unavailable even though the domain is supported:
- still show canonical metadata
- mark update as unsupported on this HA version
- Present:
**Helper: {title}** (config-entry `{domain}`)
- **Entry ID:** {entry_id}
- **Config-entry state:** {state}
- **Linked entities:** {linked_entities summary}
- **Supports options-flow editing:** {yes/no}
- **Current flow step:** {step_id or "metadata-only fallback"}
- **Current editable fields:** {field summary from the current options step when available}
Creating a helper
- Confirm the requested domain is supported in
skills/ha-nova/helper-flow-schemas.md.
- treat that file as observed field inventory, not a full validation schema
- if required field semantics remain uncertain, fail loud and ask one blocking question
- Prepare the full create plan using
skills/ha-nova/helper-flow-schemas.md:
- for one-step domains, the plan is one submit body
- for
groupwith subtypesensor, include the requirednext_step_idmenu choice and the observed final form - for any other
groupsubtype, plan only the menu choice before the flow starts; inspect the live subtype form before promising the final field set - for
statisticsandhistory_stats, prepare every later step body before preview
- Preview:
- title/name
- domain
- known step plan
- all fields already known at this point
- for unobserved
groupsubtypes, say that the final subtype form will be previewed after the menu step returns live fields
- Ask for natural confirmation.
- Capture a pre-create baseline:
``text ha-nova relay ws --data-file --out ` with containing {"type":"config_entries/get"}`.
- Start the flow:
``text ha-nova relay core --method POST --path /api/config/config_entries/flow --body-file ` ` must contain the handler-start body only.
- Read the start response and extract
flow_idbefore continuing.
- persist it in a variable or note file
- fail loud if the start response did not return
flow_id
- Iterate the flow until terminal success:
- if the current response is a menu step, submit only the selected
next_step_id - if that menu step leads to an unobserved
groupsubtype form, stop and preview the live subtype fields before the terminal submit - after that live subtype preview, ask for a second natural confirmation before sending the terminal subtype-specific payload
- if the current response is a form step, submit only the fields exposed for that step
- the submit body for a form step must contain form fields only
- if a required field is still unresolved and there is no safe value, stop and ask one blocking question
- if HA returns a form with validation errors, fail loud instead of guessing
- Verify success at the config-entry layer first:
- re-read
config_entries/getinto `` - if the terminal flow result includes
entry_id,passed=trueonly when that sameentry_idis present in `` - if the terminal flow result omits
entry_id, diffconfig_entries/getbefore vs after byentry_id - in the diff fallback, collect the new
entry_idvalues that were absent before and present after - in the diff fallback,
passed=trueonly when exactly one newentry_idappeared and its metadata is consistent with the requested create - if the diff fallback yields zero or multiple new
entry_idvalues, or the new entry metadata is inconsistent with the request, fail loud as ambiguous create verification domain/titleare fallback tie-breakers only; they never override a terminal-flowentry_id
- Resolve
linked_entities[]through the entity registry as secondary evidence only. - If the created entry exposes
supports_options: true, reopen the options flow and store the current editable options snapshot for the post-write response. - Run config-entry-family post-write review (see below).
Updating a helper
- Resolve the canonical config-entry helper item:
entry_iddomaintitlelinked_entities[]supports_options- if multiple candidates remain after resolution, stop and ask one blocking question
- never guess between duplicate titles or ambiguous linked-entity matches
- If
supports_optionsis false for this entry:
- fail loud with
update unsupported for this helper on this HA version - do not recreate
- do not guess a direct patch body
- Start the options flow:
``text ha-nova relay core --method POST --path /api/config/config_entries/options/flow --body-file ` with containing {"handler":"","showadvancedoptions":false}`.
- Read the start response and extract
flow_idbefore continuing.
- if the start response explicitly shows that options editing is unsupported for this entry on this HA version, fail loud with
update unsupported for this helper on this HA version - if the start call fails for another reason, surface that relay/HA error directly instead of relabeling it as unsupported
- persist it in a variable or note file
- fail loud if the start response did not return
flow_id
- Capture the current editable options snapshot from the returned form:
- use
description.suggested_valueas the current value source - if a requested field is exposed but lacks
description.suggested_value, fail loud instead of guessing its current value - do not submit read-only fields
- treat the current step as the authoritative mutable field set
- Build the update body by merging requested changes over the current options snapshot:
- carry forward unchanged required fields
- if the user requests a field the current step does not expose, fail loud as unsupported update for that field on this HA version
- do not silently ignore non-exposed requested fields
- do not invent values for fields the current step does not expose
- for
history_stats, preserve HA's two-key window invariant acrossstart,end, andduration - for
history_stats, if the requested change switches to a different valid window pair, drop the old third key explicitly so the submit body still contains exactly two ofstart,end, andduration
- Preview current vs proposed as a
## Changesdiff (seeskills/ha-nova/write-safety.md→ Pre-Write Diff). - Ask for natural confirmation.
- Submit the current step:
``text ha-nova relay core --method POST --path /api/config/config_entries/options/flow/{flow_id} --body-file ``
- If HA returns another form step, repeat the same merge-and-submit rule until terminal
create_entryor explicit failure. - Verify success:
- re-read
config_entries/get passed=trueonly when the sameentry_idstill exists- reopen the options flow
passed=trueonly when the changed fields now appear indescription.suggested_valueas requested- if a requested changed field is exposed in the verification step but lacks
description.suggested_value, fail loud as unverifiable update on this HA version
- Resolve
linked_entities[]again as secondary evidence only. - Run config-entry-family post-write review (see below).
Deleting a helper
- Resolve target to the canonical config-entry helper item:
entry_iddomaintitlelinked_entities[]when available- if multiple candidates remain after resolution, stop and ask one blocking question
- never guess between duplicate titles or ambiguous linked-entity matches
- Enforce the helper-domain allowlist before any delete:
- allowed here:
utility_meter,derivative,integration,min_max,threshold,tod,statistics,group,history_stats - if the resolved
domainis outside that allowlist, stop - do not call `DELETE /api/config/config_entries
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: markusleben
- Source: markusleben/ha-nova
- License: MIT
- Homepage: https://github.com/markusleben/ha-nova
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.