A fast Gmail and Google Calendar client for macOS.
Keyboard-driven, several accounts in one stream, and an agent with real tools over your mail and calendar. It talks to the Google APIs directly and to nothing else — no IMAP, no Outlook, no Fastmail. That is a decision, not a gap.
Every pixel renders from a local SQLite database. Opening a thread is a local read, not a request — sub-millisecond, and it works with the network off. Sync is a background loop writing into that database; the UI reacts to the changes. This is the reason the app exists, not an optimisation bolted on afterwards.
- Local first
- A 12-month backfill per account, then incremental history sync from a stored watermark. Nothing in the UI blocks on Google.
- Two-tier search
- FTS5 over the local window answers every keystroke in under 10 ms. Gmail's own server search fires in parallel and merges in as older results a moment later.
- Keyboard first
- ⌘K for search, commands and anything else; J K to move, E to archive, H to snooze, R to reply. Actions are undoable.
- Several accounts
- One ordered stream, with a colour bar per account on every row. Replies infer the from-address from the account the thread arrived on.
- A real calendar
- Day, week and month, drag to create, drag to move — not a sidebar of upcoming events.
- An agent with real tools
- Every action is a typed command in Rust, and those same commands are the agent's entire tool surface. It gets no privileged path to Google, so anything it does is undoable and shows up in the same log as anything you did by hand.
None of the following is a roadmap item. They are out of scope on purpose, and saying so is the most useful thing on this page.
- No IMAP or SMTP. The Gmail API only — the IMAP architecture is the one this design rejects.
- No other providers. No Outlook, Fastmail, iCloud, or generic mail.
- No mobile, no web, no Windows, no Linux. Refresh tokens live in the macOS Keychain and the UI is a WKWebView.
- No teams, no sharing, no settings screens for anything a constant already expresses.
- No packaged build, no releases, no auto-update. You build it from source.
-
Prerequisites
-
Bring your own Google OAuth app
Mach ships no credentials. Every user registers their own Google Cloud project and OAuth client, because this app is not submitted to Google for verification and never will be. Hand
skills/mach-setup/SKILL.mdto a coding agent that can drive a browser and it will walk the console with you — project, APIs, consent screen, a Desktop app client, the six scopes, publishing, and writing.env.local. It stops and hands the keyboard back for your password and for accepting the User Data Policy. The same file is a click-by-click checklist if you would rather do it yourself.The scary screen is expected. The first time you authorise each account, Google shows "Google hasn't verified this app". Click Advanced → Go to Mach (unsafe) and continue. It is a one-time cost per account and it is not a failure.
Publish the app to In production even though it is unverified. Left in Testing, Google expires every refresh token after seven days, which means re-authorising every account every week.
-
Build and run
git clone https://github.com/bborn/mach cd mach bun install bun run tauri devThen ⌘K → Add account. Missing credentials are a state rather than a crash: the app boots, the window paints, and the UI tells you it cannot add an account.
This is one person's mail client, built for their own use and published because someone else may find it useful. It is not a product, there is no support, and there are no releases. It is in daily use by its author.
Expect rough edges: no packaged build or auto-update, no first-run
onboarding beyond "add an account", and marketing-email HTML that renders
imperfectly. cargo test and bunx vitest run are
the safety net; there is no end-to-end suite. One command,
⌘K → Send feedback, files its result into the
author's own task runner, which you almost certainly do not have — it
says so rather than failing silently.
The architecture, and the argument for it, is written down in the repo: the design record and the README.