{"id":45845019,"url":"https://github.com/jscoats/mxctl","last_synced_at":"2026-02-28T02:01:07.856Z","repository":{"id":339799305,"uuid":"1163335048","full_name":"Jscoats/mxctl","owner":"Jscoats","description":"Automate and extend Apple Mail from the terminal — 50+ commands, structured output for AI workflows, batch ops with undo, zero dependencies","archived":false,"fork":false,"pushed_at":"2026-02-27T00:14:30.000Z","size":3287,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-27T05:46:20.798Z","etag":null,"topics":["ai-integration","apple-mail","applescript","automation-tools","cli","command-line-tool","email","macos","productivity","python","terminal"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/mxctl/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Jscoats.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-21T13:24:29.000Z","updated_at":"2026-02-27T00:14:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Jscoats/mxctl","commit_stats":null,"previous_names":["jscoats/my-apple-mail-cli","jscoats/mxctl"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/Jscoats/mxctl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jscoats%2Fmxctl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jscoats%2Fmxctl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jscoats%2Fmxctl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jscoats%2Fmxctl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jscoats","download_url":"https://codeload.github.com/Jscoats/mxctl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jscoats%2Fmxctl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29922703,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T19:37:42.220Z","status":"online","status_checked_at":"2026-02-28T02:00:07.010Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-integration","apple-mail","applescript","automation-tools","cli","command-line-tool","email","macos","productivity","python","terminal"],"created_at":"2026-02-27T01:22:11.792Z","updated_at":"2026-02-28T02:01:07.838Z","avatar_url":"https://github.com/Jscoats.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo/splash.png\" alt=\"mxctl — Apple Mail from your terminal\" width=\"700\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003e\n  \u003ccode\u003emxctl\u003c/code\u003e\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pypi.org/project/mxctl/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/mxctl.svg\" alt=\"PyPI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/Jscoats/mxctl/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/Jscoats/mxctl/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.python.org/downloads/\"\u003e\u003cimg src=\"https://img.shields.io/badge/python-3.10%2B-blue.svg\" alt=\"Python 3.10+\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/Jscoats/mxctl\"\u003e\u003cimg src=\"https://img.shields.io/badge/coverage-100%25-brightgreen.svg\" alt=\"Coverage: 100%\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-green.svg\" alt=\"License: MIT\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003e Apple Mail from your terminal.\n\n**50+ commands.** Triage with AI, batch-process newsletters, turn emails into Todoist tasks — all from the terminal. Every command supports `--json` for scripting and AI workflows. Zero external dependencies.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo/demo.gif\" alt=\"mxctl demo — inbox, triage, summary, and batch operations\" width=\"700\"\u003e\n\u003c/p\u003e\n\n## Table of Contents\n\n- [Key Features](#key-features)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Example Output](#example-output)\n- [Command Categories](#command-categories)\n- [Requirements](#requirements)\n- [Usage Tips](#usage-tips)\n- [Built for AI Workflows](#built-for-ai-workflows)\n- [AI Demos](#ai-demos)\n- [Architecture](#architecture)\n- [Why Not X?](#why-not-x)\n- [Contributing](#contributing)\n\n## Key Features\n\n- **50+ Commands** - Everything from basic operations to advanced batch processing\n- **Any Account, One Interface** - iCloud, Gmail, Outlook, Exchange, IMAP -- whatever Mail.app has, this works with\n- **Gmail Mailbox Translation** - Automatically maps standard names (`Trash`, `Spam`, `Sent`) to Gmail's `[Gmail]/...` paths\n- **Built for AI Workflows** - Every command supports `--json` output designed for AI assistants to read and act on\n- **Todoist Integration** - Turn any email into a task with `mxctl to-todoist` (project, priority, due date)\n- **Batch Operations with Undo** - Process hundreds of emails safely with rollback support\n- **Zero Dependencies** - Pure Python stdlib, no external packages required\n- **Works with Your Existing Setup** - Doesn't replace Mail.app, extends it\n\n## Installation\n\n```bash\n# Requires Python 3.10+ and macOS\npip install mxctl\n\n# Or with uv (faster)\nuv tool install mxctl\n```\n\nThen run the setup wizard — it detects your Mail.app accounts, configures Gmail mailbox translation, and optionally connects Todoist:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo/init-demo.gif\" alt=\"mxctl init — setup wizard detecting accounts, configuring Gmail, and connecting Todoist\" width=\"700\"\u003e\n\u003c/p\u003e\n\n## Quick Start\n\n```bash\n# First time? Set up your default account\nmxctl init\n\n# See what's in your inbox\nmxctl inbox\n\n# Smart summary of unread emails (concise, one-liner per email)\nmxctl summary\n\n# Triage unread emails by urgency\nmxctl triage\n\n# Search for messages\nmxctl search \"project update\" --sender\n\n# Mark all unread as read (with undo support!)\nmxctl batch-read -m INBOX\n\n# Oops, undo that\nmxctl undo\n\n# Create email from template\nmxctl draft --to colleague@company.com --template \"weekly-update\"\n\n# Send email to Todoist as a task\nmxctl to-todoist 123 --project Work\n```\n\n## Example Output\n\n### `mxctl inbox`\n```\nInbox Overview\n------------------------------------------\n  iCloud             3 unread   (47 total)\n  Work Email         12 unread  (203 total)\n  Personal Gmail     0 unread   (18 total)\n------------------------------------------\n  Total              15 unread\n```\n\n### `mxctl triage`\n```\nTriage -- 15 Unread Messages\n==========================================\n\n[URGENT -- 2]\n  #4821  Sarah Johnson       Re: Contract review deadline TODAY\n  #4819  boss@company.com    Q4 budget approval needed\n\n[PEOPLE -- 5]\n  #4820  mom@gmail.com       Thanksgiving plans?\n  #4818  john.smith@work.com Project kickoff Thursday?\n  #4817  recruiter@corp.com  Opportunity at TechCorp\n  #4815  friend@gmail.com    Weekend hiking trip\n  #4814  alice@work.com      Coffee catch-up?\n\n[NOTIFICATIONS -- 8]\n  #4816  GitHub              [mxctl] PR #12 merged\n  #4813  noreply@bank.com    Statement available\n  ... and 6 more\n```\n\n### `mxctl summary`\n```\n15 unread -- iCloud + Work Email\n\n* Contract review deadline TODAY -- Sarah Johnson (urgent, reply needed)\n* Q4 budget approval -- boss@company.com (action required)\n* Thanksgiving plans -- mom@gmail.com (personal, low urgency)\n* Project kickoff Thursday -- john.smith@work.com (confirm attendance)\n* PR #12 merged -- GitHub notification (no action needed)\n* 10 more notifications and newsletters\n```\n\n## Command Categories\n\n### Setup\n- `init` - First-time setup wizard (auto-detects Mail accounts, configures default account and optional Todoist token)\n- `ai-setup` - Configure your AI assistant to use mxctl (Claude Code, Cursor, Windsurf, Ollama, and others)\n\n### Account \u0026 Mailbox Management\n- `inbox` - Overview of all accounts with unread counts\n- `accounts` - List all mail accounts\n- `mailboxes` - List mailboxes in an account\n- `create-mailbox`, `delete-mailbox` - Manage folders\n- `count` - Unread message count (for scripting and status bars)\n- `empty-trash` - Empty trash with confirmation dialog\n\n### Message Operations\n- `list` - List messages with filters (unread, date range)\n- `read` - Display full message\n- `search` - Find messages by subject/sender\n- `mark-read`, `mark-unread`, `flag`, `unflag` - Message actions\n- `move`, `delete` - Organize messages\n- `junk`, `not-junk` - Mark as spam / restore from spam (moves to INBOX)\n- `open` - Open message in Mail.app GUI\n- `unsubscribe` - Unsubscribe from mailing lists via List-Unsubscribe header (supports one-click RFC 8058)\n- `attachments`, `save-attachment` - Handle attachments\n\n### AI-Ready Features\n- `summary` - Ultra-concise summaries optimized for AI assistants\n- `triage` - Smart categorization by urgency (flagged -\u003e people -\u003e notifications)\n- `context` - Thread messages with parent/child relationships\n- `find-related` - Discover similar messages\n- `process-inbox` - Diagnostic inbox categorization\n\n### Batch Operations\n- `batch-read` - Mark all unread as read\n- `batch-flag` - Flag all from sender\n- `batch-move` - Move messages by sender\n- `batch-delete` - Delete messages by sender and/or age\n- `undo`, `undo --list` - Rollback batch operations\n\n### Analytics \u0026 Tools\n- `stats` - Message statistics for timeframe\n- `top-senders` - Most frequent senders\n- `digest` - Grouped unread summary\n- `show-flagged` - List flagged messages\n- `weekly-review` - Past 7 days summary\n- `clean-newsletters` - Archive/delete newsletter subscriptions\n\n### System\n- `check` - Trigger Mail.app to fetch new mail\n- `headers` - Full email header analysis (SPF, DKIM, DMARC, hop count, return path)\n- `rules` - List, enable, or disable mail rules\n\n### Compose \u0026 Templates\n- `draft` - Create email draft (supports templates)\n- `templates list/create/show/delete` - Manage email templates\n- `reply`, `forward` - Create response drafts\n- `thread` - Show full conversation thread for a message\n\n### Integrations\n- `to-todoist` - Send email to Todoist as task\n- `export` - Export messages as markdown (use `--to` for destination path/directory)\n\n## Requirements\n\n- **macOS 12 or later** (uses AppleScript to communicate with Mail.app)\n- **Python 3.10+**\n- **Mail.app** with at least one configured account\n- **Permissions:** First run will prompt for Mail.app automation permission in System Settings\n- **Note:** Mail.app will be launched automatically if it is not already running -- this is normal macOS/AppleScript behavior\n\n## Usage Tips\n\n### Multi-Account Support\n\nWorks with any combination of iCloud, Gmail, Outlook, Exchange, or custom IMAP accounts -- whatever you have configured in Mail.app.\n\n```bash\n# Commands default to your primary account (set during init)\nmxctl list\n\n# Switch accounts with -a\nmxctl list -a \"Work Email\"\nmxctl list -a \"Personal\"\n\n# Commands like inbox, summary, and triage scan ALL accounts automatically\nmxctl inbox\n```\n\n**Three-tier account resolution:** Commands use the first available: (1) explicit `-a` flag, (2) default account from config, (3) last-used account from state.\n\n### Gmail Mailbox Translation\n\nGmail uses non-standard mailbox names (`[Gmail]/Spam` instead of `Junk`, `[Gmail]/Sent Mail` instead of `Sent Messages`, etc.). If you tag your Gmail accounts during `mxctl init`, the CLI auto-translates standard names so you don't have to remember Gmail's conventions.\n\n```bash\n# These just work -- no need to type [Gmail]/... paths\nmxctl list -a \"Work Gmail\" -m Trash     # -\u003e [Gmail]/Trash\nmxctl list -a \"Work Gmail\" -m Spam      # -\u003e [Gmail]/Spam\nmxctl list -a \"Work Gmail\" -m Sent      # -\u003e [Gmail]/Sent Mail\nmxctl list -a \"Work Gmail\" -m Archive   # -\u003e [Gmail]/All Mail\n\n# iCloud and other accounts pass through unchanged\nmxctl list -a \"iCloud\" -m Trash         # -\u003e Trash (no translation)\n```\n\nSupported translations: `Trash`, `Spam`/`Junk`, `Sent`/`Sent Messages`, `Archive`/`All Mail`, `Drafts`, `Starred`, `Important`.\n\n### Todoist Integration\n\nTurn any email into a Todoist task without leaving the terminal. The task includes the email subject, sender, and a link back to the message.\n\n```bash\n# Set up during init, or add manually to ~/.config/mxctl/config.json\nmxctl init  # step 3 prompts for your Todoist API token\n\n# Send an email to Todoist\nmxctl to-todoist 123\n\n# With project and priority\nmxctl to-todoist 123 --project \"Work\" --priority 3\n\n# With a due date (natural language)\nmxctl to-todoist 123 --due \"next Monday\"\n```\n\nTo get your token: [Todoist Settings -\u003e Integrations -\u003e Developer](https://todoist.com/prefs/integrations)\n\n### Short Message Aliases\n\nListing commands assign short numbers starting from `[1]` -- no more copying 5-digit IDs:\n\n```bash\nmxctl list                    # Shows [1], [2], [3]...\nmxctl read 1                  # Read message [1]\nmxctl flag 2                  # Flag message [2]\nmxctl move 3 --to Archive     # Move message [3]\n```\n\nAliases update each time you run a listing command (`list`, `inbox`, `search`, `triage`, `summary`, etc.). Full message IDs still work if you prefer them. JSON output includes both `id` (real) and `alias` (short number).\n\n### Export Messages\n```bash\n# Export a single message\nmxctl export 123 --to ~/Documents/mail/ -a \"iCloud\"\n\n# Bulk export all messages in a mailbox\nmxctl export \"Work\" --to ~/Documents/mail/ -a \"Work Email\"\n\n# Bulk export messages after a date\nmxctl export \"INBOX\" --to ~/Documents/mail/ -a \"iCloud\" --after 2026-01-01\n```\n\n### Email Templates\n```bash\n# Create a template\nmxctl templates create \"meeting-followup\" \\\n  --subject \"Re: {original_subject}\" \\\n  --body \"Thanks for the meeting today...\"\n\n# Use it\nmxctl draft --to client@company.com --template \"meeting-followup\"\n```\n\n## Built for AI Workflows\n\nEvery command supports `--json`, making your inbox data available to any AI assistant. Commands like `summary`, `triage`, and `context` are specifically designed to give AI a structured understanding of your inbox in seconds.\n\n### Pointing Your AI Assistant to mxctl\n\nFor an AI assistant to use mxctl effectively, it needs to know the tool is available. The fastest way is the built-in setup command:\n\n```bash\nmxctl ai-setup\n```\n\nIt walks you through selecting your AI assistant (Claude Code, Cursor, or Windsurf), previews the snippet it will write, and asks for confirmation before touching any file. Run it once; skip it any time you don't need it.\n\n#### Manual setup\n\nPrefer to configure it yourself? Run `mxctl ai-setup --print` to get the raw snippet, then paste it into your assistant's context file (`~/.claude/CLAUDE.md`, `.cursorrules`, `.windsurfrules`, etc.).\n\n#### Local AI (Ollama, LM Studio, Aider, etc.)\n\nUse `--print` to get the raw snippet for piping:\n\n```bash\nmxctl ai-setup --print | pbcopy              # clipboard\nmxctl ai-setup --print \u003e\u003e ~/Modelfile         # Ollama\nmxctl ai-setup --print \u003e .aider.prompt.md     # Aider\n```\n\nFor a one-off session, `mxctl --help` gives any AI the full command reference.\n\n### With Claude Code\n\nJust ask in natural language:\n\n\u003e *\"Run mxctl triage and tell me what's urgent\"*\n\u003e\n\u003e *\"Summarize my unread mail and create Todoist tasks for anything that needs action\"*\n\n### With any AI tool\n```bash\n# Pipe structured data to any LLM CLI\nmxctl summary --json | llm \"What needs my attention?\"\n\n# Feed triage results to AI for prioritization\nmxctl triage --json | llm \"Draft responses for the urgent items\"\n```\n\n### For scripting and automation\n```bash\n# Unread count for your status bar\nmxctl count\n\n# Every command supports --json\nmxctl inbox --json | jq '.[].unread'\nmxctl search \"invoice\" --json | jq '.[].subject'\n```\n\n## AI Demos\n\nThese demos show how an AI assistant (like Claude Code) uses mxctl to manage your inbox conversationally. You say what you want in plain English, and the AI picks the right commands, checks before acting, and reports back.\n\n### Inbox triage and drafting\n\nThe AI triages your inbox, marks newsletters as read, flags important messages for follow-up, and drafts a reply to your mom -- all from a single request.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo/ai-demo.gif\" alt=\"AI assistant triaging inbox, flagging messages, and drafting a reply\" width=\"700\"\u003e\n\u003c/p\u003e\n\n### Bulk sender cleanup\n\nThe AI finds your noisiest senders, dry-runs the deletes so you can see what would be removed, then cleans up 60 marketing emails in seconds. Everything is undoable with `mxctl undo`.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo/batch-delete-demo.gif\" alt=\"AI assistant finding top spammy senders and batch-deleting 60 messages\" width=\"700\"\u003e\n\u003c/p\u003e\n\n### Newsletter unsubscribe\n\nThe AI analyzes which newsletters you actually read vs. ignore, then unsubscribes from the ones with 0% open rate while leaving the ones you engage with. One-click unsubscribe when the header supports it, browser fallback when it doesn't.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"demo/unsubscribe-demo.gif\" alt=\"AI assistant analyzing newsletter read rates and unsubscribing from unread ones\" width=\"700\"\u003e\n\u003c/p\u003e\n\n## Architecture\n\nBuilt with modern Python patterns:\n- **Zero runtime dependencies** (stdlib only)\n- **Comprehensive test suite** (678 tests)\n- **Modular command structure** (16 focused modules)\n- **AppleScript bridge** for Mail.app communication\n- **Three-tier account resolution** (explicit flag -\u003e config default -\u003e last-used)\n\nSee [ARCHITECTURE.md](ARCHITECTURE.md) for detailed architecture documentation.\n\n## Why Not X?\n\n| | **mxctl** | **mutt/neomutt** | **Gmail/Outlook API** | **Raw AppleScript** |\n|---|---|---|---|---|\n| **Approach** | Extends Mail.app | Replaces Mail.app | Per-provider SDK | DIY scripting |\n| **Multi-account** | Any account in Mail.app | Config per account | Separate auth per provider | Manual per account |\n| **macOS integration** | Notifications, Rules, Continuity | None (terminal-only) | None | Partial |\n| **Structured output** | `--json` on every command | Text only | JSON (provider-specific) | Raw text |\n| **AI-ready** | Built for it (triage, summary) | No | Build it yourself | No |\n| **Batch + undo** | Built-in with rollback | No undo | Build it yourself | No |\n| **Setup** | `pip install mxctl \u0026\u0026 mxctl init` | Extensive config | OAuth flows + API keys | Write your own scripts |\n| **Dependencies** | Zero (stdlib only) | Varies | SDK + auth libraries | None |\n\n**In short:** mutt replaces Mail.app (you lose macOS integration). Provider APIs lock you into one service. Raw AppleScript works but you're building everything from scratch. mxctl gives you 50+ structured commands on top of the Mail.app you already use.\n\n## Contributing\n\nContributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Contact\n\n- **GitHub:** [@Jscoats](https://github.com/Jscoats)\n- **Issues:** [Report bugs or request features](https://github.com/Jscoats/mxctl/issues)\n\n---\n\n**Like this project?** Star it on GitHub and share it with fellow terminal enthusiasts!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjscoats%2Fmxctl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjscoats%2Fmxctl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjscoats%2Fmxctl/lists"}