Home Assistant · guest access

Give someone the porch light. Not your house.

Your sister is staying a week. She needs three things: the porch light, the guest room lamp, the coffee machine.

Today your options are to make her a Home Assistant account — which shows her every camera, every lock and every sensor you own, and which you have to remember to delete afterwards — or to hand over your phone, or to leave a note on the counter and hope.

A2HA gives you a third option: a link. Three big buttons, no app, no account, no login. It stops working on Sunday, or the moment you revoke it.

Guest room expires sun

This is the real thing — press one. On a guest's phone the lamp shows what's actually on in the house, read live from Home Assistant.

The guarantee

A guest only ever sends a number.

There is no text box on that page. There is nothing to type. Whatever arrives is a digit between one and nine, and it selects from actions you defined. That is the entire protocol, and it's why the rest of this is possible to promise.

Entity IDs, service names, your other pads None of it is in the page. There is nothing to enumerate and no list to walk.
Anything you didn't put on that pad One link reaches one pad. Not the next room, not the front door, not the cameras.
The link, after you're done with it Expiry and revocation are checked on every single tap, not at page load. Kill it mid-visit and it dies mid-visit.
Whether the light is actually on Read live from Home Assistant when the page opens — so nobody presses a button to find out.
The buttons, and the labels you wrote That's the whole payload.

Some smaller decisions that matter more than they look: opening the page fires nothing, because chat apps fetch links to build previews and pasting one into a group chat shouldn't turn on your lights. Share links are stored as a hash, so nobody — including the software — can recover one afterwards. A dead link returns a plain notice rather than a 404, so a forwarded link looks calm instead of alarming.

Let's address it

No model touches a button press.

You're on a Home Assistant forum. You've watched a hundred projects bolt a chatbot onto something that worked fine. So here it is plainly:

A guest pressing a button is: token → look up which slot → call Home Assistant. No inference, no API key, no network call to anyone but your own house.

Unplug the language model entirely and every pad keeps working. A house-sitter would never know. It's also why button presses cost nothing to run, no matter how many times someone taps.

There is an assistant, and it's optional. It exists because building a dashboard by hand is an afternoon of dragging cards, and renaming forty entities that arrived from an integration as sensor.0x00158d0004a1b2c3_battery is nobody's evening.

When you do talk to it, it asks Home Assistant first. Your own Assist pipeline parses "turn on the office lamp" locally and acts on it — free, and faster than a model deliberating about it. Only what Assist can't handle escalates. Every reply says which happened:

you › is the office lamp on?
HA › No, it's off.
you › build a kitchen panel with the lights and the kettle
LLM › Done — four cards. Want it as the wall screen's home?

The prefix isn't decoration. One of those cost nothing and one didn't, and you can't tell from the words.

The unglamorous half

The jobs you keep putting off.

Everything here goes through Home Assistant's own APIs, so what it makes shows up in the UI editor like anything you'd have built yourself. It is not a parallel system and it doesn't hold your config hostage.

Dashboards
Built from what's actually in the room. It checks which card types your install really renders — including custom ones from HACS — and refuses to invent ones that don't exist.
Automations
Written through the config API, editable afterwards in the UI like any other.
Tidying up
What's unavailable, what's duplicated, what hasn't reported in a month, what's named badly.
The small stuff
Helpers, a weather card, working out which automation fires at 3am.
Undo
Every destructive change is snapshotted first. Home Assistant keeps no history of its own, so this is the only rollback there is.

Where it runs

Home Assistant never needs a public URL.

The agent can join your tailnet and reach Home Assistant over WireGuard, which means the only thing facing the internet is the guest pad — and that only exposes buttons you chose. Your house stays where it is.

You can also skip the agent entirely. The pad server is a zero-dependency Node app with two environment variables. Run it on the same box as Home Assistant, behind whatever proxy you already have, and you have the guest-access feature with no cloud, no key and no running cost.

Licence
MIT. Yours to fork.
Dependencies
The pad server: none, just Node's standard library. The agent's CLIs: one package, ssh2, loaded only if you turn on YAML editing. No build step to rot.
Hosting
Pinata's free tier, self-hosted Hermes, or no agent at all.
Model
Your choice, including one running on your own hardware. Or none.
Data
Pads and share tokens live in a folder you can back up. Nothing phones home.

It started as one feature that kept earning its keep.

The guest pad came out of Fanad, where it was the thing people actually used. This lifts it out on its own, and adds the assistant for the configuration work — clearly separated, so you can take one and leave the other.