ha-tool
A CLI tool for discovering, querying, and controlling Home Assistant over WebSocket. Designed for both human use and AI agent consumption.
Features
- Entity Discovery — Search, inspect, and list entities with flexible filtering
- Registry Editing — Rename, re-area, relabel, and bulk-remap entities live
- Service Calls — Call any Home Assistant service with JSON data/targets
- Configuration Reload — Reload automations, scripts, scenes, and more
- Template Rendering — Test Jinja2 templates against your live instance
- Entity Verification — Validate entity references in YAML/config files
- Dual Output — Human-readable tables or JSON for scripting/AI agents
- Stateless — Each invocation opens a connection, performs the action, and exits
Installation
# As a standalone CLI (recommended)
uv tool install ha-tool
# Or with pip
pip install ha-tool
# From source
uv tool install .
pip install -e .
Configuration
Set these environment variables:
export HASS_SERVER=https://your-ha-instance:8123
export HASS_TOKEN=your_long_lived_access_token
HASS_URL is also accepted as a fallback for HASS_SERVER.
Create a long-lived access token in Home Assistant: Profile → Security → Long-Lived Access Tokens.
Usage
Search entities
# Substring match
ha-tool search "pool"
# Filter by domain, device class, area
ha-tool search --domain sensor --device-class temperature
ha-tool search --area "Kitchen"
ha-tool search "pool" -d sensor -a "Pool"
# Glob patterns
ha-tool search 'sensor.pool_temp_*'
ha-tool search 'binary_sensor.door_?'
# Regex patterns (auto-detected by metacharacters like [] | ^ $ + ())
ha-tool search 'temperature_[0-9]+'
ha-tool search 'pool|kitchen'
# Include disabled entities
ha-tool search "pool" --include-disabled
Inspect entities
ha-tool inspect climate.wq3a25a01264
ha-tool inspect sensor.pool_temp light.kitchen climate.hvac
Get entity state
ha-tool get sensor.pool_temperature
List areas
ha-tool areas
List domains
ha-tool domains
List integrations
ha-tool integrations
List/search services
ha-tool services
ha-tool services --domain light
ha-tool services "temperature"
Call services
# Turn on a light
ha-tool call light.turn_on --target '{"entity_id": "light.kitchen"}'
# Set thermostat temperature
ha-tool call climate.set_temperature --data '{"temperature": 22}' --target '{"entity_id": "climate.hvac"}'
# Trigger an automation
ha-tool call automation.trigger --target '{"entity_id": "automation.morning_routine"}'
Reload configuration
# List available reload domains
ha-tool reload
# Reload specific domain
ha-tool reload automations
ha-tool reload scripts
ha-tool reload scenes
# Reload all configuration
ha-tool reload all
Refresh Lovelace dashboards
# Discover all yaml-mode dashboards and refresh them + the default dashboard
ha-tool lovelace-refresh
# Refresh specific dashboards by url_path ("default" = the built-in dashboard)
ha-tool lovelace-refresh lovelace
ha-tool lovelace-refresh power default
Home Assistant caches parsed YAML-mode dashboards in memory, so replacing the
file on disk is invisible to clients. This sends lovelace/config with
force: true to re-read each dashboard from disk. Exits 1 if any refresh fails.
Restart Home Assistant
ha-tool restart # Prompts for confirmation
ha-tool restart -y # Skip confirmation
Render Jinja2 templates
ha-tool template '{{ states("sensor.temperature") }}'
ha-tool template '{{ now().strftime("%H:%M") }}'
ha-tool template '{{ state_attr("climate.hvac", "current_temperature") }}'
Verify entity references in files
# Check all entity references in a file
ha-tool verify automations.yaml
# Multiple files
ha-tool verify automations.yaml scripts.yaml configuration.yaml
# Only show missing/invalid references
ha-tool verify --filter missing automations.yaml
Extracts all patterns matching <known_domain>.<object_id> from the given files, filters out known service names (e.g. light.turn_on), and checks each entity against the live HA instance.
Edit the entity registry
# Only the fields you pass are changed
ha-tool set-entity sensor.pool_temp --name "Pool Temperature" --area "Pool"
ha-tool set-entity light.kitchen --icon mdi:ceiling-light --category config
ha-tool set-entity switch.old_name --new-id switch.new_name
# rename-entity is a shorthand for set-entity --new-id
ha-tool rename-entity switch.old_name switch.new_name
Live edit via config/entity_registry/update — no restart. --new-id must stay
in the same domain. --label is repeatable and replaces the whole label set.
Bulk rename by regex
# Dry-run by default — prints every old -> new
ha-tool bulk-rename 'sensor\.old_(.*)' 'sensor.new_\1'
ha-tool bulk-rename -d switch 'switch\.zb_(.*)' 'switch.\1' --apply
PATTERN is a Python regex fullmatched against each entity_id; REPLACEMENT
supports backrefs. A batch containing any collision or cross-domain rename is
refused before anything changes.
Wrap a switch as another domain
ha-tool wrap-entity switch.desk_lamp --as light --name "Desk Lamp"
ha-tool wrap-entity switch.vent --as fan -y
Creates a new switch_as_x entity backed by the source switch. Useful for
re-creating switch→light / switch→fan mappings after an integration rebuild.
Inspect a device
ha-tool device-inspect "Kitchen Motion" # name substring
ha-tool device-inspect a1b2c3d4e5 # exact device_id
Device metadata plus its full entity roster. Ambiguous name matches list the candidates to pick from.
Report unhealthy entities
ha-tool stale-report
ha-tool stale-report --stale 2d -d sensor
ha-tool stale-report --only unavailable --only orphaned
Read-only sweep flagging unavailable, unknown, stale, restored,
orphaned, disabled, and hidden entities. Change-only sensors can
false-positive on stale, so treat that flag as advisory.
Removal commands
ha-tool remove-entity input_boolean.test_toggle -y
ha-tool remove-device <device_id> <config_entry_id> -y
ha-tool remove-config-entry <entry_id> -y
Registry cleanup. Prompts for confirmation unless -y / --yes.
Validate config
ha-tool check-config
Validates configuration.yaml (exits 1 when invalid).
Discovery (extra)
ha-tool info # core config (version, location, units)
ha-tool panels # registered UI panels
ha-tool config-entries # integrations and their config entries
ha-tool labels # label registry
ha-tool floors # floor registry
ha-tool categories <scope> # category registry (default scope: automation)
History and logs
ha-tool history sensor.outdoor_temperature --since 6h
ha-tool logbook --since 30m -e light.kitchen
ha-tool error-log -n 50
--since / --until accept 1h, 30m, 2d, today, now, or ISO 8601.
Diagnostics
ha-tool health # system health snapshot per integration
ha-tool repairs # active repair issues
ha-tool notifications list
ha-tool notifications dismiss <notification_id>
Live event stream and calendar
ha-tool watch --event-type state_changed
ha-tool watch -t state_changed -e light.kitchen
ha-tool calendars
ha-tool calendar calendar.work --start now --end 7d
watch outputs NDJSON until Ctrl-C.
Output formats
Default output is a human-readable table. Use -o json for machine-parseable JSON:
ha-tool -o json search "pool"
ha-tool -o json inspect sensor.pool_temp
ha-tool -o json services --domain climate
Debugging
Use -v to see WebSocket connection details on stderr:
ha-tool -v search "pool"
Architecture
- Single WebSocket connection per invocation, fires all registry queries concurrently, then closes. Stateless.
- Joins entity registry → device registry → area registry to resolve area names, device info, and friendly names.
- Entity's own
area_idtakes precedence over its device'sarea_id. - Disabled entities are excluded by default.
- Search pattern auto-detection: plain text → substring,
*/?→ glob, regex metacharacters → regex.
For AI Agents
The installable skill at skills/ha-tool.md is structured documentation optimized for AI agent consumption, including:
- Command reference with exact output schemas
- Discovery workflow patterns
- Common usage examples
See AGENTS.md for guidance on extending or fixing the repo itself.
Claude Code Integration
Install the ha-tool skill for Claude Code:
./scripts/install-skill.sh
This copies the skill to ~/.claude/commands/ha-tool.md, making it available globally in Claude Code.
Dependencies
- Python 3.12+
- typer — CLI framework
- pydantic — Data validation
- websockets — WebSocket client
License
MIT License. See LICENSE for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ha_tool-0.4.1.tar.gz.
File metadata
- Download URL: ha_tool-0.4.1.tar.gz
- Upload date:
- Size: 38.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54a2337a7985ba4589977ff687170c945081160ef5a438724168e0e352bfbb9c
|
|
| MD5 |
aa3742fee490592f2fec7864fc144a2a
|
|
| BLAKE2b-256 |
c16c3cac538b777fbcf78c75dae7c025c23a474d03eaf59ce02525781ca2591a
|
Provenance
The following attestation bundles were made for ha_tool-0.4.1.tar.gz:
Publisher:
publish.yml on szsolt/ha-tool
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ha_tool-0.4.1.tar.gz -
Subject digest:
54a2337a7985ba4589977ff687170c945081160ef5a438724168e0e352bfbb9c - Sigstore transparency entry: 2415080814
- Sigstore integration time:
-
Permalink:
szsolt/ha-tool@2d19885ab0280149b4778b4fa159faa509cb3b66 -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/szsolt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2d19885ab0280149b4778b4fa159faa509cb3b66 -
Trigger Event:
release
-
Statement type:
File details
Details for the file ha_tool-0.4.1-py3-none-any.whl.
File metadata
- Download URL: ha_tool-0.4.1-py3-none-any.whl
- Upload date:
- Size: 33.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0257861219b01f2957f033c4055da4c2eb593b63e3b970224388a87deb659081
|
|
| MD5 |
f4d08c545b1652e86184a9ac35606e07
|
|
| BLAKE2b-256 |
35cb9263e5e2d2476643701f7b1e3cf5260e31c4ccbc71cd39890015d4ef8b06
|
Provenance
The following attestation bundles were made for ha_tool-0.4.1-py3-none-any.whl:
Publisher:
publish.yml on szsolt/ha-tool
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ha_tool-0.4.1-py3-none-any.whl -
Subject digest:
0257861219b01f2957f033c4055da4c2eb593b63e3b970224388a87deb659081 - Sigstore transparency entry: 2415080820
- Sigstore integration time:
-
Permalink:
szsolt/ha-tool@2d19885ab0280149b4778b4fa159faa509cb3b66 -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/szsolt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2d19885ab0280149b4778b4fa159faa509cb3b66 -
Trigger Event:
release
-
Statement type: