On this page
On this page
Mainstream messaging
Matrix encryption and verification
Enable end-to-end encryption for a Matrix account, verify the gateway device, and repair crypto state when it drifts.
Encryption and verification
In encrypted (E2EE) rooms, outbound image events use thumbnail_file so image previews are encrypted alongside the full attachment; unencrypted rooms use plain thumbnail_url. No configuration is needed - the plugin detects E2EE state automatically.
All openclaw matrix commands accept --verbose (full diagnostics), --json (machine-readable output), and --account <id> (multi-account setups). Output is concise by default.
verify status, verify bootstrap, and verify device use the running local
Gateway's account and crypto owner. Other commands on this page require stopping
the local Gateway through its service owner first, then restarting it afterward.
Account preparation and shutdown can persist crypto data, so offline commands
retain exclusive ownership through that cleanup. Unsupported Gateway versions
and failed routed requests never fall back to local writes.
For a managed installation, use the normal openclaw update flow. The updater stops and restarts the managed Gateway and updates the official npm Matrix plugin with OpenClaw. If separate Gateway or CLI installations share the account state, stop their older processes and upgrade those installations before resuming concurrent use. An older process does not honor the crypto-store owner lock.
The first upgrade still depends on the installed version completing its final save. The new version cannot recover keys that an older process failed to persist or retroactively detect that failure. Keys received after that process's last successful snapshot may be lost.
Once the upgraded version owns the account, a failed final save or abnormal process exit makes OpenClaw refuse another crypto owner. A small .owner.poisoned guard stays on disk after clean shutdown and must match a seal in the canonical SQLite snapshot. The seal is written after the final crypto snapshot and sync cursor; losing that final publication also blocks reuse. Guard presence alone does not mean the account is blocked. Missing or malformed guards for sealed snapshots require recovery.
Run openclaw matrix doctor inspect to list blocked account stores; openclaw doctor also reports them but --fix never clears this refusal. Preserve a copy of the state directory for investigation. Once all Gateway and CLI processes are stopped, inspect the canonical SQLite snapshot and any backup. If you accept that keys received after the last successful snapshot may be lost, run openclaw matrix doctor recover --account <id> --accept-snapshot-rollback, then restart the Gateway. Recovery requires exactly one blocked store for that account, an exclusive owner lock, and a SQLite snapshot that passes complete IndexedDB replay in isolation. It publishes a new guard and seal; it does not prove the snapshot contains the failed owner's latest keys. If the snapshot is absent/invalid or the account has multiple blocked stores, recovery refuses; seek storage-owner assistance. Do not delete .owner.poisoned manually. If Rust initialization fails, custody remains held until the process exits because backend teardown cannot be confirmed.
An invalid canonical SQLite snapshot also stops startup and prevents snapshot replacement, even without a blocked-owner marker. Missing metadata with leftover chunks, malformed metadata or payloads, missing chunks, and checksum failures are errors, not a new account. Preserve the account state and backups, stop all processes using it, and restore a valid backup or seek storage-owner assistance. Doctor recovery does not repair corrupt snapshots. Startup also replays the complete candidate snapshot in isolation before replacing retained account databases; invalid keys, schemas, or index constraints refuse startup without changing those databases.
Enable encryption
Bootstraps secret storage and cross-signing, creates a room-key backup if needed, then prints status and next steps. Useful flags:
--recovery-key-stdinreads a recovery key from stdin without exposing it in process arguments;--recovery-key <key>remains available for compatibility--force-reset-cross-signingdiscard the current cross-signing identity and create a new one (intentional use only)
For a new account, enable E2EE at creation time:
--encryption is an alias for --enable-e2ee. Both setup commands finish their Matrix client operations before saving the enabled config; restart the Gateway after the command completes. If bootstrap fails, the encryption setting is still saved; use the reported diagnostics and next steps to finish verification.
Setup preserves unrelated configuration changes made while it runs. If the selected account changes, setup leaves that newer configuration intact and asks you to review it and rerun the command.
Manual config equivalent:
Status and trust signals
With --include-recovery-key, text output confirms when a raw recovery key is available and directs you to add --json. Text output never prints the key itself; keep JSON output containing a recovery key private.
verify status reports three independent trust signals (--verbose shows all of them):
Locally trusted: trusted by this client onlyCross-signing verified: the SDK reports verification via cross-signingSigned by owner: signed by your own self-signing key (diagnostic only)
Verified by owner is yes only when Cross-signing verified is yes; local trust or an owner signature alone is not enough.
--allow-degraded-local-state returns best-effort diagnostics without preparing the Matrix account first; useful for offline or partially-configured checks.
Verify this device with a recovery key
Pipe the recovery key via stdin instead of passing it on the command line:
The command reports three states:
Recovery key accepted: Matrix accepted the key for secret storage or device trust.Backup usable: room-key backup can be loaded with the trusted recovery material.Device verified by owner: this device has full Matrix cross-signing identity trust.
It exits non-zero when full identity trust is incomplete, even if the recovery key unlocked backup material. In that case, finish self-verification from another Matrix client:
verify self waits for Cross-signing verified: yes before exiting successfully. Use --timeout-ms <ms> to tune the wait.
The literal-key form openclaw matrix verify device "<recovery-key>" also works, but the key ends up in shell history.
Bootstrap or repair cross-signing
The repair/setup command for encrypted accounts. In order, it:
- bootstraps secret storage, reusing an existing recovery key when possible
- bootstraps cross-signing and uploads missing public keys
- marks and cross-signs the current device
- creates a server-side room-key backup if one does not already exist
If the homeserver requires UIA to upload cross-signing keys, OpenClaw tries no-auth first, then m.login.dummy, then m.login.password (requires channels.matrix.password).
Useful flags:
--recovery-key-stdin(pair withprintf '%s\n' "$MATRIX_RECOVERY_KEY" | ...) or--recovery-key <key>--force-reset-cross-signingto discard the current cross-signing identity (intentional only; requires the active recovery key stored or supplied with--recovery-key-stdin)
Room-key backup
backup status shows whether a server-side backup exists and whether this device can decrypt it. backup restore imports backed-up room keys into the local crypto store; omit --recovery-key-stdin if the recovery key is already on disk.
OpenClaw reads prior edits to notify only newly mentioned recipients. If an edit reports that its history is not fully decrypted, restore the missing room keys with backup restore, then retry the edit. If those keys are unavailable, send a new message.
To replace a broken backup with a fresh baseline (accepts losing unrecoverable old history; can also recreate secret storage if the current backup secret is unloadable):
Add --rotate-recovery-key only when the previous recovery key should intentionally stop unlocking the fresh backup baseline.
Listing, requesting, and responding to verifications
Lists pending verification requests for the selected account.
Sends a verification request from this account. --own-user requests self-verification (accept the prompt in another Matrix client of the same user); --user-id/--device-id/--room-id target someone else. --own-user cannot combine with the other targeting flags.
For lower-level lifecycle handling - typically while shadowing inbound requests from another client - these commands act on a specific request <id> (printed by verify list and verify request):
| Command | Purpose |
|---|---|
openclaw matrix verify accept <id> |
Accept an inbound request |
openclaw matrix verify start <id> |
Start the SAS flow |
openclaw matrix verify sas <id> |
Print the SAS emoji or decimals |
openclaw matrix verify confirm-sas <id> |
Confirm that the SAS matches what the other client shows |
openclaw matrix verify mismatch-sas <id> |
Reject the SAS when the emoji or decimals do not match |
openclaw matrix verify cancel <id> |
Cancel; takes optional --reason <text> and --code <matrix-code> |
accept, start, sas, confirm-sas, mismatch-sas, and cancel all accept --user-id and --room-id as DM follow-up hints when the verification is anchored to a specific direct-message room.
Multi-account notes
Without --account <id>, Matrix CLI commands use the implicit default account. With multiple named accounts and no channels.matrix.defaultAccount, commands refuse to guess and ask you to choose. When E2EE is disabled or unavailable for a named account, errors point at that account's config key, for example channels.matrix.accounts.assistant.encryption.
Startup behavior
With encryption: true, startupVerification defaults to "if-unverified". On startup an unverified device requests self-verification in another Matrix client, skipping duplicates and applying a cooldown (24 hours by default). Tune with startupVerificationCooldownHours or disable with startupVerification: "off".
Startup also runs a conservative crypto bootstrap pass reusing the current secret storage and cross-signing identity. If bootstrap state is broken, OpenClaw attempts a guarded repair even without channels.matrix.password; if the homeserver requires password UIA, startup logs a warning and stays non-fatal. Already-owner-signed devices are preserved.
See Matrix migration for the full upgrade flow.
Verification notices
Matrix posts verification lifecycle notices into the strict DM verification room as m.notice messages: request, ready (with "Verify by emoji" guidance), start/completion, and SAS (emoji/decimal) details when available.
Incoming requests from another Matrix client are tracked and auto-accepted. For self-verification, OpenClaw starts the SAS flow automatically and confirms its own side once emoji verification is available - you still need to compare and confirm "They match" in your Matrix client.
Verification system notices are not forwarded to the agent chat pipeline.
Deleted or invalid Matrix device
If verify status says the current device is no longer listed on the homeserver, create a new OpenClaw Matrix device. For password login:
For token auth, create a fresh access token in your Matrix client or admin UI, then update OpenClaw:
Replace assistant with the account ID from the failed command, or omit --account for the default account.
Device hygiene
Old OpenClaw-managed devices can accumulate. List and prune:
Crypto store
Matrix E2EE uses the official matrix-js-sdk Rust crypto path with fake-indexeddb as the IndexedDB shim. Crypto state persists in the account's state/openclaw.sqlite database with restrictive file permissions. The pre-July crypto-idb-snapshot.json import is retired; see Matrix migration for recovery guidance.
Encrypted runtime state lives under ~/.openclaw/matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/ and includes the sync store, crypto store, recovery key, IDB snapshot, thread bindings, and startup verification state. When the token changes but the account identity stays the same, OpenClaw reuses the best existing root so prior state remains visible.
A single older token-hash root can be a normal token-rotation continuity path. If OpenClaw logs matrix: multiple populated token-hash storage roots detected, inspect the account directory and archive stale sibling roots only after confirming the selected active root is healthy. Prefer moving stale roots into an _archive/ directory over deleting them immediately.