Reaching the door with your hands full is exactly when a key is hardest to find. This recipe opens the door for you. When your arrival signal moves from away to home, it unlocks the door, but only if the house was locked, so it responds to you actually arriving rather than firing while you are already inside.
What counts as arriving
The arrival signal is a tracked phone or person, which the Home Assistant companion app sets up for every phone signed in to it. There is no extra hardware to buy for this one, and nothing to pick from the device catalog.
A room presence sensor is deliberately not accepted, even though the catalog is full of good ones. A room sensor reports that something is moving in a room, which is not the same as somebody coming home, and the difference matters when the consequence is an exterior door unlocking. A pet, a robot vacuum, or a sensor misfiring should never open the front door.
An auto-unlock still trades a little security for convenience, and it is worth being clear-eyed about that. Pair it with the Auto Lock at Night recipe so the door that opened for you locks itself again later.
A lit welcome after dark
Coming home in the dark, the useful thing is not just an open door but a lit one. Pick an outdoor light and it comes on with the unlock so the step and the keyhole are lit, and pick indoor lights and the hallway is on as you walk in. Both only come on after dark, judged from the sun, so an afternoon arrival opens the door without switching lights on you do not need.
Files Selora AI's pipeline reads to install this recipe. The manifest declares roles, inputs, and integrations; the package files are Jinja-templated YAML applied to Home Assistant.
# Unlock on Arrival — unlock the door when a presence signal moves from away to
# home, but only when the house is locked.
#
# The presence role is the arrival signal; its off-to-on transition triggers
# the unlock. An "any lock is locked" guard makes the recipe act only on a real
# arrival to a secured house, which also keeps a twitchy sensor from re-firing
# while the house is already open. Optional outdoor and indoor lights come on
# with the unlock, gated to after dark by the sun.
slug: unlock-on-arrival
version: 1.0.0
title: Unlock on Arrival
tagline: The door opens when you get home to a locked house, and lights the way in after dark.
description: >-
Unlocks the door when your presence signal moves from away to home, and only
when a lock is currently locked, so it responds to a genuine arrival. Optional
outdoor and indoor lights come on with the unlock after dark.
author: Selora AI
released: "2026-08-28"
min_integration_version: "0.12.0"
tags: [security, locks, arrival]
roles:
# Locks to open on arrival — multi-select. kind lock. min_count 1.
- id: locks
title: Smart locks
kind: lock
min_count: 1
selection: required
description: >-
The locks that open when you arrive. Only a locked lock is opened.
# Arrival signal — the unlock trigger. kind device_tracker, whose not_home to
# home transition is what "someone arrived" actually means in HA, and which is
# bound to a person rather than a place. NOT a binary_sensor + occupancy room
# sensor: that is the detected/clear class, so a pet or a false positive would
# unlock the house. This role opens exterior locks, so narrowing what the
# wizard can offer is the guardrail rather than a warning in the description.
# Every home running the companion app has a device_tracker per phone.
# min_count 1.
- id: presence_sensors
title: Arrival signal
kind: device_tracker
min_count: 1
selection: required
description: >-
The person or phone whose arrival home unlocks the door. Any one of them
arriving triggers the unlock.
# Optional outdoor lights lit with the unlock after dark. kind light.
- id: outdoor_lights
title: Outdoor lights
kind: light
min_count: 0
selection: required
description: >-
Optional. Outdoor lights that come on with the unlock after dark. Leave
empty to skip.
# Optional indoor lights lit with the unlock after dark. kind light.
- id: indoor_lights
title: Entry lights
kind: light
min_count: 0
selection: required
description: >-
Optional. Hallway or entry lights that come on with the unlock after
dark. Leave empty to skip.
inputs:
# Whether the lights only come on after dark. When true, the light step is
# gated to sun below the horizon; when false, the lights come on whenever the
# door unlocks.
- id: lights_only_after_dark
type: boolean
label: Lights only after dark
description: >-
When on, the optional lights only come on if it is dark outside. When
off, they come on with every arrival unlock.
default: true
package_files:
- package/automations/arrival.yaml.j2
{# Unlock on Arrival.
Triggered by any tracked person or phone moving into home from anywhere. A
device_tracker is used rather than a room presence sensor because this
automation opens exterior locks: it has to be someone arriving, not something
moving in a hallway.
The "any lock is locked" OR condition means the recipe only acts on a genuine
arrival to a secured house, so it does not re-fire while the house is already
open. It unlocks every lock, then, when lights were picked, turns them on,
gated to sun below the horizon unless the after-dark option is turned off. #}
{% set lights = roles.outdoor_lights + roles.indoor_lights %}
automation:
- id: selora_recipe_{{ slug | replace('-', '_') }}_arrival
alias: "Unlock on Arrival: unlock"
description: >-
When a presence signal moves from away to home and the house is locked,
unlock the door and, after dark, light the way in.
mode: single
trigger:
{% for sensor in roles.presence_sensors %}
# Any transition into home, not only from not_home. A phone sitting in a
# named zone reads as that zone, so with sparse GPS updates it commonly
# goes Work straight to home and never passes through not_home at all;
# requiring that as the from state dropped exactly the arrivals this
# recipe exists for. unknown and unavailable are still excluded so the
# restore that follows a restart cannot unlock the door.
- platform: state
entity_id: {{ sensor }}
to: "home"
not_from:
- "unknown"
- "unavailable"
{% endfor %}
condition:
# not_from only filters the state strings it lists. An entity created
# straight into its trigger state reports from_state as null and slips
# past it, which happens on startup and on any integration reload. For an
# automation that opens exterior locks, require a real prior state so a
# reload cannot stand in for somebody coming home.
- condition: template
value_template: "{% raw %}{{ trigger.from_state is not none }}{% endraw %}"
- condition: or
conditions:
{% for lock in roles.locks %}
- condition: state
entity_id: {{ lock }}
state: "locked"
{% endfor %}
action:
- service: lock.unlock
target:
entity_id:
{% for lock in roles.locks %}
- {{ lock }}
{% endfor %}
{% if lights %}
{% if inputs.lights_only_after_dark %}
- if:
- condition: state
entity_id: sun.sun
state: "below_horizon"
then:
- service: light.turn_on
target:
entity_id:
{% for light in lights %}
- {{ light }}
{% endfor %}
{% else %}
- service: light.turn_on
target:
entity_id:
{% for light in lights %}
- {{ light }}
{% endfor %}
{% endif %}
{% endif %}