Email for AI agents — read, search, send and triage Gmail / QQ / 163 / any IMAP from the CLI or MCP. Part of the *-use family.
Overview
One CLI over Gmail, QQ, 163, Outlook and any IMAP/SMTP box — every command speaks JSON, every destructive one is dry-run until you pass --confirm. Part of the *-use family — small tools that each give an agent hands on one real thing. - Every response carries success: boolean, and failures carry error_code from a fixed set (auth_failed, folder_not_found, imap_error, …). Documented in docs/CLI_JSON_CONTRACT.md. - Cached reads report from_cache, cache_age_seconds and cache_stale, and a snapshot old enough to mean "nothing is syncing" is refused in favour of a live fetch. An empty inbox is never a silent "nothing arrived". - delete / mark / move / send return a dry-run preview — grouped per account and folder, with sample subjects — and change nothing until --confirm. --all-folders skips Sent/Drafts/Junk/Trash unless asked.
README
mail-use
Email, as something an AI agent can actually operate. One CLI over Gmail, QQ,
163, Outlook and any IMAP/SMTP box — every command speaks JSON, every destructive
one is dry-run until you pass --confirm.
mail-use code --json # the newest verification code, one live pass
mail-use email recent --format compact --json
mail-use email delete --from [email protected] --confirm --json
Part of the *-use family — small tools that each give an agent
hands on one real thing.
Why this and not an IMAP snippet
- A stable JSON contract, not scraped text. Every response carries
success: boolean, and failures carryerror_codefrom a fixed set (auth_failed,folder_not_found,imap_error, …). Documented indocs/CLI_JSON_CONTRACT.md. - It tells you when it might be wrong. Cached reads report
from_cache,cache_age_secondsandcache_stale, and a snapshot old enough to mean “nothing is syncing” is refused in favour of a live fetch. An empty inbox is never a silent “nothing arrived”. - Destructive by consent only.
delete/mark/move/sendreturn a dry-run preview — grouped per account and folder, with sample subjects — and change nothing until--confirm.--all-foldersskips Sent/Drafts/Junk/Trash unless asked. - Built for token budgets.
--format compactprojects each email to the ten fields worth scanning (~30% smaller than the full shape),--with-previewfolds a body snippet into the list call, and batchshowreuses one IMAP connection. - Fast enough to call in a loop. A persistent daemon pools IMAP connections and
syncs to local SQLite in the background: five sequential
email listcalls go from 25s to 0.83s. See the table below. - MCP too.
mail-use mcp config --jsonprints a paste-ready entry; the server exposes 16 tools with the same dry-run defaults.
Renamed from Mailbox to mail-use. The command is now
mail-use;mailboxstill works as an alias, and your config in~/.config/mailboxis untouched.
Supported providers
163 / 126 · QQ · Gmail · Outlook / Hotmail · any custom IMAP+SMTP server.
Search behaves differently per provider and the CLI says so: Gmail searches bodies
server-side via X-GM-RAW, while QQ/163/Outlook have broken IMAP TEXT search, so
--query falls back to matching subject + sender only. Use --from / --subject
there for predictable results.
Install
One line, no npm, no Node
curl -fsSL https://raw.githubusercontent.com/leeguooooo/mail-use/main/install.sh | sh
mail-use --help
Downloads the prebuilt binary for your platform (macOS arm64/x64, Linux x64/arm64) from the
latest GitHub Release, verifies its
checksum, and installs to ~/.local/bin. Pin a version with MAIL_USE_VERSION=v2.11.2, or
change the dir with MAIL_USE_INSTALL_DIR=.... A missing .sha256 aborts the install
(MAIL_USE_INSECURE=1 overrides; a mismatch is always fatal). Each tarball also carries
signed build provenance: gh attestation verify mail-use-.tar.gz --repo leeguooooo/mail-use.
The installer also drops a mailbox symlink next to it, so scripts written against the old
name keep working.
There is no npm package. Distribution is GitHub Release binaries only — that keeps
releases free of NPM_TOKEN and 2FA prompts, and keeps install free of a Node toolchain.
The pre-rename @leeguoo/mailbox-cli packages on npm are frozen and no longer updated.
Upgrading
mail-use upgrade --check # is there a newer release? (`mail-use 3.3.1 -> 3.3.2`)
mail-use upgrade --check --json # the same check as JSON: name, current, latest, update_available, skills, install_channel, checked_only
mail-use upgrade # (--json only changes the output format) CLI only: download, verify sha256, check the new binary's version, swap atomically, restart the daemon
mail-use upgrade --skills # the same, then refresh this tool's own skill copies (skill-only when the CLI is current)
mail-use upgrade --tag v3.1.0 # pin an exact release (also the way to roll back)
Exit code 0 means the command worked (an update being available is not an error); 2
means the check, the download or the verification failed (the installed binary is left
as it was); 1 means it refused because Homebrew, npm or a source checkout owns this
install (it prints that manager’s command instead), or a skill could not be refreshed.
A plain upgrade only lists the skill copies it finds, with the command that would refresh
each. upgrade --skills refreshes them: a Claude Code plugin
(claude plugin update mail-use@leeguooooo-plugins, or printed if claude isn’t on PATH),
a git checkout linked into ~/.agents/skills, ~/.claude/skills or ~/.codex/skills
(git pull --ff-only, never forced), or a copied folder from npx skills add (it prints
npx skills update mail-use for you to run).
Any other command checks for a new release at most once a day (cached in
${XDG_CACHE_HOME:-~/.cache}/mail-use/update-check.json, 2 s timeout, failures silent) and,
when one exists, prints a single line to stderr — stdout stays clean JSON:
mail-use 3.3.2 is available (you have 3.3.1). Upgrade: mail-use upgrade. Set CI,
MAIL_USE_NO_UPDATE_CHECK or USE_NO_UPDATE_CHECK to turn it off.
When the daemon is running it notices new releases for you: one unauthenticated GET to
the GitHub releases API per day (MAILBOX_UPDATE_CHECK_HOURS, 0 disables), surfaced as
update in mail-use daemon status --json. It only ever reports — it never downloads
or installs anything.
upgrade is never automatic and never runs on its own: a tool that silently replaces
its own executable is a supply-chain surprise, not a convenience. It refuses to install
a tarball whose published .sha256 is missing or doesn’t match, or whose binary does not
report the requested version, and refuses to run at all from a Homebrew, npm or dev-checkout
install. Re-running the curl … install.sh | sh
line does the same job.
As an AI Skill (Claude Code / Cursor / etc.)
# Project scope — installs into ./.claude/skills/mail-use (or ./.cursor/skills/...):
npx skills add leeguooooo/mail-use --skill mail-use
# User scope — installs into ~/.claude/skills/mail-use:
npx skills add leeguooooo/mail-use --skill mail-use -g
The skill assumes the CLI is on PATH (install via the curl … install.sh | sh above).
For the biggest speedup also run mail-use daemon install once.
MCP server (Claude Desktop / Code / Cursor)
mail-use mcp config --json # prints a paste-ready mcpServers entry
From source (development)
pnpm install
pnpm test
# build a local platform binary into dist/mail-use
pnpm build:binary
If a test run is interrupted (editor task killed, agent session closed), its
Vitest workers can be left behind and hold memory. Check with
pgrep -fl vitest and kill what remains.
Configure accounts
mkdir -p ~/.config/mailbox
cp examples/accounts.example.json ~/.config/mailbox/auth.json
Config locations:
- Credentials:
~/.config/mailbox/auth.json - Other settings:
~/.config/mailbox/config.toml
Apple Mail, both ways
Agents use mail-use, people use Apple Mail; both talk to the same server, so an account only has to be set up once:
mail-use apple-mail status # which mailboxes each side has
mail-use apple-mail # mail-use → Apple Mail: opens System Settings on the profile, click Install
mail-use apple-mail import # Apple Mail → mail-use: paste one app password / authorization code per mailbox
mail-use account add # neither side has it yet: start here
Apple Mail keeps its passwords to itself (and Gmail added through Google sign-in has none), so importing needs one authorization code per mailbox; macOS only installs profiles through System Settings, so exporting needs one click. Mailboxes already in Apple Mail are skipped, so nothing gets duplicated. Step-by-step guide (Chinese), where to get each provider’s code, and FAQ: docs/guides/apple-mail.md.
Common commands
# CLI help
mail-use --help
# newest verification code across all accounts, one live pass
mail-use code --json
# list accounts
mail-use account list --json
# list unread emails (cache by default; --from filters cache-side)
mail-use email list --unread-only --limit 20 --json
mail-use email list --account-id my_account_id --from "newsletter" --json
# show one email (response includes list_unsubscribe when the header is set)
mail-use email show 123456 --account-id my_account_id --json
# mark read (use --dry-run to validate first)
mail-use email mark 123456 --read --account-id my_account_id --folder INBOX --dry-run --json
mail-use email mark 123456 --read --account-id my_account_id --folder INBOX --confirm --json
# delete
mail-use email delete 123456 --account-id my_account_id --folder INBOX --confirm --json
# bulk mutate by sender or subject (no UID list needed)
mail-use email mark --from "[email protected]" --read --confirm --account-id my_account_id --json
mail-use email delete --from "newsletter" --account-id my_account_id --json # dry-run preview
mail-use email delete --subject "[ad]" --account-id my_account_id --confirm --json
Cache + sync
- Cache DB default:
~/.local/share/mailbox/email_sync.db - Listing uses cache by default where possible. Add
--liveto force IMAP.
mail-use sync status --json
mail-use sync force --json
mail-use sync init
mail-use sync daemon
Persistent daemon (5-30× faster CLI calls)
Each one-shot invocation otherwise spends 1-3s on TCP+TLS+IMAP LOGIN. With the daemon
running, calls reuse pooled connections and a background SQLite sync means email list
usually doesn’t touch IMAP at all.
The curl … install.sh | sh installer sets this up for you when accounts are already
configured (MAIL_USE_NO_DAEMON=1 opts out). Otherwise:
mail-use daemon install # autostart at login (macOS launchd / Linux systemd-user)
mail-use daemon status --json
mail-use daemon reload # drop pooled connections after editing auth.json
Measured on Gmail INBOX, M2 MacBook over residential WAN:
| Operation | No daemon | Daemon (--live) |
Daemon (cached) |
|---|---|---|---|
Single email list |
5.0s | 1.0s | 0.17s |
email folders |
5.0s | 0.85s | n/a |
5 sequential email list |
25s | 5.3s | 0.83s |
3 parallel email show |
~15s | 2.7s | 0.88s |
Resource footprint (many agent sessions on one machine)
The daemon is one process per user, shared by every agent session through a Unix socket — so more sessions do not mean more IMAP connections. Measured idle on macOS with 3 accounts connected:
| Idle CPU | ~0.15% |
| Idle RSS | 3-15 MB |
| Connections | max 3 per account (MAILBOX_POOL_MAX), reaped back to 1 after 10 min idle |
| 12 concurrent calls | 1.6s wall clock, pool stayed at 1 connection per account |
Knobs, if the defaults do not suit you:
| Env | Default | Effect |
|---|---|---|
MAILBOX_POOL_MAX |
3 |
Max concurrent IMAP connections per account |
MAILBOX_POOL_IDLE_MS |
600000 |
Close connections idle this long (0 disables reaping) |
MAILBOX_POOL_KEEP_WARM |
1 |
Connections per account kept warm through reaping |
MAILBOX_NO_DAEMON |
unset | 1 makes the CLI skip the daemon entirely |
MAILBOX_UPDATE_CHECK_HOURS |
24 |
Daemon’s passive update check (0 disables it and the CLI’s daily notice) |
MAIL_USE_NO_UPDATE_CHECK / USE_NO_UPDATE_CHECK |
unset | Any value turns off the CLI’s daily “new version” notice |
AI usage guide
Mail classification belongs to the calling AI. mail-use cleanup --limit 50 --json
returns live metadata, body previews and gids for review; use --offset for the
next page and email show for full content. The AI selects specific gids
and executes them with email move, mark, flag or delete. cleanup and
inbox never classify or choose actions, and legacy category cleanup is rejected.
If you’re integrating this CLI into an AI agent, start here:
docs/AI_SKILL_MAIL_USE.md
OpenClaw integration
This repo includes an OpenClaw skill at skills/mail-use/SKILL.md.
OpenClaw loads skills from:
/skills~/.openclaw/skills
Quick link helper (symlink into ~/.openclaw/skills):
./scripts/link_openclaw_skill.sh
Force replace an existing link:
./scripts/link_openclaw_skill.sh --force
To use this repo without copying files, add the repo skills directory to
skills.load.extraDirs in ~/.openclaw/openclaw.json:
{
"skills": {
"load": {
"extraDirs": [
"/path/to/mcp-email-service/skills"
]
}
}
}
OpenClaw handles channel delivery and scheduling; mail-use returns structured JSON outputs and optional text summaries.
Verify OpenClaw picked up the skill:
openclaw skills list --eligible
openclaw skills check
The *-use family
Small, composable CLIs that give an AI agent hands on one real thing. Same shape
everywhere: curl … install.sh | sh to install, npx skills add leeguooooo/
to teach your agent, JSON on stdout.
| Repo | Gives your agent |
|---|---|
| chrome-use | A real browser — logged-in sessions, forms, scraping, screenshots |
| mail-use | Email — read, search, send, triage across Gmail / QQ / 163 / any IMAP |
| iphone-use | A real iPhone — tap, type, screenshot, pull on-device data |
| wechat-use | WeChat on macOS — send messages, query contacts and history |
| discord-use | Discord — messages, channels, forums, webhooks (REST-only, Rust) |
| cookie-use | Many logged-in accounts per site — capture, switch, apply sessions |
| profile-use | Your personal profile, safely — fill signup / KYC / checkout forms |
| bitwarden-use | Bitwarden / Vaultwarden — headless passkey (FIDO2) login |
| chatgpt-use | Your ChatGPT subscription as a coding-agent backend — no API key |
| computer-use | The macOS desktop itself |
| pixcake-use | Read-only PixCake probing — snapshot / diff / SQLite inspection |
Contract
docs/CLI_JSON_CONTRACT.md
Built by leeguooooo — field notes on AI agents, reverse engineering & Cloudflare Workers at blog.misonote.com · follow on X @leeguooooo
Author
Built by 郭立 (Guo Li / leeguoo) — leeguoo.com · GitHub · X · more tools in the *-use family.
Install
npx skills update mail-use` for you to run).