Best practices for Home Assistant automations, helpers, scripts, and device controls. TRIGGER THIS SKILL WHEN: - Creating or editing HA automations, scripts, or scenes - Writing automation conditions or triggers - Creating template sensors or binary sensors - Using wait_template or wait_for_trigger - Choosing between device triggers and state triggers - Selecting automation modes (single/restart/queued/parallel) - Setting up Zigbee button/remote automations (ZHA or Zigbee2MQTT) - Deciding whether to use a built-in helper vs template sensor SYMPTOMS THAT TRIGGER THIS SKILL: - Agent defaults to Jinja2 templates where native constructs exist - Agent creates template sensors for simple aggregation (sum/min/max/mean) - Agent uses template conditions instead of native state/numeric_state conditions - Agent uses wait_template instead of wait_for_trigger - Agent uses device_id instead of entity_id in triggers/actions - Agent chooses wrong automation mode (e.g., single for motion lights)
View on GitHubskills/home-assistant-best-practices/SKILL.md
February 1, 2026
Select agents to install to:
npx add-skill https://github.com/homeassistant-ai/skills/blob/main/skills/home-assistant-best-practices/SKILL.md -a claude-code --skill home-assistant-best-practicesInstallation paths:
.claude/skills/home-assistant-best-practices/# Home Assistant Best Practices
**Core principle:** Use native Home Assistant constructs wherever possible. Templates bypass validation, fail silently at runtime, and make debugging opaque.
## Decision Workflow
Follow this sequence when creating any automation:
### 1. Check for native condition/trigger
Before writing any template, check `references/automation-patterns.md` for native alternatives.
**Common substitutions:**
- `{{ states('x') | float > 25 }}` → `numeric_state` condition with `above: 25`
- `{{ is_state('x', 'on') and is_state('y', 'on') }}` → `condition: and` with state conditions
- `{{ now().hour >= 9 }}` → `condition: time` with `after: "09:00:00"`
- `wait_template: "{{ is_state(...) }}"` → `wait_for_trigger` with state trigger
### 2. Check for built-in helper
Before creating a template sensor, check `references/helper-selection.md`.
**Common substitutions:**
- Sum/average multiple sensors → `min_max` integration
- Binary any-on/all-on logic → `group` helper
- Rate of change → `derivative` integration
- Cross threshold detection → `threshold` integration
- Consumption tracking → `utility_meter` helper
### 3. Select correct automation mode
Default `single` mode is often wrong. See `references/automation-patterns.md#automation-modes`.
| Scenario | Mode |
|----------|------|
| Motion light with timeout | `restart` |
| Sequential processing (door locks) | `queued` |
| Independent per-entity actions | `parallel` |
| One-shot notifications | `single` |
### 4. Use entity_id over device_id
`device_id` breaks when devices are re-added. See `references/device-control.md`.
**Exception:** Zigbee2MQTT autodiscovered device triggers are acceptable.
### 5. For Zigbee buttons/remotes
- **ZHA:** Use `event` trigger with `device_ieee` (persistent)
- **Z2M:** Use `device` trigger (autodiscovered) or `mqtt` trigger
See `references/device-control.md#zigbee-buttonremote-patterns`.
---
## Critical Anti-Patterns
| Anti-pattern | Use instead | Why | Reference