HA OpenCode - An addon to plug opencode AI into your Home Assistant

Adding 2 vacuum cards (which failed) to a dashboard is not complex and the user could probably do it faster by just using the normal GUI.

Making automations instead is a whole lot trickier with a huge number of possible pitfalls.
There is a reason why only a limited set of automations can be made through the GUI.

Haha! That was not the best demo I’ve seen. :see_no_evil:
I wish I’d knew about this beforehand…

I think the particular issue can be attributed to the free tier LLM. It is quite simple…

But, it does show what some in this thread has made a point of, that this tool can never fully be trusted! :wink:

1 Like

I’m using opencode to build HA Addons for my HomeAssistant on a boat. Works like a charm. But I’m not running opencode on the HomeAssistant directly, I run it on my Labtop in a container and give it ssh access to HomeAssistant. Sure, it can brick your installation, sure it can be a security nightmare and it’s as powerful as running it on HomeAssistant directly.

I was thinking about doing exactly this and googling if it already exists, brought me here.

I think this can be a great tool you did and it’s exactly each users responsibility to use it or not use it. Just don’t come back crying, when it bricks your installation! There are other Addons out there that can do damage to your installation in many ways. If you want safe, use HomeKit or whatever other golden cage.

In general, AI is very capable, when used correctly and guided. In my case, I know what I want it to do and what the result should look like and that helps to write specific prompts that lead to clean results.
I think the fact that it can get things wrong when running unchecked by people who have no idea what they are doing, does not justify calling out people for using AI and ban it or condemning all code written by AI.

Interesting. I did some quick tries in plan mode with a local ollama qwen3.5 27b - it actually does nothing :smiley: So when prompting anything, it just comes back to me with general information like that it is in plan mode and asks me what i want to do, but maybe can not find my prompt input in all the context it has(?).

Using opencode locally with a git clone of my /config and a SKILL.md like this works pretty ok:

---
name: home-assistant-config
description: >
  Use this skill whenever working with Home Assistant configuration files in /config.
  Triggers on any task involving HA YAML configs, custom integrations, automations,
  scripts, lovelace dashboards, secrets, or any files under the /config directory.
  Use this skill when editing, creating, debugging, or explaining Home Assistant files,
  even if the user just mentions "HA", "home assistant", "config folder", or "custom_components".
---

# Home Assistant /config – File Handling Guide

## Directory Structure

/config/
├── configuration.yaml # Main HA config entry point
├── secrets.yaml # Sensitive values (API keys, passwords)
├── automations.yaml # Automations (or split into /automations/)
├── scripts.yaml # Scripts
├── scenes.yaml # Scenes
├── groups.yaml # Groups
├── customize.yaml # Entity customizations
├── ui-lovelace.yaml # Dashboard (if in YAML mode)
├── .storage/ # Internal HA state – DO NOT EDIT MANUALLY
├── custom_components/ # Custom integrations (HACS or manual)
│ └── <integration_name>/
│ ├── init.py
│ ├── manifest.json
│ └── *.py
├── www/ # Static files served at /local/
├── packages/ # Optional: modular config packages
└── blueprints/ # Automation/script blueprints


---

## Core Rules

### 1. YAML Syntax
- Home Assistant uses **YAML** for all config files.
- Indentation is **2 spaces** (never tabs).
- Strings with special characters (`!`, `{`, `:`) must be quoted.
- Multiline strings use `|` (literal) or `>` (folded).

```yaml
# Correct
name: "My Automation: Test!"
message: >
  This is a long
  folded message.

# Wrong – tabs or inconsistent indent will break HA
name:	"My Automation"   # tab used!

2. secrets.yaml

  • Never hardcode passwords, tokens, or API keys directly.
  • Reference via !secret <key>:
# In configuration.yaml or any config file:
api_key: !secret my_api_key

# In secrets.yaml:
my_api_key: abc123xyz

3. Splitting Config Files

Use !include to split large configs:

# configuration.yaml
automation: !include automations.yaml
script: !include scripts.yaml
# Include all yaml files from a folder:
automation manual: !include_dir_list automations/

custom_components – Structure & Rules

Every custom integration under /config/custom_components/<name>/ requires:

manifest.json

{
  "domain": "my_integration",
  "name": "My Integration",
  "version": "1.0.0",
  "documentation": "https://github.com/...",
  "requirements": ["some_package>=1.0.0"],
  "dependencies": [],
  "codeowners": ["@github_user"],
  "iot_class": "local_polling"
}

Important for requirements:

  • Use >= instead of == where possible to avoid version conflicts.
  • Example: "matplotlib>=3.7.0" instead of "matplotlib==3.9.2".
  • HA installs requirements via pip into its internal venv on startup.
  • If a requirement fails, the integration will not load and HA logs the error.

init.py (minimal example)

from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry

DOMAIN = "my_integration"

async def async_setup(hass: HomeAssistant, config: dict) -> bool:
    hass.data.setdefault(DOMAIN, {})
    return True

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    return True

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    return True

Editing Best Practices

Before Editing

  1. Check HA is not running critical automations – changes take effect on restart.
  2. Backup first if making structural changes:
    • HA UI: Settings → System → Backups
    • Or copy the file before editing.

Validation

After editing YAML, always validate before restarting:

  • HA UI: Developer Tools → YAML → Check Configuration
  • Or via CLI (if SSH add-on is installed):
    ha core check
    

Applying Changes

Change type Required action
configuration.yaml Full restart or “Reload” in UI
automations.yaml Developer Tools → Automations → Reload
scripts.yaml Developer Tools → Scripts → Reload
custom_components/ Full HA restart required
secrets.yaml Full restart required
Lovelace YAML Refresh browser (F5)

Common Patterns

Automation (automations.yaml)

- id: "unique_id_001"
  alias: "Turn on light at sunset"
  trigger:
    - platform: sun
      event: sunset
      offset: "-00:30:00"
  action:
    - service: light.turn_on
      target:
        entity_id: light.living_room

Template Sensor (configuration.yaml)

template:
  - sensor:
      - name: "Outside Temp Rounded"
        state: "{{ states('sensor.outside_temp') | round(1) }}"
        unit_of_measurement: "°C"

Input Boolean (configuration.yaml)

input_boolean:
  guest_mode:
    name: Guest Mode
    icon: mdi:account-multiple

.storage – Never Edit Manually

The .storage/ directory contains HA’s internal runtime state (entity registry, device registry, etc.). Never edit these files manually unless you know exactly what you are doing. Corruption here can break your entire HA instance. Always restore from backup if something goes wrong.


Debugging Tips

  • Logs: Settings → System → Logs or /config/home-assistant.log
  • Template testing: Developer Tools → Template
  • Service calls: Developer Tools → Services
  • State inspection: Developer Tools → States
  • Integration errors appear at startup in the logs with the domain name.

File Encoding & Line Endings

  • Always use UTF-8 encoding.
  • Use Unix line endings (\n), not Windows (\r\n).
  • YAML is whitespace-sensitive – trailing spaces can cause issues.
Any thoughts on why the addon ghosts me? :sweat_smile:

So you’re AI vegetarian then, not AI vegan? :star_struck:
It’s the gluttons I worry about. Deeply.

Read the comments too…

FYI, someone has vibe-coded a kind of related project currently called “Home Assistant Cowork”:

You can read more about the ideas behind that here in his announcement on Reddit:

Make that “it’s” announcement, now deleted, as the post, and army of subsequent bot comments were clearly not of human origin.

@magnus.overli FYI,you and others who might want to have an official Home Assistant CLI some day should be interested in this new roadmap tracker from the Open Home Foundation → Offer an official Home Assistant CLI · Issue #98 · OpenHomeFoundation/roadmap · GitHub

It's been a while....
Thanks to everyone that is using the addon, and thank you to everyone that is contributing with issues, ideas, and even a PR!

Just today I had a great time placing my trust in OpenCode, backed by GPT 5.5, and thought I would share the experience... So here is a little success story! :slight_smile:

This might interest you @Hedda...

A Small ZBT-2 Firmware Success Story

The short version: I used OpenCode, backed by GPT 5.5, to help build and flash a self-built firmware image for a Home Assistant Connect ZBT-2.

The slightly longer version is what made it interesting: this was not just “ask AI for a command and paste it into a terminal”. I let LLM-driven workflows handle the full engineering loop: research, source build guidance, tool comparison, firmware validation, flashing, troubleshooting, recovery, and final verification.

What I Was Trying To Do

I wanted to upgrade a Home Assistant Connect ZBT-2 from the HA-offered stable Zigbee NCP firmware:

7.5.1.0

to a self-built firmware image:

9.0.2.0

Another OpenCode/GPT session had already helped drive the firmware build process from source, using the Nabu Casa firmware builder project as the base:

A modified version of that project was used so the build could support newer versions of the tooling and inputs involved in the process. My instruction there was basically: use the newest verifiable SDKs, package versions, and build inputs, then iterate until we have a valid ZBT-2 Zigbee NCP image.

The resulting artifact was:

zbt2_zigbee_ncp_9.0.2.0_zbt2.gbl

Artifact Validation

Before flashing anything, the assistant validated the firmware metadata:

{
  "fw_type": "zigbee_ncp",
  "fw_variant": "zbt2",
  "ezsp_version": "9.0.2.0",
  "baudrate": 460800,
  "sdk_version": "2025.12.3"
}

That gave us confidence that this was actually a ZBT-2 Zigbee NCP image and that it used the expected ZBT-2 EZSP baudrate.

The version information I could verify from the generated GBL itself was ezsp_version: 9.0.2.0 and sdk_version: 2025.12.3. I am intentionally not listing exact versions for build dependencies that were not embedded in the firmware metadata.

Some additional details from inspecting the GBL:

File size: 250172 bytes
SHA256: 703de6b03166c0eedb0b24b80e129c2e2c6e2e5176dd865a143e51de3f22bc0b
GBL tags: HEADER, APP_INFO, PROGRAM_DATA2, METADATA, END
Program data start: 0x08006000
Program data size: 249940 bytes
Program data end: 0x08043054

Tooling Choice

I also have the Silicon Labs Flasher add-on installed, so the assistant investigated that first.

It found:

Silicon Labs Flasher add-on: 0.5.0
Bundled universal-silabs-flasher: 0.0.37
Manual flasher used: universal-silabs-flasher 1.1.0

The add-on’s bundled flasher did not include the newer documented ZBT-2 --profile zbt2 path. The newer upstream universal-silabs-flasher did, so we chose the newer manual flasher path instead of the add-on.

Flashing

The actual flash used the official ZBT-2 profile:

python -m universal_silabs_flasher \
  --device /dev/serial/by-id/<zbt2-device> \
  flash \
  --profile zbt2 \
  --firmware zbt2_zigbee_ncp_9.0.2.0_zbt2.gbl

Before running it, the assistant:

  • verified that ZHA was healthy,
  • verified the exact serial device,
  • verified the firmware metadata and checksum,
  • disabled ZHA to release the serial port,
  • and only then started the flash.

The flash completed successfully. No physical unplug/replug was required.

The Interesting Recovery Step

After rebooting/re-enabling ZHA, Home Assistant raised this:

Network settings do not match most recent backup

The repair diff showed that only the coordinator IEEE had changed. Accepting the new radio settings would likely have orphaned the existing Zigbee network, so the previous coordinator IEEE needed to be restored.

The built-in ZHA repair flow refused the write because it considered the IEEE rewrite destructive for this firmware. The assistant diagnosed this from the logs, then used the newer flasher directly:

python -m universal_silabs_flasher \
  --device /dev/serial/by-id/<zbt2-device> \
  --probe-methods ezsp:460800 \
  write-ieee \
  --ieee <previous-coordinator-ieee> \
  --force

After that, ZHA loaded cleanly and the repair issue disappeared.

Final State

ZHA: loaded
Installed firmware: 9.0.2.0
HA-advertised latest firmware: 7.5.1.0
ZHA repair issue: cleared
Physical unplug/replug: not needed

Why I Am Sharing This

The part I found genuinely impressive was not simply that the firmware was flashed. It was that I could trust the assistant to drive the process in a controlled way.

One LLM session iteratively drove a modified NabuCasa/silabs-firmware-builder setup to a completed firmware artifact. Another session then:

  • researched the correct flashing strategy,
  • compared flasher versions,
  • rejected the older add-on path for this specific case,
  • validated the firmware metadata,
  • controlled the Home Assistant integration state,
  • flashed the coordinator,
  • diagnosed the post-flash network mismatch,
  • recovered the coordinator identity,
  • and verified that the system returned to a clean state.

My role in the process was mostly setting the goal, defining the risk boundary, approving the few truly consequential actions, and being available to physically unplug/replug the adapter if needed.

The operational execution was handled by the assistants.

That is the kind of practical, high-trust workflow I hoped tools like this would make possible. :slight_smile:

EDIT:
And, yes.... The firmware works fine! No issues so far at least :crossed_fingers:

1 Like

For reference, I had OpenCode prepare a changelog based on the version I moved from and to:

Compact Changelog: 7.5.1.0 to 9.0.2.0

Version / Platform

  • 7.5.1.0: EmberZNet SDK 7.5 Rev 1, Gecko SDK Suite 4.5, EZSP 0x0D.
  • 9.0.2.0: Zigbee SDK 9.0 Revision 2, Simplicity SDK 2025.12.3, EZSP 0x12.

Major Protocol Changes

  • Added Zigbee 4.0 certification-ready stack support. (7.5.1.0 baseline: Zigbee R23 compliance)
  • Added BDB 3.1 support.
  • Added Zigbee 4.0 Trust Center extension behavior for coordinators/trust centers.
  • Added Zigbee 4.0 Dynamic Link Key-related joining behavior in SDK support.
  • Zigbee PRO R23 support remains present. (7.5.1.0 baseline: Zigbee R23 compliance)

NCP / Coordinator-Relevant Changes

  • Added Host/NCP Dynamic Hardware Configuration for PA calibration/auditing over EZSP.
  • Improved Host-NCP Inter-PAN filtering support.
  • Fixed Zigbee UART NCP + FreeRTOS hang/not-working issue.
  • Improved NCP reset/RSTACK timing handling in the newer SDK path.

Build / Optimization

  • Expanded GCC LTO use in Zigbee NCP-related builds. (7.5.1.0 baseline: limited, minimally tested GCC LTO support)
  • This may improve optimization characteristics, but it is not proof of better mesh range or speed.

Fixes Potentially Relevant To Real Networks

  • Fixed invalid APS frame-size packet assert cases.
  • Fixed malformed packet/bus-fault/assert paths inherited from older branches.
  • Fixed router rejoin behavior around competing networks/PANs.
  • Fixed APS duplicate rejection behavior.
  • Fixed broadcast sending with alias source IDs.
  • Fixed multiple Green Power-related table/token/packet issues.

Already Present In 7.5.1.0

  • Granular packet send failure status reporting was already present in 7.5.1.0, so it is not counted here as a new 9.0.2.0 change.
  • Network steering handling for excessive beacons was already fixed in 7.5.1.0, so it is not counted here as a new 9.0.2.0 change.

Known Cautions

  • Home Assistant still advertises 7.5.1.0 as latest for ZBT-2, so 9.0.2.0 is outside the official HA firmware channel.
  • 9.0.x has a known issue where large networks with more than 30 devices can have join failures if coordinator Secure Key Storage is enabled and PSA key slot count is not sized correctly.
  • Zigbee Classic Key Storage is deprecated in 9.0.x.
1 Like

Ok, after confguring a local qwen3.6 27b with ~150k context i have to add that this is for sure not frontier level but ridiculously useful.