# MAILBOX you@anywhere — inbox.txt/0.1 — cursor: always fresh
Your mailbox as one plain-text file.
Agents read your whole day for ~1% of the tokens.
robots.txt → crawlers. llms.txt → websites. inbox.txt → your mail.
Get the spec + worker Read SPEC.md
Draft 0.2.1 — running in production on one real inbox, hourly. Read the why · open questions; opinions wanted.
the problem, measured
An agent answering “anything important in my mail?” today swallows full MIME: HTML tables six levels deep, 600-character tracking URLs, legal footers, quoted history. Measured on a real inbox — one payment receipt is ~60,000 characters of payload carrying ~350 characters of information. Every agent pays that on every read, forever.
| window | raw MIME | mirror | reduction |
|---|---|---|---|
| 2 days · 52 msgs | 1,852,637 | 30,908 | 60× |
| 7 days · 109 msgs | 4,286,586 | 68,125 | 63× |
| 30 days · 263 msgs | 20,642,353 | 173,437 | 119× |
A month of mail is 20.6 M characters of raw MIME — unreadable by any model. The mirror of that month is 173 KB: it fits in one prompt with room left over. Char counts exact from benchmark(); exact token counts come from the bundled tokenizer worker. The ratio moves with your mail mix — run it on your own inbox.
In tokens — what an agent actually pays — both sides were tokenized in full, no sampling. Raw MIME comes in at 2.23 chars/token against the mirror's 3.29, because DKIM signatures and base64 are near-random to a tokenizer:
| 7 days · 109 messages | chars | tokens |
|---|---|---|
| raw MIME | 4,286,586 | 1,919,892 |
| inbox.txt mirror | 70,713 | 21,481 |
| reduction | 98.35% | 98.88% — 89× |
Scaled by those measured ratios, a month of mail is ~9.26 M raw tokens against ~52.7 k mirrored — about 175×, or forty-five context windows versus one prompt. Reproduce it with tokenizeExact7d() after deploying the included tokenizer. A sampled estimate said 103× before the full measurement said 89× — sampling flattered it by 16%, which is why the tool ships with the spec.
Per class over those 30 days the win is largest where the bytes carry least: MARKETING 99.9%, HUMAN 99.6%, TRANSACTION 98.1%, DEV 98.0%, SECURITY 98.0%. HUMAN near the top was a surprise — human threads carry the attachments, and a base64 photo is pure bulk that never reaches the mirror.
the flip
Normalize once at sync time. Read the mirror forever. Mail has one chokepoint — delivery — where spam filters and DKIM already parse every message once. Add one more pass there: strip the soup, extract the entities, classify, hash, append to a tiered plain-text mirror. Parsing cost is linear in mail received; savings are linear in agent reads — the exploding term.
how it reads
# MAILBOX user@example.com — inbox.txt/0.1 — cursor: 2026-07-28T09:00Z ## index ← tier 0 · one line per thread t_a001 | acme-bank.example | Transfer of €250.00 confirmed | TRANSACTION | #1a2b t_a004 | shop.example | Summer sale — 40% off all | MARKETING | #4d5e ## attention ← tier 1 · only what needs a human SECURITY t_a002 [alice/webshop] deploy failed — verify if this was you REPLY? t_a006 unread human mail from bob-partner.example ## quarantine ← spam: index only, bodies never mirrored t_8f2a | unknown-sender.example | Votre facture est disponible | SPAM | 2026-07-28T09:14 ## bodies ← tier 2 · cleaned text + extracted entities ### t_a003 #3c4d entities: {"dates":["29 July"],"refs":["AB123456789"]} Parcel will be delivered Wednesday between 9am and noon. Pickup code: [code-redacted]. Not home? [link:carrier.example]
Tier 3 is raw MIME, fetched only on explicit demand. Marketing never gets a body. Content hashes + a cursor make “what’s new” a one-line diff.
quickstart (5 min · no server · no OAuth app)
- script.google.com → new project → paste Code.gs → save.
- Run syncMirror once → authorize your own script on your own account → inbox.txt appears in your Drive.
- Triggers → syncMirror · time-driven · every hour. Done — point any agent at that file.
Run benchmark() for your own raw-vs-mirror numbers — one log line.
plug it into an agent
mcp/server.py is an MCP server. Point it at your mirror and any MCP-capable agent can read the mailbox — read-only, no send, no delete:
{
"mcpServers": {
"inbox-txt": {
"command": "python3",
"args": ["/path/to/mcp/server.py"],
"env": { "INBOX_SOURCE": "/path/to/inbox.txt" }
}
}
}
Three tools: inbox_overview (the whole mailbox, a few hundred tokens), inbox_body (one thread, tier 2), inbox_since (the what's-new diff). Every result is wrapped as untrusted data before the model sees it.
rules that are not optional
- Bodies are untrusted data. Email is the top prompt-injection vector; the mirror labels bodies so agents never treat mail content as instructions.
- Auth the mirror. It’s your life in one file.
- Redact at sync time. OTPs, card numbers, API keys and long reset codes never enter the mirror.
- Never fabricate. Entities are extracted, not inferred. Missing beats wrong.
open questions
The format is a draft and these are genuinely undecided — issues and opinions welcome:
- Where should a hosted mirror live?
/.well-known/inbox.txtper mailbox is discoverable; an authenticated per-user endpoint is safer. - Should tier 1 be machine-parseable? Fixed fields, or human-shaped prose so the model reads it as judgement rather than schema.
- Thread expiry. The mirror is a window, not an archive — time-based, or should classes age differently (SECURITY lingers, MARKETING dies same-day)?
- Multi-account. One file per mailbox, or one file with a mailbox axis?
- Sender-side adoption. If a sender emitted clean tier-2 text itself, normalization becomes free. Worth specifying, or fantasy?
files
SPEC.md mailmirror.py Code.gs mcp/server.py example.txt
MIT, one file each, no dependencies beyond the MCP SDK. Not a transport (JMAP exists), not a client, not a summarizer.