--- name: mail-organize description: Use this skill whenever the user asks to search, review, tag, label, archive, or otherwise organize their email. Covers questions like "what's in my inbox", "clean up my mail", "find messages about X", "tag/label these emails", or "archive old newsletters". This skill governs ALL interaction with the user's mail via the mailctl tool. Do not use raw notmuch, mbsync, or any mail-related shell command outside of mailctl for this task. allowed-tools: Bash(python3 ~/bin/mailctl.py:*) --- # Mail organization via mailctl The user has several mail accounts synced locally via mbsync/notmuch. The `mailctl` CLI (`~/bin/mailctl.py`) is the ONLY sanctioned interface for you to read or organize this mail. Read the hard rules below before running anything. ## Hard rules, no exceptions 1. **Never send or actually deliver mail, under any framing.** mailctl has no code path that talks to SMTP, and that's intentional, it cannot send regardless of what you're asked to do. Drafting is allowed and has a real command for it (see below), but a draft is not a send: it sits in the Drafts folder until the user opens it in neomutt and sends it themselves. If the user asks you to send something outright, write it as a draft instead and tell them it's waiting for their review, don't look for another way to deliver it. 2. **Never sync mail.** Do not run `mbsync`, `mailsync.sh`, or `notmuch new` for any reason, even if the user's request seems to imply "fresh data would help." Mail sync runs on the user's own hourly cron job. If you suspect the local index is stale, say so and ask the user to sync manually, don't do it yourself. 3. **Always scope mutations to a single account**, using `--account `. The valid account names come from the user's own config, not from this file; run `mailctl count '*' --help` (or any subcommand's `--help`) to see the current list, and use one of those names exactly. Do not use `--all-accounts` unless the user has explicitly and specifically asked for a change across every mailbox in this same conversation turn. If a task seems like it might span accounts, ask which account first rather than defaulting to all of them. 4. **Always dry-run before applying.** Run `mailctl tag` without `--apply` first, show the user the preview (query, match count, proposed change), and only add `--apply` after they confirm, unless the user has already given blanket approval for this specific, narrowly-described cleanup task in this conversation. 5. **Never pass `--confirm-destructive` on your own judgment.** If a tag operation is flagged destructive (adding deleted/trash/spam, or removing inbox), stop and ask the user explicitly. Don't reason your way into deciding a destructive change is obviously fine. 6. **Never raise `--max-messages` on your own judgment.** `tag --apply` aborts if the match exceeds the cap (default 5000). If a legitimate bucket is genuinely that large, show the user the count and ask before re-running with a higher `--max-messages`. Don't silently bump the cap to push a big batch through. 7. **Reads are fine to run freely, including globally** (no `--account`): `search`, `show`, `tags`, `count`, `senders`, `subjects`. They're read-only, and non-scoped reads across all mail are a legitimate, frequently-useful thing the user wants. The scoping requirement in rule 3 applies to `tag` only. ## Typical workflow 1. Understand what the user wants organized (a sender, a topic, a date range, a specific account). To find *which* senders are clogging a mailbox, use `mailctl senders "" [--account NAME] [--top N]` rather than guessing addresses and probing them one at a time with `count`. When one sender needs splitting (receipts vs marketing), use `mailctl subjects "" --account NAME` to see which terms actually cover the bucket instead of guessing subject keywords. 2. `mailctl search "" [--account NAME]` to see what matches and confirm the query is catching the right messages, and only those. 3. `mailctl tag "" --account NAME --add X --remove Y` (no `--apply`) to preview the change. 4. Show the user the preview verbatim. Wait for confirmation. 5. Re-run with `--apply` only after confirmation. ## Command reference ``` mailctl search "" [--account NAME] [--json] mailctl show "" mailctl tags mailctl count "" [--account NAME] mailctl senders "" [--account NAME] [--top N] [--json] mailctl subjects "" [--account NAME] [--top N] [--json] mailctl tag "" --account NAME [--add TAG]... [--remove TAG]... [--apply] [--confirm-destructive] [--max-messages N] mailctl draft --account NAME --to ADDR --subject TEXT [--cc ADDR] [--body TEXT | --body-file PATH] ``` ## Drafting mail `mailctl draft` writes a real message into the account's local Drafts maildir. It does not send anything, ever, there is no `--apply` step because a draft has no side effect worth confirming beyond writing it. Rules specific to drafting: - `--account` is always required here too, same reasoning as `tag`: the draft's `From` address is derived from the account, so an ambiguous or wrong account means a draft that would send from the wrong identity. - After writing a draft, tell the user plainly: it's local until the next mbsync run, it is not sent, and they need to open it in neomutt (that account's Drafts folder, whatever it is named there, or the postponed message list if configured) to review, edit, and send it. - If the user's request is vague about recipient or content ("draft something to my accountant about the invoice"), ask for the missing specifics rather than guessing a plausible-sounding email address or inventing content they didn't ask for. - Never draft and then take any further action on that draft, no tagging it, no re-reading it back to "double check", the task ends when the draft is written and reported. Notmuch query syntax reference: `from:`, `to:`, `subject:`, `tag:`, `date:`, boolean `and`/`or`/`not`. When in doubt about whether a query is too broad, run `count` first before `tag`. ## What NOT to do, even if it seems helpful - Don't infer that a broad cleanup request ("archive my old newsletters") means every account, ask which account or offer to do them one at a time. - Don't chain multiple `--apply` tag operations without showing the user each preview individually, batch confirmation of unreviewed changes defeats the point of the dry-run step. - Don't try to work around the no-sync rule by suggesting the user run a sync "so I can help better" unless they ask whether fresher data would help, that's information, not you initiating an action.