apple-mail-cli
A Claude Code plugin marketplace with two read-only macOS automation tools. Both target macOS 13+ Apple Silicon (arm64) only and communicate with Apple apps via Apple Events — no credentials, no network access, no API keys.
| Plugin | Binary | What it does |
|---|
apple-mail | amail | Read and manage Mail.app — accounts, mailboxes, messages, rules, send |
ical | aical | Read Calendar.app — calendars and events with date-range filtering |
Platform: macOS 13+ · Apple Silicon (arm64) only
Install via Claude Code
Add this marketplace to Claude Code, then install the plugin(s) you want:
/plugin marketplace add trodemaster/apple-mail-cli
/plugin install apple-mail@amail-plugins
/plugin install ical@amail-plugins
Each plugin ships a pre-built, ad-hoc-signed arm64 binary in its bin/ directory. The plugin system adds it to PATH automatically — no manual setup required. On first use, macOS will prompt for automation permission — click Allow.
Build from source
Requires Go 1.21+ and macOS Apple Silicon.
make # build, sign (ad-hoc), and install both binaries to $GOBIN
make skill # cross-compile both arm64 plugin binaries and sign them
make skill-mail # apple-mail plugin only
make skill-ical # ical plugin only
amail commands
Accounts
amail accounts
Lists all configured email accounts with name, addresses, and type.
Mailboxes
amail mailboxes [--account "Account Name"]
Lists all mailboxes with unread and total message counts. Filter to one account with --account.
Messages
# List messages in a mailbox
amail messages list --account "iCloud" --mailbox "INBOX" [--limit 25] [--unread] [--summary]
# Read a full message by ID
amail messages read <message-id>
# Search across mailboxes
amail messages search [--from "addr"] [--subject "text"] [--query "text"] \
[--account "Name"] [--mailbox "Name"] [--limit 25] [--summary]
--summary fetches message bodies and shows a 2-line plain-text preview (HTML stripped, word-wrapped in Go)
--from and --subject use Mail.app's indexed search — fast even on mailboxes with thousands of messages
--query searches subject, sender, and body — slower; use --mailbox to scope it
- Without
--mailbox, search automatically skips Trash, Junk, Sent, Drafts, and All Mail
Send
amail send --to "[email protected]" --subject "Subject" --body "Body text" \
[--to "[email protected]"] \
[--cc "[email protected]"] \
[--bcc "[email protected]"] \
[--attachment "/absolute/path/to/file"]
--to, --cc, --bcc, and --attachment are all repeatable.
Rules
# List all filter rules with conditions and actions
amail rules list
# Add a condition to an existing rule
amail rules add-condition --rule "services" --expression "example.com" \
[--type from] [--qualifier ends-with]
# Create a new rule that moves matching messages to a mailbox
amail rules create --name "services2" --move "Services" --expression "example.com" \
[--account "Account Name"] [--type from] [--qualifier ends-with]
# Apply a single rule to a mailbox using fast indexed queries (recommended)
amail rules apply --rule "services" [--mailbox INBOX] [--account "Account Name"]
# Apply all enabled rules (batched; slower on large mailboxes)
amail rules apply [--mailbox INBOX] [--batch-size 500]
Condition types: from to cc subject any-recipient body account
Qualifiers: contains not-contains begins-with ends-with equals
Rule scale: Mail.app's GUI degrades beyond ~80 conditions per rule. When a rule is full, create a numbered sibling (services2, services3, etc.).
Schema
amail schema
Emits the full JSON spec of every command, subcommand, flag, type, and default. Useful for agents and scripting.
aical commands
Calendars
aical calendars
Lists all calendars with id, name, writable flag, and description.
Events
# Events for the next 7 days (default)
aical events
# Just today
aical events --today
# Specific date range
aical events --from 2026-05-01 --to 2026-05-31
# Relative window
aical events --days 14
# Filter to one calendar
aical events --calendar "Work" --days 30 [--limit 100]
Flags: --calendar NAME, --from YYYY-MM-DD, --to YYYY-MM-DD, --today, --days N (default 7), --limit N (default 50), --format json, --pretty
Output
All commands (amail and aical) print a human-readable table by default. When piped or when --format json is passed, output is a JSON envelope:
{
"ok": true,
"data": <T>,
"error": { "code": "...", "message": "..." } | null,
"meta": { "command": "...", "timestamp": "..." }
}
Use --pretty for formatted JSON.