feat(matrix): add Matrix channel integration#6
Open
theredspoon wants to merge 17 commits intosimple10:mainfrom
Open
feat(matrix): add Matrix channel integration#6theredspoon wants to merge 17 commits intosimple10:mainfrom
theredspoon wants to merge 17 commits intosimple10:mainfrom
Conversation
Scopes Matrix messaging integration as an alternative to Telegram. Covers plugin vs. sidecar approaches, Conduit self-hosted option, idempotency, open questions on OpenClaw plugin API and E2E encryption.
Wires in the @openclaw/matrix plugin as a first-class deploy concern:
- stack.yml.example: matrix: defaults block with all config options;
commented per-claw example (access_token env var pattern)
- docker-compose.yml.hbs: MATRIX_ENABLED always emitted; homeserver and
access_token emitted only when enabled (sensitive var guard)
- entrypoint.sh: idempotent plugin install at startup (filesystem check
before install, runs as node uid 1000 for correct ownership)
- openclaw/default/openclaw.jsonc: matrix channel block with env var
substitution, disabled by default via MATRIX_ENABLED=false
- build/pre-deploy.mjs: validateClaw checks homeserver + access_token
when matrix.enabled; matrix_enabled derived boolean for Handlebars;
MATRIX_HOMESERVER and MATRIX_ACCESS_TOKEN added to potentiallyEmptyVars
so openclaw.jsonc ${VAR} resolves cleanly when Matrix is disabled
- docs/MATRIX.md: operator setup guide (account, token, pairing, rooms,
E2EE, token rotation, troubleshooting)
- docs/PROPOSAL-MATRIX-CHANNEL.md: updated from initial draft to reflect
confirmed native plugin support and full implementation scope
Matrix sync state and E2EE crypto keys live in .openclaw/matrix/. Without this, a restore would lose the bot's device identity and require re-verification in all encrypted rooms. matrix_dir is conditionally populated (ls -d 2>/dev/null) so the tar command is unchanged for claws without Matrix enabled. Also updates the 06-backup.md "What Gets Backed Up" table.
Critical:
- pre-deploy: always include MATRIX_HOMESERVER and MATRIX_ACCESS_TOKEN in
empty-env-vars regardless of any claw's config. Previously computed against
only the first claw, breaking multi-claw stacks with heterogeneous Matrix
config (enabled on one claw, disabled on another).
- openclaw.jsonc: add @openclaw/matrix to plugins.allow and plugins.entries
(enabled via ${MATRIX_ENABLED}). Without this, a sync-deploy that rewrites
openclaw.json removes Matrix plugin allowance even when the plugin is
installed — and the entrypoint's directory-existence check prevents reinstall.
Moderate:
- entrypoint: change matrix plugin install failure from warning to hard error
(exit 1). Booting with MATRIX_ENABLED=true and a non-functional Matrix
channel is misleading; a clear failure is better than a silent degradation.
- MATRIX.md: fix deploy command (service name is <project>-openclaw-<claw>,
not just the claw key); fix E2EE section (encryption not rendered from
stack.yml — must edit per-claw openclaw.jsonc directly); update room config
section to clarify groups require openclaw.jsonc edit or Control UI.
- stack.yml.example: annotate which matrix fields are rendered into
docker-compose.yml vs which require direct openclaw.jsonc configuration.
…external Confirmed against a live OpenClaw installation: @openclaw/matrix ships bundled with OpenClaw (extensions dir is empty; matrix/ state dir exists). No install step is needed. Plugin key in config is "matrix" (unscoped), not "@openclaw/matrix". - entrypoint: remove the `openclaw plugins install @openclaw/matrix` block entirely - openclaw.jsonc: remove "@openclaw/matrix" from plugins.allow (not needed for bundled plugins); rename plugins.entries key from "@openclaw/matrix" to "matrix" - MATRIX.md: update §5 Deploy and Plugin install troubleshooting to reflect that the plugin is bundled and auto-loaded when MATRIX_ENABLED=true
Confirmed from live install: @openclaw/matrix is bundled with OpenClaw, not an external extension. Update all sections that assumed an install step was needed, that the plugin lives in ~/.openclaw/extensions/, or that the config key is "@openclaw/matrix". Update status to Implemented.
…ot bundled Reverts the incorrect inference from 40cae9b and e831726 that @openclaw/matrix is bundled with OpenClaw. The empty ~/.openclaw/extensions/ on the reference server was because OpenClaw was installed from a git checkout (local path ./extensions/matrix), not because the plugin ships with the binary. Source of truth: extensions/matrix/package.json blurb says "install the plugin to enable" and openclaw.install.npmSpec = "@openclaw/matrix" with defaultChoice = "npm". The plugin key "matrix" (unscoped) from openclaw.plugin.json is kept — that part was correctly identified. - Restore entrypoint.sh matrix plugin install block (exit 1 on failure, gosu node, directory-existence idempotency check) - Restore plugins.allow "matrix" entry in openclaw/default/openclaw.jsonc - Fix plugin comments in openclaw.jsonc (external, not bundled) - Fix docs/MATRIX.md §5 and "Plugin not loading" section - Fix docs/PROPOSAL-MATRIX-CHANNEL.md plugin model description throughout
Set deviceName to "OPENCLAW_GATEWAY" statically in openclaw.jsonc. userId is auto-generated by OpenClaw from the claw name — not configured here.
- §4: remove groups-in-stack.yml example (groups not rendered from stack.yml); point to openclaw.jsonc via cross-reference to Rooms section - Rooms section: fix duplicate 1. list items → 1/2/1 (linter requires 1/1/1) - Token rotation: fix service name to match correct pattern
614a31c incorrectly concluded the plugin was external based on package.json metadata. Live testing confirms it ships inside the Docker image at /app/extensions/matrix/ and loads without an install step. The entrypoint install block was creating a second copy at ~/.openclaw/extensions/@openclaw/matrix/, causing a "duplicate plugin id" warning and a load failure (wrong import paths in the installed copy). - Remove entrypoint matrix plugin install block - Remove "matrix" from plugins.allow (not needed for bundled plugins) - Update docs and proposal to reflect bundled model
…t template updates
Entrypoint: patch keyed-async-queue subpath regression (openclaw#32772),
install matrix plugin deps on first boot (openclaw#16031).
resolve-config-vars: coerce "${VAR}" whole-value patterns to native
booleans/numbers so MATRIX_ENABLED=true resolves to true, not "true".
Default template: set groupPolicy to "open", always load matrix plugin,
keep encryption off as safe default.
Gate Telegram channel on stack.yml telegram.enabled (default: true). When disabled, the channel block is stripped from the deployed openclaw.json so it doesn't appear in the Control UI. Same mechanism as matrix.enabled — resolve-config-vars strips disabled channels after resolving env vars.
When a channel ID env var (e.g. ADMIN_TELEGRAM_ID) is unset, ${VAR}
resolves to "", producing [""] in allowFrom arrays. Filter these out
so optional channels don't leave phantom empty entries.
The default template uses groupPolicy: open (respond in any joined room when mentioned), not allowlist. Updated docs to match and explain how to switch to allowlist if needed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@openclaw/matrixplugin — configured throughstack.yml, deployed viapre-deploy, with env var coercion and channel block stripping inresolve-config-vars.mjstelegram.enabled/matrix.enabledtoggles that gate credential emission in docker-compose and strip disabled channel blocks from the deployed config (so they don't appear in the Control UI)What's included
stack.yml.example— Matrix defaults (homeserver, enabled flag)pre-deploy.mjs— validation (homeserver + access_token required when enabled), derivedmatrix_enabled/telegram_enabledbooleansdocker-compose.yml.hbs— conditional env var emission for both channelsresolve-config-vars.mjs—${VAR}→ native boolean coercion, disabled channel block strippingentrypoint.sh— conditional Matrix plugin dependency installopenclaw/default/openclaw.jsonc— Matrix channel config templatedocs/MATRIX.md— setup guidedocs/TELEGRAM.md— updated with toggle docsTest plan
npm run pre-deploy:drywithmatrix.enabled: false— Matrix channel block stripped, secrets omittednpm run pre-deploy:drywithmatrix.enabled: true— channel block preserved, secrets emitted