Skip to content

Quick start

After installing, you have one binary: mxr. The TUI is what you’ll use most; the CLI handles scripting and one-off operations. Both talk to the same daemon.

Start with a realistic local demo before connecting your own mail:

Terminal window
mxr demo

This creates a separate mxr-demo config, database, socket, and daemon. It seeds a 50k-message, two-account synthetic inbox with repeat senders, threads, attachments, links, images, newsletters, promos, spam, suspicious inbox mail, receipts, alerts, and demo rules. Demo setup also prewarms analytics, Wrapped, and semantic vectors for the active profile so you can try search, labels, summaries, sender profiles, analytics, and keyboard triage without granting access to your real inbox.

The demo also pre-seeds every “empty queue” surface so the first click on any feature shows something useful: snippets, signatures, custom labels, saved searches, screener decisions, snoozed messages, reply-later flags, and a couple of in-progress drafts. LLM-backed features (summarize, briefing, ask, draft-assist, voice, decisions, commitments) are answered by an in-process canned provider, so the demo works fully offline — no OPENAI_API_KEY needed, and your real LLM credentials are never invoked even if [llm] is configured.

Demo mode is sticky. Once mxr demo finishes, every subsequent mxr command (mxr search, mxr cat, mxr archive, mxr web, …) automatically targets the demo profile. The TUI status bar and the web app’s topbar both show a DEMO chip so you always know which profile you’re on. Exit with:

Terminal window
mxr demo stop

Other demo subcommands:

Terminal window
mxr demo status # is demo active? where are its files?
mxr demo reset # wipe demo data so the next `mxr demo` re-seeds from scratch
mxr demo --reset # equivalent: reset + restart in one step
mxr demo --no-tui # seed + sync without launching the TUI

For Gmail on your local machine:

Terminal window
mxr accounts add gmail

The wizard prompts for an account name and your Gmail address, then opens a browser to authorize. If you’re SSH’d into a remote box, see the Gmail setup notes on SSH-friendly flows.

For IMAP+SMTP non-interactively (e.g. Gmail with an app password):

Terminal window
MXR_IMAP_PASSWORD="$APP_PASSWORD" MXR_SMTP_PASSWORD="$APP_PASSWORD" \
mxr accounts add imap-smtp \
--account-name personal \
--email you@gmail.com \
--imap-host imap.gmail.com \
--imap-username you@gmail.com \
--smtp-host smtp.gmail.com \
--smtp-username you@gmail.com

MXR_IMAP_PASSWORD / MXR_SMTP_PASSWORD env vars resolve when stdin is not a TTY — handy for CI. You can also pass --imap-password / --smtp-password literal values if you don’t mind shell history.

Terminal window
mxr sync --wait

--wait blocks until the initial sync completes. Subsequent syncs are incremental and run automatically in the background once the daemon is up.

Terminal window
mxr

j/k to navigate, <Enter> to open, R for reader mode, Ctrl-p for the command palette, / for search, ? for help.

Terminal window
# Search
mxr search "from:alice is:unread" --format json | jq .
# Read the first match
mxr cat <message-id>
# Reply and send
mxr reply <message-id> --body "On it." --yes
# Archive a query
mxr archive --search "label:newsletters older_than:30d" --dry-run
mxr archive --search "label:newsletters older_than:30d" --yes

Most read/list/status/mutation surfaces accept --format json; the generated CLI reference lists the exact formats per command.

Run into something? See Troubleshooting.