A Matrix-to-OpenCode bridge that lets you interact with OpenCode (AI coding assistant) directly from Matrix chat rooms.
operator is a relay service that:
- Connects to your Matrix homeserver and monitors configured rooms for messages
- Runs OpenCode to respond to messages automatically using AI
- Provides an HTTP API for external agents to send/receive messages via Redis queues
- Supports in-room CLI commands for checking usage, models, and managing model overrides
flowchart LR
A[Matrix Room] -->|messages| B[operator<br/>relay-core]
B -->|queue| C[Redis Queue]
B -->|spawn| D[OpenCode]
D -->|invoke| E[External Agents]
- Matrix Ingress: Messages from configured rooms are queued to Redis (
[project]:user) - Matrix Egress: Agent responses from Redis (
[project]:agent) are sent to rooms - Auto OpenCode: When enabled, automatically runs OpenCode to process user messages
- HTTP API: External services can poll/send via
/v1/agent/polland/v1/agent/send
- Bun runtime
- Redis server
- Matrix homeserver account with access token
- OpenCode CLI (required)
- Install dependencies:
bun install- Create your config file:
cp config.example.json config.json-
Edit
config.jsonwith your settings:homeserverUrl: Your Matrix server URL (e.g.,https://matrix.org)accessToken: Your Matrix access token (get from Element: Settings > Help & About > Advanced)adminUserIds: List of Matrix user IDs allowed to trigger bot responsesagentApiToken: Secret token for HTTP API accessredisUrl: Redis connection URL
-
Configure projects (rooms the bot should monitor):
{
"projects": {
"my-project": {
"roomId": "!abc123:matrix.org",
"projectWorkingDirectory": "/path/to/your/codebase",
"senderAllowlist": ["@you:matrix.org"]
}
}
}- Run the daemon:
bun run src/index.tsYou can use these commands directly in Matrix rooms:
| Command | Description |
|---|---|
!op start |
Run guided onboarding flow |
!op usage <model> [--days N] |
Show usage stats for a specific model |
!op stats [--days N] [--models] |
Show overall usage statistics |
!op models [--verbose] |
List available models |
!op model |
Show current model override for this project |
!op model <model-id> |
Set a model override for this project |
!op model reset |
Clear model override (use OpenCode default) |
!op help |
Show command help |
stop |
Stop the active auto-opencode job |
Example:
!op start
!op usage openai/gpt-5.3-codex --days 30
!op model openai/gpt-4-turbo
Use these commands in your configured management room to add/remove/list projects.
| Command | Description |
|---|---|
!op list |
Show all configured projects |
!op create <name> --room <roomId> --path <dir> |
Create a new project |
!op delete <name> |
Delete a project |
!op show <name> |
Show one project configuration |
!op reload |
Reload config.json from disk |
!op help |
Show management command help |
Examples:
!op list
!op create operator --room !QefzZvtgPwIGrHuOuo:palantir --path /home/xangelo/repos/operator
!op show operator
!op reload
When using !op create, the sender who runs the command is automatically added to
that project's senderAllowlist.
The relay exposes an HTTP API for external agents:
curl http://localhost:8888/v1/healthcurl -X POST http://localhost:8888/v1/agent/poll \
-H "Authorization: Bearer $AGENT_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"my-project","agent":"bot","block_seconds":30}'curl -X POST http://localhost:8888/v1/agent/send \
-H "Authorization: Bearer $AGENT_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"my-project","agent":"bot","markdown":"Hello!","format":"markdown"}'curl http://localhost:8888/v1/metrics| Key | Required | Description |
|---|---|---|
port |
No | HTTP server port (default: 8888) |
homeserverUrl |
Yes | Matrix homeserver URL |
accessToken |
Yes | Matrix bot access token |
adminUserIds |
No | User IDs allowed to enqueue messages |
agentApiToken |
No* | Token for HTTP API (*required if using API) |
redisUrl |
No | Redis URL (default: redis://localhost:6379/0) |
| Key | Required | Description |
|---|---|---|
roomId |
Yes | Matrix room ID |
prefix |
No | Legacy prefix for message routing |
agent |
No | Agent label (default: opencode) |
command |
No | Command to run (default: ["opencode", "run"]) |
commandPrefix |
No | In-room command prefix (default: !op) |
projectWorkingDirectory |
Yes | Working directory for OpenCode |
senderAllowlist |
Yes | Allowed senders (auto-seeded for !op create projects) |
timeoutSeconds |
No | Timeout for OpenCode runs (default: 300, 0=disable) |
verbosity |
No | Output mode: output, debug, thinking, thinking-complete |
output: Acknowledgment + final output only (default)debug: Full status stream + outputthinking: Reasoning section titles + outputthinking-complete: Full reasoning stream, suppress duplicate final output
# Push agent message to queue
bun run src/index.ts push-agent my-project "Hello from CLI"
# Push user message to queue
bun run src/index.ts push-user my-project "Run tests" --sender @admin:matrix.org
# Poll user messages
bun run src/index.ts poll-user my-project --block 30- Sync State: Matrix sync position stored at Redis key
operator:sync:next-batch:v1 - Message Format: Outbound messages support Markdown, converted to Matrix HTML
- Security:
commandruns with the process's permissions - treat as privileged config - Legacy:
autoCodex*andautoOpenCode*config keys are no longer supported
Run tests:
bun testType check:
bunx tsc --noEmit