Power-user Apple Mail CLI for macOS and AI agents
- Python 97.1%
- Shell 2.9%
| bin | ||
| skills/mailctl | ||
| src/mailctl | ||
| tests | ||
| .gitignore | ||
| install.sh | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
mailctl
mailctl is an unofficial command-line interface for Apple Mail designed for both people and AI agents.
It uses Mail's native macOS scripting interface through osascript, then adds terminal ergonomics:
- human-readable output by default
--jsonoutput for agentscommands,schema,manifest, anddocsdiscovery- first-class commands for common Mail workflows
callandbatchfor structured automation plans- dry-run output and confirmation gates for writes
The design follows the same philosophy as devonctl and RemCTL: the native app remains the source of truth, the CLI is a fast power-user and agent surface, and setup/permissions are explicit.
Install
cd /Users/abdo/Developer/mailctl
./install.sh --bootstrap --agent all
Or run without installing:
PYTHONPATH=src python3 -m mailctl --help
Examples
mailctl doctor
mailctl onboard
mailctl commands
mailctl schema messages --json
mailctl manifest --json
mailctl accounts
mailctl mailboxes --recursive
mailctl mailboxes --account Personal --counts
mailctl tree --account Personal
mailctl messages --special inbox --limit 10
mailctl search "invoice" --special inbox --limit 20 --json
mailctl selected --json
mailctl read 12345 --max-chars 4000
mailctl headers 12345 --name from --name subject
mailctl source 12345 --max-chars 10000
mailctl open 12345
mailctl mark-read 12345 --dry-run --json
mailctl flag 12345 --dry-run
mailctl move 12345 --to-mailbox Archive --dry-run
mailctl delete 12345 --dry-run
mailctl compose --to person@example.com --subject "Hello" --body "Draft text"
mailctl reply 12345 --body "Thanks, I will follow up." --dry-run
mailctl check
mailctl address "Jane Doe <jane@example.com>"
Safety
mailctl does not read or write Mail's private database files. It talks to Mail through the same automation layer that Apple exposes to scripts.
Writes have guardrails:
--dry-runshows the backend command and arguments without changing Mail.deleterequires--yesunless--dry-runis used.compose,reply, andforwardcreate drafts by default.- sending requires both
--sendand--yes. - batch plans containing delete or send operations require
--yeswhen--executeis used.
Agent Contract
Agents should prefer:
mailctl --json doctor
mailctl --json commands
mailctl --json schema messages
mailctl --json manifest
mailctl messages --special inbox --limit 20 --json
mailctl search "query" --special inbox --json
mailctl read MESSAGE_ID --max-chars 4000 --json
mailctl mark-read MESSAGE_ID --dry-run --json
mailctl batch @plan.json --json
Use first-class commands for common workflows, and use call for backend automation commands that do not need a dedicated shortcut.