Agent-First Mail v0.6: Fewer Doors

by Agent-First Kit Contributors

v0.6 collapses the separate archive subcommand into case, replaces archive/reopen cycles for contacts and cases with explicit delete, and splits message restore into unspam and untrash — fewer places to look, more precise actions.

afmail builds a local workspace your agent navigates by path. The design premise is that an agent shouldn’t need to memorise which subcommand a thing lives under — it should find it by asking what the thing is, not what lifecycle stage it’s in. v0.6 applies that premise to a handful of places where the command surface had drifted.

One place for cases, active or archived

Through v0.5, the workspace held two parallel surfaces for cases: case for active work and archive case for finished cases. To list archived cases you ran afmail archive case list. To show one you ran afmail archive case show c20260612001. To restore you ran afmail archive case restore.

That split made sense as a safeguard early on, but in practice it just meant the agent had to remember two trees for the same noun. v0.6 collapses them:

afmail case list                          # active cases (unchanged)
afmail case list --archived               # archived cases
afmail case show c20260612001             # works for active or archived
afmail case restore c20260612001 --group support --reason "reopened by customer"
afmail case move c20260612001 --group billing --reason "wrong queue"

Archived cases are cases. case is the subcommand. The archive top-level subcommand is gone.

The other addition on the archive side: case move now works on archived cases too, so you can reorganise the archive without having to restore a case into active, move it, and re-archive it.

Delete, not reopen

For contacts, the v0.5 lifecycle was: contacts could be archived (removed from the active surface) and later reopened. In practice, the two operations were almost never used together — a contact either mattered and stayed active, or it didn’t and should be removed. The archive/reopen pair added a step with no real benefit.

v0.6 replaces both with a single delete:

afmail contact delete p20260612001 --reason "duplicate, merged into p20260610001"

The same reasoning applies to empty active cases. Instead of case reopen (which was already removed in v0.5 for active cases that had never been archived), there’s now case delete for an active case with no messages left in it:

afmail case remove c20260620003 --message message_inbox_90233_7 --reason "wrong thread"
afmail case delete c20260620003 --reason "empty after removing misrouted message"

case remove extracts one message back to triage. case delete cleans up the empty shell. If you want to stop working a case and have it keep its messages, case archive still does that — archived cases are just navigated through case now, not through a separate archive tree.

Unspam and untrash

message restore was doing two different things depending on which disposition the message was in. A spam false-positive needs the message unmarked and queued for a move out of Junk. A trash false-positive needs it unmarked and queued for a move out of Trash. Same verb, different remote effects, no way for the agent to be explicit about which.

v0.6 splits them:

afmail message unspam message_inbox_90233_7 --reason "newsletter I actually want"
afmail message untrash message_inbox_88214_3 --reason "accidental discard"

Each command spells out what it does. unspam marks the message back to triage and queues a move out of Junk when the message has a remote location there. untrash does the same for Trash. The push remains explicit — nothing moves on the server until you run afmail push --confirm.

Notification delete

Notification collections now have a delete path alongside the existing move, remove, and log commands:

afmail notification delete n20260620001 --reason "campaign ended, no longer needed"

The collection must be empty (no messages) before deletion is allowed. If you’ve added user-authored notes to notes.md, pass --allow-notes to confirm that’s intentional.

IMAP robustness

One change that doesn’t surface in the command API: afmail now falls back to COPY + EXPUNGE when the IMAP server doesn’t advertise the MOVE capability. The fallback requires UIDPLUS for precise single-message targeting — without it, the server gets an error explaining why the operation can’t proceed safely. Most servers support both, but the fallback means afmail works correctly with servers that implement an older IMAP subset.

Install

brew install agentfirstkit/tap/afmail        # macOS / Linux
scoop bucket add agentfirstkit https://github.com/agentfirstkit/scoop-bucket
scoop install afmail                          # Windows
cargo install agent-first-mail                # any platform

After installing, run afmail skill install so your agent reloads afmail’s updated behavior rules.