mcpField
H
hass-config-flow

hass-config-flow

github.com/edmundmillerOther8046 installsUpdated today
Repository

About hass-config-flow

hass-config-flow is a Home Assistant operations skill for inspecting entities and calling services, with guidance for integrations that require config flows. It combines hass-cli usage with REST API procedures and NixOS-specific references.

Key features

  1. 01Inspect entities and devices with hass-cli
  2. 02Call Home Assistant services
  3. 03Start, submit, and abort config flows
  4. 04Register application credentials
  5. 05Generate API tokens and query REST endpoints

Use cases

  1. 01Inspect entity states on a Home Assistant host
  2. 02Set up Spotify or Matter integrations
  3. 03Call a service when hass-cli lacks coverage

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/edmundmiller/dotfiles --skill hass-config-flow

After installing, type/hass-config-flowin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
default-integrations.md
device-protocols.md
integration-flows.md
scripts/
ha-api.sh
ha-call.sh
ha-entities.sh
ha-flow.sh
ha-integrations.sh
ha-token.sh

Details

From the project README

Home Assistant REST API

Docs: https://developers.home-assistant.io/docs/api/rest/

NixOS extraComponents bundles integration code, but config-flow-only integrations (Spotify, Matter, HomeKit Controller, Cast, etc.) require the REST API or UI to complete setup.

hass-cli (preferred for inspection/simple calls)

home-assistant-cli is installed on the NUC. Prefer it over raw curl for entity listing, service calls, device/area management, and event watching.

# On NUC (after getting a token):
export HASS_SERVER=http://localhost:8123
export HASS_TOKEN=<token>

hass-cli state list 'light.*'          # list entities by glob
hass-cli state get light.office        # get single entity (yaml)
hass-cli service call homeassistant.toggle --arguments entity_id=light.office
hass-cli device list                   # all devices with area
hass-cli area list                     # all areas
hass-cli device assign Kitchen --match "Kitchen Light"  # bulk assign area
hass-cli event watch                   # watch all events
hass-cli event watch deconz_event      # watch specific event type
hass-cli -o yaml state list            # yaml output
hass-cli -o json state list 'light.*' | jq '[.[] | {entity: .entity_id, name: .attributes.friendly_name, state: .state}]'
hass-cli -o json state list 'light.*' | python3 -c "import json,sys; d=json.load(sys.stdin); print([x['entity_id'] for x in d if x['state']=='on'])"

Note: hass-cli info is broken on current HA (deprecated endpoint). All other commands work.

Use raw curl (below) for config flows, app credentials, and anything hass-cli doesn't cover.

Querying the API (inline SSH)

Scripts in scripts/ exist but are local — they can't be referenced by path on the NUC. Use inline SSH commands instead.

Get a token
TOKEN=$(ssh nuc "sudo python3 -c '
import hashlib, hmac, base64, time, json
auth = json.load(open(\"/var/lib/hass/.storage/auth\"))
for t in auth[\"data\"][\"refresh_tokens\"]:
    if t.get(\"client_name\") == \"agent-automation\":
        header = base64.urlsafe_b64encode(json.dumps({\"alg\":\"HS256\",\"typ\":\"JWT\"}).encode()).rstrip(b\"=\")
        now = int(time.time())
        payload = base64.urlsafe_b64encode(json.dumps({\"iss\":t[\"id\"],\"iat\":now,\"exp\":now+86400*365}).encode()).rstrip(b\"=\")
        sig_input = header + b\".\" + payload
        sig = base64.urlsafe_b64encode(hmac.new(t[\"jwt_key\"].encode(), sig_input, hashlib.sha256).digest()).rstrip(b\"=\")
        print((sig_input + b\".\" + sig).decode())
        break
'" 2>/dev/null)
List entities (by domain)
ssh nuc "curl -s -H 'Authorization: Bearer $TOKEN' http://localhost:8123/api/states" | python3 -c "
import json, sys
states = json.load(sys.stdin)
for s in sorted(states, key=lambda x: x['entity_id']):
    eid = s['entity_id']
    name = s['attributes'].get('friendly_name', '')
    domain = eid.split('.')[0]
    if domain in ('light', 'switch', 'cover', 'media_player', 'fan', 'binary_sensor', 'scene', 'humidifier'):
        print(f'{eid:55s} {name}')
"

Change the domain in (...) filter as needed, or remove it for all entities.

Call a service
ssh nuc "curl -s -X POST -H 'Authorization: Bearer $TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{\"entity_id\": \"media_player.tv\"}' \
  http://localhost:8123/api/services/media_player/turn_off"
Start a config flow
ssh nuc "curl -s -X POST -H 'Authorization: Bearer $TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{\"handler\": \"spotify\"}' \
  http://localhost:8123/api/config/config_entries/flow"
Helper scripts (reference)

Scripts in scripts/ are useful as reference for the API patterns but must be piped via SSH or inlined — they aren't deployed to the NUC.

ScriptPurpose
ha-token.shGenerate JWT from auth storage
ha-api.shGeneral-purpose API wrapper
ha-entities.shList entities by domain
ha-integrations.shList configured integrations
ha-call.shCall a service on an entity
ha-flow.shManage config flows (start/submit)

References

Read these for detailed information:

FileContents
references/integration-flows.mdPer-integration config flow behavior, abort reasons, mDNS discovery commands
references/default-integrations.mdNixOS defaultIntegrations list — what's auto-loaded, Nix config examples
references/device-protocols.mdIdentify device protocol (Matter/Zigbee/Thread/HomeKit) from device registry; vendor model-name conventions; decision tree for ZHA migration

Token generation

HA long-lived tokens are HS256 JWTs signed with a per-token key in /var/lib/hass/.storage/auth. Use scripts/ha-token.sh or inline:

ssh nuc "sudo bash ha-token.sh"           # uses "agent-automation" token
ssh nuc "sudo bash ha-token.sh my-token"  # use a different token name

If no token exists yet, create via HA UI: Profile → Security → Long-Lived Access Tokens → Create Token

Verify: curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8123/api/ → {"message":"API running."}

API quick reference

All requests to http://127.0.0.1:8123 with Authorization: Bearer $TOKEN.

ActionMethodEndpointBody
Health checkGET/api/—
HA configGET/api/config—
List statesGET/api/states—
Get entity stateGET/api/states/{entity_id}—
Set entity statePOST/api/states/{entity_id}{"state": "...", "attributes": {...}}
Fire eventPOST/api/events/{event_type}{...event_data}
Call servicePOST/api/services/{domain}/{service}{"entity_id": "..."} + service data
List servicesGET/api/services—
List config entriesGET/api/config/config_entries/entry—
Start config flowPOST/api/config/config_entries/flow{"handler": "domain"}
Submit flow stepPOST/api/config/config_entries/flow/{flow_id}step-specific data
Abort flowDELETE/api/config/config_entries/flow/{flow_id}—
Delete config entryDELETE/api/config/config_entries/entry/{entry_id}—
Add app credentialsPOST/api/config/application_credentials{"domain":"...","client_id":"...","client_secret":"..."}
Render templatePOST/api/template{"template": "{{ states('...') }}"}
Check configPOST/api/config/core/check_config—

Key workflows

Config flow (non-OAuth)
ha-flow.sh start cast           # auto-discovery, usually creates entry immediately
ha-flow.sh start matter         # returns form → submit with URL
ha-flow.sh submit <flow_id> '{"url":"ws://localhost:5580/ws"}'
OAuth integrations (Spotify, Google, etc.)
  1. Register app credentials first (abort reason: missing_credentials)
  2. Start config flow — returns auth URL for user
ha-api.sh POST /api/config/application_credentials \
  '{"domain":"spotify","client_id":"ID","client_secret":"SECRET"}'
ha-flow.sh start spotify

See references/integration-flows.md for per-integration details.

NixOS context

  • Auth storage: /var/lib/hass/.storage/auth
  • API: http://127.0.0.1:8123 (localhost only), HTTPS via Tailscale serve
  • Public URL: https://homeassistant.cinnamon-rooster.ts.net/
  • defaultIntegrations auto-loads input helpers, automation, scene, script, etc. — see references/default-integrations.md

Comments

Markdown supported