Three windows, one engine
How Malachi Mail is built, for the curious, for your IT and for developers: one engine, three native windows, what runs where, how little it needs, what keeps hostile mail in check, and how to build a client of your own on the same engine.
Native on every desktop
Not a web page in a frame. Each client is written in its platform's own language and toolkit, with its keyring, notifications and conventions, and all three are driven by the same mail engine: the same behaviour, the same security decisions, one set of translations.
How it fits together
The engine, malachid, is one Go program that owns everything about mail: accounts and synchronisation, the local store and its search index, HTML sanitising, threading, the Board's rules, the calendar, Jira and the CRM. A window is a separate process that only shows and sends commands, over JSON-RPC on a local socket the engine protects with a key it generates at every start. The GTK client is the reference; the macOS and Windows apps mirror it feature for feature, and the MCP bridge for agents is a client of the same engine with the rights of a window, no more.
The same source tree builds the engine for all three systems; what differs between them, the keyring, the notifications, the web view, lives in the client. The decisions and their reasons are in the project's architecture notes.
A mail client should not cost more than the mail
The window is GTK, AppKit or WinUI. The system's own web view draws the message body, and only while a message is open.
The whole mail engine, from IMAP to the search index, is a single native program with no runtime to carry.
Stored mail is compressed transparently. Preferences show the space used.
Keep attachments offline for 30 days, for ever, or never: older ones stay on the server until you open them.
Security your IT will read
Built for hostile mail
Every message is sanitised in the engine before a window sees it. Remote images stay blocked until you say so, the renderer has no network, passwords never leave the system keyring, and every parser is tested against deliberately broken mail.
Two processes, one key
Passwords and tokens only in the system keyring: Secret Service, the login keychain, Credential Manager. A server's certificate can be pinned by its fingerprint, and there is no ignore certificate. The window and the engine authenticate each other with a key the engine writes at every start. The engine talks to your mail servers, your Jira, your CalDAV server and your CRM, and to nothing else unless you turn an assistant on.
Tools decided at start, not by the model
What an agent may do is fixed when the MCP bridge starts. A tool outside the granted tier is not registered at all, so it does not even appear in the agent's list. Reading and drafts are always allowed; modifying, sending and triage are separate flags.
Mail is data, not instructions
Everything that comes from a message, a calendar or an issue is fenced with a one-time marker before the model sees it, and the bridge tells the model so. The assistant can annotate the board, but cannot set a state, a reminder or Done, archive, or delete a draft.
The whole threat model is in the project's security notes; what the assistant may and may not do is on its own page.
The interfaces underneath
Where the choice of interface makes the difference.
Microsoft 365 through Microsoft Graph
Not IMAP, not EWS: the API Microsoft keeps. It works where basic authentication is off, signs in in your browser with the client the app ships, and the calendar comes with the same sign-in.
Microsoft is retiring Exchange Web Services for Exchange Online from October 2026; clients built on it are still catching up.
An MCP bridge for your agents
Claude Code, Claude Desktop, Cursor, Zed or any MCP client gets a gated view of the mail, the calendar and the board. Mail content is fenced as data, never as instructions, and attachments arrive as text.
Build a client of your own
The engine is meant to be reused: not only by the three windows here, but by any mail client you want to write.
Everything a mail client needs is behind the engine's API: accounts and their sign-in, synchronisation with IMAP, Microsoft Graph, Jira, CalDAV and eWay-CRM, the local store with its retention and compression, search, threading, sanitised HTML bodies, attachments on demand, drafts and the outbox, the board, the calendar, the keyring, and a notification for every change. A client shows and asks; it never parses a message, never sees a password and never talks to a server. That is also why a new client inherits every security decision of the engine on its first day.
The contract is JSON-RPC 2.0 over a local socket, one JSON object per line, with a handshake on a key the engine writes at every start. It is written down method by method, with every notification and error code, in the API document; the Go types in backend/pkg/api are its machine-readable form and change in the same commit, under a protocol version. Any language will do: the GTK client is Go, the macOS client Swift, the Windows client C#, and the MCP bridge is a client of the same engine. malachi-rpc in the repository calls any method from the command line before a window exists, and malachi-devmail gives you a sample mailbox with a Jira site and a CRM to develop against, with no account of your own at risk.
Start with the architecture notes and the API, run the engine alone with make run-backend, and keep the one rule that makes a client small: logic belongs in the engine, a window only displays. An open-source client is free to build and ship under the AGPL; a proprietary one takes the commercial licence below.
Open source, two licences
The engine is licensed under the AGPL-3.0 and is also available under a commercial licence for products that cannot be AGPL; the three clients and everything else are GPL-3.0-or-later. The notices of third-party components ship with every package. Details are in LICENSING.md; what each client needs and uses is in the table of the three clients, and building from source is described on the download page.