For agents
mxr is built so an LLM agent can run it directly. The CLI emits structured JSON, every mutation has a dry-run, and the HTTP bridge exposes the same surface for non-shell clients. There is no provider-specific SDK to wrap, no headless browser, no DOM scraping — the agent uses the same commands a human would.
This page is the practical guide. For the comprehensive list of what’s safe to script, see the automation contract. For the field-level JSON shape, see JSON output schemas.
Safety primitives, all the time
Section titled “Safety primitives, all the time”- Read first.
mxr search,mxr cat,mxr stale,mxr sender,mxr summarizenever mutate. Use them to understand the situation before acting. - Dry-run everything.
--dry-runworks on every mutation; show the user the affected count before you run the real thing. --yesis opt-in. Without--yes, mutations prompt. When stdin isn’t a TTY (i.e. piped from an agent), pass--yesexplicitly so the user has a clear “I authorise this batch” moment in the loop.- Use
mxr history. Every mutation gets amutation_id. Capture it; offermxr undo <id>within ~60 seconds.
Worked example 1 — Newsletter prune
Section titled “Worked example 1 — Newsletter prune”Goal: unsubscribe from low-engagement subscriptions, archive the residue.
mxr subscriptions --rank --format jsonThe agent gets:
{ "subscriptions": [ { "sender": "newsletter@example.com", "list_id": "<list.example.com>", "messages_30d": 12, "open_rate_30d": 0.0, "last_opened": null, "unsubscribe": { "OneClick": { "url": "https://..." } } } /* ... */ ]}The agent picks candidates with open_rate_30d == 0 and messages_30d >= 4, presents them to the user, then dry-runs:
mxr unsubscribe --search 'list:<list.example.com> OR list:<...>' --dry-runUser confirms. Agent runs:
mxr unsubscribe --search 'list:<list.example.com> OR list:<...>' --yesmxr archive --search 'from:newsletter@example.com OR from:<...>' --yesAgent verifies and reports:
mxr history --category mutation --limit 3 --format jsonWorked example 2 — Meeting prep
Section titled “Worked example 2 — Meeting prep”Goal: for tomorrow’s 1:1 with Sarah, gather the relevant threads from the last two weeks and draft an agenda.
mxr search 'from:sarah@example.com OR to:sarah@example.com after:2026-04-23' --format jsonThe agent gets compact search rows with message_id, from, subject, date, read, starred, and score. When it needs thread context, it exports the matching search directly as markdown:
for tid in 01JFQ7K3M2X8N5R0VYZA9CTBPF 01JFQ8...; do mxr export "$tid" --format markdowndoneOr in one call with --search:
mxr export --search 'from:sarah@example.com OR to:sarah@example.com after:2026-04-23' --format markdown > /tmp/sarah-context.mdAgent feeds the markdown into its summariser, then uses mxr draft-assist to generate a suggested reply body on stdout. The agent can show that body to the user or pass it into mxr compose --body-stdin / mxr reply --body-stdin after approval:
mxr draft-assist <thread_id> "Build a 1:1 agenda. Group by open question, decision needed, status update."The agent never sends. The user reviews the generated body, saves a draft, or sends only after explicit approval.
Worked example 3 — CI failure cleanup
Section titled “Worked example 3 — CI failure cleanup”Goal: archive every CI failure email from last week whose underlying test has since been fixed.
mxr search 'from:noreply@github.com subject:"failed" after:2026-04-30' --format jsonFor each failure, the agent extracts the commit SHA and test name from the body (using mxr cat <id> --view reader). It cross-references against the local repo:
git log --since=1.week --pretty='%H %s' | grep -i 'fix.*test'It builds a list of message IDs to archive. Dry-run:
echo 01JFQ... 01JFQ... | xargs mxr archive --dry-runUser confirms. Apply:
echo 01JFQ... 01JFQ... | xargs mxr archive --yesCapture the mutation_id in the output. If the user notices an over-archive, the agent runs mxr undo <mutation_id> within 60 seconds.
What stays local, what doesn’t
Section titled “What stays local, what doesn’t”- Embeddings (semantic search) — local, with locally-stored model weights. Never sent off-device.
mxr summarizeandmxr draft-assist— call your configured[llm]endpoint. That can be a local server (Ollama, LM Studio) or a remote provider. Configure inconfig.toml. The thread content goes wherever the LLM is.- Provider mail content — passes through mxr to whatever provider the account is connected to (Gmail, IMAP). mxr never proxies through third parties.
If you want a strict local-only setup: set [llm].base_url = "http://localhost:11434/v1" for Ollama and [search.semantic].enabled = true. No third-party calls beyond your own provider.
Token-budget tips
Section titled “Token-budget tips”- Use
--limitaggressively.mxr search 'is:unread' --format json --limit 20is plenty for triage. - Use
--format idswhen you only need to drive a mutation. Saves tokens vs. full envelopes. - Use
mxr summarize <thread_id>for long threads instead of feedingmxr catinto the model. - Use
mxr export <thread_id> --format llmfor thread context formatted for an LLM (omits redundant headers, strips signatures).
IPC bucket model (skim)
Section titled “IPC bucket model (skim)”Behind the CLI, every request lands in one of four IPC buckets: core-mail, mxr-platform, admin-maintenance, client-specific. The first three are stable; the fourth is per-client view-shape and not part of the daemon contract. If you’re scripting against the HTTP bridge, think in those buckets — they’re the contract surface.
Current limits (be honest)
Section titled “Current limits (be honest)”- No first-party MCP server yet. The agent surface is the CLI plus the HTTP bridge; both are real and stable.
- No
--read-onlydaemon mode yet. Usesafety_policy = "restricted"or"read-only"in[general]to cap mutations daemon-wide if you need the guardrail. - No agent-specific account scoping yet. The agent sees every account the user sees.
If you need any of these as enforcement (rather than convention), file an issue — the design space is open.
See also
Section titled “See also”- Automation contract — exhaustive table of
--format,--dry-run, stdin support - JSON output schemas — field names for
jq - Recipes — pipelines for common tasks
- Agent skill — install the mxr skill into Claude Code, Cursor, Continue, Aider
- HTTP bridge — same surface over HTTP
- API explorer — interactive Scalar reference