Created
June 22, 2026 21:58
-
-
Save mfellner/fb908b9210d0ca793150dbdc96d32a71 to your computer and use it in GitHub Desktop.
hermes-proton-mail-runbook.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Hermes ⇄ Proton Mail Runbook | |
| Set up the **Hermes agent** to **read and send Proton Mail**, on macOS, via | |
| **Proton Mail Bridge** + the **himalaya** CLI (driven by Hermes' bundled | |
| `himalaya` skill). | |
| > Last verified: 2026-06-22 · macOS (Apple Silicon/arm64) · himalaya 1.2.0 · Hermes Agent v0.17.0 | |
| --- | |
| ## How it fits together | |
| ``` | |
| Hermes agent ──runs──▶ himalaya CLI ──IMAP/SMTP(STARTTLS)──▶ Proton Mail Bridge ──▶ Proton servers | |
| (himalaya skill) (config.toml) on 127.0.0.1 (self-signed cert) | |
| ``` | |
| - **Why himalaya, not the Email gateway:** Hermes' Email *gateway* is an inbox-bot | |
| (people email the agent) and connects with implicit TLS (`IMAP4_SSL`) + cert | |
| verification — it **cannot** talk to the Bridge (STARTTLS-only, self-signed cert). | |
| The **himalaya skill** is a real IMAP/SMTP client the agent drives on demand = | |
| "read/send my mail". This is the supported path. | |
| - **Bridge runs on `127.0.0.1`**, so **Hermes must run on the same machine** as the | |
| Bridge. (Remote Hermes would need an SSH tunnel to the Bridge ports.) | |
| --- | |
| ## ⚠️ Per-machine values (DO NOT copy blindly) | |
| These three things are **different on every machine / Bridge install** — always | |
| re-read them, never reuse the values below: | |
| | Thing | Example value | Where to get the real value | | |
| |---|---|---| | |
| | **Your Proton address** | `you@proton.me` | Your own Proton account (may be `@proton.me`, `@protonmail.com`, or a custom domain). | | |
| | **SMTP port** | `1026` (default is 1025 — but may differ!) | Bridge GUI → Settings, or `lsof -nP -iTCP -sTCP:LISTEN \| grep bridge`. Bridge auto-increments if the default port is already in use. | | |
| | **IMAP port** | `1143` | same | | |
| | **Bridge password** | *(per-install secret)* | Bridge GUI → click the account → "Mailbox configuration". **NOT** your Proton login password. | | |
| | **TLS certificate** | self-signed, `CN=127.0.0.1`, `SAN: IP 127.0.0.1` | Unique per Bridge install; regenerated on cert reset. Step 3 always exports the *current* one. | | |
| Stable values: host `127.0.0.1`, both IMAP+SMTP use **STARTTLS**, himalaya | |
| account name **`proton`**. (Your Proton address goes in `config.toml`, Step 5.) | |
| --- | |
| ## Setup from scratch (new machine) | |
| ### 1. Proton Mail Bridge | |
| Install <https://proton.me/mail/bridge>, launch it, log in to the Proton account, | |
| and let it finish the initial sync. Note the IMAP/SMTP **host, ports, username, | |
| password** from the Bridge GUI (Settings → the account → Mailbox configuration). | |
| Confirm it's listening: | |
| ```bash | |
| lsof -nP -iTCP -sTCP:LISTEN | grep bridge # note the IMAP + SMTP ports | |
| ``` | |
| ### 2. Install himalaya | |
| ```bash | |
| brew install himalaya # installs 1.2.0+ | |
| himalaya --version | |
| ``` | |
| ### 3. Trust the Bridge's self-signed cert (macOS login keychain) | |
| himalaya 1.2.0 has **no in-config cert option**; it uses `rustls-platform-verifier`, | |
| which trusts the macOS keychain. The Bridge cert has `SAN: IP 127.0.0.1` + `CA:TRUE`, | |
| so trusting it works. This step grabs whatever cert the Bridge is currently serving: | |
| ```bash | |
| mkdir -p ~/.config/himalaya && chmod 700 ~/.config/himalaya | |
| # Export the LIVE bridge cert (adjust 1143 if your IMAP port differs) | |
| openssl s_client -connect 127.0.0.1:1143 -starttls imap </dev/null 2>/dev/null \ | |
| | openssl x509 -outform PEM > ~/.config/himalaya/proton-bridge.pem | |
| # Trust it for SSL in the login keychain (may pop a Touch ID / password dialog — approve it) | |
| security add-trusted-cert -r trustRoot -p ssl \ | |
| -k ~/Library/Keychains/login.keychain-db \ | |
| ~/.config/himalaya/proton-bridge.pem | |
| # Verify | |
| security verify-cert -c ~/.config/himalaya/proton-bridge.pem -p ssl -s 127.0.0.1 | |
| # → "...certificate verification successful." | |
| ``` | |
| ### 4. Store the Bridge password (0600 file, no newline) | |
| ```bash | |
| printf '%s' 'PASTE-BRIDGE-PASSWORD-HERE' > ~/.config/himalaya/proton-bridge-password | |
| chmod 600 ~/.config/himalaya/proton-bridge-password | |
| ``` | |
| ### 5. Write `~/.config/himalaya/config.toml` | |
| Adjust `email`, IMAP `port`, and SMTP `port` for this machine. | |
| ```toml | |
| [accounts.proton] | |
| email = "you@proton.me" | |
| default = true | |
| # --- IMAP (reading) --- | |
| backend.type = "imap" | |
| backend.host = "127.0.0.1" | |
| backend.port = 1143 | |
| backend.encryption.type = "start-tls" | |
| backend.login = "you@proton.me" | |
| backend.auth.type = "password" | |
| backend.auth.cmd = "cat ~/.config/himalaya/proton-bridge-password" | |
| # --- SMTP (sending) --- | |
| message.send.backend.type = "smtp" | |
| message.send.backend.host = "127.0.0.1" | |
| message.send.backend.port = 1026 | |
| message.send.backend.encryption.type = "start-tls" | |
| message.send.backend.login = "you@proton.me" | |
| message.send.backend.auth.type = "password" | |
| message.send.backend.auth.cmd = "cat ~/.config/himalaya/proton-bridge-password" | |
| # --- Folder aliases (himalaya canonical names -> Proton folder names) --- | |
| folder.aliases.inbox = "INBOX" | |
| folder.aliases.sent = "Sent" | |
| folder.aliases.drafts = "Drafts" | |
| folder.aliases.trash = "Trash" | |
| ``` | |
| ```bash | |
| chmod 600 ~/.config/himalaya/config.toml | |
| ``` | |
| ### 6. Test himalaya (note: account flag goes AFTER the subcommand) | |
| ```bash | |
| himalaya folder list -a proton # should list INBOX, Sent, Drafts, ... | |
| himalaya envelope list -a proton --page-size 5 | |
| himalaya message read <id> -a proton | |
| ``` | |
| > A harmless `WARN ... Rectified faulty continuation request` from imap_codec is a | |
| > Proton Bridge quirk — ignore it. | |
| ### 7. Install Hermes — use the OFFICIAL installer (not Homebrew) | |
| The official uv-based installer ships the full Python deps and seeds all bundled | |
| skills, avoiding the Homebrew breakages (see Troubleshooting). | |
| ```bash | |
| # Fresh machine (lets it run the setup wizard for API keys): | |
| curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash | |
| # Re-install on an ALREADY-configured machine (skip the wizard): | |
| curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash -s -- --skip-setup | |
| # If migrating off Homebrew first: | |
| brew uninstall hermes-agent # ~/.hermes and ~/.config/himalaya are NOT touched | |
| ``` | |
| Installs to `~/.hermes/hermes-agent`, command linked at `~/.local/bin/hermes`. | |
| Then `source ~/.zshrc` (or open a new terminal). | |
| ### 8. Confirm the bundled himalaya skill is enabled | |
| The official installer seeds it automatically as a **builtin** skill: | |
| ```bash | |
| hermes skills list | grep himalaya # → himalaya │ email │ builtin │ builtin │ enabled | |
| ``` | |
| If it's missing: `hermes skills opt-in --sync` | |
| ### 9. End-to-end verification | |
| ```bash | |
| # himalaya reaches the mailbox | |
| himalaya folder list -a proton | |
| # Hermes agent uses the skill (one-shot, read-only): | |
| hermes -z "Using himalaya with account 'proton', list my Proton email folder names." | |
| ``` | |
| --- | |
| ## File inventory | |
| | Path | What | | |
| |---|---| | |
| | `~/.config/himalaya/config.toml` | himalaya account config (no secrets) | | |
| | `~/.config/himalaya/proton-bridge-password` | Bridge password, `chmod 600` | | |
| | `~/.config/himalaya/proton-bridge.pem` | exported Bridge cert (trusted in keychain) | | |
| | `~/.hermes/` | Hermes config (`config.yaml`), secrets (`.env`), sessions, skills — **survives reinstalls** | | |
| | `~/.hermes/skills/email/himalaya/` | the bundled himalaya skill (`SKILL.md` + `references/`) | | |
| | `~/.local/bin/hermes` | the `hermes` command (official install) | | |
| --- | |
| ## Troubleshooting / recovery after an update | |
| ### Bridge cert no longer trusted → himalaya TLS errors | |
| Symptom: `verify-cert` shows `CSSMERR_TP_NOT_TRUSTED`, or himalaya fails to connect. | |
| Cause: Bridge was reinstalled / cert reset → new cert. **Re-do Step 3** (re-export + | |
| re-trust). Optionally remove the stale entry first: | |
| ```bash | |
| sudo security delete-certificate -c 127.0.0.1 ~/Library/Keychains/login.keychain-db 2>/dev/null | |
| ``` | |
| ### IMAP/SMTP port changed | |
| After a Bridge reinstall the ports can move (esp. SMTP). Re-check with | |
| `lsof -nP -iTCP -sTCP:LISTEN | grep bridge` and update `config.toml`. | |
| ### himalaya skill shows source `url` instead of `builtin` | |
| (Happens if it was hand-installed from a URL.) Make it the bundled one: | |
| ```bash | |
| hermes skills reset himalaya --restore --yes | |
| # If it STILL shows 'url', remove the stale hub entry: | |
| python3 - <<'PY' | |
| import json,os | |
| p=os.path.expanduser("~/.hermes/skills/.hub/lock.json") | |
| d=json.load(open(p)); d.get("installed",{}).pop("himalaya",None) | |
| json.dump(d,open(p,"w"),indent=2) | |
| PY | |
| hermes skills list | grep himalaya # → builtin | |
| ``` | |
| ### `No module named 'websockets'` (Homebrew installs only) | |
| The Homebrew formula omitted it; the official installer includes it. Quick fix: | |
| ```bash | |
| <hermes-venv>/bin/python -m pip install 'websockets==15.0.1' | |
| ``` | |
| Better fix: reinstall via the official installer (Step 7). | |
| ### `agent-browser` → `Volta error: Could not execute command` (Homebrew installs) | |
| Volta's shim symlink dangles into a deleted temp dir. The official installer | |
| reinstalls agent-browser cleanly. Manual repair if needed: | |
| ```bash | |
| ln -sf ~/.volta/tools/image/packages/agent-browser/lib/node_modules/agent-browser/bin/agent-browser-darwin-arm64 \ | |
| ~/.volta/tools/image/packages/agent-browser/bin/agent-browser | |
| agent-browser --version | |
| ``` | |
| ### Gateway started but shows tool warnings | |
| Restart it after fixing the above so it reloads modules: | |
| ```bash | |
| hermes gateway # or: hermes gateway install (run as a service) | |
| ``` | |
| --- | |
| ## Quick reference | |
| ```bash | |
| himalaya envelope list -a proton # list inbox | |
| himalaya envelope list -a proton from x@y.com # search | |
| himalaya message read <id> -a proton # read | |
| himalaya message write -H "To:x@y.com" -H "Subject:Hi" "body" # send | |
| himalaya folder list -a proton # folders | |
| # Ask Hermes naturally: "summarize my 5 latest Proton emails", "reply to ...", etc. | |
| ``` | |
| Key gotchas: **SMTP port ≠ 1025** (check it) · **Bridge password ≠ Proton password** · | |
| **cert must be trusted in keychain** · **himalaya `-a proton` goes after the subcommand** · | |
| **use the official Hermes installer, not Homebrew**. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment