What Postio is
Postio is a local-first, keyboard-first email client built for people who have too much email.
Read less. Find anything. Act faster.
If you’ve used a mail client that makes you wait — for the inbox to load, for search to come back, for a click to register — Postio is built to never do that. It keeps a full copy of your mail in a local database with a built-in search index, so opening the app, searching, and moving around never touch the network. Every action you take — archive, flag, move, delete, undo — applies instantly to that local copy and is sent to the server in the background. You are never staring at a spinner waiting for your own mailbox to respond.
The three things it has to be better at
Speed. Startup, navigation, and search are held to a real budget — under half a second to a usable inbox, under 100ms for a search — and it’s checked automatically, not just claimed.
Search. Search isn’t a box in the corner; it’s a primary way to move
through your mail. from:ada after:2026-01-01 has:attach is a query you can
type, save, or pin as a folder — one language, everywhere it appears.
Keyboard. Every action has a shortcut. j/k move, e replies, a
archives, u undoes anything, / searches, Ctrl+K opens the command
palette, ? shows the full cheat sheet. The mouse works too, and is never
required.
What v1 does
One IMAP + SMTP account, authenticated with a password or an app-specific password. Inbox, folders, threads. Read/unread, archive, delete, flag, move. HTML and plain-text reading, attachments, quoted-message folding. Compose, reply, reply-all, forward, drafts. Local full-text search with operators. Vim-style navigation and a command palette, every binding rebindable. Background sync, full offline reading, undo.
What it deliberately doesn’t do yet
Postio is Linux-only for now (GTK4/libadwaita), and v1 has no AI features — not because they aren’t planned, but because shipping AI over a mediocre mail client would just produce a mediocre mail client with AI in it. Core mail, search, and the keyboard come first. Rules, contacts management, and snooze/scheduled send are also out of v1, each with its own tracked issue.
Ready to try it? See Installing Postio.
This is the reference documentation. The Postio home page is the wider tour: what it looks like, what it is for, and where the project stands.
Installing Postio
Postio is pre-release and, for now, Linux only: GTK4/libadwaita, Wayland first, X11 where it happens to work. There’s no packaged release yet, so installing it means building from source.
System dependencies
Fedora 40+:
sudo dnf install gtk4-devel libadwaita-devel webkitgtk6.0-devel \
sqlite-devel libsecret-devel glib2-devel pkgconf-pkg-config
Ubuntu 26.04 (earlier releases ship a GTK older than Postio’s floor):
sudo apt install build-essential pkg-config libgtk-4-dev libadwaita-1-dev \
libwebkitgtk-6.0-dev libsqlite3-dev libsecret-1-dev \
libglib2.0-dev libpango1.0-dev
Rust is pinned by the project’s rust-toolchain.toml — with
rustup installed, the right compiler arrives
automatically on your first cargo command.
Build and install
git clone https://github.com/dlapiduz/postio.git
cd postio
scripts/install-local.sh # builds --release, installs to ~/.local
That puts postio on your $PATH and adds it to your app grid, with its
icon. scripts/install-local.sh --uninstall removes exactly what it
installed.
Prefer to just try it without installing anything?
cargo run -p postio-app
Prefer a sandboxed build? Postio ships a Flatpak manifest under flatpak/
that builds against the GNOME 50 runtime — see flatpak/README.md in the
repository for the one-time SDK setup. Postio isn’t on Flathub yet, so for
now that means building the Flatpak yourself too.
First run
First run opens onto a one-screen setup: type your email address, and Postio’s autoconfig probe fills in the server settings for you (checking a built-in provider table, then Thunderbird’s autoconfig service, then DNS SRV records — or you can enter everything manually). Your password goes straight into your desktop’s keyring; it is never written to a file. iCloud accounts need an app-specific password, generated at https://account.apple.com.
From there, drive it from the keyboard: j/k to move, Enter to open,
e to reply, a to archive, u to undo anything, / to search
(from:ada is:unread …), Ctrl+K for the command palette, ? for the
full cheat sheet. Every binding is rebindable — see the
keyboard reference.
Troubleshooting
cargo build fails looking for a library (a pkg-config error naming
gtk4, libadwaita-1, webkitgtk-6.0, sqlite3, or libsecret-1): a
system dependency from the list above is missing or too old. Check what you
have against what’s needed with pkg-config --modversion gtk4 (and so on
for the others).
The window fails to open, or opens with broken rendering: only Wayland
is verified. If you’re on X11 and hit a rendering issue, try a Wayland
session first, or force the X11 backend explicitly with
GDK_BACKEND=x11 cargo run -p postio-app before filing an issue.
Onboarding won’t save the account, or every launch reopens onboarding:
Postio stores credentials in your OS keyring over the Secret Service D-Bus
API, which needs a running keyring daemon — GNOME Keyring or KWallet’s
Secret Service integration are the common ones. Minimal desktop
environments often don’t start one by default; on Fedora,
sudo dnf install gnome-keyring and make sure your session starts it. A
locked keyring blocks the same way — unlock it and try again.
Keyboard reference
Every command below is also in the Ctrl+K palette and the ? cheat
sheet, because all three are generated from one table.
Bindings come from the design canvas — e replies, not r.
docs/PRODUCT.md §8 records that resolution; this table is the registry.
Rebinding
Every binding is overridable from the [keys] section of
config.toml, keyed by the command id in the last column:
[keys]
archive = "y"
first_message = "g g"
A chord joins modifiers to a key with + (ctrl+k); a sequence
separates chords with a space (g g). Shift is written into the
character, so A is what you get by holding shift — a and A are
different bindings. An override that cannot be used, or that collides
with a key already taken in the same place, is reported in the settings
panel and the command keeps its default.
mod is the primary accelerator: Control here, Command on macOS.
Every default above uses it, which is why the same config.toml
means the same thing on both. Writing ctrl instead pins the
binding to Control everywhere.
While you are typing, single-key bindings do not fire. Only Escape,
the function keys, and chords holding Ctrl, Alt or Super reach a
command from inside a text field.
Bindings
| Keys | Command | Where | Undo | Id |
|---|---|---|---|---|
j or Down | Next message | List, conversation, reader, search | next_message | |
k or Up | Previous message | List, conversation, reader, search | prev_message | |
g g | First message | List, conversation, reader, search | first_message | |
G | Last message | List, conversation, reader, search | last_message | |
Return or l or Right | Open message | List, conversation, search | open_message | |
x | Toggle selection | List, conversation, reader, search | toggle_selection | |
J or shift+Down | Extend selection down | List, reader, search | extend_selection_down | |
K or shift+Up | Extend selection up | List, reader, search | extend_selection_up | |
ctrl+a | Select all | List, conversation, reader, search | select_all | |
h or Left | Previous view | List, conversation, reader | prev_view | |
Escape | Back | Everywhere | back | |
o | Toggle result order | Search | toggle_result_order | |
J | Next message in conversation | Conversation | next_in_conversation | |
K | Previous message in conversation | Conversation | prev_in_conversation | |
z | Fold or unfold this message | Conversation | toggle_fold | |
ctrl+o | View original | List, conversation, reader | view_original | |
O | Expand all | Conversation | expand_all | |
I | Hide or show the conversation rail | Conversation | toggle_rail | |
e | Reply | List, conversation, reader, composer | reply | |
E | Reply to all | List, conversation, reader, composer | reply_all | |
f | Forward | List, conversation, reader, composer | forward | |
a | Archive | List, conversation, reader | Undoable | archive |
A | Archive thread | List, conversation, reader | Undoable | archive_thread |
d | Delete | List, conversation, reader | Undoable | delete |
m | Move to… | List, conversation, reader | Undoable | move |
s | Flag | List, conversation, reader | Undoable | flag |
U | Mark unread | List, conversation, reader | Undoable | mark_unread |
b | Snooze | List, conversation, reader | Undoable | snooze |
B | Unsnooze | List, conversation, reader | Undoable | unsnooze |
L | Add label… | List, conversation, reader | Undoable | add_label |
/ | Search | List, conversation, reader | search | |
ctrl+s | Save search as folder | Search | save_search | |
c | Compose | List, conversation, reader | compose | |
ctrl+Return | Send | Composer | Undo briefly | send |
ctrl+shift+Return | Schedule send… | Composer | schedule_send | |
ctrl+s | Save draft | Composer | save_draft | |
ctrl+d | Discard draft | Composer | Asks first | discard_draft |
ctrl+shift+m | Mark as sent | List, composer | mark_sent | |
ctrl+shift+r | Retry send | List, composer | retry_send | |
ctrl+shift+x | Cancel send | List, composer | cancel_send | |
ctrl+shift+a | Attach file… | Composer | attach_file | |
ctrl+shift+o | Detach composer | Composer | detach_composer | |
ctrl+shift+c | Cc and Bcc | Composer | copy_fields | |
ctrl+shift+g | Insert image… | Composer | insert_image | |
ctrl+b | Bold | Composer | bold | |
ctrl+i | Italic | Composer | italic | |
ctrl+shift+8 | Bulleted list | Composer | bullet_list | |
ctrl+shift+7 | Numbered list | Composer | numbered_list | |
ctrl+shift+k | Insert link… | Composer | insert_link | |
ctrl+shift+9 | Quote block | Composer | quote_block | |
u | Undo | List, conversation, reader, account list | undo | |
ctrl+k | Command palette | Everywhere | command_palette | |
? | Keyboard shortcuts | List, conversation, reader | cheat_sheet | |
ctrl+comma | Settings | Everywhere | settings | |
ctrl+shift+n | Add account | Everywhere | add_account | |
ctrl+e | Edit configuration | List, conversation, reader | edit_config | |
ctrl+b | Toggle sidebar | List, conversation, reader | toggle_sidebar | |
g f | Focus the folder list | List, conversation, reader, search | focus_sidebar | |
tab | Next pane | List, conversation, reader, folder list | cycle_pane | |
shift+tab | Previous pane | List, conversation, reader, folder list | cycle_pane_back | |
j or Down | Next folder | Folder list | next_folder | |
k or Up | Previous folder | Folder list | prev_folder | |
space | Expand or collapse folder | Folder list | toggle_folder | |
r | Rename saved search | Folder list | rename_saved_search | |
shift+Up | Move saved search up | Folder list | move_saved_search_up | |
shift+Down | Move saved search down | Folder list | move_saved_search_down | |
d | Delete saved search | Folder list | Asks first | delete_saved_search |
Return | Enable or disable account | Account list | toggle_account_enabled | |
d | Remove account | Account list | Undoable | remove_account |
c | Update account credential | Account list | update_credential | |
r | Rebuild search index | Account list | rebuild_account_index | |
m | Set as default account | Account list | set_default_account | |
M | Map mailbox role | Account list | Undoable | map_mailbox_role |
g a | Next scope | List, folder list | next_scope | |
F5 or R | Refresh | List, conversation, reader | refresh | |
p | Show message parts | Reader | open_parts | |
j or Down | Next part | Parts panel | next_part | |
k or Up | Previous part | Parts panel | prev_part | |
Return | Open part | Parts panel | open_part | |
s | Save part | Parts panel | save_part | |
S | Save all parts | Parts panel | save_all_parts | |
x | Open part externally | Parts panel | open_part_externally | |
H | Render part once | Parts panel | render_part_once | |
Page_Down or space | Scroll reading pane down | List, conversation, reader | scroll_reader_down | |
Page_Up or shift+space | Scroll reading pane up | List, conversation, reader | scroll_reader_up |
Configuration reference
~/.config/postio/config.toml is the settings – there is no separate
store. A missing or empty file is not an error: every key below has a
working default, and Postio writes a starter file on first run so
there is something to find and edit rather than a blank buffer. The
file is watched and re-parsed live; a key this build does not
recognise survives a round trip untouched, in case a newer Postio
wrote it.
[ui]
| Key | Type | Default | Description |
|---|---|---|---|
density | string | "airy" | Message-list row height: airy, comfortable or compact. |
theme | string | "system" | Light/dark preference: system (follows the desktop), light or dark. |
show_hover_actions | boolean | true | Show per-row actions when the pointer rests over a row. |
show_key_hints | boolean | true | Show the focused row’s key hints (e reply, a archive). Off leaves every binding in force – this only stops the row from naming them. |
sender_avatars | boolean | true | Show each row’s sender-initials chip. |
[sync]
| Key | Type | Default | Description |
|---|---|---|---|
check_for_mail | string | "idle" | How Postio learns about new mail: idle (hold an IDLE connection on INBOX for push delivery), poll (no IDLE, every mailbox reconciled on poll_interval_secs), or manual (never checks on its own). |
poll_interval_secs | integer | 300 | Polling interval for folders without IDLE, in seconds. |
max_connections | integer | 5 | Maximum simultaneous IMAP connections per account. |
sync_on_startup | boolean | true | Start a sync as soon as the app opens. |
body_fetch | string | "lazy" | When message bodies are downloaded: lazy (headers first, bodies backfilled) or eager. |
attachment_fetch | string | "on_open" | When an attachment’s bytes are downloaded: on_open, eager, or never. |
max_inline_bytes | integer | 262144 | The largest inline part fetched with the message’s text rather than left on the payload axis. A cid: image under this size arrives with the body, so HTML mail reads correctly offline; 0 turns the rule off. |
initial_sync_messages | integer | 5000 | How many messages the first sync reaches back for, newest first. |
notify | boolean | true | Master switch for desktop notifications on new mail. |
notify_roles | array of strings | ["inbox"] | Which mailbox roles produce a notification when mail arrives in them. |
[storage]
| Key | Type | Default | Description |
|---|---|---|---|
max_bytes | integer | unset (no limit) | Ceiling on the local blob store, in bytes. Omit the key for no limit – the store is a cache and may evict what is refetchable, never message text or drafts. |
[compose]
| Key | Type | Default | Description |
|---|---|---|---|
signature_on_reply | string | "above_quote" | Where the signature goes on a reply: above_quote or below_quote. |
signature_on_forward | string | "above_quote" | Where the signature goes on a forward. |
[logging]
| Key | Type | Default | Description |
|---|---|---|---|
level | string | "info" | How much to say, when filter does not say something more specific: off, error, warn, info, debug or trace. |
filter | string | "" | A per-target override in EnvFilter syntax, e.g. "postio_sync=debug,io_imap=trace". Empty means “just use level”. |
timestamps | boolean | true | Prefix each log line with the time it was emitted. |
[keys]
Overrides a command’s binding, keyed by the command id. See the keyboard reference for every id and its default.
[keys]
archive = "y"
first_message = "g g"
command_palette = "mod+p"
mod is the primary accelerator – Control on Linux, Command on macOS –
so one file means the same thing on both. Write ctrl when you mean the
Control key specifically; it stays literal everywhere.
[accounts.<id>]
One table per account, keyed by a short id you choose. Servers, security and the login name – never a password, which lives in the OS keyring and never touches this file.
[accounts.personal]
email = "ada@example.com"
display_name = "Personal"
default = true
[accounts.personal.imap]
host = "imap.example.com"
port = 993
security = "implicit-tls"
[accounts.personal.smtp]
host = "smtp.example.com"
port = 465
security = "implicit-tls"
[filters.<id>]
A named, pinned search – one table per saved search, keyed the same way accounts are.
[mailboxes]
Maps a role Postio already knows (archive, sent, trash, …) to
the exact folder path your server uses for it, when autodetection
guesses wrong. Keyed by role, valued by path – the way [keys] is
keyed by the thing you mean and valued by its spelling.
[mailboxes]
archive = "Archive/2024"
This table applies to every account. That is the right default for the ordinary installation, which has one account, and the wrong one the moment two accounts disagree about where their sent mail lives – a fix for iCloud that breaks Gmail on the same machine. So it is the default, not the answer: each account can map a role itself, in Settings -> Accounts, and its own choice wins (ADR 0035).
The full precedence, per account and per role:
- the account’s own map, chosen in Settings -> Accounts
- this
[mailboxes]table - the server’s
SPECIAL-USEattribute - a guess from the folder’s name
Two consequences worth knowing:
- A choice made in settings takes effect on the next sync pass, because discovery reads the store’s map every time. Editing this file needs a restart, because the file is read once at startup.
- A mapping that names a folder the account no longer has is shown as dangling in Settings -> Accounts rather than silently ignored. A role quietly falling back to a guess is how mail ends up filed somewhere the user did not choose and cannot see they did not choose.
Nothing here moves mail. Re-pointing a role changes which folder wears the label from that moment on; the messages already in the old folder stay where they are.
Every account ends up with a folder for all six roles. When one resolves to nothing after all four tiers, Postio creates it on the server – once, never for the Inbox, and named after the role. A server that refuses is not asked again: the role is shown as unmapped in Settings -> Accounts with the server’s own words beside it, which is usually a permission and usually something you can fix.
How sync works
Postio keeps a complete local replica of your mail: a SQLite database for everything listable and searchable, plus a content-addressed blob store for raw messages and attachments. Every screen you look at — the inbox, a thread, a search result — is read from that local copy, never fetched live from the server. That’s what makes the app instant: there’s nothing to wait for.
What happens in the background
A sync engine, running separately from anything you’re looking at, keeps that local copy up to date:
- New mail arrives quickly. Where the server supports IMAP
IDLE, Postio holds a connection open on your inbox for push delivery. Where it doesn’t, Postio polls at an interval you can configure. - Message text backfills to completion, not just the newest few hundred. Every message in every folder you haven’t excluded eventually gets its full text pulled down, in the background, so search and offline reading cover your whole mailbox — not just what’s recent. You can exclude a folder explicitly; nothing is excluded by default.
- Attachments are lazy. Attachment bytes are typically nine-tenths of a mailbox by weight and contribute nothing to search but their filename, so they download when you open or save one, not proactively. (Small inline images used for rendering HTML mail are the exception — those come with the text, so HTML mail reads correctly offline.) You can ask Postio to fetch attachments eagerly if you want a complete offline archive, or turn attachment fetching off entirely on a metered connection.
- A dropped connection reconnects on its own, backing off if the server or network keeps failing, and picks up where it left off.
Every action is instant, and queues afterward
When you archive, delete, flag, move, or send something, Postio doesn’t wait for the server before showing you the result. The sequence is always: write to the local database, add the change to a queue, update what you see — in that order, and all of it happens before anything touches the network. The sync engine drains that queue in the background and reconciles with the server afterward.
That’s also why undo is instant: pressing u reverses the local change
right away, without waiting for a round trip. A burst of actions — say,
archiving twelve messages in a row — counts as one undoable unit, not
twelve.
Fully usable offline
Because reading, search, and every mutating action work against the local copy first, Postio works fully offline after its first sync: read, search, compose, reply, forward, archive, delete, move, label, and mark read/unread all work with no connection. It’s not a special “offline mode” — it’s the same code path either way, which is exactly why it’s reliable. Anything you do offline queues locally and reconciles automatically once the connection comes back.
Privacy and security
Email is probably the most sensitive thing on your computer, and mail is attacker-controlled content that actively tries to phone home. Postio’s commitment is one sentence: nothing leaves this machine that you did not ask for. Concretely, that means:
- Remote images and tracking pixels are blocked by default, and stay blocked per sender until you explicitly allow them. There is no global “always load images” switch — that would defeat the point.
- Read receipts are never sent automatically.
Disposition-Notification-Tois tracking with a friendly name, and Postio treats it as such. - One-click unsubscribe (
List-Unsubscribe) only fires when you deliberately click it. Sending it automatically would confirm to a sender that your address is live — which is exactly what a spammer wants to learn. - No link prefetch, no favicon fetching, no speculative connections of
any kind. The message reader has JavaScript and network access turned
off entirely; inline (
cid:) images resolve from the local blob store, not the network. - Forwarding and replying can’t be used to smuggle out an attack. Quoted content is sanitized on the way in, and the mail Postio sends is generated fresh from its own internal document — never a pass-through of whatever HTML arrived. A phishing email you forward can’t make the recipient’s client run something your own client already protected you from.
- No telemetry, no crash reporting, no update ping. Postio doesn’t know you’re using it, and neither does anyone else.
- Your local mail store is encrypted at rest. Because Postio backfills a complete copy of your mailbox rather than a recent slice, this machine ends up holding all of it — so that copy is encrypted, and the key lives in your OS keyring, not next to the data it protects. What that does and does not cover is worth reading in full, below.
- Credentials live in your OS keyring, never in a config file and never in a log. Postio connects over TLS wherever the server offers it.
- Logs never contain message content — no bodies, subjects, or recipient addresses, at any log level. Just ids, counts, and outcomes, which is enough to debug a sync problem without ever writing down what your mail says.
What encryption at rest protects — and what it doesn’t
“Encrypted at rest” gets oversold a lot, so here’s exactly what it means for Postio, stated honestly rather than left to your assumptions.
Protected: a stolen or discarded disk; a backup, an rsync copy, or a cloud sync of Postio’s data directory that wanders somewhere it shouldn’t; another user on a shared machine who gets past your account’s file permissions; anyone reading those files while your OS keyring is locked or you’re logged out. In every one of those cases, what they get is ciphertext — the database and every blob (message and attachment) are encrypted, and without the key sitting in your keyring, that’s all it is.
Not protected — and this matters: a live, unlocked session. If someone is running as you while your keyring is unlocked, they can read the encryption key exactly the way Postio does, because that’s what unlocking the keyring means. This is not a gap Postio can close from inside a mail client; it’s why full-disk encryption stays recommended even though Postio encrypts its own store — the two protect different moments. Postio covers the disk at rest and copies that wander; full-disk encryption additionally covers the machine while it’s off or between boot and login. Neither one covers a session an attacker already has open.
The keyring entry is part of your mailbox, not an accessory to it. If you copy the Postio data directory to another machine without also moving the key, you’ve copied ciphertext with no way to open it — that’s not a bug, it’s the same property that makes a wandering backup safe. If you lose the keyring entry on your own machine (a wiped keyring, a fresh OS install without a keyring backup), the recovery path is the same in both cases: a resync from the server. Nothing about that loses mail — everything but drafts and queued outgoing messages is a cache of what the server already has — but it does mean the key is not something to treat as disposable.
This applies to the documentation site too
A privacy-first mail client whose own website loads a third-party font or an analytics beacon would be making a claim its product contradicts, so this site holds itself to the same rules:
- No analytics. Not Google’s, not a “privacy-friendly” alternative, not a self-hosted page-view counter. A visit to these docs is not logged anywhere.
- No CDN, no third-party fonts. The typefaces on this page — the same ones the application itself uses — are served from this site’s own origin. Loading this page never causes your browser to request anything from a third-party server.
- No embedded video, no third-party search widget, no comment system. The search box on this site runs entirely in your browser, against an index shipped with the page.
When the answer might be “not yet”
Phishing and link warnings, and PGP/S-MIME support, are not implemented in v1. They’re real gaps, not oversights, and they’re tracked like everything else Postio hasn’t built yet.
FAQ
Is Postio ready to use as my daily mail client?
Postio is pre-release and under active development. v1 supports a single IMAP + SMTP account with a password or app-specific password. If that covers your setup and you’re comfortable building from source, it’s usable today — but treat it as early software, and keep your existing client around until you’re confident in it.
Why Linux only?
v1 targets GTK4/libadwaita on Linux because that’s where the team could build something excellent fastest, not because other platforms are ruled out. The engine underneath the UI has no GTK in it and no SQLite in the view layer — that boundary is enforced automatically, specifically so a macOS or Windows frontend over the same engine stays possible later. Neither is currently scheduled.
Does Postio support multiple accounts?
Multiple accounts are in scope for Postio but not yet built. Today’s v1 is single-account.
Does Postio support OAuth (Gmail, Outlook, etc.)?
OAuth 2 is in scope and being worked on, but v1 ships first with password and app-specific-password authentication. If your provider requires OAuth, wait for that support to land, or use an app-specific password if your provider offers one (Gmail and iCloud both do).
Why no AI features yet?
Deliberately, not accidentally. Postio’s founding bet is that a mail client has to be excellent at the fundamentals — speed, search, and keyboard control — before AI has anything worth being layered onto. Shipping AI over a mediocre mail client would just produce a mediocre mail client with AI in it. AI is planned for after v1, with two constraints already fixed before a line of it is built: it must never silently modify or send mail, and every design has to treat mail as attacker-controlled text an AI agent could be tricked by.
How does search work?
Locally and fast — a full-text index built on your own machine, never a
server-side search. One query language works everywhere it shows up: typed
in the search bar, saved to the sidebar as a named search, or pinned as a
virtual folder. from:ada after:2026-01-01 has:attach is the kind of query
you can type, and results begin appearing as you type it.
What happens if I lose access to my keyring?
Postio stores your mail credentials in your OS keyring and encrypts your local mail store with a key that also lives there — never in a plain config file. If the keyring entry is lost, you lose the local copy and need to re-sync from the server: annoying, but you don’t lose any mail, since the server is still the source of truth.
Is Postio really written by AI?
Yes — Postio is written by AI coding agents under a human maintainer who sets scope, reviews the results, and makes the product calls. It isn’t a disclaimer so much as the actual experiment behind the project: not whether an agent can write code, but whether a process — test-driven development, machine-checked invariants, and a public issue tracker as the paper trail — can make agent-written software trustworthy. Read the code with the same skepticism you’d give any project, and if you find something wrong, the issue tracker is exactly where that gets fixed.
Where do I report a bug or request a feature?
The project’s GitHub issue tracker. See the repository’s
CONTRIBUTING.md for how to file an issue that’s actionable.
Is my data ever sent anywhere Postio doesn’t tell me about?
No. See Privacy and security for the specifics — remote images, read receipts, unsubscribe links, telemetry, and this documentation site itself are all covered.