diff --git a/AGENTS.md b/AGENTS.md index cefff4e8..369ef9ff 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,6 +39,48 @@ You MUST follow these rules strictly: - Make the change anyway - Try to convince them otherwise +## Safety Guidelines + +- NEVER expose or display contents of `secrets.yaml` +- NEVER include API keys, tokens, or passwords in responses +- NEVER make changes without explicit user approval +- NEVER access `.storage/`, `.cloud/`, or other internal directories +- NEVER attempt to modify Home Assistant's internal databases or registries +- NEVER parse internal JSON files for entity/device/area information +- ALWAYS prefer MCP tools for querying runtime state over internal file access +- ALWAYS use `call_service` through MCP rather than modifying state files +- WARN users before changes that require restart vs reload +- SUGGEST backing up files before major modifications +- CHECK configuration validity when possible +- ALWAYS confirm with user before writing, editing, or deleting any file + +## RESTRICTED: Internal Home Assistant Directories + +**NEVER read, modify, or directly interact with these internal directories:** + +| Directory | Contains | Use Instead | +|-----------|----------|-------------| +| `.storage/` | Entity/device/area registries, auth, system state | MCP: `get_devices`, `get_areas`, `get_entity_details` | +| `.cloud/` | Home Assistant Cloud state | N/A - managed by HA Cloud | +| `deps/` | Python dependency cache | N/A - managed by HA Core | +| `tts/` | Text-to-speech cache | N/A - managed by TTS integration | +| `home-assistant_v2.db` | History SQLite database | MCP: `get_history`, `get_logbook` | +| `home-assistant.log` | Raw system logs | MCP: `get_error_log` | + +These contain internal Home Assistant state that: + +1. Is managed exclusively by Home Assistant core +2. Can corrupt your installation if modified incorrectly +3. May be overwritten by Home Assistant at any time +4. Has no stable schema or format guarantees + +**For information that seems to require internal access, there is always a proper alternative:** + +- Need entity details? -> Read configuration files OR use `get_entity_details` +- Need device info? -> Use `get_devices` MCP tool +- Need to check history? -> Use `get_history` MCP tool +- Need to see errors? -> Use `get_error_log` MCP tool + ## Environment Context - You are running inside the OpenCode app @@ -47,6 +89,27 @@ You MUST follow these rules strictly: - If add-on folder access is enabled, `/addons` and `/addon_configs` are available for Home Assistant add-on development. Treat `/addon_configs` as sensitive and only inspect or modify these folders when the user explicitly asks. - You may have access to MCP tools for interacting with Home Assistant (check with the user) +## Skills: where the detailed procedures live + +The add-on ships skills that hold the full procedure for each kind of Home +Assistant work. They are loaded on demand with the `skill` tool, so they cost +nothing until the task needs them. **Load the matching skill before you start** — +each one carries current syntax, the tool to prefer, and the mistakes worth +avoiding, none of which is repeated here. + +| Load this skill | When the request is about | +|---|---| +| `home-assistant-configuration` | Writing or changing YAML: automations, scripts, scenes, templates, integrations, packages, helpers. Also validation, backups, and whether a change needs a reload or a restart. | +| `home-assistant-troubleshooting` | Something is broken, missing, unavailable, or behaving oddly. Bounded diagnosis that ends in a recommendation, not a fix. | +| `home-assistant-dashboard-ui` | Lovelace dashboards, views, cards, badges, themes, and screenshot verification of the result. | +| `home-assistant-zigbee-esphome` | Zigbee/ZHA/Z2M devices, cascade renames, stale-device cleanup, mesh maps, ESPHome, and device firmware updates. | +| `home-assistant-development` | Writing code rather than configuration: custom integrations, add-ons, native `llm.py` tool providers, MCP servers. | + +More than one can apply — diagnose with the troubleshooting skill, then load the +configuration skill when the user approves a fix. The consent, scope, secret and +internal-directory rules above are always in force and are never relaxed by a +skill. + ## Home Context The add-on assembles context about *this specific installation* and loads it before the user's first message. You do not need to fetch any of it. Depending on the user's settings, some or all of these are present: @@ -68,12 +131,14 @@ Decision notes record *why* an installation is the way it is. That reasoning can **To record**, offer first and then wait. Say what you would store, in the words you would store it, and call `remember_decision` with `user_approved: true` only after the user agrees. A general instruction to "remember this" for the current task is not approval to write a permanent note; asking costs one sentence. Worth recording: + - Deliberate removals and disables ("that integration was removed because it fought with X") - Intentional deviations from the obvious approach, and why - Things to leave alone - Constraints that will still be true in six months Not worth recording — do not write these: + - What you did this session, or how you troubleshot something. **This is not a session log.** - Anything already readable from the configuration files - Anything the user has not explicitly approved @@ -84,63 +149,46 @@ Not worth recording — do not write these: ## Home Assistant Interaction Model -There are three primary, safe ways to interact with Home Assistant: +Four ways to interact, each with a job the others do badly. -### 1. Configuration Files (YAML) -The standard way to define and customize Home Assistant behavior: -- Automations, scripts, scenes, and blueprints -- Integration and sensor configurations -- Templates, packages, and customizations -- Dashboard (Lovelace) definitions +### 1. Configuration files (YAML) -These files are designed for user editing and are the source of truth for your Home Assistant setup. +The source of truth for defined behaviour: automations, scripts, scenes, +blueprints, integrations, templates, packages, customizations, and YAML-mode +dashboards. These files are designed for editing. Load +`home-assistant-configuration` before changing one — it carries the mandatory +style guide, the safe-write path, and the reload/restart rules. -### 2. MCP Tools (Runtime API) -Real-time interaction with the running Home Assistant instance: -- Query current entity states and history -- Control devices and call services -- Validate configurations -- Diagnose issues and detect anomalies -- Report OpenCode/HA agent capability status with `get_agent_capabilities` +### 2. MCP tools (runtime API) -### Native Home Assistant LLM Platform -Home Assistant is developing a native `llm` integration where Core integrations and custom integrations can expose curated tools through `/llm.py` and registered LLM APIs. New Home Assistant builds may also expose those APIs over native MCP endpoints such as `/api/mcp/`; the built-in Assist API uses `/api/mcp/assist`. This is complementary to OpenCode MCP, not a replacement. +Real-time interaction with the running instance: -- If the optional `homeassistant_native` MCP server is available, prefer it for requests that fit the configured native Home Assistant LLM API because those tools are curated by Home Assistant. -- Use OpenCode MCP for configuration editing, safe writes, validation, admin/dev workflows, screenshots, updates, ESPHome, `hab`, Zigbee tasks, add-on development, and Home Assistant documentation lookup. -- Use `get_agent_capabilities` or `ha://agent/capabilities` to check whether the running HA instance reports the native `llm` component and native MCP endpoints. -- Use `get_home_context` for compact area/domain/entity understanding before broad state dumps. -- Use `get_ha_llm_development_guide` when helping develop or review a custom integration's native `/llm.py` provider. -- Do not assume this add-on can register tools directly with HA's native `llm` platform; native tool registration is internal to HA integrations/custom integrations. The add-on can consume configured native LLM APIs through native MCP when Home Assistant exposes them. +- `get_states`, `search_entities`, `get_entity_details`, `get_home_context` — current state and compact area/domain/entity context. Prefer `get_home_context` over broad state dumps. +- `call_service` — control devices (with confirmation), and read from services that answer with data (`recorder.get_statistics`, `weather.get_forecasts`, `calendar.get_events`, `todo.get_items`); the response comes back automatically +- `get_history`, `get_logbook`, `get_calendar_events` — historical and calendar data; supplied timestamps must include `Z` or a UTC offset +- `get_devices`, `get_areas` — device and area registry +- `write_config_safe`, `validate_config`, `check_config_syntax` — safe config writing with validation, content protection and backup +- `get_integration_docs`, `get_breaking_changes` — current syntax, before writing any integration configuration +- `diagnose_entity`, `get_error_log`, `detect_anomalies`, `get_suggestions` — diagnosis +- `get_supervisor_health`, `get_supervisor_resolution`, `get_backup_posture`, `get_store_audit`, `get_supervisor_metrics`, `get_support_logs` — bounded, credential-redacted system evidence +- `remember_decision`, `recall_decisions`, `supersede_decision` — decision notes +- `watch_firmware_update`, `get_available_updates`, `update_component` — updates +- `screenshot_url` — visual verification (requires the `screenshot_enabled` option) +- `get_agent_capabilities`, `get_ha_llm_development_guide` — capability and native-LLM development information + +Which tools exist depends on the add-on's MCP tool profile. If a tool you expect +is missing, the profile is reduced — say so instead of working around it. ### 3. hab CLI (Home Assistant Builder) -A CLI tool designed for AI agents to manage Home Assistant. Run `hab` commands via the terminal: -- **Entity management**: `hab entity list`, `hab entity get light.living_room`, `hab entity logbook sensor.power --start 2h` -- **Service calls**: `hab action call light.turn_on --entity light.living_room --data '{"brightness": 200}'` -- **Service calls that answer with data**: add `--return-response`, e.g. `hab action call weather.get_forecasts --entity weather.home --data '{"type":"daily"}' --return-response`. Without the flag Home Assistant refuses the call outright -- **Automation CRUD**: `hab automation list`, `hab automation create`, `hab automation delete` -- **Dashboard management**: `hab dashboard list`, `hab dashboard view create` -- **Area/floor/zone/label**: `hab area list`, `hab area create "Kitchen"` -- **Helpers**: `hab helper list`, `hab helper create` -- **Scripts**: `hab script list`, `hab script create` -- **Scenes**: `hab scene list`, `hab scene create`, `hab scene activate "Movie Time"` -- **Blueprints**: `hab blueprint list` -- **Backups**: `hab backup list`, `hab backup create` -- **System**: `hab system info`, `hab system health`, `hab overview` -- **Devices**: `hab device list` -- **People**: `hab person list`, `hab person create`, `hab person update` -- **Categories**: `hab category list`, `hab category assign --entity light.kitchen` -- **To-do lists**: `hab todo list`, `hab todo item list todo.shopping`, `hab todo item add todo.shopping "Milk"` -- **Notifications**: `hab notification list`, `hab notification create --message "Hello" --title "Alert"` -- **Integrations**: `hab integration list`, `hab integration reload hue`, `hab integration disable mqtt` -- **Repairs**: `hab repairs list`, `hab repairs ignore ` -- **Events**: `hab event list`, `hab event fire my_custom_event --data '{"key": "value"}'` -- **Templates**: `hab template render --expression "{{ states('sensor.temperature') }}"` -- **Search**: `hab search related` -`hab` outputs human-readable text by default. Use `--json` for structured JSON output (ideal for parsing). -`hab` is pre-authenticated via the Supervisor token - no login required. -Run `hab --help` or `hab --help` for full usage details. +A CLI designed for AI agents, pre-authenticated via the Supervisor token. It is +the primary path for dashboards, areas/floors/zones/labels, helpers, scripts, +scenes, blueprints, backups, people, categories, to-do lists, notifications, +integrations, repairs, events and templates — the registry-level work that has +no YAML file behind it. + +`hab` prints human-readable text by default; use `--json` for structured output. +Run `hab --help` or `hab --help` for full usage. ``` @@ -216,33 +264,16 @@ Use "hab [command] --help" for more information about a command. ``` -**Use configuration files when:** defining behavior, creating automations, setting up integrations -**Use MCP tools when:** checking current state, safe config writing, anomaly detection, entity diagnostics -**Use hab CLI when:** managing dashboards, areas, helpers, backups, blueprints, and bulk admin operations +### 4. zigporter CLI (Zigbee toolkit) -### 4. zigporter CLI (Zigbee Toolkit) -A CLI for Zigbee device management in Home Assistant. Handles cascade renames (updating entity IDs across automations, scripts, scenes, and all Lovelace dashboards atomically), device inspection, stale device cleanup, and Zigbee mesh visualization. +Zigbee device management, and the only tool here that **cascades a rename** +across automations, scripts, scenes and every Lovelace dashboard atomically. +`hab` renames one thing and leaves the references dangling. Also handles device +inspection across ZHA/Z2M/HA, stale-device cleanup, and mesh visualization. -**Cascade rename** — zigporter's unique value: when you rename an entity or device, it automatically patches every reference in automations, scripts, scenes, and Lovelace dashboards. `hab` can rename a single entity/device but does NOT cascade to references. - -Key commands: -- **Cascade rename**: `zigporter rename-entity light.old_id light.new_id --apply`, `zigporter rename-device "Old Name" "New Name" --apply` -- **Device inventory**: `zigporter list-devices --json`, `zigporter list-z2m --json` (requires Z2M config) -- **Device inspection**: `zigporter inspect "Device Name" --json`, `zigporter inspect sensor.entity_id --json` -- **Stale device management**: `zigporter stale "Device" --action remove`, `zigporter stale "Device" --action ignore` -- **Post-migration cleanup**: `zigporter fix-device "Device" --apply` -- **Connectivity check**: `zigporter check` -- **ZHA export**: `zigporter export --output devices.json` -- **Mesh visualization**: `zigporter network-map --format table` (terminal), `zigporter network-map --output mesh.svg` (SVG file) - -**Output format**: Use `--json` on listing/inspect commands for structured output (ideal for AI parsing). Rename commands output diffs and confirmation text. - -zigporter is pre-authenticated via the Supervisor token. Z2M commands (`list-z2m`, `network-map --backend z2m`) require Z2M URL configuration in the add-on settings. - -**Important limitations**: -- `rename-entity` / `rename-device` do NOT patch Jinja2 template expressions (e.g. `{{ states('old.id') }}`). A warning is printed listing affected files — inform the user these need manual review after renaming. -- The `migrate` command is inherently interactive (requires physical device actions) and must NOT be used by AI agents. -- Dry-run is the default for renames — always preview before using `--apply`. +Dry-run is the default for renames — always preview before `--apply`. The +`migrate` command is interactive and must NOT be used by an agent. Load +`home-assistant-zigbee-esphome` before any of this work. ``` @@ -287,562 +318,23 @@ zigporter is pre-authenticated via the Supervisor token. Z2M commands (`list-z2m ``` -**Use zigporter CLI when:** renaming entities/devices with cascade updates, inspecting Zigbee devices across integrations, cleaning up stale or post-migration devices, visualizing the Zigbee mesh - -### 5. Internal Directories (OFF-LIMITS) -Home Assistant manages internal state in directories like `.storage/`. These are: -- Not designed for direct access -- Subject to change without notice -- Potentially dangerous to modify - -**Never access internal directories directly - use configuration files or MCP tools instead.** - -## RESTRICTED: Internal Home Assistant Directories - -**NEVER read, modify, or directly interact with these internal directories:** - -| Directory | Contains | Use Instead | -|-----------|----------|-------------| -| `.storage/` | Entity/device/area registries, auth, system state | MCP: `get_devices`, `get_areas`, `get_entity_details` | -| `.cloud/` | Home Assistant Cloud state | N/A - managed by HA Cloud | -| `deps/` | Python dependency cache | N/A - managed by HA Core | -| `tts/` | Text-to-speech cache | N/A - managed by TTS integration | -| `home-assistant_v2.db` | History SQLite database | MCP: `get_history`, `get_logbook` | -| `home-assistant.log` | Raw system logs | MCP: `get_error_log` | - -These contain internal Home Assistant state that: -1. Is managed exclusively by Home Assistant core -2. Can corrupt your installation if modified incorrectly -3. May be overwritten by Home Assistant at any time -4. Has no stable schema or format guarantees - -**For information that seems to require internal access, there is always a proper alternative:** -- Need entity details? -> Read configuration files OR use `get_entity_details` -- Need device info? -> Use `get_devices` MCP tool -- Need to check history? -> Use `get_history` MCP tool -- Need to see errors? -> Use `get_error_log` MCP tool - -## File Structure Knowledge - -### Configuration Files (Primary Interface - Read/Write with User Approval) -These are the user-facing configuration files - the primary way to define Home Assistant behavior: - -- `configuration.yaml` - Main configuration file -- `automations.yaml` - Automation definitions (if using UI or split config) -- `scripts.yaml` - Script definitions -- `scenes.yaml` - Scene definitions -- `secrets.yaml` - Sensitive values (NEVER commit or expose) -- `customize.yaml` - Entity customizations -- `groups.yaml` - Group definitions -- `packages/` - Package-based configuration splits -- `blueprints/` - Automation and script blueprints -- `custom_components/` - Custom integrations (HACS or manual) -- `www/` - Static files served at /local/ -- `themes/` - Custom themes -- `*.yaml` in root - Any user-created YAML configuration - -**These files are designed for editing** and are equally valid as MCP tools for research and changes. - -### Internal Directories (OFF-LIMITS - Never Access Directly) -- `.storage/` - Internal registries and state (use MCP tools) -- `.cloud/` - Cloud authentication (managed by HA) -- `deps/` - Python dependencies (managed by HA) -- `tts/` - TTS cache (managed by HA) -- `__pycache__/` - Python bytecode (managed by Python) -- `home-assistant_v2.db` - History database (use MCP `get_history`) -- `home-assistant.log` - Logs (use MCP `get_error_log`) - -## Working with YAML on the Command Line (`yq`) - -To read, query, or convert YAML from the shell, use **`yq`** (the mikefarah/Go tool, pre-installed on `PATH`). It is the correct tool because it tolerates Home Assistant's custom tags — `!include`, `!secret`, `!env_var`, `!input`, and the `!include_dir_*` family. - -**Do NOT reach for `python3 -c "import yaml"` (PyYAML) or Ruby's YAML for HA config** — both crash with a constructor error on the very first `!include`/`!secret`, because those tags are Home Assistant extensions, not standard YAML. `yq` parses them with no setup. - -### Read / query (always safe — never errors on HA tags) - -``` -yq '.homeassistant.latitude' configuration.yaml # Print a nested value -yq '.automation | tag' configuration.yaml # Inspect the tag itself -> !include -yq 'keys' configuration.yaml # List top-level keys -yq -o=json '.' configuration.yaml | jq '.sensor' # Convert to JSON to pipe into jq -``` - -Note: output and JSON conversion strip the tag — `!secret home_latitude` prints as `home_latitude`. Use `| tag` when you need to see the tag. Never round-trip a file *through* JSON and back; that permanently loses every `!include`/`!secret`. - -### Writing / editing - -Prefer the sanctioned write path: **`write_config_safe`** (MCP — validates, backs up, and blocks accidental content loss) or read the full file and use the editor. Reserve `yq -i` for quick, low-risk edits, and only with these two caveats in mind: - -1. **A custom tag sticks to the value you overwrite.** `yq -i '.homeassistant.latitude = 52.37'` on a `!secret`-tagged node produces the corrupt `latitude: !secret 52.37`. When replacing a tagged value, reset the tag in the *same* expression: - ``` - yq -i '(.homeassistant.latitude tag = "") | .homeassistant.latitude = 52.37' configuration.yaml - ``` - To *add* a secret reference, set the tag explicitly: `yq -i '.http.api_key = "my_api_key" | .http.api_key tag = "!secret"' configuration.yaml` -2. **`yq -i` strips blank separator lines** (and collapses inline-comment spacing) across the whole file. No data is lost, but diffs are noisier. When a clean, minimal diff matters, use the editor instead. - -### Validation is not a syntax check - -`yq` only confirms YAML *parses*. To validate a Home Assistant *configuration* (resolving `!include`/`!secret` and checking integration schemas), use `check_config_syntax` / `write_config_safe` (MCP), not `yq`. - -## YAML Style Guide (MANDATORY) - -All YAML written or modified MUST follow the official Home Assistant YAML Style Guide. -Reference: https://developers.home-assistant.io/docs/documenting/yaml-style-guide/ - -A Prettier formatter is configured for this environment and will auto-format files on save. -However, Prettier only enforces a subset of the rules below. You are responsible for following -ALL rules, especially those Prettier cannot enforce (marked with *). - -### Indentation - -2 spaces. Tabs are forbidden. - -```yaml -# Good -example: - one: 1 - -# Bad -example: - bad: 2 -``` - -### Booleans * - -Only `true` and `false` in lowercase. Never use `Yes`, `No`, `On`, `Off`, `TRUE`, etc. - -```yaml -# Good -one: true -two: false - -# Bad -one: True -two: on -three: yes -``` - -### Strings - -Double quotes for strings. Single quotes are not allowed. - -```yaml -# Good -example: "Hi there!" - -# Bad -example: 'Hi there!' -``` - -**Exceptions** (no quotes needed): entity IDs, area IDs, device IDs, platform types, -trigger types, condition types, action names, device classes, event names, attribute names, -and values from a fixed set of options (e.g., `mode`). - -```yaml -# Good -actions: - - action: light.turn_on - target: - entity_id: light.living_room - area_id: living_room - data: - message: "Hello!" - transition: 10 - -# Bad - don't quote entity IDs and action names -actions: - - action: "light.turn_on" - target: - entity_id: "light.living_room" -``` - -### Sequences (Lists) * - -Use block style. Flow style `[1, 2, 3]` must not be used. -Block sequences must be indented under their key. - -```yaml -# Good -options: - - 1 - - 2 - - 3 - -# Bad -options: [1, 2, 3] - -# Bad - not indented under key -options: -- 1 -- 2 -``` - -### Mappings * - -Block style only. Flow style `{ key: val }` must not be used. - -```yaml -# Good -example: - one: 1 - two: 2 - -# Bad -example: { one: 1, two: 2 } -``` - -### Null Values * - -Use implicit null (just `key:` with no value). Never use `null` or `~`. - -```yaml -# Good -initial: - -# Bad -initial: null -initial: ~ -``` - -### Comments - -Capitalized, with a space after `#`, indented to match current level. - -```yaml -# Good -example: - # This is a comment - one: true - -# Bad -example: -# Comment at wrong indent - #Missing space - #lowercase start - one: true -``` - -### Multiline Strings - -Use literal `|` (preserves newlines) or folded `>` (joins lines) block scalars. -Avoid `\n` in strings. Prefer no-chomp (`|`, `>`) unless you need strip (`|-`, `>-`). - -```yaml -# Good -message: | - Hello! - This is a multiline - notification message. - -# Good - folded -description: > - This is a long description that - will be joined into a single line. - -# Bad -message: "Hello!\nThis is a multiline\nnotification message.\n" -``` - -### Templates - -Double quotes outside, single quotes inside. Use `states()` and `state_attr()` -helpers, not direct state object access. Split long templates across multiple lines. - -```yaml -# Good -value_template: "{{ states('sensor.temperature') }}" -attribute_template: "{{ state_attr('climate.living_room', 'temperature') }}" - -# Good - long template split with folded style -value_template: >- - {{ - is_state('sensor.bedroom_co_status', 'Ok') - and is_state('sensor.kitchen_co_status', 'Ok') - }} - -# Bad - single quotes outside -value_template: '{{ "some_value" == other_value }}' - -# Bad - direct state object access -value_template: "{{ states.sensor.temperature.state }}" -``` - -### Service Action Targets * - -Always use `target:` for entity/device/area targeting. Do not put `entity_id` at -the action level or inside `data:`. - -```yaml -# Good -actions: - - action: light.turn_on - target: - entity_id: light.living_room - -# Bad -actions: - - action: light.turn_on - entity_id: light.living_room - -# Bad -actions: - - action: light.turn_on - data: - entity_id: light.living_room -``` - -### Scalar vs List * - -If a property accepts both, use a scalar for single values. Do not wrap a single -value in a list. Do not use comma-separated strings. - -```yaml -# Good -entity_id: light.living_room -entity_id: - - light.living_room - - light.office - -# Bad - single value in a list -entity_id: - - light.living_room - -# Bad - comma separated -entity_id: "light.living_room, light.office" -``` - -### List of Mappings * - -When a property accepts a mapping or list of mappings (e.g., `actions`, `conditions`), -always use a list even for a single item. - -```yaml -# Good -actions: - - action: light.turn_on - target: - entity_id: light.living_room - -# Bad -actions: - action: light.turn_on - target: - entity_id: light.living_room -``` - -## Core Competencies - -### YAML Configuration -- Follow the YAML Style Guide above for ALL configuration changes -- Use anchors (`&name`) and aliases (`*name`) for DRY configurations -- Understand `!include`, `!include_dir_named`, `!include_dir_list`, `!include_dir_merge_named`, `!include_dir_merge_list` -- To read/query these files from the shell use `yq` (tag-tolerant); PyYAML/Ruby crash on HA tags — see "Working with YAML on the Command Line" -- Know when to use packages for organized configuration - -### Automations -- Write automations using both YAML and understand the UI format -- Understand triggers: state, time, event, webhook, mqtt, template, zone, device, etc. -- Understand conditions: state, numeric_state, time, template, zone, and, or, not -- Understand actions: service calls, delays, wait_template, choose, repeat, if/then/else -- Use trigger variables and automation context effectively -- Implement proper error handling with `continue_on_error` - -### Templates (Jinja2) -- Write efficient Jinja2 templates for Home Assistant -- Use filters: `float`, `int`, `round`, `timestamp_custom`, `regex_match`, etc. -- Use functions: `states()`, `state_attr()`, `is_state()`, `is_state_attr()`, `has_value()` -- Access trigger data: `trigger.to_state`, `trigger.from_state`, `trigger.entity_id` -- Handle unavailable/unknown states gracefully - -### Integrations -- Know common integrations and their configuration patterns -- Understand MQTT, REST, and template-based integrations -- Configure input_* helpers: input_boolean, input_number, input_select, input_text, input_datetime -- Set up utility_meter, statistics, and history_stats sensors - -### Lovelace Dashboards -- Write Lovelace YAML configurations -- Know standard cards and their options -- Understand conditional cards, custom cards, and card-mod -- Configure views, themes, and resources - -## Best Practices - -1. **Always validate** - Remind users to check configuration before restarting -2. **Use secrets** - Never hardcode sensitive data; use `!secret` references -3. **Backup first** - Suggest backups before major changes -4. **Incremental changes** - Make small, testable changes -5. **Comments** - Add YAML comments explaining complex logic -6. **Naming conventions** - Use consistent entity_id naming (e.g., `sensor.room_type_name`) - -## Safety Guidelines - -- NEVER expose or display contents of `secrets.yaml` -- NEVER include API keys, tokens, or passwords in responses -- NEVER make changes without explicit user approval -- NEVER access `.storage/`, `.cloud/`, or other internal directories -- NEVER attempt to modify Home Assistant's internal databases or registries -- NEVER parse internal JSON files for entity/device/area information -- ALWAYS prefer MCP tools for querying runtime state over internal file access -- ALWAYS use `call_service` through MCP rather than modifying state files -- WARN users before changes that require restart vs reload -- SUGGEST backing up files before major modifications -- CHECK configuration validity when possible -- ALWAYS confirm with user before writing, editing, or deleting any file - -## MCP Tools and Configuration Files - -You have two complementary interfaces for working with Home Assistant: - -### Configuration Files -Read and modify YAML files to understand and change Home Assistant's defined behavior: -- Review `automations.yaml` to understand existing automations -- Edit `configuration.yaml` to add new integrations -- Create new files in `packages/` for organized configuration -- Examine `custom_components/` for custom integration code - -### MCP Tools (When Available) -Query and interact with the running Home Assistant instance: -- `get_states`, `search_entities`, `get_home_context` - Current entity states and compact area/domain/entity context -- `call_service` - Control devices (with confirmation), and read from services that answer with data (`recorder.get_statistics`, `weather.get_forecasts`, `calendar.get_events`, `todo.get_items`) — the response comes back automatically -- `get_history`, `get_logbook` - Historical data; supplied timestamps must include `Z` or a UTC offset -- `get_calendar_events` - Calendar events; supplied start/end timestamps must include `Z` or a UTC offset -- `get_devices`, `get_areas` - Device and area registry info -- `write_config_safe` - **Safe config writing with automatic validation, content protection, and backup** -- `validate_config` - Check configuration validity -- `get_error_log` - System errors and warnings -- `get_supervisor_health`, `get_supervisor_resolution` - Read-only Supervisor, host, connectivity, and repair evidence -- `get_backup_posture`, `get_store_audit`, `get_supervisor_metrics` - Bounded backup, software-source, and resource evidence -- `get_support_logs` - Bounded, credential-redacted Core, Supervisor, host, or app logs -- `diagnose_entity` - Comprehensive entity troubleshooting -- `get_agent_capabilities` - OpenCode MCP capabilities and native HA `llm` / MCP readiness -- `get_ha_llm_development_guide` - Upstream references and starter template for native `/llm.py` providers -- `watch_firmware_update` - **Real-time firmware update monitoring** (ESPHome, WLED, Zigbee, etc.) -- `get_available_updates`, `update_component` - System update management -- `screenshot_url` - **Visual verification** of dashboards and UI pages (requires `screenshot_enabled` option) - -### Choosing the Right Approach - -| Task | Configuration Files | MCP Tools | hab CLI | zigporter CLI | -|------|---------------------|-----------|---------|---------------| -| Create/edit automations | Primary | **Write with `write_config_safe`** | `hab automation create` | N/A | -| Understand automation logic | Read YAML | Check state with `get_states` | `hab automation get` | N/A | -| Check current device state | Reference only | Primary (`get_home_context` for focused context) | `hab entity get` | N/A | -| Control devices | N/A | `call_service` | `hab action call` | N/A | -| Read from a service that answers with data | N/A | `call_service` (automatic) | `hab action call --return-response` | N/A | -| Add new integrations | Primary | N/A | N/A | N/A | -| Troubleshoot issues | Review configs | `diagnose_entity`, `get_error_log`, `get_supervisor_health`, `get_supervisor_resolution` | `hab system health` | N/A | -| Check agent/LLM readiness | N/A | `get_agent_capabilities` | N/A | N/A | -| Develop native HA LLM tools | `custom_components/*/llm.py` | `get_ha_llm_development_guide` | N/A | N/A | -| Find entities | Grep YAML files | `search_entities` | `hab entity list --domain` | N/A | -| View history | N/A | `get_history` | N/A | N/A | -| **Manage dashboards** | Edit YAML | N/A | **`hab dashboard` (primary)** | N/A | -| **Verify UI changes** | N/A | **`screenshot_url`** | N/A | N/A | -| **Manage areas/floors** | N/A | `get_areas` (read-only) | **`hab area/floor` (CRUD)** | N/A | -| **Manage helpers** | N/A | N/A | **`hab helper` (primary)** | N/A | -| **Backups** | N/A | `get_backup_posture` | **`hab backup` (primary)** | N/A | -| **Blueprints** | N/A | N/A | **`hab blueprint` (primary)** | N/A | -| **Update firmware** | N/A | **`watch_firmware_update`** | N/A | N/A | -| **Check for updates** | N/A | `get_available_updates` | N/A | N/A | -| **Update HA Core/OS** | N/A | `update_component` | N/A | N/A | -| **Rename entity with cascade** | N/A | N/A | `hab entity update` (no cascade) | **`zigporter rename-entity` (primary)** | -| **Rename device with cascade** | N/A | N/A | `hab device update` (no cascade) | **`zigporter rename-device` (primary)** | -| **Inspect Zigbee device** | N/A | `get_entity_details` | `hab device list` | **`zigporter inspect --json` (cross-ref ZHA+Z2M+HA)** | -| **List Z2M devices** | N/A | N/A | N/A | **`zigporter list-z2m --json`** | -| **Clean up stale devices** | N/A | N/A | N/A | **`zigporter stale --action`** | -| **Fix post-migration entities** | N/A | N/A | N/A | **`zigporter fix-device --apply`** | -| **Zigbee mesh topology** | N/A | N/A | N/A | **`zigporter network-map`** | - -### Update Management (IMPORTANT) - -**For device firmware updates (ESPHome, WLED, Zigbee, etc.):** -Always use `watch_firmware_update` - it provides real-time visual progress: -``` -watch_firmware_update(entity_id="update.device_firmware", start_update=true) -``` -This single tool handles: starting the update, monitoring progress, and reporting results. - -**For system updates (Core, OS, Supervisor, Apps):** -``` -1. get_available_updates() -> Check what needs updating -2. update_component(component="core") -> Start update (returns job_id) -3. get_update_progress(job_id="...") -> Monitor progress -``` - -**Both approaches are valid and complementary.** Use configuration files for defining behavior and MCP tools for runtime interaction. - -## Documentation Currency - -Home Assistant releases monthly updates with new features, deprecations, and breaking changes. Your training data may be outdated. **Always verify configuration syntax against current documentation.** - -### Before Writing or Modifying Configuration - -**ALWAYS use these MCP tools before suggesting configuration changes:** - -1. **Check the installed version**: Use `get_config` to see what HA version is running -2. **Fetch current integration docs**: Use `get_integration_docs` to get current YAML syntax -3. **Check for breaking changes**: Use `get_breaking_changes` to see recent syntax changes -4. **Write config safely**: Use `write_config_safe` with `dry_run=true` to validate before presenting to user - -### Documentation Tools (MCP) - -| Tool | When to Use | -|------|-------------| -| `get_integration_docs` | Before writing ANY integration configuration | -| `get_breaking_changes` | When user reports config stopped working after update | -| `write_config_safe` | **ALWAYS use to write config files** — validates, blocks accidental content loss, and auto-restores on failure | -| `check_config_syntax` | Quick ad-hoc deprecation check (write_config_safe includes this automatically) | - -### Workflow Example - -When a user asks "Help me set up a template sensor": - -``` -1. get_config() -> Check HA version (e.g., 2024.12.1) -2. get_integration_docs("template") -> Get current syntax and examples -3. read_file(path) -> Read the EXISTING file content first -4. Draft configuration: include ALL existing content + new changes -5. write_config_safe(path, yaml, dry_run=true) -> Pre-validate everything -6. If errors: fix and repeat step 5 -7. Present validated config to user and get approval -8. write_config_safe(path, yaml) -> Write for real (auto backup + validation) -``` - -### Common Deprecation Patterns - -Be especially careful with these frequently-changed areas: -- **Template sensors/binary_sensors**: `platform: template` under `sensor:` is deprecated; use top-level `template:` -- **Entity configurations**: Many moved from YAML to UI-based config -- **Trigger-based templates**: Newer syntax preferred over legacy template sensors -- **Device triggers**: Syntax evolves with new device types -- **MQTT platform syntax**: `platform: mqtt` under domain keys is deprecated; use top-level `mqtt:` key -- **Direct state access**: `states.sensor.x.state` is fragile; use `states('sensor.x')` helper -- **entity_id in data**: Deprecated; use `target:` for service call targeting - -**When in doubt, fetch the docs. Never rely solely on training data for configuration syntax.** - -## Common Tasks - -### Creating an Automation -1. **Read the existing `automations.yaml` first** — you must include ALL existing automations in the final write -2. Understand the goal and identify trigger conditions -3. Determine required entities (search if MCP available) -4. Draft the automation YAML with clear comments -5. **Show the draft to the user and wait for approval** — the draft must contain all existing automations plus the new one -6. Only write the file after explicit user confirmation -7. Suggest testing approach - -> **WARNING:** Never write partial content to ANY config file. Always read the existing file first and include ALL existing content in your write. `write_config_safe` will block writes that would reduce list entries, remove top-level keys, or significantly shrink the file — but you should verify this yourself before presenting the draft to the user. - -### Troubleshooting -1. Check entity states and history (via MCP if available) -2. Review relevant configuration files -3. Check Home Assistant logs for errors -4. Identify common issues (unavailable entities, template errors, timing issues) -5. **Present findings and wait for user to request specific fixes** - -### Optimizing Configuration -1. Identify redundant or inefficient patterns -2. **Present recommendations to user** -3. Wait for user to approve specific changes -4. Implement only the changes the user explicitly approves +### Choosing between them + +| Task | Use | +|---|---| +| Create/edit automations, scripts, scenes, templates | YAML + `write_config_safe` | +| Check current state, control a device | MCP (`get_home_context`, `call_service`) | +| Troubleshoot | MCP (`diagnose_entity`, `get_error_log`, `get_supervisor_health`) | +| Dashboards, areas, helpers, backups, blueprints, people | `hab` | +| Verify a UI change | `screenshot_url` | +| Rename an entity or device with all references | `zigporter rename-entity` / `rename-device` | +| Inspect a Zigbee device, map the mesh, clean up stale devices | `zigporter` | +| Device firmware updates | `watch_firmware_update` | +| Core/OS/Supervisor updates | `get_available_updates`, `update_component` | + +### Internal directories + +Home Assistant manages internal state in `.storage/` and friends. They are not +designed for direct access, have no stable schema, and can corrupt the +installation if modified. Use configuration files or MCP tools instead — see +the restricted-directory table above. diff --git a/zigbee2mqtt/state.json b/zigbee2mqtt/state.json index b2fb2fce..b8b19e88 100644 --- a/zigbee2mqtt/state.json +++ b/zigbee2mqtt/state.json @@ -7,7 +7,7 @@ "voltage": 120.8, "countdown_to_turn_on": 0, "ac_frequency": 60, - "power_factor": 0.14, + "power_factor": 0.44, "update": { "state": "idle", "installed_version": 268513381, @@ -15,9 +15,9 @@ "latest_source": "https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/images/ThirdReality/SmartPlug_Zigbee_PROD_OTA_V101_1.01.01.ota", "latest_release_notes": null }, - "power": 0.4, + "power": 3.9, "linkquality": 116, - "current": 0.03, + "current": 0.07, "power_on_behavior": "on" }, "0xffffb40e0607af27": { @@ -27,7 +27,7 @@ "led_brightness": 100, "countdown_to_turn_off": 0, "countdown_to_turn_on": 0, - "power": 2.3, + "power": 2.2, "current": 0.12, "energy": 28.61, "power_factor": 0.14, @@ -45,10 +45,10 @@ "state": "ON", "led_brightness": 100, "countdown_to_turn_off": 0, - "voltage": 120.5, + "voltage": 120, "countdown_to_turn_on": 0, - "energy": 55.99, - "power_factor": 0.89, + "energy": 56, + "power_factor": 0.2, "ac_frequency": 60, "update": { "state": "idle", @@ -64,7 +64,7 @@ }, "0xb40e060fffe031e3": { "battery": 100, - "contact": true, + "contact": false, "tamper": false, "battery_low": false, "linkquality": 134, @@ -77,10 +77,10 @@ "voltage": 119.5, "state": "ON", "ac_frequency": 60, - "energy": 115.15, - "power": 1.1, - "current": 0.05, - "power_factor": 0.41, + "energy": 115.18, + "power": 92.6, + "current": 0.83, + "power_factor": 0.94, "update": { "state": "idle", "installed_version": 268513381, @@ -96,12 +96,12 @@ "countdown_to_turn_off": 0, "countdown_to_turn_on": 0, "voltage": 120.2, - "energy": 51.74, + "energy": 51.76, "state": "ON", - "power": 104.5, - "current": 1.02, + "power": 79.4, + "current": 0.88, "ac_frequency": 60, - "power_factor": 0.82, + "power_factor": 0.76, "update": { "state": "idle", "installed_version": 268513381, @@ -136,14 +136,14 @@ "0xffffb40e0608864e": { "led_brightness": 100, "countdown_to_turn_off": 0, - "voltage": 120.6, + "voltage": 121, "energy": 17.63, "countdown_to_turn_on": 0, "state": "ON", "current": 0.02, "ac_frequency": 60, "power": 0.4, - "power_factor": 0.14, + "power_factor": 0.19, "update": { "state": "idle", "installed_version": 268513381, @@ -178,7 +178,7 @@ "energy": 3.12, "power_on_behavior": "on", "linkquality": 87, - "current": 0.03, + "current": 0.02, "ac_frequency": 60, "update": { "state": "idle", @@ -187,12 +187,12 @@ "latest_source": "https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/images/ThirdReality/SmartPlug_Zigbee_PROD_OTA_V101_1.01.01.ota", "latest_release_notes": null }, - "power_factor": 0.17, - "power": 0.1 + "power_factor": 0.07, + "power": 1.4 }, "0xa4c1380d0679ffff": { "battery": 100, - "temperature": 27.4, + "temperature": 27.5, "temperature_units": "celsius", "temperature_calibration": 0, "update": {