Encrypted terminal client for the Fortrx messaging system.
This client is built around:
- End-to-End Encryption: X3DH / PQXDH-style session bootstrap ensures secure communication.
- Local-First & Offline: Chat history is stored in an encrypted client database (SQLCipher), allowing you to read synced conversations without an internet connection.
- Background Daemon: Runs silently in the background for inbox sync, live delivery, and presence updates.
- Encrypted key initialization and local private-key storage
- Local chat history and conversation summaries
- Background daemon for sync and WebSocket listening
- Contacts and conversation overview
- Offline chat viewing with
--no-sync - Self-messaging stored locally as
Saved Messages
- Python 3.11+
- A running Fortrx server
- Redis enabled on the server for live delivery and presence
- SQLCipher Python bindings are preferred for encrypted local storage
Production defaults to https://fortrx-server.duckdns.org.
For local development, create .env.local with:
SERVER_URL=http://localhost:8000You can also point the client at a different stack by setting FORTRX_ENV_FILE to an alternate env file path before running commands.
Install dependencies:
pip install -r requirements.txt-
Log in:
py run.py login <username> --password <account_password> --storage-password <local_storage_password>
-
Initialize keys once:
py run.py init --password <local_storage_password>
-
Start the background daemon:
py run.py daemon start --password <local_storage_password>
-
Send a message:
py run.py send <recipient_id> "hello" --password <local_storage_password>
-
View conversations:
py run.py contacts --password <local_storage_password> py run.py inbox --password <local_storage_password> py run.py chat <contact_id> --password <local_storage_password>
Authentication and setup:
py run.py register <username> <email> --password <account_password>
py run.py login <username> --password <account_password> --storage-password <local_storage_password>
py run.py init --password <local_storage_password>
py run.py verify <user_id> --password <local_storage_password>Messaging:
py run.py send <recipient_id> "message" --password <local_storage_password>
py run.py inbox --password <local_storage_password>
py run.py contacts --password <local_storage_password>
py run.py chat <contact_id> --password <local_storage_password>
py run.py chat <contact_id> --password <local_storage_password> --before 2026-04-08T10:00:00+00:00Daemon and sync:
py run.py daemon start --password <local_storage_password>
py run.py daemon run --password <local_storage_password>
py run.py daemon status
py run.py daemon stopOffline usage:
py run.py contacts --password <local_storage_password> --no-sync
py run.py inbox --password <local_storage_password> --no-sync
py run.py chat <contact_id> --password <local_storage_password> --no-syncThe client stores data in .fortrx/fortrx.db by default.
The database contains:
- encrypted auth token storage
- private keys
- ratchet sessions
- message history
- conversation summaries
- presence cache
- verification data
Already-synced messages can be read offline. New messages still require the server.
- Sending to yourself does not go through the server. Those messages are stored locally as
Saved Messages. contactsis the fastest overview command for large histories because it uses conversation summaries instead of scanning all messages.inboxmarks listed conversations as viewed.chat <contact_id>marks only that conversation as viewed.
Run a quick compile sanity check:
@'
import compileall
print(compileall.compile_dir("client", quiet=1))
'@ | python -Run tests:
pytest- CLI entrypoint: run.py
- Main app: client/main.py
- Local DB layer: client/storage/db.py
- Messaging flow: client/services/messaging.py
- Daemon: client/services/daemon.py