<!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
<!-- SPDX-FileCopyrightText: Netresearch DTT GmbH -->
# Matrix Skill
Agentic Skills for Matrix, distributed as a Claude Code plugin. Three skills ship in this repo:
| Skill | Purpose | API surface |
|-------|---------|-------------|
| [**matrix-communication**](skills/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**](skills/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**](skills/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](https://github.com/anthropics/agentic-skills).
## 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'` sets `m.mentions`, which is what
notifies a client, and renders that name in your text as a pill; a plain
`@name` without `--mention` does neither
- **Smart link shortening** โ Jira, GitHub, GitLab URLs become readable links
- **Room links** โ `#room:server` becomes a clickable room link
- **Code blocks** โ syntax-highlighted multi-line code
- **Emotes** โ `/me` style 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](https://github.com/netresearch/claude-code-marketplace) once, then browse and install skills:
```bash
# 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:
```bash
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](https://skills.sh))
Install with any [Agent Skills](https://agentskills.io)-compatible agent:
```bash
npx skills add https://github.com/netresearch/matrix-skill --skill matrix-communication
```
> **Limitation:** `npx skills` installs `SKILL.md`-based skills only. This repo also ships `commands`, which it does not install โ use the marketplace or the skills directory for those.
### Download Release
Download the [latest release](https://github.com/netresearch/matrix-skill/releases/latest) and extract to your agent's skills directory.
### Git Clone
```bash
git clone https://github.com/netresearch/matrix-skill.git
```
### Composer (PHP Projects)
```bash
composer require netresearch/matrix-skill
```
Requires [netresearch/composer-agent-skill-plugin](https://github.com/netresearch/composer-agent-skill-plugin).
### npm (Node Projects)
```bash
npm install --save-dev \
@netresearch/agent-skill-coordinator \
github:netresearch/matrix-skill
```
Requires [@netresearch/agent-skill-coordinator](https://github.com/netresearch/node-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:
```json
{
"pnpm": {
"onlyBuiltDependencies": ["@netresearch/agent-skill-coordinator"]
}
}
```
## Prerequisites
**For E2EE support** (most Matrix rooms), install libolm:
```bash
sudo apt install libolm-dev # Debian/Ubuntu
sudo dnf install libolm-devel # Fedora
brew install libolm # macOS
```
## Usage
Paths are shortened to `$C` below:
```bash
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
```bash
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
```bash
# 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
```bash
uv run $C/matrix-rooms.py
uv run $C/matrix-rooms.py --search ops
```
### Read Messages
```bash
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
```bash
uv run $C/matrix-resolve.py "#myroom:matrix.org"
```
### Check the Setup
```bash
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
```bash
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](https://github.com/matrix-nio/matrix-nio/issues/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:
```bash
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](https://element-hq.github.io/synapse/latest/usage/administration/admin_api/index.html). **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:
```bash
# 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/`](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_body` always, 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.text` vs `m.notice`** โ `m.notice` for 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 as `m.image`
- **Seven `formatted_body` skeletons** โ 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
```bash
# 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/`](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](https://github.com/netresearch/.github/blob/main/GOVERNANCE.md): ownership, roles, how decisions are made and disputes resolved, and continuity.
- [Roadmap](https://github.com/netresearch/.github/blob/main/ROADMAP.md): planned and explicitly excluded work for the coming year.
- [Handling of dependency and code analysis findings](https://github.com/netresearch/.github/blob/main/SECURITY.md#handling-of-dependency-and-code-analysis-findings): thresholds, deadlines and the exception process for dependency (SCA) and static analysis (SAST) findings.
- [Secret management](https://github.com/netresearch/.github/blob/main/SECURITY.md#secret-management): how CI and release credentials are stored, accessed and rotated.
- [Access roster](https://github.com/netresearch/.github/blob/main/docs/access-roster.md): 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](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`: every `skills/**/test_*.py` suite) and Label PR (`labeler.yml`).
- Pull requests to `main` or `master`: `security.yml` with 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](https://github.com/netresearch/.github/blob/main/SECURITY.md#static-analysis-sast)), and CodeQL (actions, python); 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: 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`, `betterleaks` and `Opengrep OSS`. GitHub secret scanning with push protection is enabled as a repository setting.
## License
This project uses split licensing:
- **Code** (scripts, workflows, configs): [MIT](LICENSE-MIT)
- **Content** (skill definitions, documentation, references): [CC-BY-SA-4.0](LICENSE-CC-BY-SA-4.0)
See the individual license files for full terms.
## Author
Netresearch DTT GmbH - https://www.netresearch.de