Skip to main content

Standalone Matrix CLI client: send messages, listen to rooms, and manage E2E encrypted communication

Project description

black-lint mypy and pytests Docker Pulls PyPI Downloads

Gemini_Generated_Image_2bsor82bsor82bso_250x250.png

minimatrix

Standalone Matrix CLI client with E2E encryption. Send messages, listen to rooms, and list joined rooms — all from the command line.

Status

Beta (v0.0.1) — core CLI with E2E encryption, password/SSO/JWT authentication, and basic room operations are implemented.

Features

  • Send encrypted messages to Matrix rooms
  • Listen for incoming messages in real-time (prints to stdout)
  • List joined rooms with display names and member counts
  • E2E encryption via matrix-nio with persistent crypto store
  • TOFU device trust — automatically trusts all devices in a room
  • Multiple auth methods: password, SSO, or JWT via Keycloak (ROPC + JWKS)
  • Flexible config: YAML file, environment variables, and CLI args (in ascending priority)
  • Structured logging via loguru

Installation

From PyPI

pip install minimatrix

From source

git clone https://github.com/vroomfondel/minimatrix.git
cd minimatrix
make venv
source .venv/bin/activate
pip install .

Docker

docker build -t minimatrix .

Quick Start

1. Create a config file (optional)

# ~/.config/minimatrix/config.yaml
homeserver: "https://matrix.example.com"
user: "myuser"
password: "mypassword"

2. List joined rooms

minimatrix rooms

3. Send a message

minimatrix send --room '!abc123:example.com' "Hello from minimatrix!"

# Or pipe from stdin
echo "Hello from a pipe" | minimatrix send --room '!abc123:example.com'

4. Listen for messages

minimatrix listen --room '!abc123:example.com'
# [2026-02-22 14:30:01] <@alice:example.com> Hi there!
# Press Ctrl+C to stop

Configuration

Configuration is resolved in this order (later overrides earlier):

  1. YAML config file (~/.config/minimatrix/config.yaml by default)
  2. Environment variables
  3. CLI arguments

General Options

Variable / Config Key CLI Argument Default
MATRIX_HOMESERVER / homeserver --homeserver http://synapse.matrix.svc.cluster.local:8008
MATRIX_USER / user --user — (required)
MATRIX_PASSWORD / password --password — (required)
CRYPTO_STORE_PATH / crypto_store_path --crypto-store-path ~/.local/share/minimatrix/crypto_store
AUTH_METHOD / auth_method --auth-method password
LOGURU_LEVEL DEBUG

CLI Subcommands

Subcommand Description
rooms List joined rooms with display name and member count
send --room ROOM_ID [MESSAGE] Send a text message (reads from stdin if message omitted)
listen --room ROOM_ID Listen for messages and print to stdout

Use minimatrix --help or minimatrix <subcommand> --help for full usage.

JWT Authentication

When AUTH_METHOD=jwt is set, minimatrix authenticates via Keycloak ROPC (Resource Owner Password Credentials) grant instead of direct Matrix password login. This enables centralized identity management through Keycloak while allowing non-interactive authentication.

Authentication Flow

sequenceDiagram
    participant CLI as minimatrix
    participant KC as Keycloak
    participant Syn as Synapse

    CLI->>KC: 1. ROPC grant (username + password)
    KC-->>CLI: 2. JWT access token
    CLI->>Syn: 3. Matrix login (JWT)
    Syn->>KC: 4. Validate JWT (JWKS or introspection)
    KC-->>Syn: JWT valid
    Syn-->>CLI: 5. Matrix access token

Supported Login Types

Login Type Synapse Config Validation Method Use Case
com.famedly.login.token.oauth (default) synapse-token-authenticator oauth: JWKS endpoint Recommended — automatic key rotation
com.famedly.login.token synapse-token-authenticator jwt: Symmetric secret (HS512) Internal services with shared secret
org.matrix.login.jwt Native jwt_config: Public key (RS256) Simple setup, manual key management

JWT Environment Variables

Variable / Config Key CLI Argument Default
AUTH_METHOD / auth_method --auth-method password
KEYCLOAK_URL / keycloak_url --keycloak-url — (required if jwt)
KEYCLOAK_REALM / keycloak_realm --keycloak-realm — (required if jwt)
KEYCLOAK_CLIENT_ID / keycloak_client_id --keycloak-client-id — (required if jwt)
KEYCLOAK_CLIENT_SECRET / keycloak_client_secret --keycloak-client-secret "" (empty for public clients)
JWT_LOGIN_TYPE / jwt_login_type --jwt-login-type com.famedly.login.token.oauth

Requires synapse-token-authenticator on the Synapse side for the com.famedly.login.token.* login types.

Synapse Setup for JWT Authentication

Prerequisites

  • Keycloak instance (any recent version)
  • Synapse homeserver
  • Admin access to both Keycloak and Synapse

Step 1: Keycloak Realm Setup

Create a dedicated realm for Matrix (or use an existing one).

Recommended realm settings:

  • registrationAllowed: false — disable self-registration
  • loginWithEmailAllowed: false — use usernames, not emails (Matrix localparts)
  • registrationEmailAsUsername: false — important for Matrix username compatibility

Step 2: Create OAuth Client

Create a confidential client with ROPC (Direct Access Grants) enabled:

Setting Value Reason
publicClient false Confidential client with secret
clientAuthenticatorType client-secret Use client secret for auth
directAccessGrantsEnabled true Required — enables ROPC grant
standardFlowEnabled false No browser redirects needed
serviceAccountsEnabled false Not using service account

After creation, copy the Client secret from the Credentials tab.

Step 3: Create User in Keycloak

Create a user account in your Keycloak realm. The Keycloak username must match the desired Matrix localpart — Synapse extracts it from the preferred_username JWT claim.

Step 4: Configure Synapse

Option A: OAuth with JWKS Validation (Recommended)

modules:
  - module: synapse_token_authenticator.TokenAuthenticator
    config:
      oauth:
        jwt_validation:
          jwks_endpoint: "https://keycloak.example.com/realms/<realm>/protocol/openid-connect/certs"
          localpart_path: "preferred_username"
          require_expiry: true
          validator:
            type: exist
        registration_enabled: true

Option B: JWT with Symmetric Secret

modules:
  - module: synapse_token_authenticator.TokenAuthenticator
    config:
      jwt:
        secret: "your-256-bit-secret-here"
        algorithm: HS512
        allow_registration: false
        require_expiry: true

Option C: Native Synapse JWT (No Module Required)

# Get the realm public key
curl -s "https://keycloak.example.com/realms/<realm>" | jq -r '.public_key'
jwt_config:
  enabled: true
  secret: |
    -----BEGIN PUBLIC KEY-----
    <paste the public key here>
    -----END PUBLIC KEY-----
  algorithm: "RS256"
  subject_claim: "preferred_username"
  issuer: "https://keycloak.example.com/realms/<realm>"

Login Type Comparison

Feature com.famedly.login.token.oauth com.famedly.login.token org.matrix.login.jwt
Key management Automatic (JWKS) Manual (shared secret) Manual (public key)
Key rotation Automatic Manual secret update Manual config update
Algorithm RS256 (asymmetric) HS512 (symmetric) RS256 (asymmetric)
Module required Yes Yes No
Recommended for Production Internal services Simple setups

Troubleshooting

"Invalid username or password" from Synapse:

  • Verify the Keycloak user exists and password is correct
  • Check that preferred_username in JWT matches an existing Matrix user (or registration_enabled: true)
  • Verify JWKS endpoint is accessible from Synapse

"ROPC grant failed" from Keycloak:

  • Ensure directAccessGrantsEnabled: true on the client
  • Verify client secret is correct
  • Check user is enabled in Keycloak

"JWT signature validation failed":

  • For JWKS: verify the endpoint URL is correct and accessible
  • For native JWT: ensure public key is correctly formatted with PEM headers
  • Check issuer matches the JWT iss claim

Useful Keycloak Endpoints

Endpoint Purpose
/realms/<realm>/.well-known/openid-configuration OIDC discovery document
/realms/<realm>/protocol/openid-connect/certs JWKS endpoint (public keys)
/realms/<realm>/protocol/openid-connect/token Token endpoint (ROPC)
/realms/<realm> Realm info (includes public key)

Development

Target Description
make venv Create virtualenv and install all dependencies
make tests Run pytest
make lint Format code with black (line length 120)
make isort Sort imports with isort
make tcheck Static type checking with mypy (strict)
make commit-checks Run pre-commit hooks on all files
make prepare Run tests + commit-checks
make pypibuild Build sdist + wheel with hatch
make pypipush Publish to PyPI with hatch

License

This project is licensed under the LGPL where applicable/possible — see LICENSE.md. Some files/parts may use other licenses: MIT | GPL | LGPL. Always check per‑file headers/comments.

Authors

  • Repo owner (primary author)
  • Additional attributions are noted inline in code comments

Acknowledgments

  • Inspirations and snippets are referenced in code comments where appropriate.

⚠️ Note

This is a development/experimental project. For production use, review security settings, customize configurations, and test thoroughly in your environment. Provided "as is" without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software. Use at your own risk.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

minimatrix-0.0.2.tar.gz (19.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

minimatrix-0.0.2-py3-none-any.whl (22.5 kB view details)

Uploaded Python 3

File details

Details for the file minimatrix-0.0.2.tar.gz.

File metadata

  • Download URL: minimatrix-0.0.2.tar.gz
  • Upload date:
  • Size: 19.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.16.3 cpython/3.14.3 HTTPX/0.28.1

File hashes

Hashes for minimatrix-0.0.2.tar.gz
Algorithm Hash digest
SHA256 235138b5376933ce063a398bdf6273d946d05917426ba3310a58173f4917c1cd
MD5 5200bfeef9dae3d2668c97d6bb6a96e2
BLAKE2b-256 a5563d800d9a9ef1f59f28bcc2aee361ab73249245f3760df1c18320ba554ee6

See more details on using hashes here.

File details

Details for the file minimatrix-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: minimatrix-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 22.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.16.3 cpython/3.14.3 HTTPX/0.28.1

File hashes

Hashes for minimatrix-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 02be833f707abb7ed3d485fc603e6e5aca58f866a8060686f42f82d853f0f116
MD5 36c6704b0afa1dd47c727c665cf17a21
BLAKE2b-256 4d4e1c870c1436b885a6819769e19746b317c3217d15d2d1137e29b6a9ae9d65

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page