Agent-facing command mailbox over mail, calendars, todos and contacts. A daemon
holds a local Mirror of the servers; the CLI reads the Mirror and never waits on a
network. The CLI is not a mail client: the human surfaces — the Qt client in
gui/, the bar widgets in plugins/ — are clients of the same socket reading the
same Mirror. How it fits together: docs/DESIGN.md.
Mirror: The daemon's local copy of what the servers hold. It is the answer a read command gives, not an optimisation in front of one — dropping it changes what the CLI can answer until it is rebuilt. Avoid: cache, index, local store
Daemon: The single long-lived process that owns every server connection and the Mirror. Nothing else opens IMAP, SMTP or DAV. Avoid: server, service, agent
Mirrored: Held in the Mirror, and therefore answerable offline. Every Message's envelope and text is Mirrored; an Attachment never is. Avoid: cached, synced, downloaded
Behind: The Mirror has not caught up with a server it can reach, or cannot reach it. A Behind Mirror still answers; it says so rather than failing. Avoid: stale, dirty, offline (that describes the network, not the Mirror)
Account: One login that mail comes from: IMAP + SMTP, or a Microsoft 365 sign-in. Several may be configured. Avoid: mailbox (that named the single account before there were several), profile
Backend: How an Account is spoken to: IMAP, SMTP and DAV, or Microsoft Graph for a Microsoft 365 Account, which carries its mail, calendars and contacts behind one sign-in. Nothing above the drivers knows which: a Graph Account has the same ids, Boxes and Collections as any other. Avoid: provider, server type
Primary Account: The Account carrying the Screener, Feed, Paper Trail, Aside and Block, and the Sieve Routing that fills them. There is exactly one, and it is what an unqualified ID means. Avoid: main account, default account
Secondary Account: An Account with an Inbox, Drafts and Sent, the ability to Send, and the piles — Aside, Reply Later and Bubble Up. A Graph Secondary can also carry the full Routing (Screener, Feed, Paper Trail, Block) as inbox rules; an IMAP Secondary carries only the piles. Its own connections and its own cycle, sharing the one Mirror: every row in it carries an Account. A listing spans every Account; an id names one. Avoid: extra account, sub-account
Account Colour:
An Account's identity on screen: the edge of its rows and the Send button of a mail
leaving from it. An Omarchy palette name, so it follows the theme, or a fixed
#rrggbb. The Primary's is the accent unless the config says otherwise.
Avoid: account tag, badge colour
Box:
An IMAP folder on an Account, named by an alias (inbox) or by its folder name
(INBOX/Screener).
Avoid: folder, mailbox, label
Routing:
The server-side rules that file new mail before this program sees it: blocked
senders discarded, then the Inbox, the Paper Trail and the Feed, everything left
over into the Screener. On the Primary Account it is the Sieve script on the
server; on a Graph Secondary it is the account's mailbox: inbox rules
(ADR-0032). The script or rules are the record and the Mirror's copy is a
projection. Sieve routing is in force when it is the server's active script or
when the active one includes it; Graph routing is in force when its catch-all
rule is present. A decision is about an address or a whole domain
(@example.com); an address always wins.
Avoid: filter, rule, sieve (that is the language it is written in)
Destination: Where the Routing sends one sender's mail: Inbox, Feed, Paper Trail or Block. The Screener is the absence of one, not a fifth. Named by an address or by a domain key. A decision can be made on mail read in any Box, not only the Screener's — the mail it was read on moves with it. Avoid: category, label, bucket
Screener:
Box INBOX/Screener. Mail from senders the Routing has no Destination for. A
decision is owed, and it is owed per sender rather than per Message.
Avoid: quarantine, gatekeeper, junk
Feed:
Box INBOX/Feed. Mail to skim rather than answer, marked read on arrival.
Avoid: newsletters, subscriptions
Paper Trail:
Box INBOX/Paper Trail — the name has a space in it. Receipts, confirmations,
records; marked read on arrival.
Avoid: PaperTrail, receipts, archive
Block:
A Destination and a Box. Blocking a sender discards their next mail; the waiting
mail is marked read and moved to Trash, where a mistake is still findable.
INBOX/Screener/Block is a drop target, not a pile: mail dragged into it from
another client is a block not yet written, and it is emptied once it is.
Avoid: spam, junk (those are the provider's), blacklist
Pickup: Mail that is collected rather than read: a login code, magic link or registration link, worth thirty seconds and then nothing. On arrival the Daemon takes the code out — or the link, when there is no code — puts it on the clipboard and says so, marks the mail read and bins it a quarter of an hour later. The link is copied, never followed: opening it would log you in from a notification you had not read. A Pickup owes no Routing decision — its sender is a login form you used once. Recognised from the subject, which is the only part of an auth mail that announces the genre; the body is where the code is extracted, never where the mail is classified. Avoid: OTP, 2FA mail, verification email, code (that names what it carries)
Aside:
Box INBOX/Aside, the read-later pile. A conversation is moved there and back as a
whole — setting one Message aside takes the rest of its thread out of the Inbox
with it, so the two never show halves of one conversation. The Routing never fills
it: "read this later" is a decision about a conversation, not about who sent it. A
reply landing in the thread pulls its Aside Messages back to the Inbox. A copy in
Sent stays put.
Avoid: snooze, star, later, set-aside (as a verb)
Reply Later:
Box INBOX/Reply Later — the name has a space in it. The pile of conversations you
owe a reply. Like Aside it takes and releases a whole thread at a time, and the
Routing never fills it. Answering the conversation — or a reply arriving in it from
anyone — pulls its Messages back to the Inbox: the debt is paid, or the conversation
is live again.
Avoid: snooze, follow-up, todo, reply-later (as a verb)
Bubble:
A thread set aside to come back to the Inbox on its own at a time you pick, unread,
so the phone raises a notification. It waits in Aside carrying a $bubble-* IMAP
keyword — the return time, and the record; the Mirror's column beside it is a
projection.
Avoid: snooze, reminder, defer
Message: One email, identified by its RFC822 Message-ID within an Account. Survives being moved between Boxes. Avoid: sequence number, uid (that names a Placement)
Placement:
Where a Message currently sits: a Box, a uid, and its flags. A Message usually has
one; a mail sent to yourself has two. Named [account/]box:uid —
INBOX/Screener:342 on the Primary Account, gmx/INBOX:412 on a Secondary one.
Avoid: copy, location, instance
Thread: Messages linked by References and In-Reply-To, built by the Daemon across every Box. Confined to one Account: the same conversation reaching two Accounts is two Threads. A Box listing collapses it to one row badged with the whole Thread's size — every Message wherever it sits — not just the part of it in the Box being listed. Avoid: conversation, IMAP thread (that is per-folder and narrower)
Label: An IMAP keyword on a Placement. A Message carries as many as you like and keeps all of them when it moves, which is the whole difference between labelling something and putting it in a Box. The list is derived from the mail carrying them; only a Label created and not yet used is remembered in the Mirror. A listing shows the Labels of the whole Thread, one word each — a space would reach the server as two keywords. Avoid: tag, folder, category
Search: A ranked full-text query answered entirely from the Mirror, over the sender, recipients, subject and text of every Message outside Trash. Never a server query. Avoid: IMAP SEARCH, semantic search
Correspondent: An address this mailbox has exchanged mail with, kept in step as mail is mirrored. The fallback for recipient autocomplete, after the address book. Avoid: contact (that is a card on a server), sender
Attachment: A non-text part of a Message. Never Mirrored; naming one fetches it. Avoid: file, part
Outbox: The durable local queue of Messages accepted for Send. A Message is in it before SMTP has seen it and stays afterwards, so "did that go out?" has an answer. The one place where the Mirror leads the server, and the one file that is never rebuilt. Avoid: queue, drafts, spool
Held: An Outbox Message that was at the SMTP server when the Daemon stopped. It may or may not have been delivered, so nothing sends it again until a caller says so. Avoid: failed, stuck, pending
Collection: A CalDAV or CardDAV collection on a server — one calendar, one task list, or one address book. Found by enumerating the server and matching its display name, never by a URL written down by hand. Avoid: folder, home, calendar (that is one kind of Collection)
Calendar: A Collection of Events. Avoid: Kalender (that is one Calendar's name)
Event: A timed or all-day entry on a Calendar. Avoid: meeting, appointment
Todo: Work on a task-list Collection. Undated by default; completing it ends it. Avoid: task, reminder
Habit: A repeating per-day practice. Completing one day does not end it. Not an Event and not a Todo. Avoid: recurring task, recurring event
Contact: A person on an address-book Collection. The vCard is the record; the name, addresses and numbers the Mirror holds beside it are a projection. Avoid: address, card