This guide walks you through connecting cc-connect to Matrix, the open standard for decentralized communication. Once set up, you can chat with your local AI agent from any Matrix client (Element, FluffyChat, Nheko, etc.).
- A Matrix account on any homeserver (public like
matrix.org, or self-hosted) - A machine that can run cc-connect (no public IP needed)
- Claude Code (or another supported agent) installed and configured
Advantage: Uses
/synclong polling — no public IP, no domain, no reverse proxy needed. Works behind NAT and firewalls.
If you don't already have a Matrix account:
- Visit https://app.element.io (or your self-hosted Element instance)
- Click Create Account
- Choose a homeserver (the default
matrix.orgworks for most users) - Complete registration
You can also use any existing Matrix account — a dedicated bot account is recommended but not required.
You need an access token so cc-connect can authenticate as your Matrix user.
Use curl to create a dedicated device with its own device ID. This ensures E2EE (end-to-end encryption) works correctly:
curl -XPOST "https://matrix.org/_matrix/client/v3/login" \
-H "Content-Type: application/json" \
-d '{"type":"m.login.password","user":"your-username","password":"your-password","device_id":"CC-CONNECT"}'The response contains "access_token": "syt_...". Copy it for the config.
Recommended: Set
device_idtoCC-CONNECTor another recognizable name. A dedicated device ensures encryption keys are distributed correctly.
- Log in to Element (app.element.io)
- Open Settings (click your avatar → Settings)
- Go to Help & About → scroll to Advanced
- Click Access Token → copy the token
Note: Tokens from Element reuse Element's device ID, which may cause E2EE issues. Creating a dedicated device via curl is recommended.
Warning: Treat your access token like a password. Anyone with it can send messages as you. If it leaks, you can invalidate it by logging out of all sessions in Element.
Your user ID looks like @username:matrix.org. cc-connect can auto-detect it from the access token, but you can also specify it explicitly in config.
In Element: click your avatar — your user ID is shown at the top.
Add the Matrix platform to your config.toml:
[[projects]]
name = "my-project"
[projects.agent]
type = "claudecode"
[projects.agent.options]
work_dir = "/path/to/your/project"
mode = "default"
[[projects.platforms]]
type = "matrix"
[projects.platforms.options]
homeserver = "https://matrix.org"
access_token = "syt_xxx_xxx"
# ── Optional settings ────────────────────────────────────────
# user_id = "@bot:matrix.org" # auto-detected if omitted
# allow_from = "*" # "*" = all users, or "id1,id2"
# auto_join = true # auto-accept room invites (default: true)
# auto_verify = true # auto-accept SAS key verification (default: true)
# cross_signing_password = "" # bot account password for cross-signing setup (one-time)
# share_session_in_channel = false # true = all users share one session per room
# group_reply_all = false # true = respond to all messages in group rooms
# proxy = "" # HTTP/SOCKS5 proxy, e.g. "http://proxy:8080"Common mistake:
homeservermust include the scheme (https://) and must be the same server your account is registered on.
cc-connect
# Or specify a config file
cc-connect -config /path/to/config.tomlYou should see logs like:
level=INFO msg="matrix: E2EE enabled" device_id=CC-CONNECT
level=INFO msg="matrix: connected" user=@bot:matrix.org
level=INFO msg="platform started" project=my-project platform=matrix
level=INFO msg="cc-connect is running" projects=1
If you see E2EE not available, encryption initialization failed. Encrypted rooms won't work. See the FAQ below.
- Open your Matrix client (Element, FluffyChat, etc.)
- Start a new DM with the bot's user ID (e.g.
@bot:matrix.org) - Send a message — cc-connect will respond
- Create or open a room
- Invite the bot's user ID to the room
- The bot will auto-join if
auto_join = true(default) - Send messages in the room
Note: In group rooms, the bot responds when mentioned (e.g.
@bot:matrix.org) or whengroup_reply_all = trueis set.
┌─────────────────────────────────────────────────────────────┐
│ Matrix Homeserver │
│ │
│ User Message ──→ /sync endpoint ◄── Long Polling │
│ ▲ │
└──────────────────────────┼───────────────────────────────────┘
│
│ HTTPS (no public IP needed)
▼
┌─────────────────────────────────────────────────────────────┐
│ Your Local Machine │
│ │
│ cc-connect ◄──► Claude Code CLI ◄──► Your Project Code │
│ │
└─────────────────────────────────────────────────────────────┘
| Option | Required | Default | Description |
|---|---|---|---|
homeserver |
Yes | — | Matrix homeserver URL (e.g. https://matrix.org) |
access_token |
Yes | — | Access token for authentication |
user_id |
No | auto-detected | Matrix user ID (e.g. @bot:matrix.org) |
allow_from |
No | "*" |
Comma-separated user IDs allowed to interact, or "*" for all |
auto_join |
No | true |
Automatically accept room invitations |
auto_verify |
No | true |
Auto-accept SAS key verification requests |
cross_signing_password |
No | "" |
Bot account password for cross-signing key setup (one-time, needed on first run or when keys are reset). Can also be set via MATRIX_CROSS_SIGNING_PASSWORD environment variable (takes precedence over config file) |
share_session_in_channel |
No | false |
Share a single agent session among all users in a room |
group_reply_all |
No | false |
Respond to all messages in group rooms (not just mentions) |
proxy |
No | "" |
HTTP or SOCKS5 proxy URL |
- Is cc-connect running and showing
matrix: connectedin logs? - Is the access token valid? Try regenerating it.
- In group rooms, is the bot mentioned or is
group_reply_all = trueset? - If logs show
E2EE not availableordecrypt failed, see E2EE questions below.
Set allow_from to a comma-separated list of Matrix user IDs:
allow_from = "@alice:matrix.org,@bob:matrix.org"Make sure auto_join = true (this is the default). If the bot was already invited before cc-connect started, re-invite it.
cc-connect supports encrypted rooms (E2EE) when built with the goolm build tag. If you see matrix: E2EE enabled at startup, encryption is working. If you see matrix: E2EE not available (build with -tags goolm to enable), rebuild with E2EE support:
Data storage: E2EE crypto data is stored under
~/.cc-connect/(created with0700permissions):
matrix-crypto-<device_id>.db— encryption key database (one per device)matrix-cross-signing-<device_id>.json— cross-signing seed (one per device)To reset E2EE (e.g. after changing device or reinstalling), delete these files and restart cc-connect:
rm ~/.cc-connect/matrix-crypto-*.db* ~/.cc-connect/matrix-cross-signing-*.json
go build -tags goolm ./cmd/cc-connectNote: To remove the red question mark ("encrypted by a device not verified by its owner") on bot messages, cross-signing must be set up. cc-connect does this automatically on first run, but some servers require
cross_signing_passwordin config for the initial setup. See the red question mark FAQ below.
Possible causes and fixes:
device ID not available from whoami— The server didn't return a device ID. Create a dedicated device via curl withdevice_id.not marked as shared, but there are keys on the server— Old crypto data conflicts with the current device. cc-connect tries to auto-recover. If it persists, delete old crypto databases and cross-signing seeds:rm ~/.cc-connect/matrix-crypto-*.db* ~/.cc-connect/matrix-cross-signing-*.jsonmismatching device ID in client and crypto store— The token's device ID doesn't match the crypto database. Delete the database and seeds:rm ~/.cc-connect/matrix-crypto-*.db* ~/.cc-connect/matrix-cross-signing-*.json
The sender's client didn't send the encryption key to the bot's device. This usually happens when:
- Reusing Element's access token — Element's device ID conflicts with the bot's encryption keys. Create a dedicated device via curl (see Step 2).
- Just changed the access token — The sender's client may not have discovered the bot's new device yet. Wait 1-2 minutes and send a new message.
- Corrupted crypto database — Delete and restart:
rm ~/.cc-connect/matrix-crypto-*.db* ~/.cc-connect/matrix-cross-signing-*.json
Use the Matrix API to create a dedicated device, avoiding conflicts with Element or other apps:
# Replace homeserver URL, username, and password
curl -XPOST "https://your-homeserver.com/_matrix/client/v3/login" \
-H "Content-Type: application/json" \
-d '{
"type": "m.login.password",
"user": "your-bot-username",
"password": "your-password",
"device_id": "CC-CONNECT"
}'The access_token in the response can be used in config. The device_id will be CC-CONNECT, easy to identify and manage.
This means the bot's device hasn't been cross-signed. cc-connect automatically sets up cross-signing on first run, but some Matrix servers require password authentication (UIA) to publish the cross-signing keys.
If logs show no supported UIA flow for cross-signing, provide the bot account's password. You can set it in config:
cross_signing_password = "your-bot-password"Or preferably via environment variable (avoids storing the password in the config file):
export MATRIX_CROSS_SIGNING_PASSWORD="your-bot-password"The environment variable takes precedence over the config file value. This is a one-time operation — once cross-signing keys are published and saved, remove the password from config or unset the environment variable.
cc-connect auto-accepts SAS key verification requests (when auto_verify = true, which is the default). To verify from Element:
- Open a DM with the bot
- Click the bot's avatar → Verify (or go to Settings → Security → find the bot's device)
- The bot will automatically accept and confirm the verification
- Element will show the device as verified
After verification, encrypted messages from the bot will no longer show warnings.
Set homeserver to your server's URL (e.g. https://synapse.example.com). Make sure the URL is reachable from the machine running cc-connect.
proxy = "http://proxy-host:8080"
# or SOCKS5:
proxy = "socks5://proxy-host:1080"