xydac

Managing Home Assistant from a terminal conversation with Claude Code

6 min read

This is part 2 of my Home Assistant journey. In part 1 I wrote about turning a $21 ESP32 touchscreen into a wall-mounted control panel. What I didn’t mention is that almost the entire project was done through Claude Code. Not just the blog post. The actual firmware research, config files, YAML editing, deploying to Home Assistant over SSH, debugging MQTT, all of it.

At some point I realized I wasn’t really using the Home Assistant UI anymore. I was just telling Claude what I wanted and it would figure out the rest. So I leaned into it and built a proper workflow around it.

Here’s how that works.

The setup

My Home Assistant runs in a VirtualBox VM on my Mac. It’s got SSH access on port 22 with key-based auth, a Mosquitto MQTT broker, Frigate for cameras, and a handful of smart lights and sensors around the house.

Claude Code can reach all of it. It SSHs into the HA box to run commands, edit config files, restart services, check logs. It calls the HA REST API and WebSocket API to query entity states, trigger automations, and manage the device registry. It deploys config changes with scp and reloads the right component without needing a full restart.

The key pieces that make this work:

  1. SSH access to Home Assistant OS (ssh [email protected])
  2. A long-lived access token for the HA API (created in the HA UI under your profile)
  3. Two CLI tools that wrap the HA APIs so Claude can use them naturally
  4. A CLAUDE.md file that teaches Claude about my specific setup

The CLI tools

I adapted two tools from danbuhler/claude-code-ha that give Claude structured access to Home Assistant.

ha-api (REST API)

A bash script that wraps curl and jq. Good for quick state checks, service calls, and entity searches:

# Check a sensor value
./bin/ha-api state sensor.hallway_temperature
# sensor.hallway_temperature: 22.3

# Find all light entities
./bin/ha-api states light
# light.bedroom_light
# light.smart_bulb_a19_led_2
# light.smart_bulb_a19_led_3
# ...

# Toggle a light
./bin/ha-api call light turn_on '{"entity_id":"light.bedroom_light"}'

# Search for anything bedroom-related
./bin/ha-api search bedroom

# Get the last 48 hours of temperature readings
./bin/ha-api history sensor.hallway_temperature 48

It reads credentials from a .env.ha file in the project root:

HA_URL=http://homeassistant.local:8123
HA_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOi...

ha-ws (WebSocket API)

A Python script for deeper queries. The WebSocket API exposes things the REST API doesn’t, like the entity registry, device registry, areas, and related automations:

# List all entities with their platform and area
./bin/ha-ws entity list light

# Get full details on a specific entity, including related automations
./bin/ha-ws entity get light.bedroom_light

# List all devices
./bin/ha-ws device list

# Call a service with parameters
./bin/ha-ws call light.turn_on entity_id=light.bedroom_light brightness=255

# Check for pending updates
./bin/ha-ws states update

The REST tool is fast and good for simple things. The WebSocket tool is slower but gives you the full picture. Between the two, Claude has everything it needs to understand and control the system.

The CLAUDE.md file

This is the part that ties it all together. In the project root there’s a CLAUDE.md file that gives Claude context about my specific Home Assistant setup. It includes:

  • The HA IP address and version
  • SSH access details
  • What add-ons are running (Frigate, Mosquitto, etc.)
  • All the devices and the entities they use
  • How to deploy config changes
  • CLI tool usage examples
  • Remote command cheatsheets
  • Known issues and limitations

Every time I start a conversation, Claude already knows that my hallway temperature comes from a Nest thermostat, that the driveway light is light.smart_bulb_a19_led_2, that the display communicates over MQTT, and that I need to check disk space before running updates.

It’s like handing someone a complete runbook for your house before they start working on it.

What this actually looks like in practice

Here are some real things I’ve done entirely through conversation with Claude:

Writing automations

I told Claude I wanted all the lights to turn on at sunset. It wrote the automation YAML, deployed it to HA over SSH, and reloaded the automation component without restarting. When I later said “actually make it 30 minutes before sunset”, it found the automation, added the offset, re-deployed, and reloaded. The whole exchange was maybe 30 seconds.

Running updates

I asked Claude to take care of all pending updates. It checked what was available (HA Core, Frigate, HACS components), checked disk space first (because it knows from past experience that Docker overlay2 bloat can fill the disk), then installed them in the right order: frontend cards first, then add-ons, then Core last since that triggers a restart.

Debugging the display

When I was building the openHASP control panel from part 1, Claude was the one figuring out MQTT topic structures, writing the JSONL UI layout, creating the HA entity mapping config, and testing button states. When something didn’t work, it would check Mosquitto logs, verify entity states, and adjust the config.

Surviving a disk crisis

One day HA crashed hard. “Bad message” errors everywhere, Core wouldn’t restart. Claude SSHed in, figured out the disk was 99% full from Docker overlay2 layer accumulation (old images from past updates just pile up), ran a supervisor repair to clean things up, and got everything back online. Then we expanded the VirtualBox virtual disk from 17GB to 22GB so it wouldn’t happen again.

I genuinely don’t know how long that would have taken me to debug on my own. Docker overlay2 bloat inside a VirtualBox VM running Home Assistant OS is not exactly a well-documented failure mode.

Building the display config

The entire openHASP setup from part 1 was a conversation. I described what I wanted (buttons for lights, temperature readings, color-coded states) and Claude wrote the pages.jsonl, figured out the right MQTT mapping, created the HA YAML config with Jinja2 templates, and deployed it. When I wanted to add new buttons for the fountain and patio, it updated everything and re-deployed.

Lessons from doing it this way

The CLAUDE.md file is everything. Without it, every conversation starts from zero. With it, Claude knows your setup cold. Invest time in keeping it accurate. When you add a new device or change an IP address, update the file. It pays off immediately.

Two API tools beats one. The REST API is fast for simple state queries and service calls. The WebSocket API is needed for registry access and understanding relationships between entities. Having both means Claude picks the right tool for the job automatically.

SSH access is non-negotiable. A lot of HA management happens at the system level. Checking logs, restarting services, editing config files, managing backups. The API alone isn’t enough. Claude needs to be able to get into the box.

Let it learn from failures. When the disk crisis happened, I made sure the lessons got captured in CLAUDE.md. Now Claude checks disk space before updates and knows about Docker overlay2 bloat. That kind of institutional knowledge is exactly what makes this workflow get better over time.

The HA UI still has its place. I still use the HA dashboard for real-time monitoring and the mobile app for quick toggles when I’m away from my desk. But for anything that involves editing configs, writing automations, debugging, or system management, the terminal conversation is just faster.

What’s next

I’m looking at adding a cheap ESP32 as a Bluetooth presence detector so HA knows when I’m home. The display board can’t do it (no RAM for WiFi + BLE + display simultaneously), so it’ll be a separate $4 board running ESPHome with the bluetooth_proxy component.

The nice thing is that when I get around to it, I’ll probably just tell Claude what I want and it’ll figure out the ESPHome config, deploy it, set up the HA integration, and write the automation. Same workflow, different hardware.

The tools

Everything mentioned in this post:


If you’re running Home Assistant and you haven’t tried managing it through Claude Code, set up the two CLI tools and write a CLAUDE.md describing your setup. It’ll take maybe 20 minutes. After that, you might not open the HA settings page much.