Skip to content
nick-friedrichPublic

About

Private, multi-account desktop mail client for macOS and Linux — unified inbox, keyboard navigation, and nine color themes.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Emzero

A private, multi-account desktop mail client for Linux and macOS, with a Laravel-powered product website.

Emzero's unified inbox across two accounts, in the Light theme

Screenshots

Reading a conversation in the Rosé Pine Dawn theme with the Source Serif 4 font Quick appearance dialog with nine color themes and four interface fonts
Read threads beside the unified inbox. Rosé Pine Dawn with Source Serif 4. Quick appearance (⌘⇧P) switches theme and font instantly.
Unified inbox in the Tokyo Night theme with JetBrains Mono Unified inbox in the Gruvbox Dark theme
Tokyo Night with JetBrains Mono. Gruvbox Dark.
Unified inbox in the Rosé Pine Dawn theme
Starred, unread, and other mail grouped, with per-account colors and hover actions.

Install

macOS

brew install --cask nick-friedrich/tap/emzero

Apple Silicon and Intel are both supported on macOS 12 (Monterey) or newer. Homebrew selects the matching build. Releases are signed with a Developer ID certificate and notarized by Apple, so they launch without a Gatekeeper prompt.

Upgrade later with brew upgrade --cask emzero.

Linux

Download the package for your distribution from the latest release and install it:

sudo apt install ./emzero_*_amd64.deb
sudo dnf install ./emzero-*.x86_64.rpm

Linux packages are currently built for x86_64 only.

macOS builds are also published as .zip archives on the releases page for anyone not using Homebrew. Direct downloads do not update themselves.

From source

There is no Arch Linux package yet, and building yourself is also the way to run only code you have inspected. See docs/BUILDING.md for the build steps, the system tools each package format needs, and how to verify a published build against its recorded checksum.

Development

Requirements: Node.js and pnpm 11.22. pnpm runs the project's scripts with Node.js 24 whatever your system version is, downloading it if needed (devEngines in package.json); packaging fails silently on newer Node releases.

corepack enable
pnpm install
pnpm dev

The initial application lives in apps/desktop. Electron main and preload own desktop capabilities; the sandboxed React renderer contains the shadcn-based UI.

Commands

  • pnpm dev — start the desktop app with hot reload
  • pnpm check — run linting, type checks, unit tests, and packaged Electron smoke tests
  • pnpm build — create an unpacked application in apps/desktop/out
  • pnpm --filter @emzero/desktop make — create platform installers
  • EMZERO_DEMO=1 pnpm dev — start in demo mode

Demo mode

Demo mode runs Emzero on a sample mailbox, for presentations and screenshots. It uses a separate Demo profile inside the app's data directory. Your accounts and mail are never loaded, and nothing is sent over the network. Reading, replying, sending, drafts, starring, moving, deleting, folders, search, and smart inboxes all work on the sample mail. Mail sent to one of the demo addresses arrives in that account's Inbox. AI drafting keeps using the provider configured in your own profile.

You can start demo mode in three ways: launch with --demo (or EMZERO_DEMO=1), click Restart in demo mode in Settings → General, or click the logo five times. The sample mailbox resets every time demo mode starts. Exit it from the sidebar or from Settings.

See plan.md for the current product scope.

Website

The Laravel 13 website lives in apps/web and uses Inertia, React, and SQLite locally. It includes the public landing page, waitlist, blog, and a private admin area.

cd apps/web
composer run setup
php artisan app:create-admin you@example.com --name="Your Name"
composer run dev

Open http://localhost:8000. The development command runs PHP, the queue listener, logs, and Vite together.

Production does not need a Node.js server. Run npm ci && npm run build during deployment, deploy the resulting application and public/build assets, point the web server document root at apps/web/public, and send PHP requests to the shared PHP-FPM container. Then run php artisan migrate --force and the usual Laravel cache commands. Configure a persistent production database; SQLite is only the local default.

Public registration is disabled. Create or promote the owner account on the production host with php artisan app:create-admin you@example.com; the command prompts securely for the password.

Personal provider setup

Gmail

Emzero currently connects to Gmail over IMAP and SMTP with a Google app password:

  1. Turn on 2-Step Verification for your Google account.
  2. Create a 16-character Google app password.
  3. Add the account in Emzero, select Gmail / Google Workspace, and enter the app password instead of your normal Google password.

This transitional flow requires no Emzero Google OAuth project. Native Google OAuth and a Gmail API backend can replace it later without changing password-based accounts.

Outlook and Microsoft 365

Emzero uses its registered Microsoft public-client application and device-code OAuth:

  1. Add an account and select Outlook / Microsoft 365.
  2. Select Connect with Microsoft.
  3. Copy the displayed device code, select Open Microsoft, and approve mail access in the browser.

The public Microsoft application ID is stored with the account. The Microsoft refresh token is encrypted with Electron's operating-system credential storage; access tokens are kept in memory and refreshed as needed.

License

Emzero is licensed under the MIT License. Third-party dependencies retain their own licenses and notices.

Automated checks

The root GitHub Actions workflow runs on pushes to main, version tags (v*), pull requests, and manual dispatch. It scans the full Git history with Gitleaks, runs desktop checks and creates packages on Linux and macOS, and builds and checks the website. The nested website workflow is a starter-template file; GitHub uses the root workflow for this monorepo.

To scan locally with Gitleaks 8.30.1:

gitleaks git . --log-opts="--all" --config=.gitleaks.toml --redact=100

These checks validate unsigned packages. Pushing a v* tag runs the release workflow, which packages Linux and macOS builds and publishes them as GitHub Release assets; the macOS build is signed and notarized only when the APPLE_SIGNING_IDENTITY, APPLE_CERTIFICATE_P12, APPLE_CERTIFICATE_PASSWORD, KEYCHAIN_PASSWORD, APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, and APPLE_TEAM_ID repository secrets are configured. Passing CI alone does not publish a release or change repository visibility.

About

Private, multi-account desktop mail client for macOS and Linux — unified inbox, keyboard navigation, and nine color themes.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages