Repository navigation
Upgrading to 7.0
Lock Code Manager 7.0 replaces the engine that keeps your locks in sync. What you configure is unchanged — the same users, PINs, conditions, entities, actions and dashboards — but how LCM talks to each lock is new, and a few behaviours you can see have changed. The biggest ones:
- LCM never touches a code it didn't create. A lock that already holds codes in an entry's slots is refused rather than overwritten.
- A restart no longer rewrites PINs on locks that hide their codes.
- Locks that can't report their codes are recognised, and you are told which slots LCM will use on them.
- When LCM stops trying a slot, it stays stopped until you click Submit on the repair, change the user, or a fresh read shows the lock already matches. A slot the lock keeps changing back, or a PIN the lock refuses, waits for you.
There is nothing to migrate and nothing to search your automations for:
- Config entries stay at version 5. No migration runs, and nothing is renamed or renumbered.
-
No actions, entities or events are removed.
hard_refresh_usercodesgains an optionalforget_reportingfield. - Requirements are unchanged: Home Assistant 2026.9.0 or newer, and for Z-Wave JS locks a driver (zwave-js) of 15.24.3 or newer.
7.0 adds one storage file, .storage/lock_code_manager.core. To roll back to
6.0.x, restore the older version and delete that file. Taking a Home Assistant
backup before upgrading is still a good idea.
Each lock now has a single worker that handles every read, write, retry and pause for that lock, shared by every config entry that uses it. Things you may notice:
- Every write is checked. After setting or clearing a code, LCM reads that slot back. A slot only shows as in sync once the lock confirms it.
- Turning a user off and on quickly shows the slot as pending until the lock confirms it, instead of showing an unknown code for a while.
- Z-Wave JS writes are faster. The extra read the integration did after each write is gone; LCM's own read-back confirms it.
- An entry's entities no longer wait for its slowest lock to finish setting up.
- Debug logs show every exchange with a lock, with how long it took. See Troubleshooting: Debug Logs.
The sync_status attribute of the in sync sensors now takes only
in_sync, out_of_sync, syncing and suspended (and is absent while the
slot hasn't been read yet). pending_confirmation and loading are no longer
reported; a write waiting for the lock's confirmation reads syncing. If an
automation or template checks for either old value, update it.
Many locks (Matter, many Z-Wave locks) never show the PIN in a slot, only that there is one. Before 7.0, after a restart LCM couldn't tell whether those codes were its own, and wrote them again.
LCM now remembers what it wrote to each slot — as a salted fingerprint, never
the PIN itself — in .storage/lock_code_manager.core. After a restart, a
hidden code that matches is treated as in sync and left alone.
- Adding a lock that already holds codes in the entry's slots is refused, naming the slots: "Clear those slots on the lock, then add it again." Before, those codes were overwritten. A lock that can't be read is refused too, rather than added unchecked. This applies to the options flow and to reauth. See Adding and Removing Locks.
- New users go only in free slots. Allocation skips any slot that holds a code, on every provider.
- Turning a slot off or removing a user never touches a lock user without LCM's tag, on locks that have users (Z-Wave User Credential, Matter): only users carrying LCM's tag are cleared or deleted. One exception is kept for upgrades from before LCM tagged its users: when LCM writes a slot your configuration already uses, an untagged user already sitting in that slot is taken over and tagged rather than duplicated.
- Akuvox and Schlage no longer pull existing codes into LCM. Before, at setup and at a hard refresh, they tagged codes added outside LCM into LCM slots. Now such codes are left alone, like on every other provider. Codes LCM already tagged are not affected. To bring one of those people under LCM, add them as a user in LCM (LCM writes its own code), then delete their old code on the lock.
On Z-Wave User Credential and Matter locks, removing an LCM user now removes only the PIN LCM wrote:
- The lock user is deleted only if nothing else is left on it. If the person also has, say, a fingerprint added at the lock, the user is kept and loses LCM's tag.
- On Matter, only PINs created by Home Assistant's own fabric count as LCM's. A PIN added from another Matter controller is never removed.
- A user named just a number (or
lcm3) in the vendor's app is never mistaken for LCM's. LCM writes those short names only where its full tag can't be used: on Z-Wave, a short name counts as LCM's only on a lock whose name limit is too short forlcm:<slot>:; on Matter, only on a user Home Assistant's own fabric created.
Some locks never say what a slot holds — a Zigbee2MQTT lock answering
not_supported_255, or a ZHA lock answering status 0xFF. LCM now recognises
them:
- The setup, options, add-user and reauth flows tell you when a lock can't report its codes, which slots LCM will use, and that any keypad code in those slots will be replaced. Saving goes ahead.
- The lock codes card shows such slots as Not reported.
- LCM remembers, across restarts, whether a lock has ever reported a code. On
a lock that has, a slot it can't describe counts as taken. If a lock was
wrongly taken for one that can report, use
hard_refresh_usercodeswithforget_reporting: trueon it — see Services and Actions.
See Repair Issues for every repair.
-
Sync suspended and Code not removed: LCM stops trying the slot, and
Submit now means "try again". Changing the user (new PIN, turning them
off or on) also starts the slot over. LCM keeps checking the slot without
writing to it, and clears the repair itself once a fresh read shows the lock
already matches — for example after the radio link recovers, or after you
delete a code at the keypad. On Z-Wave JS locks, which LCM doesn't poll, that
check happens when you run
hard_refresh_usercodes. A push from the lock never clears it, since it may come from a cache. - A slot the lock keeps changing back (for example a keypad taking the code back) stays stopped until you click Submit or change the user, even if the lock later agrees.
- A suspended slot's repair names the cause when the lock or integration gave one.
- Re-paired locks. When a lock is re-paired under the same entity ID (for example a Zigbee2MQTT lock re-joined under the same name), LCM moves to the new device on its own. Two new repairs cover the edge cases: Check slots on re-paired lock names slots whose clear was dropped, and Reload Lock Code Manager to use re-paired lock asks for a reload. See Adding and Removing Locks.
- Unmanaged code → Clear on a lock that isn't answering now waits for the lock and clears the code when it is back.
The lock codes card never presents a configured PIN as if the lock had reported it. New states: Checking… (waiting for the lock to confirm the slot), Disabled on lock, Not reported, and hollow dots for a code whose value is unknown (hidden, or the lock didn't answer). A managed slot that is in sync on a lock that hides its codes shows LCM's PIN in italics, as configured rather than read.
The user card's per-lock status no longer shows Confirming; a write waiting for confirmation shows as Syncing.
- Z-Wave JS UI: a lock refusing a duplicate code is now recognised. Before, a lock that hides its codes could show in sync with a PIN it had refused; now the user is turned off with a Slot disabled repair.
- ZHA: a passing failure answer on a write is treated as no answer and retried, not as a refused PIN.
- Schlage and Akuvox: a validation error on a write is treated as a refused PIN (Slot disabled repair).
- Schlage: a new PIN is written only after the old code is deleted, so the old PIN can't stay working beside it. Availability comes from the lock entity instead of a full cloud read every 30 seconds.
- Zigbee2MQTT: a cached state republished by Zigbee2MQTT can no longer be mistaken for the lock's answer after a write.
- Matter: user names are capped at 9 bytes, so names with non-ASCII characters are shortened correctly.
- Check Settings → System → Repairs first. See Repair Issues.
- Debug logs and diagnostics: Lock Code Manager's diagnostics include each lock's state as the new engine sees it — whether the lock is answering, and each slot's status, hold and tries.
- To roll back, install 6.0.x and delete
.storage/lock_code_manager.core.
Getting Started
- Upgrading to 7.0
- Upgrading to 6.0
- Upgrading to 5.0
- Configuration Structure
- Adding and Removing Locks
- Migrating from keymaster
UI
Features
- Managing Guests and Rentals
- Services and Actions
- Blueprints
- Tracking lock state change events
- Using Condition Entities
- Unsupported Condition Entities
Advanced
Development
Troubleshooting
FAQ
Supported Integrations