Matrix Skill
Agentic Skills for Matrix, distributed as a Claude Code plugin. Three skills ship in this repo:
| Skill | Purpose | API surface |
|---|---|---|
| matrix-communication | Send / read / edit / react in chat rooms on behalf of a regular user, with full E2EE support, and follow a room live through a daemon | Matrix Client-Server API |
| matrix-administration | Operate a Synapse homeserver — snapshot rooms, rate room health, render a Graphviz map, force-join, promote, harden, deactivate, search history | Synapse Admin API |
| matrix-announcement | Compose scannable, structured Matrix announcements — release notes, digests, heads-ups, postmortems. HTML subset, type-tag system, glyph rules, and HTML-card-to-PNG templates. | Content guidance only — pairs with matrix-communication |
The three skills are independent — you can install the plugin and use any combination. matrix-communication and matrix-administration share ~/.config/matrix/config.json. matrix-announcement has no runtime; it's reference material the agent reads while composing messages.
What is an Agentic Skill? Platform-agnostic instructions and tools that AI coding agents can use. This skill is packaged as a Claude Code plugin but follows the open Agentic Skills specification.
matrix-communication — Features
Follow a room while you work. matrix-watchd.py holds the E2EE store, syncs,
decrypts, and appends every event of a watched room to a per-room JSONL log.
matrix-watch.py follows that log without opening the store, so any number of
readers run at once — an agent can stay current with a room, post its status and
answer, without a second process ever touching the encryption state.
- Send messages to any joined Matrix room
- Rich formatting — bold, italic, code, strikethrough, spoilers, lists, blockquotes
- Real mentions —
--mention '@user:server'setsm.mentions, which is what notifies a client, and renders that name in your text as a pill; a plain@namewithout--mentiondoes neither - Smart link shortening — Jira, GitHub, GitLab URLs become readable links
- Room links —
#room:serverbecomes a clickable room link - Code blocks — syntax-highlighted multi-line code
- Emotes —
/mestyle action messages (--emote) - Thread replies — keep discussions organized (
--thread) - Reactions — add emoji reactions to messages
- Edit and redact — modify or delete messages you sent
- Visual effects — confetti, fireworks, snowfall (Element clients)
- List rooms to find the right destination
- Read messages — both unencrypted and E2EE decryption
- Bot prefix — optional 🤖 prefix for automated messages
- Device verification — SAS emoji verification for E2EE
- One writer per store — every path that opens the E2EE store takes an exclusive lock, so two processes cannot corrupt it
Installation
Marketplace (Recommended)
Add the Netresearch marketplace once, then browse and install skills:
# Claude Code
/plugin marketplace add netresearch/claude-code-marketplace
/plugin install matrix-communication@netresearch-claude-code-marketplace
Without a marketplace
Since Claude Code 2.1.157 a plugin directory under your personal skills directory loads on its own, including the commands this repo ships:
mkdir -p ~/.claude/skills
git clone https://github.com/netresearch/matrix-skill.git \
~/.claude/skills/matrix-communication
It loads as matrix-communication@skills-dir on the next session. Update with git -C ~/.claude/skills/matrix-communication pull and start a new session; remove it by deleting the directory. This route has no claude plugin update.
npx (skills.sh)
Install with any Agent Skills-compatible agent:
npx skills add https://github.com/netresearch/matrix-skill --skill matrix-communication
Limitation:
npx skillsinstallsSKILL.md-based skills only. This repo also shipscommands, which it does not install — use the marketplace or the skills directory for those.
Download Release
Download the latest release and extract to your agent's skills directory.
Git Clone
git clone https://github.com/netresearch/matrix-skill.git
Composer (PHP Projects)
composer require netresearch/matrix-skill
Requires netresearch/composer-agent-skill-plugin.
npm (Node Projects)
npm install --save-dev \
@netresearch/agent-skill-coordinator \
github:netresearch/matrix-skill
Requires @netresearch/agent-skill-coordinator, which discovers the skill in node_modules and registers it in AGENTS.md via a postinstall hook. For pnpm, also allowlist the coordinator's postinstall:
{
"pnpm": {
"onlyBuiltDependencies": ["@netresearch/agent-skill-coordinator"]
}
}
Prerequisites
For E2EE support (most Matrix rooms), install libolm:
sudo apt install libolm-dev # Debian/Ubuntu
sudo dnf install libolm-devel # Fedora
brew install libolm # macOS
Usage
Paths are shortened to $C below:
C=skills/matrix-communication/scripts
The *-e2ee.py scripts are the ones to use. Most Matrix rooms are encrypted, and
the non-E2EE variants cannot read or write in them. Prepend set +H to any
command whose arguments contain !, or bash history expansion eats it.
Send a Message
set +H && uv run $C/matrix-send-e2ee.py "#myroom:matrix.org" "Deployment complete"
set +H && uv run $C/matrix-send-e2ee.py "!abc123:matrix.org" "**Build passed** for abc123"
# Notify someone. --mention is what actually reaches them.
set +H && uv run $C/matrix-send-e2ee.py "#dev:matrix.org" \
"alex, schaust du drauf?" --mention '@alex:matrix.org'
Follow a Room
# Add rooms to watch_rooms in ~/.config/matrix/config.json, then:
uv run $C/matrix-watchd.py --start
uv run $C/matrix-watchd.py --status
# One line per event on stdout, for a human or an agent's monitor
uv run $C/matrix-watch.py "#myroom:matrix.org"
# What arrived since this reader last looked, then exit
uv run $C/matrix-watch.py "#myroom:matrix.org" --once
While the daemon runs it owns the store; send, react, redact and edit route through it automatically. With no daemon they open the store themselves. Nothing changes at the call site either way.
List Joined Rooms
uv run $C/matrix-rooms.py
uv run $C/matrix-rooms.py --search ops
Read Messages
uv run $C/matrix-read-e2ee.py "#myroom:matrix.org" --limit 10
uv run $C/matrix-read-e2ee.py "#myroom:matrix.org" --limit 50 --json
Resolve Room Alias
uv run $C/matrix-resolve.py "#myroom:matrix.org"
Check the Setup
python3 $C/matrix-doctor.py # verifies every credential against the homeserver
E2EE Support
matrix-e2ee-setup.py creates a dedicated "Matrix Skill E2EE" device that runs
alongside your Element client. It logs in once with your password, which is used
and not stored.
| Script | Purpose |
|---|---|
matrix-send-e2ee.py | Send encrypted messages |
matrix-read-e2ee.py | Read and decrypt messages |
matrix-edit-e2ee.py | Edit a message you sent |
matrix-download-e2ee.py | Download and decrypt attachments |
matrix-e2ee-setup.py | Create or remove the agent's device |
matrix-e2ee-verify.py | SAS emoji verification |
matrix-fetch-keys.py | Request missing room keys from your other devices |
matrix-key-backup.py | Restore room keys from the server-side backup |
matrix-watchd.py | The daemon that owns the store and follows rooms |
First run takes ~2–5 s for the initial key sync; later runs are faster.
Never reuse a running client's access token
Not from Element, Element X, FluffyChat or a browser session. A token carries a
device_id, and E2EE state is per device: two clients on one device cannot read
each other's messages, and the one that breaks is the client you use — it starts
showing [Unable to decrypt] for its own messages. Nothing fails at the moment
you paste it.
Earlier versions of this documentation offered that as a fallback "if password-based setup isn't possible". That advice was wrong and is retracted. No password means no E2EE, and that is the answer.
Verification
C=skills/matrix-communication/scripts
# You start it, aimed at one of your own devices
uv run $C/matrix-e2ee-verify.py --list # find the device id
uv run $C/matrix-e2ee-verify.py --request DEVICE --timeout 300
# Or Element starts it and this side waits — needs --listen
uv run $C/matrix-e2ee-verify.py --listen --timeout 300
Without --request and without --listen the script picks a device itself,
which is rarely the one you are sitting in front of.
Use Element Desktop or Element Android. Element X has an incompatible verification flow.
The matrix-nio pin
The scripts pin matrix-nio[e2e]<0.26. 0.26 sends the SAS commitment in a
format Element rejects, so no verification completes
(matrix-nio#570), and the
two releases write incompatible store formats — opening one with the other fails
as BAD_ACCOUNT_KEY, which names a key that is not the problem.
Moving the pin is a migration, not a version bump. The store cannot be converted:
uv run $C/matrix-e2ee-setup.py --logout && uv run $C/matrix-e2ee-setup.py
uv run $C/matrix-key-backup.py --import-keys
uv run $C/matrix-e2ee-verify.py --request DEVICE
matrix-administration — Features
Synapse homeserver administration via the Synapse Admin API. Stdlib-only Python (no E2EE deps required). Works against any Synapse 1.x server.
- Paginated room snapshot (
synapse-fetch-rooms.py→rooms.json) - Health rating with EN+DE phrasing — public, unencrypted, orphaned-from-spaces
- Colour-coded Graphviz SVG of the entire room/space tree
- Force-join, promote-admin, link-room-to-space
- One-shot hardening pipeline: add to space + restrict joins + enable encryption + restore power levels
- Destructive user deactivation with optional GDPR
--erase - Inspection: list user's admin/membership rooms, replay join/leave timelines, search unencrypted history, find biggest rooms by DB size
Quick start:
# Snapshot all rooms (the admin token comes from ~/.config/matrix/config.json)
python3 skills/matrix-administration/scripts/synapse-fetch-rooms.py
# Rate them in German, treating !home:example.com as our home space
python3 skills/matrix-administration/scripts/synapse-rate-rooms.py \
--language de --space '!home:example.com'
# Render a Graphviz SVG (requires the `dot` binary)
python3 skills/matrix-administration/scripts/synapse-graph.py --space '!home:example.com'
Full reference and safety guide live in skills/matrix-administration/.
matrix-announcement — Features
Content-design guidance for any agent-authored Matrix room post longer than a single line — release notes, version bumps, weekly digests, breaking-change heads-ups, postmortems, RFCs, multi-skill pipeline summaries.
- Five rules — one headline,
formatted_bodyalways, lists beat paragraphs, code in<pre><code>, layout-heavy → render to PNG - Type-tag system —
Release/Patch/Heads-up/Digest/Postmortem/RFC/New skill. Pick one; never stack. - Glyph rules — one prefix glyph max, no rockets (🚀), no party emoji (🎉), no multi-emoji ladders
m.textvsm.notice—m.noticefor unattended automation (bots can't auto-reply, prevents loops)- Three rendered HTML card templates —
release-card.html(1200×630),weekly-digest.html(1200×1500),comparison.html(1200×900) — render headlessly with Chromium and post asm.image - Seven
formatted_bodyskeletons — drop-in templates for each type tag - Visual gallery at
skills/matrix-announcement/references/gallery.html— preview every rule, all five worked examples, and the three card templates side-by-side
# Open the live preview gallery
xdg-open skills/matrix-announcement/references/gallery.html
# Render a release card to PNG
chromium --headless=new --hide-scrollbars --window-size=1200,630 \
--screenshot=card.png \
"file://$(pwd)/skills/matrix-announcement/references/templates/release-card.html"
Full reference lives in skills/matrix-announcement/.
Structure
matrix-skill/
├── .claude-plugin/
│ └── plugin.json # Plugin manifest (lists all three skills)
├── skills/
│ ├── matrix-communication/ # Client-Server API, E2EE chat
│ │ ├── SKILL.md
│ │ ├── scripts/
│ │ │ ├── _lib/ # stdlib-only shared helpers
│ │ │ ├── matrix-create-room.py # Create a room
│ │ │ ├── matrix-doctor.py # Health check (python3, not uv run)
│ │ │ ├── matrix-download-e2ee.py # Download attachments (E2EE)
│ │ │ ├── matrix-e2ee-setup.py # Create or remove the agent device
│ │ │ ├── matrix-e2ee-verify.py # SAS emoji verification
│ │ │ ├── matrix-edit-e2ee.py # Edit (E2EE) — USE THIS
│ │ │ ├── matrix-edit.py # Edit (non-E2EE fallback)
│ │ │ ├── matrix-fetch-keys.py # Request missing room keys
│ │ │ ├── matrix-invite.py # Invite a user
│ │ │ ├── matrix-key-backup.py # Restore keys from server backup
│ │ │ ├── matrix-power-level.py # Read or set power levels
│ │ │ ├── matrix-react.py # React to messages
│ │ │ ├── matrix-read-e2ee.py # Read (E2EE) — USE THIS
│ │ │ ├── matrix-read.py # Read (non-E2EE fallback)
│ │ │ ├── matrix-redact.py # Delete messages
│ │ │ ├── matrix-resolve.py # Resolve aliases
│ │ │ ├── matrix-rooms.py # List rooms
│ │ │ ├── matrix-send-e2ee.py # Send (E2EE) — USE THIS
│ │ │ ├── matrix-send.py # Send (non-E2EE fallback)
│ │ │ ├── matrix-watch.py # Follow a room's event log
│ │ │ └── matrix-watchd.py # Daemon: owns the store, follows rooms
│ │ └── references/
│ ├── matrix-administration/ # Synapse Admin API, server ops
│ │ ├── SKILL.md
│ │ ├── scripts/
│ │ │ ├── _lib/ # stdlib-only shared helpers
│ │ │ ├── synapse-fetch-rooms.py
│ │ │ ├── synapse-rate-rooms.py
│ │ │ ├── synapse-graph.py
│ │ │ ├── synapse-biggest-rooms.py
│ │ │ ├── synapse-join-room.py
│ │ │ ├── synapse-make-admin.py
│ │ │ ├── synapse-add-to-space.py
│ │ │ ├── synapse-migrate-room.py
│ │ │ ├── synapse-deactivate-user.py
│ │ │ ├── synapse-user-admin-rooms.py
│ │ │ ├── synapse-user-rooms.py
│ │ │ ├── synapse-room-member-flow.py
│ │ │ └── synapse-search.py
│ │ └── references/
│ │ ├── synapse-admin-api.md
│ │ ├── room-health-checks.md
│ │ ├── room-graph-pipeline.md
│ │ └── safety-guide.md
│ └── matrix-announcement/ # Content guidance (no scripts)
│ ├── SKILL.md
│ ├── README.md
│ ├── evals/evals.json
│ └── references/
│ ├── html-subset.md
│ ├── structure.md
│ ├── glyphs.md
│ ├── image-cards.md
│ ├── threading.md
│ ├── anti-patterns.md
│ ├── text-templates.md
│ ├── gallery.html # visual preview of all rules + examples
│ └── templates/
│ ├── release-card.html # 1200×630
│ ├── weekly-digest.html # 1200×1500
│ └── comparison.html # 1200×900
├── docs/
│ ├── ARCHITECTURE.md # system design and distribution
│ ├── specs/ # design documents (OKF)
│ └── exec-plans/ # implementation plans
├── LICENSE-MIT # Code license (MIT)
├── LICENSE-CC-BY-SA-4.0 # Content license (CC-BY-SA-4.0)
└── README.md
Governance and policies
This repository follows the Netresearch organisation policies:
- Governance: ownership, roles, how decisions are made and disputes resolved, and continuity.
- Roadmap: planned and explicitly excluded work for the coming year.
- Handling of dependency and code analysis findings: thresholds, deadlines and the exception process for dependency (SCA) and static analysis (SAST) findings.
- Secret management: how CI and release credentials are stored, accessed and rotated.
- Access roster: who holds administrative access to this repository and the organisation.
The security assurance case for these skills (threat model, trust boundaries, where tokens and key material are read, stored and sent, countermeasures and limits) is in docs/SECURITY-ASSURANCE.md.
Checks that run on pull requests in this repository:
- Every pull request: Skill Validation (
lint.yml: skill structure, markdownlint, yamllint, actionlint, JSON syntax, ShellCheck, ruff lint and format), Eval Validation (eval-validate.yml), Unit Tests (tests.yml: everyskills/**/test_*.pysuite) and Label PR (labeler.yml). - Pull requests to
mainormaster:security.ymlwith Betterleaks (secret scanning), zizmor (workflow static analysis), dependency review (fails on vulnerabilities of severity high or above), Composer Audit and Opengrep SAST (thresholds as in the organisation's static analysis rule); Harness Verification (harness-verify.yml) and Template Drift (check-template-drift.yml). - Every pull request, skipped unless Renovate or Dependabot opened it: Auto-merge dependency PRs (
auto-merge-deps.yml). - Configured outside the workflow files: CodeQL default setup (actions, python), SonarCloud Code Analysis (automatic analysis, settings in
.sonarcloud.properties), the DCO check and the CodeRabbit review status. Code scanning also reports each analyser's results as a check run of its own:CodeQL,SonarCloud,zizmor,betterleaksandOpengrep OSS. GitHub secret scanning with push protection is enabled as a repository setting.
License
This project uses split licensing:
- Code (scripts, workflows, configs): MIT
- Content (skill definitions, documentation, references): CC-BY-SA-4.0
See the individual license files for full terms.
Author
Netresearch DTT GmbH - https://www.netresearch.de