Skip to main content

A Terminal UI for Matrix chat - simple and AI-friendly

Project description

Matrix TUI Logo

Matty - Matrix CLI Client

A simple, functional Matrix chat client built with Python, Typer, Pydantic, Nio, and Rich. Every interaction is a single CLI command for easy automation.

PyPI Build Status CodeCov GitHub Repo stars Ruff

Features

  • Fast CLI commands for quick Matrix operations
  • Thread support - view and navigate threaded conversations
  • Reactions support - add and view emoji reactions on messages
  • Message redaction - delete messages with optional reasons
  • AI-friendly - every action is a single CLI command
  • Functional programming style (minimal classes, maximum functions)
  • Environment-based configuration
  • Multiple output formats (rich, simple, JSON)
  • Type-safe with dataclasses and type hints
  • Persistent simple ID mapping for complex Matrix IDs

Installation

uv tool install matty
# or
pipx install matty
# or
pip install matty

For development, clone the repo and install dependencies:

# Clone the repository
git clone https://github.com/basnijholt/matrix-cli
cd matrix-cli

# Install dependencies with uv
uv sync

# Optional: Install pre-commit hooks
uv run pre-commit install

Configuration

Matty uses environment variables for configuration. Create a .env file in your working directory with your Matrix credentials:

MATRIX_HOMESERVER=https://matrix.org
MATRIX_USERNAME=your_username
MATRIX_PASSWORD=your_password
MATRIX_SSL_VERIFY=true  # Set to false for test servers

Environment Variables

Variable Description Default Example
MATRIX_HOMESERVER The Matrix homeserver URL to connect to https://matrix.org https://matrix.example.com
MATRIX_USERNAME Your Matrix username (without @ or :server) None (required) alice
MATRIX_PASSWORD Your Matrix account password None (required) secretpassword
MATRIX_SSL_VERIFY Whether to verify SSL certificates true false (for test servers)

Notes:

  • The username should be provided without the @ prefix or :server suffix
  • Set MATRIX_SSL_VERIFY=false when connecting to test servers with self-signed certificates
  • Command-line options (--username, --password) override environment variables

Usage

Available Commands


 Usage: matty [OPTIONS] COMMAND [ARGS]...

 Functional Matrix CLI client

╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --install-completion            Install completion for the current shell.              │
│ --show-completion               Show completion for the current shell, to copy it or   │
│                                 customize the installation.                            │
│ --help                -h        Show this message and exit.                            │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ─────────────────────────────────────────────────────────────────────────────╮
│ rooms         List all joined rooms. (alias: r)                                        │
│ messages      Show recent messages from a room. (alias: m)                             │
│ users         Show users in a room. (alias: u)                                         │
│ send          Send a message to a room. Supports @mentions. (alias: s)                 │
│ threads       List all threads in a room. (alias: t)                                   │
│ thread        Show all messages in a specific thread. (alias: th)                      │
│ reply         Reply to a specific message using its handle. (alias: re)                │
│ thread-start  Start a new thread from a message using its handle. (alias: ts)          │
│ thread-reply  Reply within an existing thread. (alias: tr)                             │
│ react         Add a reaction to a message using its handle. (alias: rx)                │
│ edit          Edit a message using its handle. (alias: e)                              │
│ redact        Delete/redact a message using its handle. (alias: del)                   │
│ reactions     Show detailed reactions for a specific message. (alias: rxs)             │
│ tui           Launch interactive TUI chat interface.                                   │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Rooms Command

List all joined Matrix rooms:


 Usage: matty rooms [OPTIONS]

 List all joined rooms. (alias: r)

╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --username  -u      TEXT                Matrix username (overrides MATRIX_USERNAME env │
│                                         var)                                           │
│ --password  -p      TEXT                Matrix password (overrides MATRIX_PASSWORD env │
│                                         var)                                           │
│ --format    -f      [rich|simple|json]  Output format (rich/simple/json)               │
│                                         [default: rich]                                │
│ --help      -h                          Show this message and exit.                    │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Messages Command

Get recent messages from a room:


 Usage: matty messages [OPTIONS] [ROOM]

 Show recent messages from a room. (alias: m)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room      [ROOM]  Room ID or name                                                    │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --limit     -l      INTEGER             [default: 20]                                  │
│ --username  -u      TEXT                Matrix username (overrides MATRIX_USERNAME env │
│                                         var)                                           │
│ --password  -p      TEXT                Matrix password (overrides MATRIX_PASSWORD env │
│                                         var)                                           │
│ --format    -f      [rich|simple|json]  Output format (rich/simple/json)               │
│                                         [default: rich]                                │
│ --help      -h                          Show this message and exit.                    │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Users Command

List users in a room:


 Usage: matty users [OPTIONS] [ROOM]

 Show users in a room. (alias: u)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room      [ROOM]  Room ID or name                                                    │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --username  -u      TEXT                Matrix username (overrides MATRIX_USERNAME env │
│                                         var)                                           │
│ --password  -p      TEXT                Matrix password (overrides MATRIX_PASSWORD env │
│                                         var)                                           │
│ --format    -f      [rich|simple|json]  Output format (rich/simple/json)               │
│                                         [default: rich]                                │
│ --help      -h                          Show this message and exit.                    │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Thread Commands

View and interact with threads:


 Usage: matty threads [OPTIONS] [ROOM]

 List all threads in a room. (alias: t)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room      [ROOM]  Room ID or name                                                    │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --limit     -l      INTEGER             Number of messages to check [default: 50]      │
│ --username  -u      TEXT                Matrix username (overrides MATRIX_USERNAME env │
│                                         var)                                           │
│ --password  -p      TEXT                Matrix password (overrides MATRIX_PASSWORD env │
│                                         var)                                           │
│ --format    -f      [rich|simple|json]  Output format (rich/simple/json)               │
│                                         [default: rich]                                │
│ --help      -h                          Show this message and exit.                    │
╰────────────────────────────────────────────────────────────────────────────────────────╯


 Usage: matty thread [OPTIONS] [ROOM] [THREAD_ID]

 Show all messages in a specific thread. (alias: th)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room           [ROOM]       Room ID or name                                          │
│   thread_id      [THREAD_ID]  Thread ID (t1, t2, etc.) or full Matrix ID               │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --limit     -l      INTEGER             Number of messages to fetch [default: 50]      │
│ --username  -u      TEXT                Matrix username (overrides MATRIX_USERNAME env │
│                                         var)                                           │
│ --password  -p      TEXT                Matrix password (overrides MATRIX_PASSWORD env │
│                                         var)                                           │
│ --format    -f      [rich|simple|json]  Output format (rich/simple/json)               │
│                                         [default: rich]                                │
│ --help      -h                          Show this message and exit.                    │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Send Command

Send messages to rooms:


 Usage: matty send [OPTIONS] [ROOM] [MESSAGE]

 Send a message to a room. Supports @mentions. (alias: s)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room         [ROOM]     Room ID or name                                              │
│   message      [MESSAGE]  Message to send (use @username for mentions)                 │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --stdin                      Read message from stdin                                   │
│ --file         -f      PATH  Read message from file                                    │
│ --no-mentions                Don't parse @mentions in messages                         │
│ --username     -u      TEXT  Matrix username (overrides MATRIX_USERNAME env var)       │
│ --password     -p      TEXT  Matrix password (overrides MATRIX_PASSWORD env var)       │
│ --help         -h            Show this message and exit.                               │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Reply Command

Reply to messages:


 Usage: matty reply [OPTIONS] [ROOM] [HANDLE] [MESSAGE]

 Reply to a specific message using its handle. (alias: re)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room         [ROOM]     Room ID or name                                              │
│   handle       [HANDLE]   Message handle (m1, m2, etc.) to reply to                    │
│   message      [MESSAGE]  Reply message                                                │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --no-mentions                Don't parse @mentions in messages                         │
│ --username     -u      TEXT  Matrix username (overrides MATRIX_USERNAME env var)       │
│ --password     -p      TEXT  Matrix password (overrides MATRIX_PASSWORD env var)       │
│ --help         -h            Show this message and exit.                               │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Thread Start Command

Start a thread from a message:


 Usage: matty thread-start [OPTIONS] [ROOM] [HANDLE] [MESSAGE]

 Start a new thread from a message using its handle. (alias: ts)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room         [ROOM]     Room ID or name                                              │
│   handle       [HANDLE]   Message handle (m1, m2, etc.) to start thread from           │
│   message      [MESSAGE]  First message in the thread                                  │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --no-mentions                Don't parse @mentions in messages                         │
│ --username     -u      TEXT  Matrix username (overrides MATRIX_USERNAME env var)       │
│ --password     -p      TEXT  Matrix password (overrides MATRIX_PASSWORD env var)       │
│ --help         -h            Show this message and exit.                               │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Thread Reply Command

Reply in a thread:


 Usage: matty thread-reply [OPTIONS] [ROOM] [THREAD_ID] [MESSAGE]

 Reply within an existing thread. (alias: tr)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room           [ROOM]       Room ID or name                                          │
│   thread_id      [THREAD_ID]  Thread ID (t1, t2, etc.) or full Matrix ID               │
│   message        [MESSAGE]    Reply message                                            │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --no-mentions                Don't parse @mentions in messages                         │
│ --username     -u      TEXT  Matrix username (overrides MATRIX_USERNAME env var)       │
│ --password     -p      TEXT  Matrix password (overrides MATRIX_PASSWORD env var)       │
│ --help         -h            Show this message and exit.                               │
╰────────────────────────────────────────────────────────────────────────────────────────╯

React Command

Add reactions to messages:


 Usage: matty react [OPTIONS] [ROOM] [HANDLE] [EMOJI]

 Add a reaction to a message using its handle. (alias: rx)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room        [ROOM]    Room ID or name                                                │
│   handle      [HANDLE]  Message handle (m1, m2, etc.) to react to                      │
│   emoji       [EMOJI]   Emoji reaction (e.g., 👍, ❤️, 😄)                              │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --username  -u      TEXT  Matrix username (overrides MATRIX_USERNAME env var)          │
│ --password  -p      TEXT  Matrix password (overrides MATRIX_PASSWORD env var)          │
│ --help      -h            Show this message and exit.                                  │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Reactions Command

View reactions on a message:


 Usage: matty reactions [OPTIONS] [ROOM] [HANDLE]

 Show detailed reactions for a specific message. (alias: rxs)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room        [ROOM]    Room ID or name                                                │
│   handle      [HANDLE]  Message handle (m1, m2, etc.) to show reactions for            │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --username  -u      TEXT                Matrix username (overrides MATRIX_USERNAME env │
│                                         var)                                           │
│ --password  -p      TEXT                Matrix password (overrides MATRIX_PASSWORD env │
│                                         var)                                           │
│ --format    -f      [rich|simple|json]  Output format (rich/simple/json)               │
│                                         [default: rich]                                │
│ --help      -h                          Show this message and exit.                    │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Redact Command

Delete/redact messages:


 Usage: matty redact [OPTIONS] [ROOM] [HANDLE]

 Delete/redact a message using its handle. (alias: del)

╭─ Arguments ────────────────────────────────────────────────────────────────────────────╮
│   room        [ROOM]    Room ID or name                                                │
│   handle      [HANDLE]  Message handle (m1, m2, etc.) to redact/delete                 │
╰────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────╮
│ --reason    -r      TEXT  Reason for redaction                                         │
│ --username  -u      TEXT  Matrix username (overrides MATRIX_USERNAME env var)          │
│ --password  -p      TEXT  Matrix password (overrides MATRIX_PASSWORD env var)          │
│ --help      -h            Show this message and exit.                                  │
╰────────────────────────────────────────────────────────────────────────────────────────╯

Command Aliases

For faster typing, all commands have short aliases:

  • matty rmatty rooms - List all rooms
  • matty mmatty messages - Show messages from a room
  • matty umatty users - Show users in a room
  • matty smatty send - Send a message
  • matty tmatty threads - List threads
  • matty thmatty thread - Show thread messages
  • matty rematty reply - Reply to a message
  • matty tsmatty thread-start - Start a thread
  • matty trmatty thread-reply - Reply in a thread
  • matty rxmatty react - Add a reaction to a message
  • matty delmatty redact - Delete/redact a message
  • matty rxsmatty reactions - Show reactions on a message

Examples

Basic Usage

# List all rooms
matty rooms
# or use alias: matty r

# Show users in a room (with mention hints)
matty users lobby
# or: matty u lobby

# Get recent messages from a room
matty messages lobby --limit 10
# or: matty m lobby --limit 10

# Send a message to a room
matty send lobby "Hello from CLI!"
# or: matty s lobby "Hello from CLI!"

# Send a message with mentions
matty send lobby "@alice check this out!"
# or: matty s lobby "@bob @alice meeting at 3pm"

# Use different output formats
matty rooms --format json
matty rooms --format simple
# or: matty r --format json

Working with Threads

# List threads in a room
matty threads lobby

# View messages in a specific thread (using simple ID)
matty thread lobby t1

# Start a thread from a message
matty thread-start lobby m2 "Starting a thread!"

# Reply in a thread (using simple thread ID)
matty thread-reply lobby t1 "Reply in thread"

Reactions and Redaction

# Add a reaction to a message
matty react lobby m3 "👍"
# or: matty rx lobby m3 "🚀"

# View reactions on a message
matty reactions lobby m3
# or: matty rxs lobby m3 --format simple

# Delete/redact a message
matty redact lobby m5 --reason "Accidental message"
# or: matty del lobby m5

Message Handles and Replies

# Reply to a message using handle
matty reply lobby m3 "This is a reply!"

# Reply to the 5th message in a room
matty messages lobby --limit 10
matty reply lobby m5 "Replying to message 5"

Mentions

The CLI supports @mentions in messages:

# Mention a user by username
matty send lobby "@alice can you check this?"

# Multiple mentions
matty send lobby "@bob @alice meeting in 5 minutes"

# List users to see available mentions
matty users lobby  # Shows User IDs and simplified @mentions

# Mentions work in replies and threads too
matty reply lobby m3 "@alice I agree with your point"
matty thread-reply lobby t1 "@bob what do you think?"

The mention system will:

  • Automatically find the full Matrix ID for @username mentions
  • Support full Matrix IDs like @user:server.com
  • Format mentions properly so users get notified

Message Handles and Thread IDs

The CLI uses convenient handles to reference messages and threads:

  • Message handles: m1, m2, m3, etc. - Reference messages by their position
  • Thread IDs: t1, t2, t3, etc. - Reference threads with simple persistent IDs

These IDs are stored in ~/.matrix_cli_ids.json and persist across sessions.

Why Simple IDs?

Matrix uses complex IDs like:

  • Event: $Uj2XuH2a8EqJBh4g:matrix.org
  • Room: !DfQvqvwXYsFjVcfLTp:matrix.org

Our CLI simplifies these to:

  • Messages: m1, m2, m3 (temporary handles for current view)
  • Threads: t1, t2, t3 (persistent IDs across sessions)

Output Formats

The CLI supports three output formats:

  1. Rich (default) - Beautiful terminal UI with tables and colors
  2. Simple - Plain text output, perfect for scripts
  3. JSON - Machine-readable format for automation

Example:

# Pretty tables with colors
matty rooms

# Simple text output
matty rooms --format simple

# JSON for automation
matty rooms --format json | jq '.[] | .name'

Project Structure

matrix-cli/
├── matty.py         # Main CLI application (functional style)
├── test_client.py        # Connection testing utility
├── tests/                # Test suite
│   ├── __init__.py
│   ├── conftest.py       # Pytest configuration
│   └── test_matrix_cli.py # Unit tests
├── .github/              # GitHub Actions workflows
│   └── workflows/
│       ├── pytest.yml    # Test runner
│       ├── release.yml   # PyPI release
│       └── markdown-code-runner.yml # README updater
├── .env                  # Your credentials (not in git)
├── .env.example          # Example environment file
├── CLAUDE.md            # Development guidelines
├── pyproject.toml       # Project configuration
└── README.md            # This file

Development

This project follows functional programming principles:

  • Private functions (_function_name) for internal logic
  • Dataclasses over dictionaries for data structures
  • Type hints everywhere for clarity
  • No unnecessary abstractions or class hierarchies
  • Functions over classes where possible

See CLAUDE.md for detailed development guidelines.

Testing

# Run tests
uv run pytest tests/ -v

# Test with coverage
uv run pytest tests/ -v --cov=matty --cov-report=term-missing

# Test connection to Matrix server
uv run python test_client.py

# Run pre-commit checks
uv run pre-commit run --all-files

License

MIT

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

matty-0.10.0.tar.gz (32.1 kB view details)

Uploaded Source

Built Distribution

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

matty-0.10.0-py3-none-any.whl (27.5 kB view details)

Uploaded Python 3

File details

Details for the file matty-0.10.0.tar.gz.

File metadata

  • Download URL: matty-0.10.0.tar.gz
  • Upload date:
  • Size: 32.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for matty-0.10.0.tar.gz
Algorithm Hash digest
SHA256 f1a5b409d3c99b50544f84b8214dad59cce6576504ebf324e066fc1a8ca96e29
MD5 6b6afbe5862fff6a30e20a0262e7ef0e
BLAKE2b-256 39d3c037b762ab1abffcaf36cbecc22c0c1c1f423e4ad130df37c40d1ac35922

See more details on using hashes here.

Provenance

The following attestation bundles were made for matty-0.10.0.tar.gz:

Publisher: release.yml on basnijholt/matty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file matty-0.10.0-py3-none-any.whl.

File metadata

  • Download URL: matty-0.10.0-py3-none-any.whl
  • Upload date:
  • Size: 27.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for matty-0.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 38a62a437c489527abfae8d09a402e212ea95368570e02021210bd7c472fd6a7
MD5 76328b73479d3dede500b4c222909243
BLAKE2b-256 caf7c1f4880398b9a5e0a13e5c744df669dcf0f1575b8c9267612ede546316d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for matty-0.10.0-py3-none-any.whl:

Publisher: release.yml on basnijholt/matty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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