Talk to your whole inbox.
A terminal session. mxr search returns matches from thousands of messages, the JSON output goes through jq to rank senders by volume, and mxr subscriptions lists newsletters by how often they get opened.
A keyboard-driven inbox filling the terminal, with a mailbox sidebar, a search across the whole index, and the rules and accounts screens.
An AI agent works the same inbox. It writes mxr search and jq pipelines to find the senders behind phishing attempts, then says which ones to be careful with.
try it
Section titled “try it”These commands work after mxr demo or after you connect an account.
# search your whole mailbox from the local indexmxr search "from:supplier@example.com has:attachment after:2019"
# rank newsletters by how little you read them, then leavemxr subscriptions --rank --format jsonmxr unsubscribe newsletter@example.com --dry-run
# surface what you owe a reply tomxr owed --since 7 --format json
# give an agent structured resultsmxr search "from:sarah@example.com after:2026-04-23" --format json | jq '.results[0]'Most reads can return JSON. Core mail mutations support --dry-run, so scripts and agents can show their work before changing your mailbox. Browse more examples →
read and search without a connection
Section titled “read and search without a connection”Your synced mail stays available.
Open mxr on a plane with the wifi off. Read a thread, search the archive, and write the replies you owe. Opening a message is a SQLite read, and a draft saves straight to disk. When you reconnect, mxr pulls in new mail and you can send the drafts you wrote offline.
Years of messages and labels stay indexed locally. Attachment names, types, and sizes are part of the local record. mxr downloads an attachment into its cache when you open it.
search your full history on disk
Section titled “search your full history on disk”Find a 2019 contract by the supplier’s name. Pull every receipt from a vendor. List the apology email you sent in March. mxr indexes subject, body, sender, and attachment filenames with Tantivy. Lexical search runs against the index on your disk, without a provider round trip or provider rate limit. Optional local embeddings add hybrid and semantic search.
The same local record makes mailbox analytics cheap to run: storage by sender or attachment type, response times, stale threads, subscription activity, and a year-in-review.
mxr storage --by label --limit 20mxr stale --mine --older-than-days 14mxr wrappedmxr search "subject:invoice" --format json | jq -r '.results[].from' | sort -ulet your agent use the same inbox
Section titled “let your agent use the same inbox”Search and mail reads stay on your computer. Once your mail is synced, a hosted model call is the only network wait in this workflow. The agent can use the CLI or the first-party MCP server to search, read, draft, summarize, export, and preview changes.
mxr search "from:sarah@example.com OR to:sarah@example.com" --format jsonmxr sender sarah@example.com --format jsonmxr draft-assist <thread-id> "short reply in my usual tone"mxr search "from:ci@github.com after:2026-04-30" --format json | jq -r '.results[] | [.message_id, .subject] | @tsv'git log --since=1.week --pretty='%H %s'mxr search "from:ci@github.com after:2026-04-30 subject:upload" --format ids | mxr archive --yesThe CLI, MCP server, web bridge, and TUI all call the same daemon. Most read commands can return JSON. Core mail mutations support --dry-run, and MCP mutation and send tools require confirm=true. See the automation contract →
mxr search "from:sarah@example.com after:2026-04-23" \ --mode lexical --sort relevance --format json | jq '.results[0]'{ "message_id": "019706f4-9b6e-7c31-8a3f-2a1c4de50b91", "from": "Sarah Chen <sarah@example.com>", "subject": "1:1 prep, Friday", "date": "2026-04-30T15:42:11+00:00", "read": false, "starred": false, "score": 12.4}changes stay in sync
Section titled “changes stay in sync”mxr keeps a local copy and syncs changes in both directions. Read, label, and archive in another client; mxr picks up those changes. Make the same changes in mxr; your provider receives them.
- → read a thread in Gmail web on your phone
- → apply a label in Apple Mail
- → archive a newsletter from your watch
+ IMAP / SMTP
+ IDLE
- ← mxr sees the read state
- ← the label appears in mxr’s sidebar
- ← the newsletter leaves the inbox
Gmail, Outlook, and your IMAP server remain upstream. The synced local archive stays readable on your computer when the provider or network is unavailable.
one mailbox, several interfaces
Section titled “one mailbox, several interfaces”The daemon owns sync, storage, search, rules, and provider connections. The TUI, CLI, web app, MCP server, and agent skill use the same mail and the same permissions.
Vim-native keys, Gmail-style chords, full-mailbox search, account setup, rules, and analytics. Compose in $EDITOR.
mxrSearch, read, draft, send, and manage mail from scripts or one-off commands. Pipe JSON through jq, xargs, or anything else in your shell.
mxr archive --search "from:noreply@example.com older_than:30d" --dry-run
would archive 142 messages.mxr web opens the browser app through the local HTTP and WebSocket bridge. The same bridge publishes OpenAPI and can support another client.
curl -H "Authorization: Bearer $TOKEN" \
"http://mxr.localhost:42829/api/v1/mail/search?q=is:unread"
{"results": [...]}Run mxr mcp serve for typed MCP tools, or give a shell-capable agent the mxr skill. Both use daemon-enforced account scopes and safety gates.
mxr mcp servedaily mail tools
Section titled “daily mail tools”install
three methodsHomebrew
brew install planetaryescape/mxr/mxrCargo
cargo install --git \ https://github.com/planetaryescape/mxr \ --locked mxrmxr demo uses a separate config, database, and daemon. It seeds 50,000 messages across two accounts and warms search and analytics before opening the TUI.
documentation
Section titled “documentation”Built in Rust as one binary for the supported macOS and Linux release targets. There is no telemetry and no mxr-operated server between you and your mail provider. If you use mxr and like it, star the repo so more people can find it. Contributions are welcome across provider adapters, clients, CLI commands, documentation, and tests.