66 lines
3.8 KiB
Markdown
66 lines
3.8 KiB
Markdown
# Home Assistant OpenCode Rules
|
|
|
|
You are working directly inside a live Home Assistant installation (`/homeassistant`).
|
|
|
|
## Critical Mandates & Approval Rules
|
|
|
|
1. **Read-Only by Default**: Only read files and query APIs when investigating. Never modify files or call state-changing services without explicit user confirmation.
|
|
2. **Explicit Confirmation**: Show the exact diff or file content to be written before making any change. Wait for user approval ("yes", "go ahead").
|
|
3. **One Change at a Time**: Apply minimal changes, report what changed, and verify before proceeding.
|
|
4. **No Unsolicited Work**: Do not refactor, clean up, or change unrelated code/files beyond the requested scope.
|
|
5. **Project Context Protocol**:
|
|
- Associate requests with a stable project ID in `PROJECTS.md` (e.g. `P013`).
|
|
- Read `PROJECTS.md` before starting work. Record durable context under the project ID.
|
|
- Never mark a project `Complete` unless the user explicitly confirms completion. Ask: "Should I close Pxxx?"
|
|
|
|
## Off-Limits & Restricted Paths
|
|
|
|
Never read, write, or access:
|
|
- `.storage/`, `.cloud/`, `deps/`, `tts/`
|
|
- `home-assistant_v2.db*`, `home-assistant.log*`
|
|
- `secrets.yaml` (never expose or log secret contents)
|
|
|
|
Use MCP tools (`get_devices`, `get_areas`, `get_entity_details`, `get_history`) or CLI tools (`hab`) instead of accessing internal storage or database files.
|
|
|
|
## Configuration & Architecture Gotchas
|
|
|
|
- **Directory Includes in `configuration.yaml`**:
|
|
- `automation`: Uses `!include_dir_merge_list automations/` -> Active automations are in `automations/`, **NOT** root `automations.yaml` (which is legacy/inactive).
|
|
- `script`: Uses `!include_dir_merge_named scripts/` -> Active scripts are in `scripts/`, **NOT** root `scripts.yaml`.
|
|
- `group`: Uses `!include_dir_merge_named group/` -> Active groups are in `group/`, **NOT** root `groups.yaml`.
|
|
- `packages`: Uses `!include_dir_named packages/`.
|
|
- `template`: Uses `!include_dir_merge_list templates/`.
|
|
- `sensor`: Uses `!include_dir_merge_list sensor/`.
|
|
|
|
## CLI & Tooling Reference
|
|
|
|
### Shell YAML Queries (`yq`)
|
|
- **Always use `yq`** (mikefarah/Go version) for CLI YAML processing. PyYAML and Ruby YAML crash on HA tags (`!include`, `!secret`).
|
|
- Example: `yq '.homeassistant.latitude' configuration.yaml`
|
|
|
|
### Home Assistant Admin (`hab` CLI)
|
|
- Pre-authenticated CLI tool for managing HA via terminal (`hab <command> --json`).
|
|
- Common commands:
|
|
- Entities & Devices: `hab entity list --domain light --json`, `hab device list --json`
|
|
- Automations/Scripts: `hab automation list --json`, `hab script list --json`
|
|
- Dashboards: `hab dashboard list --json`, `hab dashboard get <id> --json`
|
|
- Operations: `hab system health --json`, `hab backup create`
|
|
|
|
### Zigbee Toolkit (`zigporter` CLI)
|
|
- Handles cascade renames across automations, scripts, scenes, and Lovelace dashboards.
|
|
- Command: `zigporter rename-entity light.old light.new --apply` (Defaults to dry-run if `--apply` omitted).
|
|
- Note: `zigporter migrate` requires physical interaction and must NOT be run by AI.
|
|
|
|
### Safe Configuration Writing (MCP)
|
|
- Prefer `write_config_safe(file_path, content, dry_run=true)` to pre-validate before writing.
|
|
- Always read the target file first and preserve all existing content when writing.
|
|
|
|
## Mandatory YAML Style Rules
|
|
|
|
- **Indentation**: 2 spaces (no tabs).
|
|
- **Strings**: Double quotes (`"..."`). Exceptions: entity IDs, action names, area IDs, device classes, modes.
|
|
- **Booleans**: Lowercase `true`/`false` only. Never `on`/`off`/`yes`/`no` as YAML booleans.
|
|
- **Lists & Maps**: Block style only. Never flow style `[1, 2]` or `{key: val}`.
|
|
- **Action Targets**: Always use `target:` block (`target: entity_id: light.room`). Do not put `entity_id` inside `data:` or at root action level.
|
|
- **Templates**: Use `states('sensor.x')` and `is_state(...)` helpers. Never use direct state object access (`states.sensor.x.state`).
|