Skip to content

Releases: peltonapp/Pelton

v2026.4.1

Choose a tag to compare

@github-actions github-actions released this 15 Sep 19:13
27e9abb

Changes

  • chore: add codeowners - @TRC-Loop in #363
  • chore: change emails to @pelton.app addresses - @TRC-Loop in #360
  • chore: change emails to @pelton.app addresses - @TRC-Loop in #361
  • chore: point the flatpak manifest at the 2026.4 tarball - @TRC-Loop in #350
  • chore(deps): Bump the frontend-dependencies group across 1 directory with 10 updates - @dependabot[bot] in #359
  • chore(deps): Bump the go-dependencies group across 1 directory with 8 updates - @dependabot[bot] in #396
  • ci: build and test every pull request - @TRC-Loop in #364
  • docs: match the wails generator's blank lines in hand-written bindings - @TRC-Loop in #393
  • docs: overhauled docs - @TRC-Loop in #394
  • docs: say "Powered by Zensical" in the footer instead of "Made with" - @TRC-Loop in #400
  • feat: add Turkish (tr) locale - @xdaxer in #379
  • feat: bind message actions to their webmail letters - @TRC-Loop in #390
  • feat: choose the start menu and desktop shortcuts when installing - @TRC-Loop in #413
  • feat: deleting the open message opens the next one - @TRC-Loop in #408
  • feat: play embedded video and audio once remote content is allowed - @TRC-Loop in #395
  • feat: ship a portable windows exe alongside the installer - @TRC-Loop in #412
  • feat: show shortcut hints outside the message list - @TRC-Loop in #389
  • fix: a folder that fails to sync is reported as a clean sync - @TRC-Loop in #373
  • fix: a saved view that vanishes leaves the list showing it - @TRC-Loop in #414
  • fix: database is locked when writing during a sync - @TRC-Loop in #392
  • fix: deleting the open saved view leaves the list on it - @TRC-Loop in #382
  • fix: demo mode shows real mail before the first reload - @TRC-Loop in #391
  • fix: imported mailboxes never sync and never ask for a password - @TRC-Loop in #372
  • fix: keep the draft release tagged when updating its notes - @TRC-Loop in #348
  • fix: keep the release changelog under github's body limit - @TRC-Loop in #346
  • fix: mcp threat model comment still claims read-only tools - @TRC-Loop in #362
  • fix: moving a message into its own folder reports a silent success - @TRC-Loop in #383
  • fix: one line per pull request in the release changelog - @TRC-Loop in #347
  • fix: opening a folder or a crash report does nothing - @TRC-Loop in #371
  • fix: point sibling-repo links at their actual peltonapp names - @TRC-Loop in #399
  • fix: saving a keyword search as a view leaves the name blank - @TRC-Loop in #374
  • fix: search chips widen the bar over the reading pane - @TRC-Loop in #411
  • fix: search paging can repeat and skip messages - @TRC-Loop in #365
  • fix: select can be followed by no mailbox selected - @TRC-Loop in #366
  • fix: your own authenticated mail is no longer flagged as impersonation - @TRC-Loop in #410
  • ops: added nix flake for packaging - @TildeEthDoUsPart in #355
  • release: 2026.4.1 - @TRC-Loop in #415
  • test: add a frontend test runner and cover the logic modules - @TRC-Loop in #409
  • test: add an imap client seam to the desktop bindings - @TRC-Loop in #405
  • test: check the locale catalogs agree with english - @TRC-Loop in #406
  • test: cover autoconfig, credentials, configsync and oauth - @TRC-Loop in #388
  • test: wait for background goroutines before a test's store closes - @TRC-Loop in #407

Full Changelog: v2026.4...v2026.4.1

Checksums

SHA-256 of every file on this release, also published as SHA256SUMS.txt, which sha256sum -c reads directly.

File SHA-256
Pelton-v2026.4.1-linux-amd64 b9256a60488b75db3e74d3bd6d6c4eeca1dc3fead02846ab1e81171bf3c3e3af
Pelton-v2026.4.1-linux-amd64.deb 4684176713e49c23a1dbf2a7d0bc60e38421e478c06038fd227a830345f4fc1f
Pelton-v2026.4.1-linux-fedora-x86_64.rpm a01044e7d7ed694d3fb9341e2dc3c4d82278a4a027bc0cde045c2b32871d2174
Pelton-v2026.4.1-macos-applesilicon-app.zip 83fcc017e00ea3d4c62e7743b2600a9cc18d33d638eab233589594da639cbc65
`Pelton-v2026.4.1-macos-applesilicon...
Read more

Nightly nightly-2026.09.15 (untested, not a release)

Choose a tag to compare

@github-actions github-actions released this 15 Sep 10:39
f0a27e2

Caution

This is not a release. Do not use it with your real inbox.

This is an automated nightly build of Pelton, made from the dev
branch. It has not been reviewed, tested or released, and it is
expected to break.

It can lose or damage email. It may fail to send, send the wrong
thing, delete messages on your server, or corrupt its local cache of
your mail. Deletions on an email server can be permanent and cannot
be undone by us.

Use a test account whose contents you can afford to lose entirely.

There is no warranty of any kind and no support. You download
and use this build entirely at your own risk. To the fullest extent
permitted by law, the authors and distributors of Pelton accept no
liability for any loss of or damage to data, for lost or misdirected
email, or for any other loss or damage arising from its use. The full
warranty and liability terms are at https://pelton.app/terms and in
DISCLAIMER.md.

If you want a working email client, download a
real release
instead.

Installing alongside a normal Pelton

A nightly is deliberately kept separate from a real install and the two
can sit side by side:

  • it installs as Pelton Nightly with its own icon,
  • it keeps its own accounts, mail and settings in a separate data
    directory, so it cannot touch or corrupt your normal install's mail,
  • on Linux it is the pelton-nightly package with a pelton-nightly
    binary, and it does not register itself as your mailto: handler.

Nightlies older than 14 days are deleted automatically.


Built from dev at f0a27e2.

v2026.4

Choose a tag to compare

@github-actions github-actions released this 27 Aug 14:09

Pelton 2026.4

Pelton-2026 4-Banner

Changes

  • chore: drop the minimize-to-tray option - @TRC-Loop in #189
  • chore: Enable blank issues in issue template configuration - @TRC-Loop in #338
  • chore: point dependabot at dev from the branch it reads - @TRC-Loop in #260
  • chore: put PGPKeyDTO in the order the wails generator writes - @TRC-Loop in #224
  • chore: stamp 2026.4 in the appstream release history - @TRC-Loop in #345
  • chore: untrack frontend/package.json.md5 - @TRC-Loop in #221
  • chore(deps): bump echo to 4.15.3 for the static route bypass fix - @TRC-Loop in #343
  • chore(deps): Bump github.com/labstack/echo/v4 from 4.13.3 to 4.15.3 in the go_modules group across 1 directory - @dependabot[bot] in #339
  • chore(deps): Bump the frontend-dependencies group across 1 directory with 9 updates - @dependabot[bot] in #295
  • chore(deps): Bump the go-dependencies group across 1 directory with 7 updates - @dependabot[bot] in #319
  • chore(deps): bump wails, sqlite and five frontend packages - @TRC-Loop in #258
  • chore(deps): go and frontend dependency bumps, and target dependabot at dev - @TRC-Loop in #182
  • ci: rebuild the docs when the theme overrides change - @TRC-Loop in #233
  • Delete on backspace, and shortcut hints in the right-click menu - @TRC-Loop in #331
  • Detect tracking pixels and keep them blocked - @TRC-Loop in #263
  • docs: document the menu bar access keys - @TRC-Loop in #289
  • docs: link the discord invite directly and add it to the docs site - @TRC-Loop in #230
  • feat: alt key access to the in-app menu bar - @TRC-Loop in #274
  • feat: close the window with cmd+w without quitting - @TRC-Loop in #243
  • feat: command palette with fuzzy search for actions, mail and settings - @TRC-Loop in #212
  • feat: create, rename and delete imap folders - @TRC-Loop in #190
  • feat: decrypt and verify received pgp mail - @TRC-Loop in #227
  • feat: delete moves mail to the trash - @TRC-Loop in #284
  • feat: developer overlays for activity, process and frame timing - @TRC-Loop in #296
  • feat: dismissible password prompt with a mailbox warning marker - @TRC-Loop in #294
  • feat: empty trash from the folder context menu - @TRC-Loop in #209
  • feat: flags in the language picker - @TRC-Loop in #305
  • feat: flatpak packaging for flathub - @TRC-Loop in #210
  • feat: label mail handed to mcp agents as untrusted - @TRC-Loop in #283
  • feat: mark folders that are not syncing - @TRC-Loop in #287
  • feat: mcp write actions with per-tool permissions - @TRC-Loop in #307
  • feat: more view icons for everyday categories - @TRC-Loop in #208
  • feat: native window frame, cursors and calmer setup flow - @TRC-Loop in #241
  • feat: nightly builds from dev with their own identity and warnings - @TRC-Loop in #177
  • feat: opt-in revocation checking for s/mime certificates - @TRC-Loop in #306
  • feat: option to minimize to the notification area on Windows - @TRC-Loop in #180
  • feat: pgp key storage, import and passphrase handling - @TRC-Loop in #213
  • feat: profiles - @TRC-Loop in #299
  • feat: reading-pane tabs - @TRC-Loop in #297
  • feat: remember the window size and position across launches - @TRC-Loop in #249
  • feat: reorder and pin sidebar folders, and pick a startup selection - @TRC-Loop in #198
  • feat: save an eml copy when archiving - @TRC-Loop in #275
  • feat: scan links and attachments with VirusTotal - @TRC-Loop in #207
  • feat: setting for whether the close button quits or keeps running - @TRC-Loop in #172
  • feat: settings editors open as modals - @TRC-Loop in #301
  • **feat: sign and encrypt fr...
Read more

v2026.3.4

Choose a tag to compare

@github-actions github-actions released this 10 Aug 19:53
b5dc794

Changes

ci: build before publishing so releases and nightlies ship complete - @TRC-Loop in #200

Both workflows built their release after announcing it, which is backwards in two different ways.

Releases: build on the tag, not on publish

release.yml only ran on release: published, so publishing a draft started a 15-minute wait during which the release was live and empty. Anyone arriving in that window found a version with nothing to download.

Builds now run on the tag push instead. Pushing v1.2.3 has draft-release.yml write the changelog into a draft while this workflow fills that same draft with installers. By the time you look at it, everything is attached, and publishing is an instant manual click that rebuilds nothing.

A draft job waits for the release to appear before the builds finish (the two workflows react to the same push, and the changelog job is normally done in seconds). If it never shows up, it creates an empty draft itself rather than losing a whole build to a missing upload target.

Copr still waits for publish. It pushes to a live dnf repo that real users install from, so it must not fire while the release is an unpublished draft. It is the only job left on the release: published trigger.

workflow_dispatch gained an optional tag: with one it builds and uploads into that tag's existing release, which repairs a draft whose build failed or one tagged before this change. Without one it behaves as before and uploads nothing.

Nightlies: publish only what actually built

The prerelease was created first so three jobs could upload into it in parallel. A failed build therefore left a nightly on the releases page that was empty or half-filled, and looked downloadable.

The three platform jobs now stage their installers as artifacts, and a new publish job creates the prerelease with all of them attached in one go. It only runs when every platform succeeded, so a broken build publishes nothing at all and yesterday's nightly stays the newest thing on the page. prune follows publish rather than the build jobs.

The warning body, the same-day replace behaviour and the retention pruning are unchanged.

Notes

  • Verified with actionlint (clean) and a YAML parse of all three workflows.
  • This is on main because that is where releases are cut and where the scheduled nightly runs from. It will reach dev with the back-merge.
fix: imported mailboxes could never be given a password - @TRC-Loop in #214

A mailbox imported from another mail client could never sync, never explained why, and offered no way to fix it.

What was wrong

The Thunderbird/mbox importer creates the account row from the other client's server settings, but it cannot take that client's stored password with it, so no keyring secret is ever written. resolveIMAP then falls through to the environment-credential path meant for the legacy cli account, which does not match, and the connection fails with errNoCredentials.

There was no way out of that state from inside the app. UpdateAccountRequest carried display name, username and the four server fields, and no password at all, so editing the mailbox could not supply one either. The account just sat there failing.

The fix

You can now enter a password when editing a mailbox. UpdateAccountRequest gains an optional Password; empty leaves the stored secret alone, so an edit that only moves a port does not force you to retype it. The field is placeheld differently depending on whether a password exists, and a mailbox with none shows a short explanation of why.

Sync prompts for what is missing. AccountsNeedingPassword reports accounts with nothing in the keyring, and runSync asks about each one before syncing, one dialog at a time.

Cancelling is a real answer. Skip leaves that account alone and syncs the rest rather than blocking everything, and the skip is remembered for the session so an automatic sync every few minutes does not turn into a prompt every few minutes. It comes back next launch, because the account genuinely is still broken.

Details worth noting

  • Storing a password over an OAuth account is refused. Gmail and Outlook accounts sign in with a token; quietly replacing that with a password would produce a login the provider rejects, so SetAccountPassword returns an error instead.
  • Only a definite "nothing stored" prompts. A keyring that is locked or unreadable returns a different error, and treating that as "no password" would ask the user to retype one they already gave. needsPassword checks for ErrNotFound specifically.
  • The legacy cli account is excluded, since its password comes from the environment and it is not actually missing one.

Testing note

credentials.Load reads the real OS keyring, so a test that calls AccountsNeedingPassword against a fresh database still collides with whatever the developer running it has installed under account id 1. The decision is therefore factored into needsPassword, which takes the lookup error as an argument and is tested directly. Worth remembering for anything else that touches credentials.

Verification

go build, go vet and the desktop tests pass, including new coverage for the missing/present/unreadable keyring cases and the env-backed account. pnpm run check is 0 errors and 0 warnings; the frontend build succeeds. Six locales.

fix: nightly publish and prune failing without repo context - @TRC-Loop in #204

Both of last night's nightly runs failed. All three platforms built and staged
their installers correctly; the new publish job is what died:

failed to run git: fatal: not a git repository (or any of the parent directories): .git

publish only downloads artifacts and calls gh, so it has no
actions/checkout. Without a checkout there is no git remote for gh to infer
the repository from, and gh release create exits 1 before creating anything.
The draft job in release.yml passes --repo "$GITHUB_REPOSITORY" for the
same reason; that was not carried over to nightly.yml in #200.

This also caused the double run: the first failure never created the tag that
tells the next run there is nothing left to build.

prune had the same bug, silently

prune reports success but has never worked. From the last nightly that
actually ran (2026-08-07):

prune  2026-08-07T13:47:20  failed to run git: fatal: not a git repository
prune  conclusion: success

Same missing repo context. It is reported as a success because
gh release list | while read takes the exit status of the while, not of
gh, so the failure is swallowed. Nightlies have therefore never been pruned,
despite the release body promising it. Nothing is currently overdue, so this
deletes nothing on the next run.

Change

Four gh calls gained --repo "$GITHUB_REPOSITORY". The three
gh release upload calls in release.yml are left alone: those jobs do check
the repository out.

The pipeline that masks prune's errors is deliberately left as-is.

Verified with actionlint (clean) on both workflows.

Summary

  • Added --repo "$GITHUB_REPOSITORY" to four gh commands in the nightly publish and prune jobs.
  • Fixed release creation and release listing when jobs do not check out the repository.
  • Prevented nightly publish failures and repeated builds caused by missing repository context.
  • Kept the existing prune error-masking pipeline unchanged.
  • Left the three gh release upload commands in release.yml unchanged.
  • Verified both workflows with actionlint.

AI use

Probably AI-assisted. The change appears to use AI for summarization or review support, but there is no clear evidence of 100% agentic implementation.

Full Changelog: v2026.3.3...v2026.3.4


Pelton is free software under the GPL-3.0, provided without warranty and used at your own risk. It connects to your real mailboxes, deletions can be permanent, and Pelton is not a backup tool. Keep your own backup of anything you cannot afford to lose.

Warranty and liability: DISCLAIMER.md - pelton.app/terms

v2026.3.3

Choose a tag to compare

@github-actions github-actions released this 08 Aug 21:41
fdb06c7

Pelton can now read your mail out of the client you are leaving.

This release contains that one feature and nothing else.

Import from another mail client

Switching used to mean starting from nothing: every account retyped by hand, and any local-only mail left behind. Both halves are covered now.

Your accounts. Pelton reads Thunderbird's configuration and offers to recreate the mailboxes, so you do not retype six servers and ports. It looks where Thunderbird actually installs:

  • Linux the distro package, the Flatpak and the Snap, all three
  • macOS ~/Library/Thunderbird and ~/Library/Application Support
  • Windows %APPDATA%\Thunderbird

If your profile lives somewhere else, you can point at the folder yourself. Passwords cannot come across, so each mailbox asks for its password once.

Your mail. Single messages (.eml), whole archives (.mbox), and Thunderbird's own local folders, including nested ones. Read and flagged state comes with them. Importing the same file twice does not duplicate anything.

Large archives import in the background with a progress bar, so a multi-gigabyte mbox does not freeze the window.

Where to find it

Adding a mailbox now starts by asking whether you are setting one up or coming from another client. That choice appears wherever you add a mailbox: first run, the sidebar, the Mailbox menu, and Settings. There is also a direct entry under Settings, External.

Imported mail stays local

It lands in a new Local Folders section that has no server behind it. It is never synced, never uploaded, and never folded into the unified inbox, so importing a decade of old mail does not bury what is actually new. The section only appears once you have imported something.

Your old client is not touched

Pelton only reads. It never writes, renames or deletes anything in another program's mail store, and it leaves no cache or marker behind. That includes modification times, so the client you are migrating from cannot tell the difference. It is safe to point at a profile you are still using, and safe to run twice.

Nothing about the import touches the network.

Full Changelog: v2026.3.2...v2026.3.3

v2026.3.2

Choose a tag to compare

@github-actions github-actions released this 29 Jul 22:52
3134090

Changes

This release is about one thing: making clear, in every place Pelton is handed to you, that it comes without warranty and what that means for your mail.

Terms

  • DISCLAIMER.md ships with Pelton: warranty and liability as an additional term under GPLv3 section 7(a), German authoritative with an English translation, also published at pelton.app/terms.
  • The Windows installer shows a liability page after the GPL page.
  • The .deb, the .rpm and the macOS app bundle carry LICENSE and DISCLAIMER.md.
  • SECURITY.md documents the private reporting path for vulnerabilities.

In the app

  • Onboarding asks you to acknowledge the notice before setup continues. Installs that predate this are asked once on next start.
  • Settings, About Pelton has a new "Warranty and liability" entry next to the license links.

Fewer ways to lose data by accident

  • Importing a configuration now lists which categories it is about to overwrite and asks before writing. It used to replace settings, mailboxes, the remote-image whitelist and signatures on a single click, with no way back.
  • Removing an address book contact asks first.
  • The mailbox deletion prompt now names what is removed from this device (downloaded mail, attachments, the saved password) and says that mail on the server is not touched.

All new wording is available in English, German, French, Dutch, Spanish and Polish.

Full Changelog: v2026.3.1...v2026.3.2


Pelton is free software under the GPL-3.0, provided without warranty and used at your own risk. It connects to your real mailboxes, deletions can be permanent, and Pelton is not a backup tool. Keep your own backup of anything you cannot afford to lose.

Warranty and liability: DISCLAIMER.md - pelton.app/terms

v2026.3.1

Choose a tag to compare

@github-actions github-actions released this 27 Jul 17:48

Highlights

  • Views can now match on multiple sender and recipient addresses, and support regular expressions for text, from, to and subject.
  • Settings are reorganized into clearer groups with a search box that finds individual settings, not just categories.
  • New offline indicator in the status bar. When there is no connection, sync and the raw-source viewer say "No internet connection" instead of confusing credential or host errors.
  • Unified Inbox and the built-in view names (Inbox, Flagged, Drafts, Sent, and more) are now fully localized.
  • Optional fullscreen empty-state background image for the reading pane, off by default.
  • New "This email" action to load remote content for a single message, remembered across syncs.
  • Polish language support.

Changes

feat: add Polish (pl) locale - @TRC-Loop in #153

Closes #140.

Adds a Polish (pl) locale.

Changes

  • New frontend/src/lib/locales/pl.ts translating every key from en.ts. Key set is at exact parity with en.ts (verified by diff); placeholder tokens ({count}, {who}, {when}, {version}, {n}, {field}, {folder}, {size}, {mailbox}, {author}, {detail}) are preserved verbatim, and technical terms (IMAP, SMTP, OAuth, Gravatar, BIMI, PGP, SPF/DKIM/DMARC, MCP, TLS/SSL/STARTTLS, Markdown, HTML, Vim, proxy) are left untranslated.
  • Registered pl in the i18n loader/selector (Locale type, locales array, localeNames -> "Polski", dynamic import map), so it is selectable in Settings.
  • Extended the Go-side locale tables so Polish users also get native strings: built-in locales set (bind_locales.go), new-mail notifications (notify.go), and the native menu bar (menu_i18n.go).
  • No em-dashes in any string.

Verification

  • pl.ts key set diffs clean against en.ts.
  • go build, go test (internal/desktop), svelte-check and pnpm build all pass.

Note: this is a complete first-pass translation; a native-speaker review pass is welcome as a follow-up.

feat: fullscreen empty-state background toggle - @TRC-Loop in #152

Closes #148.

Adds an option to show the empty-state image as a full-screen background of the reading pane, instead of the small centered mark.

Changes

  • New emptyStateFullscreen boolean preference, off by default.
  • When on (and an empty-state image is set), the reading pane renders that image as a full-bleed cover background when no message is open. Otherwise the existing small, faded, centered mark is unchanged.
  • Toggle added in Settings next to the empty-state image picker; it is disabled until an image is chosen.
  • Wired through backend setting (empty_state_fullscreen), UIPrefsDTO, prefs store + setter, api key, types, and generated bindings.
  • i18n keys added to all five locales (en/de/fr/es/nl).

Verification

  • go build, svelte-check, and pnpm build all clean.
feat: group and rebalance settings categories with per-setting search - @TRC-Loop in #151

Closes #130.

The settings panel had ~20 flat categories with a badly overloaded Appearance section and several near-empty ones. This groups and rebalances them and adds real per-setting search. Every existing setting is preserved, only relocated.

Categories: 24 → 16, grouped under 6 headings

  • Appearance now holds theming only: theme/schedule, accent, density, corners, interface scale, reduce motion, empty-state image.
  • Menu bar (new): the whole macOS menu-bar cluster pulled out of Appearance.
  • Reading & display = Display + Panes + all three font pickers (body/UI/mono moved out of Appearance).
  • Message list = List + Sidebar + Avatars.
  • Composing & sending = Composing + Sending.
  • Privacy & network = Privacy + Network.
  • Accounts = Mailboxes + Contacts.
  • Backup & integrations = External + Import/Export.
  • Sync & power = Power + Offline/download.
  • Unchanged: Themes, Language, Signatures, Notifications, Gestures, Shortcuts, About.

Nav groups: Appearance / Mail / Privacy / Accounts / Advanced / About. Merged sub-groups get a labeled divider so nothing reads as a jumble.

Per-setting search

Typing filters the nav and shows a flat results list of individual settings by their own label (e.g. proxy, gravatar, vim, undo send, swipe, backup), each tagged with the category it lives in; clicking jumps straight there.

Spacing and space

  • Hints now hug the control they describe with a clear gap below, so they read as part of that setting instead of floating between two.
  • Content column widened 560 to 720px.

i18n / verification

  • New keys (groups, per-category keywords, new category labels, Menu bar) added to all five locales (en/de/fr/es/nl), files at parity.
  • Every category key maps 1:1 to a render block; no setting removed.
  • svelte-check clean, pnpm build clean.
feat: multi-address chips and regex matching in views - @TRC-Loop in #150

Closes #149.

Saved views can now filter with multiple sender/recipient addresses and match content with regular expressions.

Changes

  • Multi-address chips for From / To. The single-line from and to inputs are now chip inputs: type an address, press Enter/comma/semicolon (or blur) to add it, remove with backspace or the x. A message matches the field when it matches any chip (OR within the field); fields still AND with each other.
  • Regex toggle. A per-view "Use regular expressions" option treats the text/from/to/subject criteria as regular expressions instead of plain substrings. Invalid patterns are rejected on save; a view whose regex fails to compile at run time matches nothing rather than breaking the sidebar.

Implementation

  • Plain single-address views keep the existing full-text index path (unchanged behavior/perf). Regex or multi-address views take a scan-and-filter path: read the newest messages in scope (capped by maxViewScan), then match in Go. Matches stay capped at maxViewMatches.
  • Storage: new use_regex column (migration 0012); query_from/query_to now hold a newline-separated address list. Existing single-address views load as one-item lists, so nothing breaks on upgrade.
  • Plain matching is case-insensitive substring; regex is matched as written (use (?i) for case-insensitive).
  • i18n keys added to all five locales. Generated Wails bindings updated for the new DTO shape.

Tests

  • internal/desktop/bind_views_test.go: multi-address OR, case-insensitive plain match, regex alternation, invalid-regex rejection, and field ANDing.
  • Full go test ./internal/..., svelte-check, and pnpm build pass.
feat: persistent per-message remote content allow - @TRC-Loop in #154

Closes #136.

Adds a persistent per-message remote-content allow, so a newsletter or receipt you reopen often can render remote images every time without trusting the whole sender or domain.

Approach

Chose option 1 from the issue: a fourth banner action, This email, alongside "Load once" / "This sender" / "This domain". It is non-modal and does not change what "Load once" does (which stays ephemeral).

Changes

  • Backend AllowRemoteForMessage(messageID) records the message in a new remote_allow_messages setting. It is keyed by the RFC Message-ID header (lowercased/trimmed) so the allow survives re-sync, expunge and a changed local row id; when a message has no Message-ID it falls back to local:<row id>.
  • GetMessage now renders remote content when the message is individually allowed: remoteAutoAllow(from) || remoteMessageAllowed(m). The existing global / sender / domain paths are untouched, so privacy defaults (blocked by default) are unchanged and this stays an explicit per-message opt-in.
  • Frontend: new banner button wired to allowRemoteForMessage; on click it persists and renders remote content immediately. New i18n keys added to all five locales (en/de/fr/es/nl). No em-dashes.
  • Generated Wails bindings + api wrapper updated for the new method.

Tests / verification

  • internal/desktop/bind_images_test.go: Message-ID keying and local fallback.
  • go build, go test (internal/desktop), svelte-check and pnpm build all pass.

Full Changelog: v2026.3...v2026.3.1

v2026.3

Choose a tag to compare

@github-actions github-actions released this 25 Jul 23:01
Pelton2026 3-banner

Changes

chore(deps): Bump the frontend-dependencies group across 1 directory with 11 updates - @dependabot[bot] in #118

Bumps the frontend-dependencies group with 11 updates in the /frontend directory:

Package From To
@fontsource/familjen-grotesk 5.2.8 5.3.0
@fontsource/spline-sans-mono 5.2.8 5.3.0
@tabler/icons-svelte 3.44.0 3.45.0
@tiptap/core 3.27.3 3.28.0
@tiptap/extension-link 3.27.3 3.28.0
@tiptap/pm 3.27.3 3.28.0
@tiptap/starter-kit 3.27.3 3.28.0
marked 18.0.6 18.0.7
svelte 5.56.4 5.56.7
svelte-check 4.7.2 4.7.3
vite 8.1.4 8.1.5

Updates @fontsource/familjen-grotesk from 5.2.8 to 5.3.0

Commits

Updates @fontsource/spline-sans-mono from 5.2.8 to 5.3.0

Commits

Updates @tabler/icons-svelte from 3.44.0 to 3.45.0

Release notes

Sourced from @​tabler/icons-svelte's releases.

Release 3.45.0

20 new icons:

  • filled/brand-signal
  • outline/app-window-bottom-left
  • outline/app-window-bottom-right
  • outline/app-window-bottom
  • outline/app-window-center
  • outline/arrow-fork-triple
  • outline/brand-signal
  • outline/device-vision-pro-wifi
  • outline/device-workstation
  • outline/dragon
  • outline/italic-off
  • outline/tab-close
  • outline/text-outline
  • outline/text-regex-asterisk
  • outline/text-regex-end
  • outline/text-regex-plus
  • outline/text-regex-question
  • outline/text-regex-start
  • outline/underline-off
  • outline/virtual-space

New features

  • New package: @tabler/icons-astro — Astro support
  • Added sideEffects: false for better tree-shaking in Vue package
  • Spelling fixes: corrected misspelled icon names

Fixed icons: outline/flip-horizontal, outline/flip-vertical

Renamed icons:

  • filled/mood-confuzed renamed to filled/mood-confused
  • outline/brand-adobe-after-effect renamed to outline/brand-adobe-after-effects
  • outline/brand-kako-talk renamed to outline/brand-kakao-talk
  • outline/currency-rubel renamed to outline/currency-ruble
  • outline/foodsteps renamed to outline/footsteps
  • outline/gender-trasvesti renamed to outline/gender-travesti
  • outline/ikosaedr renamed to outline/icosahedron
  • outline/mood-confuzed renamed to outline/mood-confused
  • outline/physotherapist renamed to outline/physiotherapist
  • outline/sport-billard renamed to outline/sport-billiard
Commits

Updates @tiptap/core from 3.27.3 to 3.28.0

Release notes

Sourced from @​tiptap/core's releases.

v3.28.0

@​tiptap/extension-details

Patch Changes

  • 8614730: Fix the cursor moving to the details summary after typing in content at the start of a document.
  • @​tiptap/core@​3.28.0
    • @​tiptap/extension-text-style@​3.28.0
    • @​tiptap/pm@​3.28.0

@​tiptap/extension-list

Patch Changes

  • 8614730: Fix markdown parsing a line like (216) 555-1234 as an ordered list. A number followed by ) mid-line is no longer treated as a list marker.
  • @​tiptap/core@​3.28.0
    • @​tiptap/pm@​3.28.0

@​tiptap/react

Patch Changes

  • 8614730: Batch React node view portal store notifications that happen in the same microtask to avoid nested update depth warnings when many node views mount together.
  • 8614730: Bind onMount and onUnmount event handlers when initializing an Editor with useEditor hook.
  • @​tiptap/core@​3.28.0
    • @​tiptap/pm@​3.28.0

@​tiptap/extension-collaboration-caret

Patch Changes

  • 8614730: Bump @​tiptap/y-tiptap version to ensure users use latest version
  • @​tiptap/core@​3.28.0
    • @​tiptap/pm@​3.28.0

@​tiptap/extension-collaboration

Patch Changes

  • 8614730: Bump @​tiptap/y-tiptap version to ensure users use latest version
  • @​tiptap/core@​3.28.0
    • @​tiptap/pm@​3.28.0

@​tiptap/extension-drag-handle

Patch Changes

  • 8614730: Bump @​tiptap/y-tiptap version to ensure users use latest version
  • Updated dependencies [8614730]
    • @​tiptap/extension-collaboration@​3.28.0

... (truncated)

Changelog

Sourced from @​tiptap/core's changelog.

3.28.0

Patch Changes

  • @​tiptap/pm@​3.28.0

3.27.4

Patch Changes

  • @​tiptap/pm@​3.27.4
Commits

Updates @tiptap/extension-link from 3.27.3 to 3.28.0

Release notes

Sourced from @​tiptap/extension-link's releases.

v3.28.0

@​tipt...

Read more

v1.0.9

Choose a tag to compare

@github-actions github-actions released this 23 Jul 12:17

Pelton 1.0.9.

Highlights

  • IMAP/SMTP username auth — accounts whose login name differs from the email address can now be added and edited, plus an explicit SMTP security (SSL/TLS vs STARTTLS) selector. (#108)
  • Outbound proxy — new Preferences → Network section routing all connections (IMAP, SMTP, and web calls) through a SOCKS5 or HTTP proxy, or the system proxy environment, with keyring-stored auth. (#110)
  • Linux .deb + raw binary now published alongside the Fedora .rpm.

Important

1.0.9 is the last release to use semantic versioning. From the next release Pelton moves to Calendar Versioning (YYYY.Q.INCR — year, calendar quarter, per-quarter counter). The next version will be 2026.4.0, written as 2026.4 for the flagship (first) release of the quarter. See the README "Versioning" section for details.


Changes

ci: publish linux amd64 binary and .deb alongside the .rpm - @TRC-Loop in #112

Adds two Linux release artifacts next to the existing Fedora .rpm:

  • Raw amd64 binary Pelton-<version>-linux-amd64 for users who just want to run it directly.
  • Debian/Ubuntu .deb Pelton-<version>-linux-amd64.deb built with the same nfpm config.

How

  • The linux-fedora job is renamed linux since it now produces the binary, the .deb and the .rpm from one build.
  • nfpm's depends moved into per-packager overrides, because the gtk3/webkit2gtk runtime has different package names on Debian vs Fedora. The .deb depends on libgtk-3-0 | libgtk-3-0t64 (the second covers Ubuntu 24.04's t64 rename) and libwebkit2gtk-4.1-0; the .rpm keeps gtk3 / webkit2gtk4.1.
  • The same post-install hook that refreshes the desktop/icon caches runs on both (.rpm posttrans, .deb postinstall).
  • The version step strips a leading v for both package formats (pkg_version).

Targets dev for the 1.0.9 release.

feat: outbound proxy settings for mail and web connections - @TRC-Loop in #111

Closes #110.

Adds an outbound proxy option in Preferences -> Network that routes every Pelton connection through a proxy.

What

  • Modes: Off, System, Manual.
    • System follows the standard proxy env vars (HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY), honouring NO_PROXY per target.
    • Manual supports SOCKS5 and HTTP proxies, with optional username/password.
  • Covers everything: IMAP, SMTP, and the app's own web calls (autodiscovery, update check, one-click unsubscribe).
  • Auth in the keyring: the proxy password is stored in the OS keyring like account secrets, never in the settings db. The UI is write-only for the password (it receives only hasPassword, shows a placeholder, and keeps the stored secret unless you type a new one).
  • Test button dials a well-known endpoint through the proxy so you can confirm it works before saving.

How

  • New internal/proxy package: Config -> a TCP DialContext (SOCKS5 via golang.org/x/net/proxy, HTTP via a CONNECT tunnel in connect.go, system via httpproxy.FromEnvironment) and an *http.Client factory.
  • The IMAP/SMTP configs gain an optional Dial hook. When no proxy is set the hook is nil and the existing direct-dial path is used unchanged - so non-proxy users are byte-for-byte unaffected. Only proxied connections take the new path (which builds the client from a pre-dialed conn, since go-imap's Dial* only accepts a concrete *net.Dialer).
  • Proxy preference persisted as JSON under the proxy setting; password in the keyring. Loaded once at startup and cached on App, refreshed by SetProxyConfig.
  • The three web call sites now take an *http.Client from the proxy-aware factory.

Testing

  • New internal/proxy unit tests: config validation, credential-carrying URL, dialer selection, and a stub HTTP proxy verifying the CONNECT tunnel and Proxy-Authorization.
  • go test ./internal/..., go vet, gofmt clean; svelte-check clean.

Note

DNS resolution and the MX-probe step of autodiscovery are not tunnelled (they are not HTTP); the mail and web transports are. Full OS GUI proxy settings (macOS SystemConfiguration / Windows WinHTTP) are out of scope; System mode uses the environment variables, which is the cross-platform, GDPR-safe common denominator.

Targets dev for the 1.0.9 release.

feat: separate login username and explicit SMTP security in account setup - @TRC-Loop in #109

Fixes #108, reported by @ahornero (Alberto). Thanks for the clear report and the offer to test.

What

Two gaps in the manual IMAP/SMTP account setup:

  1. Separate login username. Some servers authenticate on a username that is not the email address. The setup form assumed username == email, so those accounts could not be added. There is now an optional Username field (add wizard and mailbox editor); leave it blank to keep logging in with the email address.
  2. Explicit SMTP security. The advanced section only exposed IMAP security (SSL/TLS vs STARTTLS). SMTP now has the same toggle. The security choice sets the conventional port as the default; the port field stays fully editable for non-standard setups.

How

  • New migration 0010_account_username.sql adds a username column (default empty = log in with email), so every existing account keeps working unchanged.
  • Username threaded through storage.Account, add/update/test-connection requests, the credential resolvers (loginName helper: username when set, else email), backup export/import, and the DTO.
  • SMTP TLS mode is derived from the port (465 implicit, 587 STARTTLS), matching the existing IMAP behaviour; the new toggle just flips the conventional port.
  • Wizard + mailbox editor UI, generated Wails bindings (hand-edited), and en/de/fr/es strings.

Testing

  • go test ./internal/... and go vet pass.
  • svelte-check clean.

Targets dev for the 1.0.9 release.

fix: correct nfpm scripts placement so the .deb builds - @TRC-Loop in #115

The 1.0.9 linux release job failed with Yaml: unmarshal errors: field posttrans not found in type nfpm.Scripts: posttrans is rpm-specific and only valid under the top-level rpm: block, not under overrides.<packager>.scripts.

Fix: keep posttrans under rpm.scripts, keep the Fedora depends at top level (used by the .rpm), and override only the .deb with its Debian dependency names plus a postinstall hook.

Validated locally with nfpm: both --packager deb and --packager rpm now build, and the .deb control lists Depends: libgtk-3-0 | libgtk-3-0t64, libwebkit2gtk-4.1-0.

macOS/Windows/Copr artifacts on 1.0.9 were unaffected; this re-cuts the linux artifacts.

Full Changelog: v1.0.8...v1.0.9

v1.0.8

Choose a tag to compare

@github-actions github-actions released this 13 Jul 18:42

Changes

chore: derive wails CLI version from go.mod in release builds - @TRC-Loop in #86

Fixes #70.

The release workflow pinned WAILS_VERSION: v2.12.0 while go.mod moved to v2.13.0, so every release since the bump was built by the older CLI (the known class of problem where a mismatched wails CLI rewrites go.mod and the runtime bindings to its own version).

Instead of bumping the pin and hoping it stays in lockstep, the env var is gone entirely: all four install steps now derive the CLI version from the module pin itself (go list -m -f '{{.Version}}' github.com/wailsapp/wails/v2), so the CLI can never drift from go.mod again.

docs: fix icon rendering, macos steps, annotation, footer - @TRC-Loop in #79

Docs site fixes after the first deploy:

  • Icons rendered filled instead of stroked (the globe was a solid blob): the theme CSS sets fill: currentColor, which beats SVG presentation attributes. The vendored tabler icons now carry their stroke styling as an inline style attribute, which wins.
  • macOS install steps now describe the real first-launch flow: Done in the blocked dialog, System Settings, Privacy & Security, Open Anyway, authenticate. The xattr one-liner stays as the shortcut. FAQ entry matches.
  • The container tree in the theme format spec uses a clickable code annotation for manifest.json instead of an inline comment.
  • Footer privacy link reads "Privacy / Datenschutz", matching the bilingual imprint label.

Verified locally: build clean, no-CDN check passes, annotation markup and inline icon styles present in the output.

Summary

  • Updated macOS installation and FAQ guidance to reflect the actual Privacy & Security → Open Anyway flow, while retaining xattr as a shortcut.
  • Replaced the inline manifest.json comment with a clickable theme-format annotation.
  • Renamed the footer link to Privacy / Datenschutz.
  • Applied inline stroke styling to vendored Tabler icons.
  • Confirmed a clean build, no-CDN compliance, and expected annotation/icon markup.

AI usage

Not Likely — no explicit AI, agent, co-author, or generated-content indicators were identified. There is insufficient evidence to conclude that AI was used.

docs: zensical site for docs.pelton.app - @TRC-Loop in #78

Sets up docs.pelton.app as a Zensical site (the successor to Material for MkDocs, by the same team), styled like Pelton itself.

Structure:

  • zensical.toml at the repo root, content in docs/, vendored tabler icons in overrides/.icons/tabler/ (generated from the same @tabler package the app uses).
  • Pages: landing (card grid), Install (macOS/Windows/Copr dnf/raw rpm/source, in content tabs), Getting started (mailboxes, app passwords, sync, data locations, privacy defaults), Themes (overview + full .peltontheme spec + create-a-theme walkthrough), Shortcuts (keys markup), FAQ.
  • docs/AGENTS.md is the machine-readable documentation; docs/llms.txt just points to https://docs.pelton.app/AGENTS.md. The deploy copies the raw markdown to /AGENTS.md next to the rendered /AGENTS/ page.

Style: Pelton's tokens mapped onto the theme variables (light and dark, toggle defaults to the system scheme), bundled Familjen Grotesk and Spline Sans Mono, flat header with hairline border, 5px radii, tabler icons only (header repo badge, palette toggles, footer socials).

No CDNs, by design and by enforcement:

  • font = false (Google Fonts off), no emoji shortcodes, no math extension, all fonts/icons/scripts served from the site itself.
  • The deploy workflow fails if the built html/css contains any external src/link/url()/@import load. Plain text links (imprint, Apple/Google help pages) are allowed.
  • Remaining "fontawesome.com" strings are license comments inside Zensical's own bundled stylesheet (inline data-URI glyphs); nothing is fetched.

Footer: copyright, pelton.app, Imprint / Impressum, Privacy, and a "For AI Agents" link to /AGENTS.md. Socials: GitHub and pelton.app with tabler icons.

Deploy: .github/workflows/docs.yml builds on pushes to main touching docs/**, zensical.toml or the workflow, runs the no-CDN check, and deploys to GitHub Pages (zensical pinned to 0.0.50). One-time setup after merge: repo Settings > Pages > Source: GitHub Actions, and a DNS CNAME for docs.pelton.app (docs/CNAME is already in the artifact).

Not included: social preview cards (Zensical 0.0.50 has no generator for them yet, revisit when it lands).

Verification: local zensical build --clean is clean, the external-load scan reports nothing, no em-dashes or slop vocabulary in the content.

Summary

  • Added a Pelton-styled Zensical documentation site for docs.pelton.app.
  • Documented installation, setup, themes, shortcuts, privacy, and FAQs.
  • Added self-hosted fonts, icons, logos, custom CSS, light/dark themes, and custom-domain configuration.
  • Added machine-readable AGENTS.md and llms.txt.
  • Added GitHub Pages deployment with a guard against external asset loads.
  • Added local site/ build-output exclusion.

AI involvement

AI use is 100% — Very Likely, with strong signs of agentic assistance, including AI-generated change summaries, the AGENTS.md file, and highly structured documentation.

feat: 12/24-hour time format setting - @TRC-Loop in #87

Fixes #62.

Adds a clock preference under Settings > Display: Auto (follows the system locale, the previous behavior and the default), 12-hour, or 24-hour.

All time rendering now goes through shared helpers in lib/format.ts that take the preference, so it applies consistently everywhere times show: message list dates, the reading-pane header, message info modal, backup file info, send-later presets, snooze presets, outbox scheduled rows, and the date picker summary. The scattered per-component toLocaleString calls were converted to the shared helpers along the way, so future call sites inherit the setting for free.

Backed by a time_format setting (stored like every other pref), default auto.

feat: auto dark mode by time of day - @TRC-Loop in #89

Fixes #61.

Adds a fourth theme mode, Scheduled, next to System/Light/Dark in appearance settings. It switches to the dark theme inside a configurable window (default 19:00 to 07:00, two native time inputs shown while the mode is selected) and back to light outside it.

  • resolveTheme in theme.ts learned the schedule preference; the window may cross midnight, and a half-typed or malformed time keeps the previous bound instead of flipping the theme.
  • Re-evaluated once a minute plus whenever the window regains focus, so waking from OS sleep (where a timer fires late) picks the right side of the boundary promptly.
  • Follows all the existing theme plumbing: native window chrome syncs on every flip, and an active custom .peltontheme still pins its own base like it does for the other modes.
  • Times persist as theme_dark_start/theme_dark_end ("HH:MM").
feat: corner style setting - @TRC-Loop in #102

Fixes #60

Adds the missing cosmetic from the #60 grab-bag: a corner style setting under Settings > Appearance with Square / Default / Rounded, applied live like theme and density.

The issue's other examples already landed elsewhere: accent color has its own picker, and list row styling shipped as the row template settings. Corner radius was the remaining gap. Square zeroes the radius tokens, Rounded softens them (10px controls, 12px cards); the implementation is a data-corners attribute on the root that swaps only the --radius-control/--radius-card tokens, so every component stays corner-agnostic, custom themes keep working (their radius tokens win while a theme is active with its own values), and the setting persists and exports/imports with the settings category like the other appearance options.

Note for merging: same trivial adjacent-line conflicts with the other settings-plumbing PRs (#87-#90) as they have among themselves; merge oldest-first and say the word if any need a rebase.

Verified: go build/vet/gofmt, desktop tests, svelte-check 0 errors. Labels in all five languages.

feat: default font dropdown for email bodies - @TRC-Loop in #90

Fixes #66.

Adds a Mail body font dropdown under Settings > Display, next to the message font size. It only changes the base font-family the reader iframe's srcdoc styles set, so emails that declare their own fonts keep them; the setting is pur...

Read more