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 destructiveone 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 agenthands 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 "nothingis 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 adry-run preview — grouped per account and folder, with sample subjects — and changenothing until--confirm.--all-foldersskips Sent/Drafts/Junk/Trash unless asked. - Built for token budgets.
--format compactprojects each email to the tenfields worth scanning (~30% smaller than the full shape),--with-previewfolds abody snippet into the list call, and batchshowreuses one IMAP connection. - Fast enough to call in a loop. A persistent daemon pools IMAP connections andsyncs to local SQLite in the background: five sequential
email listcalls go from25s to 0.83s. See the table below. - MCP too.
mail-use mcp config --jsonprints a paste-ready entry; the serverexposes 16 tools with the same dry-run defaults.
Renamed from Mailbox to mail-use. The command is now
mail-use;mailboxstillworks 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 bodiesserver-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 / --subjectthere 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) from thelatest GitHub Release, verifies itschecksum, and installs to ~/.local/bin. Pin a version with MAIL_USE_VERSION=v2.11.2, orchange the dir with MAIL_USE_INSTALL_DIR=....
The installer also drops a mailbox symlink next to it, so scripts written against the oldname keep working.
There is no npm package. Distribution is GitHub Release binaries only — that keepsreleases 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.
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), itsVitest workers can be left behind and hold memory. Check withpgrep -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
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 daemonrunning, calls reuse pooled connections and a background SQLite sync means email listusually doesn't touch IMAP at all.
The curl … install.sh | sh installer sets this up for you when accounts are alreadyconfigured (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 Unixsocket — so more sessions do not mean more IMAP connections. Measured idle on macOSwith 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 |
AI usage guide
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:
<workspace>/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 toskills.load.extraDirs in ~/.openclaw/openclaw.json:
{
"skills": {
"load": {
"extraDirs": [
"/path/to/mcp-email-service/skills"
]
}
}
}
OpenClaw handles channel delivery and scheduling; mail-use returns structuredJSON 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 shapeeverywhere: curl … install.sh | sh to install, npx skills add leeguooooo/<name>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