Skip to content

Releases

dove v0.12.1

Choose a tag to compare

@github-actions github-actions released this 14 Nov 16:07

Changed

  • Clearer descriptions for list_accounts, list_labels, get_thread, get_draft, list_drafts, list_watches,
    delete_watch, list_requests and cancel_request: each says when to use it instead of a neighbouring tool, what
    it returns when an id is unknown, and (for get_thread) how a result cut by the size budget is marked.
  • The other tool descriptions now name the neighbouring tool to use instead (for example move_messages vs
    update_messages, send_draft vs request_send, digest vs search_messages), and the draft tools say where a
    revision comes from and what to do after draft_conflict.

dove v0.12.0

Choose a tag to compare

@github-actions github-actions released this 14 Nov 15:54

Added

  • Admin web UI, part 1, under /admin on the existing listener (off by default: [admin_ui] enabled = true and
    origin). Sign-in with a passkey only (dove admin passkey add --name <device> prints a one-time link, valid for
    five minutes), sessions of 12 hours (dove admin sessions list|revoke, dove admin passkey list|remove). Pages:
    Overview (checks, index status, waiting requests, next sends), Requests (review each draft like a mail and each access
    request per mailbox, approve with a fresh passkey confirmation, deny, stop scheduled drafts or end granted access),
    Audit (search, verify the chain) and Settings (passkeys, sessions). Every action runs the same admin verb as the CLI
    and is audited as web:<passkey>. The UI only answers on its own host name, refuses any Authorization header and is
    never forwarded by the shipped Caddy and nginx templates; dove tailscale setup --admin mounts it on the tailnet name
    and refuses while Funnel is on.

Changed

  • Every tool parameter now has a description in tools/list (origin, format and enforced limits), so agents and
    registries no longer have to guess what an id or cursor refers to.

dove v0.11.0

Choose a tag to compare

@github-actions github-actions released this 14 Nov 14:49

Added

  • dove mcp catalog describes every tool over stdio without a server, mailboxes, keys or network, and refuses every
    tool call. The new root Dockerfile runs it, so MCP registries such as Glama can build Dove, list its tools and
    score them.
  • Access requests. request_access lets an agent ask for rights on mailboxes of its project (grant syntax, presets
    included), for up to 30 days or permanently, with a note for the owner. Nothing changes before the owner approves
    with dove requests approve, where mailboxes can be left out (--items) and the time shortened (--duration 2h).
    Temporary rights end on their own at the first call after their expiry and never touch the connection's earlier
    grants; clients set-grants, revoking the connection, removing the mailbox and dove requests cancel end them
    early. list_accounts and clients show show temporary rights with their end. A mailbox of another project and
    an unknown name give the same not_found.

Fixed

  • deploy/Containerfile failed to build from source: .dockerignore left out deploy/release/minisign.pub, which the
    binary embeds.

dove v0.10.0

Choose a tag to compare

@github-actions github-actions released this 14 Nov 13:49

Added

  • Scheduled sends approved by the owner. request_send asks for own drafts to be sent at fixed times (or spread over
    a window), optionally only if nobody answered the thread in the meantime (unless_reply; an answer already in Trash
    counts). The owner reviews each
    draft with dove requests show and approves with dove requests approve, which binds the exact revision shown;
    a draft changed afterwards is not sent. Nothing is retried after an unknown outcome, and an item that could not go
    out within [requests] late_grace_minutes (60) is dropped as missed. Agents follow their requests with
    list_requests and cancel_request. Needs draft on the mailbox, not send or allow_send; turn it off with
    [requests] enabled = false. Closed requests are deleted after [requests] retention_days (90), and each
    connection keeps at most 500 of them.

dove v0.9.0

Choose a tag to compare

@github-actions github-actions released this 14 Nov 12:22

Added

  • dove watch create|list|delete|events manage watches from the CLI, and dove watch listen wakes a local agent on
    new mail: it pulls watch events over outgoing HTTPS and runs a fixed command once per event, in order, with only
    ids and times in DOVE_* environment variables. The cursor is saved after each event (mode 0600), old events are
    skipped on the first start, failing commands are retried up to --max-attempts, and a lock file keeps a second
    listener on the same profile from running the command twice. Pin it to an agent session with
    claude -p --resume <session-id> --fork-session.
  • get_message reads several messages in one call: pass refs from search_messages (or account +
    message_ids), up to 20. Each id gets its own result or error under batch_read's 64 KiB response budget; a single
    id answers as before.
  • create_watch with kind: no_reply_by takes a message_id instead of a thread_id: "tell me if nobody answers
    this mail by Friday". The event names that message, so the agent can read it and follow up; a reply from someone
    else ends the watch quietly, and a message that is already answered ends it at once (end_reason: replied). CLI:
    dove watch create --no-reply-to <message-id> --deadline <time>.

Changed

  • get_thread is faster. On IMAP all members are read over one connection, with each folder opened once and one
    metadata fetch per folder (a one-folder thread of N messages needs N + 2 commands instead of 4N). On Gmail, a thread
    asked for by message_id needs one request less. Long threads stop fetching once the body budget is spent. IMAP
    reads and index sync no longer send a separate size probe per message.
  • search_messages, digest and search_contacts argument errors name the argument and say how to fix it. The
    message starts with the path (where.all[1].op: ...), lists what is valid (the operators of that field, the
    columns, the fields, what the tool takes) and, where useful, carries a valid example in details.example. Known
    mix-ups get a pointer: contains has no substring match (use terms), sender is from, query and
    page_token are where and cursor, limit over 100 pages with next_cursor, a time without offset needs
    Z or an offset.
  • These tools accept arguments that have exactly one reading: one mailbox name where a list is expected, account
    for accounts (and accounts with one name for search_contacts), lists and where written as JSON text,
    "true"/"20" for true/20, field, operator and enum names in any case, one value where a list is expected
    and a one-element list where a string is, a list of words for terms, a single order_by object or
    "received_at desc". received_at and digest's since take a calendar date (2026-11-01, that UTC day) and
    since also a span back from now (7d, 36h). Several values for a one-value argument, a time without offset
    and unknown account names are still refused; unknown and out-of-scope mailboxes remain the identical not_found.
  • The audit record of a refused call carries ~invalid=<argument path> in object_ids (for example
    ~invalid=where.all[].op): which argument failed, never its value.

Fixed

  • Watches no longer treat the owner's own mail from a Gmail send-as address as someone else's: mail with the SENT
    label (or in the IMAP Sent folder) never fires a watch and never counts as a reply, like from_self in search.
  • A no_reply_by watch no longer fires when the reply arrived in the same second as the watched message (IMAP dates
    have no milliseconds) and the sync hook had not seen it, for example because it was indexed during a rebuild.

dove v0.8.1

Choose a tag to compare

@github-actions github-actions released this 14 Nov 10:37

Changed

  • Installing and updating the client no longer needs root. The README and the deployment guide now separate the
    server install (| sudo sh, root-owned binary, sudo dove upgrade) from the client install (| sh, ~/.local/bin,
    dove upgrade without sudo, or Homebrew). install.sh prints the PATH line for your shell (zsh, bash, fish,
    others) when its target directory is not in PATH, still without touching shell files, and its closing hint
    says dove upgrade without sudo after a user install.
  • dove upgrade on a binary in a directory you cannot write now names both ways out: sudo dove upgrade on a server,
    and for your own computer how to switch to a user install (remove the root-owned binary, rerun install.sh
    without sudo, keep ~/.local/bin in PATH).
  • dove upgrade refuses to replace a binary installed by Homebrew (inside a Cellar/dove/ directory, also when
    reached through the bin symlink) and points to brew upgrade dove; the daily new-version notice and
    dove upgrade --check say that command for Homebrew installs.

dove v0.8.0

Choose a tag to compare

@github-actions github-actions released this 14 Nov 10:01

Added

  • dove sinks add --url-file <path> reads the webhook URL from a file (owner-only mode, trimmed) or from standard
    input with -. --url still works but warns that the URL lands in shell history and the process list.
  • [clients] redact_secrets_default in the service config: when true, connections created by clients create,
    clients invite and from invitations (dove login, OAuth approval) hide secrets in overview results unless created
    with the new --no-redact-secrets. Off unless set; existing connections keep their setting.

Security

  • Setting or removing IMAP junk keywords ($Junk, $NotJunk, NonJunk and any keyword containing junk or spam,
    in any case) needs the delete permission: mail clients train spam filters on them, like moving into or out of
    Junk.

Fixed

  • The hourly organize budget gives back only failures that certainly changed nothing. A Gmail move out of Trash whose
    second write failed, a Gmail write answered with a server error, a lost IMAP STORE or MOVE reply and a copy that kept
    its original now count as spent.
  • IMAP update_messages: a STORE whose reply was lost, or a failure after part of the change was stored, is reported
    as outcome_unknown instead of upstream_error or not_found.

dove v0.7.0

Choose a tag to compare

@github-actions github-actions released this 13 Nov 22:29

Agent feedback: answering "whom have I not replied to?" took many calls, broad searches were dominated by the
user's own mail, coverage: partial did not say whether to wait, and snippets could show credentials.

Added

  • search_messages thread view: group_by: "thread" returns one row per mailbox and thread with the latest
    message's columns, message_count, matched_count and reply status (last_sender_is_self, last_inbound_at,
    last_outbound_at, awaiting_reply). The thread filter awaiting_reply: true|false keeps threads whose latest
    non-draft message is or is not from the mailbox itself. It is a rule over indexed mail, not a judgement whether a
    reply is needed; a reply sent from another mailbox is not seen.
  • from_self as a filter and a column: the mailbox's own address, its IMAP aliases, or the SENT label.
  • dove search --from-self, --not-from-self, --threads and --awaiting-reply.
  • Optional secret redaction per connection (dove clients set-redaction <name> on|off, --redact-secrets on
    clients create and clients invite, off by default). Passwords, keys and one-time codes in subjects and snippets
    of search_messages, digest and list_drafts read [redacted], and rows say redacted: true. get_message,
    get_thread, get_draft and attachments stay complete. The detector is heuristic: secrets without a label or a
    known format are not caught.

Changed

  • Coverage exceptions and account_errors in search_messages, digest and search_contacts carry resolves
    (automatic, operator or never), a hint, and where known next_sync_at, next_retry_at and
    retry_after_seconds; partial results carry a top-level hint. Messages listed but not fetched yet during a
    backfill are reported as queued, not as "pending retry".

dove v0.6.0

Choose a tag to compare

@github-actions github-actions released this 13 Nov 21:57

Security hardening from an internal audit. Read "Upgrading" before you update a server with webhook sinks.

Changed

  • Tools that return mail content (get_message, get_thread, batch_read, search_messages, get_attachment,
    digest, search_contacts, list_drafts, get_draft) mark it as untrusted: structured results carry
    untrusted_content_notice, and clients without a current MCP-Protocol-Version get the JSON inside the
    <untrusted_email_content> envelope. Such clients that parsed the text content as JSON need the current protocol
    version or structuredContent.
  • The OAuth approval page shows the full redirect URI and, for dynamically registered clients, when and from which
    network they registered. A destination outside claude.ai, claude.com, chatgpt.com, chat.openai.com and loopback needs
    an extra confirmation. Dynamically registered clients never get an error redirect before approval.
  • /connect/redeem checks an invitation's --allow-ip list before using it up.
  • Failed bearer authentication on /mcp is limited per client address (limits.auth_failures_per_minute, default 60,
    IPv6 by /64): further failures get 429, valid tokens are always accepted. Loopback and unknown addresses are
    exempt.
  • Organize tools have an hourly budget per client (limits.client_organize_per_hour, default 500 messages). Moving
    mail out of Spam/Junk needs the delete action. Trash and Junk folders are recognized by name in 17 languages.
  • Webhook sinks belong to a project (dove sinks add --project, dove sinks set-project); clients only see sinks of
    their own project. Sink URLs are sealed by the vault, re-sealed by dove keys rotate, and dove sinks list shows
    only their origin.
  • dove upgrade --version refuses an older release unless --allow-downgrade is given.
  • install.sh and install.ps1 require the exact trusted comment dove <tag>; the wget fallback is HTTPS only.
  • Only Dove and its HTTP/TLS/SQLite stack may write log lines. The mail and attachment parsers (lopdf, html5ever and
    others) quoted untrusted content, such as PDF font dictionaries, in their warnings.
  • Deployment: the nginx templates take the client address from the TCP peer even when another site sets
    real_ip_header in the http context, and log Dove requests without query strings (OAuth codes). The systemd and
    .deb units forbid executing files from Dove's writable directories (NoExecPaths=). The release workflow refuses
    a tag whose commit is not on main.

Upgrading

  • The state store migrates once on start. Existing webhook sinks keep their watches and queued pushes but serve no
    client until you assign a project: dove sinks set-project <name> --project <project>.
  • An agent that moved mail out of Spam with only organize now needs delete for that mailbox.

dove v0.5.0

Choose a tag to compare

@github-actions github-actions released this 13 Nov 17:45

Added

  • Local mode (mode = "local"): Dove on your own computer as your user, for MCP hosts on the same machine, over
    http://127.0.0.1:<port> (plain HTTP only for that loopback origin; server mode is unchanged). dove local init
    creates a per-user config, keys and data directory, dove local start runs it in the foreground, dove local stop
    stops it, and dove local install / uninstall / status manage a login item (systemd user unit, launchd agent or
    Task Scheduler logon task, no administrator rights). See the threat model in the deployment guide's Local mode section.
    The dove client sends credentials to a plain-http loopback server only when your OS user holds that port
    (Linux, Windows).
  • Windows support in the code: keys protected with DPAPI, private directories by access list, the admin channel as a
    per-user named pipe with a Windows account check, and dove upgrade replacing the running dove.exe.
  • dove mcp install --client claude-desktop adds Dove to Claude Desktop's claude_desktop_config.json.
  • Windows release: dove-<tag>-x86_64-pc-windows-msvc.zip (signed like every other asset), installed with
    install.ps1. Every Windows release is smoke-tested on a Windows runner (install, local mode start and stop, upgrade).

Fixed

  • Index reads enforce their deadline with a SQLite progress handler. The previous timer interrupt was lost when the
    deadline passed before the first statement started (a slow machine or a slow connection open), and the query then
    ran without a time limit.