{"slug": "keyboard-first-terminal-email-client-imap-smtp-gmail-outlook-go-bubbletea", "title": "Keyboard first terminal email client: IMAP/SMTP, Gmail & Outlook; Go + BubbleTea", "summary": "TideMail, a keyboard-first terminal email client built in Go with the BubbleTea TUI library, launched with IMAP/SMTP support for Gmail and Outlook, a local cache, and a unified three-pane inbox across accounts. TideMail ships a headless CLI for scripts and AI agents, including an `install-skill` command that packages a portable agent skill for Codex, Claude, Pi, or Hermes so an agent can read, draft, and send mail without direct access to IMAP/SMTP credentials, with an invocation-approval step separating reading, drafting, and sending. The client includes 51 built-in themes in 23 families, an outbox that survives restarts, `Ctrl+Z` undo for queued sends and pending deletes, and an Android app in beta.", "body_md": "**Mail for people who live in a terminal.**\n\nTideMail keeps your accounts, message list, and reading pane on one screen. It speaks IMAP and SMTP, stores its cache on your machine, and gives the keyboard the good seat.\n\n[Watch the 40-second intro video](https://mylivelab.com/assets/videos/tidemail-intro-web.mp4)\n\nNeed the full settings and shortcut reference? Open the\n[setup and usage guide](https://github.com/allisonhere/tidemail/blob/main/docs/guide.md).\n\nFor shell scripts and AI agents, see the [CLI reference](https://github.com/allisonhere/tidemail/blob/main/docs/cli.md).\n [TideMail's\nheadless commands use your configured accounts and persistent queue to list,\nsearch, and read cached mail, draft and send with Markdown or attachments, and\nprocess the outbox:](https://camo.githubusercontent.com/bd495caf56c6dcd8d5d426e07671e59f370d7d7541b1c09e09790510f889462b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e45572d4443313433433f7374796c653d666c61742d737175617265)\n\n```\ntidemail messages list --unread --json\ntidemail draft create --to me@example.com --subject \"Draft\" --body-file message.md\ntidemail send --to me@example.com --subject \"Hello\" --body \"Hello\" --yes\ntidemail outbox process --json\ntidemail install-skill codex\n```\n\n`install-skill` packages a portable agent skill for Codex, Claude, Pi, or\nHermes, so an AI agent can read, draft, and send through TideMail without\ntouching your IMAP/SMTP credentials directly. Agent capabilities and an\ninvocation-approval step separate reading, drafting, and sending, so a script\nor agent only gets as much access as you grant it.\n\nFor guided CLI workflows, run `tidemail cli` for the command menu or\n`tidemail send` for the step-by-step composer and attachment browser, with\nRipple key hints, an attachment browser, a review step, and undo.\n[Interactive CLI help](https://github.com/allisonhere/tidemail/blob/main/docs/cli.md#interactive-command-menu-and-composer) covers\nkeyboard navigation and script-friendly prompt controls. **Settings → CLI**\nhas switches for quitting after a send, skipping review, and the default signature.\n\n`send` saves a draft unless you authorize delivery. `--yes` queues mail with the\nconfigured delay. The client or `outbox process` delivers due queued mail.\n\nAn Android app is in beta; you can\n[apply to join the beta](https://mylivelab.com/tide/tidemail-android/beta/login.php#apply).\nIt is developed in a separate repository, and desktop releases are built from\nthis one.\n\nOne inbox, 51 built-in themes in 23 families — Catppuccin, Tokyo Night, Rosé Pine, Gruvbox, Nord, Solarized and more, with their variants ([the list](https://github.com/allisonhere/tidemail/blob/main/docs/themes.md)).\n\n- **NO config file editing, all in the GUI.**\n- **One view for every account.** Read a unified inbox or open any account,\nfolder, or label from the same three-pane screen.\n- **Send from the right address.** Pick an account from the compose From row.\nTideMail switches its SMTP settings, Drafts folder, From address, and\nsignature with it.\n- **Mail state stays in sync.** Read state, stars, archive, move, and delete use\nIMAP. Changes made in Gmail or another client return to TideMail on sync.\n- **A few seconds to change your mind.** Press`Ctrl+Z` to stop a queued send or\nundo a pending delete, archive, or move.\n- **An outbox you can trust.** Press`O` to inspect queued, sending, failed, and\nsent mail. Failed deliveries survive restarts and can be retried or edited.\n- **Unsubscribe without hunting for a footer.** Press`Ctrl+U` while reading to\nuse the message's unsubscribe header or labeled unsubscribe link.\n- **Compose your way.** A`Ctrl+F` , then`Ctrl+R` for replacement controls). An advanced regex toggle is available via**Settings → Editor → Advanced regex search** , off by default. You can switch on Vim motions\nand commands instead. Optional AI tools can summarize mail, proofread a\ndraft, and build local filters from plain English. An optional offline spell\ncheck (**Settings → Editor** , off by default, in English or Español) underlines\nmisspelled words and steps through fixes with`F7` , with no AI provider needed.`F6` opens canned replies (six built-ins, plus any`.md` or`.txt` files in`~/.config/tidemail/templates` ) with the recipient's name filled in; see[Templates](https://github.com/allisonhere/tidemail/blob/main/docs/guide.md#templates) .\n- **See the pictures, not just the alt text.** On Ghostty, Kitty, and Rio, images in HTML mail render inline in the reading\npane, sized to fit and loaded in the background so browsing stays quick.\nRemote images wait until\nyou press`i` . Receipts keep their columns and newsletter cards stay\ntogether.\n- **Readable by design, in every theme.** Text, selection highlights, and the\nfocused-pane border are all checked against WCAG-style contrast minimums\n(4.5:1 for text, 3:1+ for large text and UI elements like borders) across\nevery built-in theme, enforced by automated tests.\n- **Match your desktop.** On[Omarchy](https://omarchy.org) , the`match-omarchy` theme follows your current desktop theme — contrast-corrected to the same\nbar as the built-ins — and repaints live when you switch it.\n- **[Experimental plugins](https://github.com/allisonhere/tidemail/blob/main/docs/plugins.md).** Install trusted plugins such as TideMail Smart (JEV) to classify mail with\nlocal annotations, Needs You signals, and optional TypeSafe/Jev analysis.\n- **PGP, through a plugin.** Install the`pgp` plugin from**Settings → Plugins → `b`** (it uses your own GnuPG) to read encrypted\nand signed mail (`D` ) and to sign (`Alt+S` ) and encrypt (`Alt+E` ) what you send.\nNothing is sent if encryption fails, and every recipient needs a public key in\nyour keyring (`gpg --locate-keys ADDRESS` ). See[PGP encryption and signing](https://github.com/allisonhere/tidemail/blob/main/docs/guide.md#pgp-encryption-and-signing) .\n- **Script it, or hand it to an agent.**`tidemail` CLI shares the client's accounts and queue: list, search, and\nread cached mail, and draft or send with JSON output for scripts, or run`tidemail cli` for a guided compose wizard with attachment browsing, review,\nand undo. Portable skills for Codex, Claude, Pi, and Hermes let an agent send\nmail within capabilities and approval you configure. See the[CLI reference](https://github.com/allisonhere/tidemail/blob/main/docs/cli.md) .\n- **Prefer the mouse?** Turn on**Settings → Display → Mouse support** (off by default, so your\nterminal's native text selection keeps working). Then click rows and panes,\ndouble-click a message to open it, use the scroll wheel over any pane, and\nright-click a folder, account, or message for a menu of just its actions.\nIn the reading pane, drag to select text and press**Ctrl+C** to copy it with\ndisplayed line breaks. This works with Focus Line enabled or disabled. Drag\nabove or below the reader to autoscroll; release retains the highlight and\nanother click clears it.\n- **Optional support, kept out of your way.** Open**Settings → Support** to\nvisit or copy Tidemail's GitHub Sponsors link;**About** and**Support** are small\nanimated scenes. No donation prompts appear during normal email use.\n\nLinux and macOS builds are available for Intel and ARM machines. Windows\nbuilds are experimental; see [Windows](#windows-experimental) below.\n\nTideMail is on the AUR as [`tidemail-bin`](https://aur.archlinux.org/packages/tidemail-bin),\nwhich packages the official release binary along with the TideMail icon and a\ndesktop entry, so TideMail shows up in your app launcher (it opens in your\ndefault terminal):\n\n```\nyay -S tidemail-bin\n# or\nparu -S tidemail-bin\n```\n\nUpdates come from your AUR helper — `yay -Syu` or `paru -Syu` alongside\neverything else, or `yay -S tidemail-bin` for just this one. Plain\n`pacman -Syu` will not do it: pacman skips packages it did not install from a\nsync repo, so it reports success and leaves TideMail where it was. TideMail\nnotices it was installed this way and points you at the right command instead\nof trying to replace a root-owned binary itself.\n\nIf you use [Homebrew](https://brew.sh), install TideMail with the following command:\n\n```\nbrew install tidemail\ncurl -fsSL https://raw.githubusercontent.com/allisonhere/tidemail/main/install.sh | sh\n```\n\nThe installer writes to `~/.local/bin` by default, so it should not ask for a\nsystem password. Set `INSTALL_DIR=/path/to/bin` on the `sh` command if you want\na different writable destination. If an older `tidemail` earlier on `PATH`\nwould still run first, the installer removes it when possible or prints the\nexact cleanup command.\n\nOn Linux the installer also adds TideMail to your app launcher (icon and desktop\nentry under `~/.local/share`); it opens in your default terminal.\n\nThe installer also puts a manual page in `~/.local/share/man/man1`, so\n`man tidemail` works. The page is built into the program: if you installed some\nother way, `tidemail man | man -l -` shows it, and `tidemail man > tidemail.1`\nsaves it for you to install.\n\nYou can also grab an archive from the\n[latest release](https://github.com/allisonhere/tidemail/releases/latest).\n\nDownload `tidemail-windows-x86_64.zip` (or `-aarch64` for ARM) from the\n[latest release](https://github.com/allisonhere/tidemail/releases/latest),\nunzip it, and run `tidemail.exe` from Windows Terminal or PowerShell. Things to\nknow:\n\n- In-app updates are not available; download each new release by hand.\n- There is no system keychain support yet, so passwords and tokens are saved in\nplain text in `%USERPROFILE%\\.config\\tidemail\\config.toml` .\n- Windows is less tested than Linux and macOS. Please report anything that misbehaves.\n\nThe left pane holds accounts and folders. The upper-right pane shows the current message list. The reading pane stays below it, so opening a message never hides the rest of your inbox.\n\nUse `j` and `k` to move. Press `Tab` to cross panes. Hit `?` whenever you forget\na key. TideMail keeps the help screen inside the app and lets you search it.\n\n- Folders show as a tree. In the left pane press `n` to create a folder,`r` to\nrename and`d` to delete the selected one,`H` to hide it locally, and`Shift+K` /`Shift+J` to walk it up or down the tree: reorder it, move it into an open folder, or out of its parent;`>` nests it under the folder above (even an empty one) and`<` moves it back out.`Enter` or`←` /`→` collapse and expand\nfolders that have subfolders.\nOn servers without a folder hierarchy, names stay literal and flat:`n` creates at the account root, and nesting is unavailable.\n- Rest on a folder to refresh a stale cache silently, press `Enter` or`s` to\nfetch it immediately, or press`F` to sync every folder.\n- Mark messages with `Space` , then archive, move, delete, or change read state as\na group.\n- Press `/` to search the local message cache across accounts.\n- Use `*` for a server-backed star. The next sync picks up star changes from\nGmail and other clients.\n- Open a message and press `r` to reply,`Ctrl+R` to reply all,`f` to forward, or`Ctrl+U` to use its\nunsubscribe header.\n\nDelete, archive, and move wait six seconds before TideMail sends them to the\nserver. `Ctrl+Z` restores the last queued action. The message leaves the list at once\nand stays hidden through folder switches, searches and reloads; the status bar\nshows the countdown and then a working pill until the server confirms. If the\nserver refuses, or never answers within 90 seconds, the message comes back with\nan error. The cursor stays on its message unless that message was removed. Pending read/unread\nand destructive operations lock conflicting actions on the affected messages.\nMailbox/account mark-all-read is blocked during conflicting operations: retry\nit when TideMail reports a pending operation. A confirmed delete with a local\ncache error stays hidden while later list reloads retry the cache cleanup.\nThe pending state shows in the status bar as a yellow pill that drains like a\nfuel gauge over the six-second undo window (plain themes show the seconds left),\nthen reads `deleting ⠋` while the server confirms and fades into a green\nconfirmation pill, or a red one if it failed. Errors show as a red pill and every other status message as a green one. See\n[alert colors](https://github.com/allisonhere/tidemail/blob/main/docs/themes.md#alert-colors) for the exact colors.\n\nCompose starts in To with one account, ready for typing. With multiple senders, it starts in From, which serves as an account picker. TideMail uses the chosen account for SMTP, drafts, the From address, and its signature. Replies, forwards, and reopened drafts use the same picker.\n\nA standalone `⁂` in the compose body marks where the selected account's signature\nwill be added when sending, before quoted text by default. Move it to change the\nposition, or delete it to send unsigned. Drafts preserve it; drafts without a\nmarker, including older drafts, send without an added signature.\n\nTo, CC, and BCC suggest saved contacts first. TideMail follows with addresses found in mail you have synced. You can manage contacts in the app and move them through vCard files.\n\nTideMail saves the draft while you type. A sent message waits five seconds by\ndefault, which gives `Ctrl+Z` time to reopen it. Set the delay to `0` if you want\nmail to leave at once. Failed sends retry up to three total attempts by default;\nchange the limit under Settings → Editor. Set it to `1` to disable retries.\n\nPress `Alt+M` in the compose panel to maximize it across the full terminal or restore its compact size. New composers and reopened drafts start compact.\n\nThe standard compose editor supports Shift-selection, clipboard shortcuts,\nundo and redo, word movement, and Home/End. Turn Vim mode on in Settings if you\nprefer commands such as `dw`, `dd`, `:w`, and `:q`.\nThe compose body soft-wraps at word boundaries (with character fallback for long\nwords and URLs) without adding line breaks to messages or saved drafts; turn it\noff in Settings → Editor → Wrap at word boundaries.\n\nRead state, stars, archive, move, and delete sync through IMAP. TideMail keeps a\nlocal SQLite cache for speed and search, then reconciles it with the server on\nsync. By default an account uses IMAP IDLE, so mail lands as the server\nannounces it (`sync_minutes = 0`); interval polling stays available for servers\nthat need it, and `-1` keeps an account manual-only.\n\nDrafts live under the selected sender account. Sent messages use that account's SMTP settings and are filed in its server-side Sent folder; Gmail's own SMTP filing is detected so it does not receive a duplicate. TideMail detects common Sent, Archive, and Trash folder names, including Gmail labels. Mark-all-read updates the server, including uncached mail. Incremental sync processes backlogs in bounded pages, and failed filter deletes keep the local message available.\n\nDraft saves are serialized; closing or sending waits for pending persistence, and save failures keep the composer open. Drafts reject ordinary message selection, archive, move, and read/star actions. SMTP submission allows up to ten minutes for uploads, with 30-second connection/authentication setup.\n\nGlobal search stays active while you move through results. The content pane can find text inside the open message, walk links, copy a visual selection, and save attachments to a folder you choose.\n\nReceipts keep item descriptions, quantities, and amounts in aligned columns, including totals with merged cells. Narrow reading panes show labelled records instead, so prices stay associated with their items.\n\nNewsletter cards stay together — each image next to its heading, description, and button — with a thin rule between neighbouring cards.\n\nTideMail renders HTML mail as terminal text. On terminals with Kitty graphics support\n(Ghostty, Kitty, Rio), images embedded in the message — CID parts, inline data\nURIs, and content-location references — are drawn as real raster images inline in\nthe reading pane, scrolling with the document. They fit the pane and the sender's\nwidth and height without being stretched or enlarged, and are laid out again when\nyou change the terminal font size. Images load in the background once you stop on\na message, so moving through the list stays quick. Remote images\nstay blocked for privacy until you press `i`, which loads them for the message you\nare reading; `[display] images = \"off\"` forces text placeholders everywhere. On\nterminals without graphics support every image becomes a labelled text placeholder.\n\nChoose **Settings → Display → Reading → Images** (`Auto` or `Off`) and press\n`Ctrl+S` to save. The change takes effect immediately; remote images still require\n`i` to load. The setting also shows whether inline images are supported.\n\nTideMail picks the graphics mode from your terminal's environment, and\nrecognises Herdr automatically. If that finds nothing (for example inside another\nterminal multiplexer), it asks the terminal at startup whether it supports Kitty\ngraphics and uses them if it does, so no setup is needed. If images still show as\ntext placeholders in a terminal that supports them, force the choice by launching\nwith `TIDEMAIL_IMAGE_PROTOCOL=kitty` (or `none` to turn graphics off), for example\n`TIDEMAIL_IMAGE_PROTOCOL=kitty tidemail`.\n\n**foot and WezTerm: inline images are currently unsupported.** TideMail uses\ntext placeholders there. foot supports Sixel images, but TideMail's renderer\nrequires Kitty Unicode placeholders; WezTerm does not support those placeholders.\nEmail text and attachment saving still work.\n\nFull headers are one `Ctrl+E` away, with SPF, DKIM, and DMARC results called out\nin color. `Ctrl+O` shows the complete message source, ready to copy.\n\nPress `e` to correct a message's classification. The Category choices include\nImportant, Work, Personal, To Do, and Later. Selecting one with `Enter` also saves\nits Thunderbird-compatible tag to the mail server. Checked choices are already\nsaved; `Space` toggles a tag without removing other assignments. Existing custom\ntags appear in the same choices after sync. Changes require a connection and\nserver support. AI/JEV does not publish tags automatically.\n\nFind tags by keyword or name with `#tag`, including `#\"To Do\"`. Custom names and\ncolors are local to each client; edit discovered tags in **Settings → Display →\nTag names and colors**. Choose **Tag icons** under **Tag style** for colored,\nThunderbird-like tag glyphs, with `#` when icons are disabled. Existing appearance\nsettings stay unchanged. Tags also appear below the date and sender in the\ncontent pane; use **Show tags in message header** under **Settings → Display →\nMessage tags** to hide that row only. See the [user guide](https://github.com/allisonhere/tidemail/blob/main/docs/guide.md#thunderbird--imap-mail-tags).\n\nConversation grouping (`g`) now uses expandable message rows: `▸` / `▾` marks\nthe parent, and children have muted tree connectors in the sender and subject\ncolumns. `Enter` expands/collapses a parent; on a child or single email it opens\nthe reader. `Right` / `l` or `Tab` opens any selected email, including a parent.\nEach row previews only its own email. Delete, archive, move, star and `Space`\naffect only that email; explicit multi-selection remains available. Collapsed\nconversations show aggregate unread state; `x` marks all members read if any is\nunread, otherwise all unread. Expanded parents and children show and toggle only\ntheir own read state. Marking unread mail read advances to the next visible row;\nmarking it unread does not. Confirmation and reloads retain that next target,\nwhile collapsed read actions keep their conversation closed. Explicit selections\ntoggle individually without advancement. Expansion survives same-view refreshes;\npassive selection follows message identity. Unread Only still hides read history. See [Expandable conversations](https://github.com/allisonhere/tidemail/blob/main/docs/guide.md#expandable-conversations).\n\nWith **Focus line** on, Up/Down moves the reading highlight. With it off,\nUp/Down scrolls one row. At the bottom, another Down selects the first LINKS\nentry. Arrows then move between entries without wrapping; Up from the first\nclears selection, and the next Up resumes scrolling. Selected LINKS entries\nkeep their highlight and chevron in both modes.\n\n`o` or `Enter` opens a selected LINKS entry or a visible link deliberately focused\nwith the keyboard. New messages start with no link selected. Clicking a LINKS\nentry selects it without opening it; ordinary body clicks and scrolling never\nopen links. `Ctrl+B` views the whole message in your browser. These actions use\n**Browser command** from Settings → Display when one is set.\n\nView in Browser (`Ctrl+B`) works from the message list or reading pane. It fetches\nthe original message without marking it read and opens its HTML as a private local\n`.html` file in your browser: the **Browser command** from Settings → Display when\none is set, otherwise the system default (`xdg-open` on Linux). Messages without\nHTML show a status message. Links are preserved. Remote content is blocked so\nopening a message does not load tracking pixels: remote images, scripts, frames,\nstylesheets, and web fonts are left out, and the status line reports how many\nremote images were dropped. Press `Ctrl+B` again right away to reopen the message\nwith remote images loaded; this tells the sender the message was opened, so it only\nhappens when you ask. Embedded CID images are not exported. Exports are\nwritten to a private per-user folder in the system temporary directory and\ndeleted automatically after an hour (older ones are also pruned when TideMail\nstarts).\n\nLink destinations containing terminal controls or Unicode line/paragraph separators are rejected, and link labels stay on one row. Bare carriage returns are removed from displayed mail while CRLF line breaks are retained.\n\nWith **Actionable links** enabled, the reader's **LINKS** section uses anchor text\nor image descriptions. `Ctrl+N` / `Alt+N` and `Alt+P` move the visible selection\nand scroll it into view. The first Next selects the first entry; the first Previous\nselects the last. `o` or `Enter` opens the selected destination; `Ctrl+C` on a LINKS\nrow copies its full URL when no text selection is active. Email actions appear\nas `[mailto: description]` and open TideMail's composer using the source message's\naccount, including in Unified Inbox. Your default sender is the fallback if that\naccount is unavailable. Recipients, subject, and body can be prefilled; your\nsignature is inserted at the `⁂` marker when you send. Nothing is sent until you\nchoose to send.\nEach entry shows its real destination host in parentheses, and a\nlabel that names a different site than the link goes to is marked with `!`, so a label\ncannot hide where a link leads. HTML resource and metadata URLs are excluded from LINKS, as are links that\nonly wrap a hidden or 1x1 tracking pixel.\n\nConnect OpenAI, Claude, Gemini, or a local Ollama server if you want message summaries and a compose proofread. TideMail can also turn a plain-language mail rule into a local filter that runs without an AI call for each message.\n\nAI stays off until you configure a provider.\n\nTideMail can run external plugins from\n`$XDG_CONFIG_HOME/tidemail/plugins/` (or `~/.config/tidemail/plugins/` when\n`XDG_CONFIG_HOME` is unset). Plugins\nreceive message metadata, never message bodies, and can add annotations such as\n`needs_reply=true` or `category=shipping`. TideMail uses those annotations for\ntags and views such as **Needs You**, while keeping the original plugin output\ninspectable. Press `e` on a message to correct its classification locally; plugin reruns\ndo not erase your correction. Result cards can offer `u` when TideMail itself\nfinds an unsubscribe option; the plugin never receives the link, and TideMail still\nshows its normal confirmation before acting. Report plugins (press `enter` on one in **Plugins\n(experimental)**) can ask TideMail read-only questions, such as message volume\nor category totals, and show the answer; they never see message bodies or get\ndatabase access.\n\nAdminister installed plugins directly in **Settings → Plugins**. Select a\nplugin and press `s` to edit its settings in the right-hand pane.\n\nTo install one, open **Settings → Plugins** and press `b` to browse the\nofficial [TideMail plugin collection](https://github.com/allisonhere/tidemail-plugins):\n`i` installs, `u` updates, `x` removes. TideMail shows the permissions first and\nchecks the download's checksum. You can also copy a plugin's binary and\n`plugin.toml` into the plugins directory by hand.\nThe full user guide is in [docs/guide.md](https://github.com/allisonhere/tidemail/blob/main/docs/guide.md#plugins-experimental).\n\nIf you are writing a plugin, start with the\n[Plugin API getting-started guide](https://github.com/allisonhere/tidemail/blob/main/docs/plugins/getting-started.md), then see\n[the developer tools guide](https://github.com/allisonhere/tidemail/blob/main/docs/plugins/developer-tools.md) for the\n`scaffold → build → validate → test` workflow, and see\nthe [protocol](https://github.com/allisonhere/tidemail/blob/main/docs/plugins/protocol.md), [manifest](https://github.com/allisonhere/tidemail/blob/main/docs/plugins/manifest.md),\nand [permissions](https://github.com/allisonhere/tidemail/blob/main/docs/plugins/permissions.md) references. Reports and\nread-only queries are covered in [queries](https://github.com/allisonhere/tidemail/blob/main/docs/plugins/queries.md) and\n[analytics](https://github.com/allisonhere/tidemail/blob/main/docs/plugins/analytics.md). Complete local examples are in\n[examples/plugins/example](https://github.com/allisonhere/tidemail/blob/main/examples/plugins/example) and\n[examples/plugins/analytics](https://github.com/allisonhere/tidemail/blob/main/examples/plugins/analytics). The\n[PGP plugin](https://github.com/allisonhere/tidemail-plugins/tree/main/plugins/pgp)\nshows the `message_raw` and `message_compose` permissions.\n\n| Key | Action | \n|---|---|\n| `j` /`k` | Move down or up | \n| `Tab` /`Shift+Tab` | Move between panes or compose fields | \n| `Up` /`Down` (compose headers) | Move between From, To, Cc, Bcc, and Subject | \n| `Enter` | Expand/collapse a conversation parent; open a child, single message, draft or picker; immediately sync a folder | \n| `c` | Compose | \n| `r` /`f` | Reply or forward from the reading pane | \n| `Space` | Select a message for a bulk action | \n| `a` /`m` /`d` | Archive, move, or delete | \n| `x` | Collapsed: toggle conversation; expanded/single: toggle email. Mark-read advances; explicit selections toggle individually without advancing | \n| `*` | Toggle the IMAP star | \n| `/` | Search messages | \n| `Ctrl+Z` | Cancel a send still in its delay, or undo a queued message action | \n| `O` | Open the Outbox | \n| `Ctrl+U` | Unsubscribe while reading; cycle sender while composing | \n| `Alt+F` /`Ctrl+R` | Attach a file while composing; remove the last attachment | \n| `Ctrl+D` | Save attachments from the open message | \n| `Ctrl+E` | Show or hide full headers | \n| `Ctrl+O` | View the message source ( `c` copies it) | \n| `Ctrl+B` | View the whole message in your browser (remote content blocked) | \n| `i` | Load remote images blocked for the open message | \n| `M` /`S` /`T` | Accounts, settings, or themes | \n| `Ctrl+L` in the account form | Look up a Custom account's mail servers | \n| `Space` in Accounts | Mark the highlighted account `★ [default]` — the sender for new messages | \n| `Shift+J` /`Shift+K` in Accounts | Move the highlighted account down or up the list | \n| `:` /`Ctrl+P` | Command palette | \n| `?` | Searchable help | \n| `q` | Quit | \n\nPress `M` to add an account. Enter the address in the first row. For a\n**Custom** account, moving to the next row looks up server settings from the\naddress's domain. TideMail tries DNS SRV records, known MX providers, and the\ndomain's HTTPS autoconfig file. Check the settings before saving with `Ctrl+S`;\nthe lookup does not connect or save. `Ctrl+L` repeats the lookup and replaces\nthe server settings. Changing or clearing the address removes settings from its\nprevious lookup, while keeping server values you edited yourself.\n\nGmail, Outlook, Yahoo, and iCloud have server settings built in. Gmail, Yahoo,\nand iCloud require an app password. Outlook can sign in with OAuth; Gmail OAuth\nis temporarily unavailable while Google approval is pending (see below). Any\nother IMAP/SMTP server, including an on-premises Microsoft Exchange server,\nuses **Custom** with a username and password.\n\nTideMail stores passwords, AI keys, and OAuth refresh tokens in libsecret on\nLinux or Keychain on macOS. If `secret-tool` is missing on Linux, TideMail falls\nback to `~/.config/tidemail/config.toml`, so protect that file.\n\nGoogle OAuth is temporarily unavailable while TideMail's Google app awaits approval. The account form and installer both call this out. Use a Google App Password instead; existing saved Gmail OAuth accounts are left unchanged.\n\nMaintainers and source-build developers: see [Google OAuth registration and\nrelease setup](https://github.com/allisonhere/tidemail/blob/main/docs/google-oauth.md) for the approval and release checklist.\n\nProvider **Outlook** covers **Outlook.com, Hotmail, and Microsoft 365 / Exchange\nOnline**. Microsoft dropped basic auth for these, so the account signs in with\nOAuth — but it needs no setup: TideMail uses Thunderbird's shared public client.\nAdd the account, keep the **Auth** row on *OAuth*, press `Ctrl+O`, open the\ncopied URL, approve, and paste the `https://localhost/?code=…` URL the browser\nlands on into the **Code** field. Set `TIDEMAIL_MS_CLIENT_ID` to your own Azure\napp to get the device-code flow instead. M365 work/school mailboxes need IMAP\nenabled by an admin (`Set-CASMailbox -ImapEnabled $true`).\n\nA self-hosted Exchange server (2016/2019/SE) is **not** the Outlook provider — it\ndoes not use Microsoft's cloud sign-in. Use the **Custom** provider with your\nserver's IMAP/SMTP hostname and your normal username and password; on-prem\nExchange still accepts basic auth over TLS. TideMail cannot connect to an on-prem\nserver that has disabled basic auth and requires NTLM or Kerberos (GSSAPI).\n\n```\ntheme = \"lavender-fields-forever\"\n# The account new messages are sent from, and the one focused at startup.\n# Holds an account id, so renaming or reordering never moves it. Omit it and\n# TideMail uses the first account below. Set it with Space in Accounts.\ndefault_account = \"8f43c9e644384bd5a25a27ff0d9c2701\"\n\n[display]\nsend_delay_seconds = 5\nsend_max_attempts = 3  # total attempts; 1 disables automatic retries\ncompose_vim = true\ncompose_word_wrap = true  # wrap compose text between words (default); false wraps at the edge\nimages = \"auto\"  # \"auto\" (inline + blocked remote), or \"off\" (text placeholders)\n\n[[account]]\nid = \"8f43c9e644384bd5a25a27ff0d9c2701\" # generated by TideMail; do not copy or edit\nname = \"Personal\"\nimap_host = \"imap.example.com\"\nimap_port = 993\nimap_tls = true\nsmtp_host = \"smtp.example.com\"\nsmtp_port = 587\nsmtp_tls = true\nuser = \"mira@example.com\"\nfrom = \"Mira Chen <mira@example.com>\"  # optional, but a name alone is not an address\nsignature = \"\"\"\nMira\nSent with TideMail\"\"\"\nsync_minutes = 0  # push via IMAP IDLE; N polls every N min, -1 is manual only\n```\n\nThe signature is a multi-line box in the account form, so `Enter` gives you a\nnew line and there is no escape to remember; editing the file by hand works too,\nand a TOML multi-line string is easier to read than `\\n` escapes.\n\nThe order of the `[[account]]` blocks is the order accounts appear everywhere:\nthe sidebar, the account list, and the `Ctrl+U` sender picker in compose.\nReorder them here, or with `Shift+J` and `Shift+K` in **Accounts**.\n\nConfig lives at `~/.config/tidemail/config.toml`. TideMail puts its SQLite cache\nat `~/.local/share/tidemail/mail.db` unless `XDG_DATA_HOME` points elsewhere.\nEach account's generated `id` is its permanent internal identity, so display\nnames may be changed or shared safely. TideMail adds missing IDs automatically\nand writes a one-time `.pre-account-ids.bak` copy beside the config first.\nTideMail refuses to start on a malformed config and prints the exact path to\nrepair, rather than loading defaults that could overwrite the real settings.\n\nTideMail requires Go. Clone the repository, build, and run the binary:\n\n```\ngit clone https://github.com/allisonhere/tidemail\ncd tidemail\ngo build -o tidemail .\n./tidemail\n```\n\nRun the test suite with:\n\n```\ngo test ./...\n```\n\nTideMail is free and MIT licensed, built and maintained by one person. If it saves you time, you can help keep it going:\n\n- **[Sponsor on GitHub](https://github.com/sponsors/allisonhere)** , one-time or monthly. It pays\nfor the test accounts, OAuth app reviews, and the hours that go into fixes and\nnew features.\n- **Star the repo** and tell a friend who still lives in a terminal. Reach matters\nas much as money.\n- **Report bugs and share ideas** in[issues](https://github.com/allisonhere/tidemail/issues) or[discussions](https://github.com/allisonhere/tidemail/discussions) .\n\nIn the app, **Settings → Support** has the same link. A single, friendly reminder\nappears after about a week of use; switch it off with **Settings → Display →\nSupport reminder** (`support_reminder = false` in the config).\n\n[Bubble Tea](https://github.com/charmbracelet/bubbletea) runs the application\nloop. [Lipgloss](https://github.com/charmbracelet/lipgloss) handles terminal\nlayout and color.\n\nYou can reuse two parts as standalone Go libraries:\n\nGrammar checks can be canceled with Esc while retaining editable compose text. Ctrl+C or Ctrl+Q during a grammar check cancels it and follows the normal quit flow. Late grammar results are ignored; pending draft persistence remains protected. OAuth refreshes run independently per account. A malformed COPY acknowledgment triggers one fresh-connection source cleanup attempt without repeating COPY; if cleanup fails, TideMail reports the completed copy and unconfirmed removal.\n\nCache deletion and Needs You dismiss/restore writes are atomic. A failed Needs You undo retains its history so you can retry.\n\nOAuth requires encrypted IMAP and SMTP connections, including localhost. Enable IMAP TLS and SMTP TLS (STARTTLS), or use SMTP port 465 for implicit TLS.", "url": "https://wpnews.pro/news/keyboard-first-terminal-email-client-imap-smtp-gmail-outlook-go-bubbletea", "canonical_source": "https://github.com/allisonhere/tidemail", "published_at": "2026-11-11 21:45:11+00:00", "updated_at": "2026-11-11 21:50:23.963326+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools"], "entities": ["TideMail", "Go", "BubbleTea", "Gmail", "Outlook", "Codex", "Claude", "Hermes"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/keyboard-first-terminal-email-client-imap-smtp-gmail-outlook-go-bubbletea", "markdown": "https://wpnews.pro/news/keyboard-first-terminal-email-client-imap-smtp-gmail-outlook-go-bubbletea.md", "text": "https://wpnews.pro/news/keyboard-first-terminal-email-client-imap-smtp-gmail-outlook-go-bubbletea.txt", "jsonld": "https://wpnews.pro/news/keyboard-first-terminal-email-client-imap-smtp-gmail-outlook-go-bubbletea.jsonld"}}