Search workflow
Core idea
Section titled “Core idea”mxr treats search as navigation, not a bolt-on filter. Search results drive the TUI mail list, saved searches, exports, and batch mutations.
Common patterns
Section titled “Common patterns”mxr search "from:alice unread"mxr search "label:work has:attachment"mxr search "subject:\"quarterly review\" after:2026-01-01"mxr search "unsubscribe"mxr search "label:inbox" --format idsmxr search "adrian in:inbox" --limit 1000mxr search "{from:amy from:david} subject:(dinner movie)"mxr search "holiday AROUND 10 vacation"mxr search "body:house of cards" --mode hybrid --explainmxr search "is:owed-reply"mxr search "has:calendar newer_than:30d"mxr search "is:unread" --account workThe is: filter has the usual suspects (unread, read, starred,
draft, sent, trash, spam, answered, inbox, archived,
reply-later) and one computed lens worth knowing about:
is:owed-reply(aliasis:owed) — threads where the latest message is inbound, no later outbound exists, the sender isn’t a newsletter/list, and the screener hasn’t denied them. Same result set asmxr owed, so the TUI sidebar can show it as a saved search.
Gmail-style operators are parsed by the mail-query crate, then executed
against mxr’s local index. The important practical consequence: syntax
parity is separate from storage parity. For example, Gmail’s color-star
operators parse, but mxr currently stores starred as a boolean, so
has:yellow-star and has:purple-question both mean “starred” locally.
Likewise +word is preserved in the AST as a no-stemming hint, but the
current Tantivy schema executes it like a normal text term until mxr grows
a non-stemmed mirror field.
Search modes
Section titled “Search modes”lexical: exact BM25/Tantivy retrievalhybrid: lexical + dense retrieval + RRFsemantic: dense retrieval only
Semantic search is optional. It is an mxr-platform feature layered on top of the mail runtime, not a requirement for normal mail sync/read/send.
Embeddings stay local. OCR is not used for semantic indexing.
Account-scoped search
Section titled “Account-scoped search”mxr search "from:github.com is:unread" --account work --format jsonmxr search "subject:invoice newer_than:30d" --account billing@example.com --format idsmxr count "has:calendar" --account personalWhat you get: search and count results limited to the selected account.
By default, mxr search searches all enabled accounts. Add
--account <selector> when you want one account only.
Selectors accept account key, email address, account id, or an unambiguous display name. Unknown or ambiguous selectors fail before the search runs.
Account filtering happens before pagination and applies to lexical,
hybrid, and semantic modes. That means --limit 50 --account work
returns up to 50 work-account hits, not “50 global hits, then filter to
work”.
mxr search "from:github.com is:unread" --account work --limit 50 --format jsonDedicated search page
Section titled “Dedicated search page”The TUI has two distinct search tools:
/from Mailbox opens Search and hits the full local indexCtrl-ffrom Mailbox filters only the current mailbox view
The Search page gives you:
- Query input
- Result list
- Preview pane
- Lexical / hybrid / semantic modes
- Normal open flow into mailbox/thread interaction once a result is previewed
Useful combinations
Section titled “Useful combinations”- Use
mxr search ... --format ids | xargs ...for shell pipelines. - Add
--account <selector>to keep a query, saved-search run, export, or mutation inside one account. - Save high-value searches in the TUI sidebar for recurring workflows.
- Use
mxr count QUERYfor quick status-bar or script integration. - Use
mxr export --search QUERY --format mboxto archive slices of mail. - Use
--explainwhen debugging hybrid/semantic fallback or dense contribution.
Fielded hybrid behavior
Section titled “Fielded hybrid behavior”Examples:
mxr search "body:house of cards" --mode hybrid --explainmxr search "subject:house of cards" --mode hybrid --explainmxr search "filename:house of cards" --mode hybrid --explainCurrent intent:
- lexical side stays literal and field-aware
- dense side respects chunk source kinds
body:searches body chunkssubject:searches header chunksfilename:searches attachment-origin chunks
Literal lexical matches should usually remain stronger than merely related semantic matches.
When search is fresh
Section titled “When search is fresh”- lexical search is fresh right after the sync batch commits
- hybrid search can use lexical results immediately, even if semantic retrieval is disabled
- semantic-only readiness depends on the active profile being built
Check semantic readiness with:
mxr semantic statusmxr doctor --semantic-statusTUI flow
Section titled “TUI flow”- Press
/in Mailbox to jump into Search. - Start typing. The Search page runs live after a short debounce.
- Press
Enterto run immediately when you do not want to wait for debounce. - Use
Tabto change lexical / hybrid / semantic mode while editing, or to switch results and preview when not editing. - Use
j/kto move the result cursor. - Use
Enter,o, orlto open the selected result in preview. - Use
Escto move preview -> results -> mailbox.
Search is full-corpus by design. It searches beyond the currently loaded mailbox slice.
Saved searches
Section titled “Saved searches”Saved searches are not a secondary convenience. They are persistent inbox lenses and appear in:
- The sidebar
- Command palette
- CLI via
mxr saved
Common flow:
mxr saved add urgent "label:inbox unread from:boss@example.com"mxr saved listmxr saved run urgentIn real life
Section titled “In real life”- Quick “did I miss anything important today”:
mxr search 'is:unread label:inbox newer_than:1d' --format json | jq 'group_by(.from) | map({sender:.[0].from, count:length})' - Find that one PDF you were sent last quarter:
mxr search 'has:attachment filename:pricing.pdf older_than:90d' --mode hybrid - Bulk-archive every receipt 30 days old:
mxr search 'label:receipts older_than:30d' --format ids | mxr archive --yes - Build a digest before a 1:1:
mxr search 'from:sarah newer_than:7d' --format json | jq -r '.[].subject' - Pull only real conversations, hide newsletters:
mxr search 'is:unread has:link-none'— strips link-heavy promotional/transactional mail in one filter. - Triage the newsletter pile in bulk:
mxr search 'has:link-heavy older_than:7d' --format ids | mxr archive --yes— auto-archives newsletter-shaped mail older than a week. - Find a shared doc someone sent you:
mxr search 'from:alice has:link newer_than:14d'—has:linkexcludes trackers/unsubscribe URLs, so it surfaces real link-bearing replies. - Work the owed-reply backlog:
mxr search 'is:owed-reply' --format ids | mxr remind --when 'friday 16:00'— pin a Friday-afternoon nudge on every thread you owe a reply on. - Owed within the last two weeks only:
mxr search 'is:owed-reply newer_than:14d'— skip ancient threads you’ve implicitly already ignored. - Review recent meeting invites:
mxr search 'has:calendar newer_than:30d' --format ids | xargs -I{} mxr invite show {}— inspect invite details before deciding whether to RSVP.
Agent prompts that work
Section titled “Agent prompts that work”"Find every email mentioning 'launch checklist' since last Monday andsummarise what's still open. Use `mxr search 'launch checklistnewer_than:7d' --format json` and `mxr summarize` for any thread with4+ messages.""What did Bob email me about pricing in Q1? Use hybrid search and`--explain` so I can see why each result matched: `mxr search'from:bob pricing after:2026-01-01 before:2026-04-01' --mode hybrid--explain`."