Provide list/read/summarize plus reason-gated archive, label, draft, and forward-as-draft, with SQLite audit logging and default-mailbox resolution. Co-authored-by: Cursor <cursoragent@cursor.com>
4.0 KiB
4.0 KiB
Usage — agent Gmail toolbox
How Cursor agents (and you) operate connected Gmail accounts via CLI. The web UI is a reader only.
Prerequisites
- Sign in via the web UI at least once per mailbox (
gmail.modifyscope — see development.md). - Set a default if more than one account is connected:
npm run gmail -- accounts
npm run gmail -- accounts --default you@gmail.com
Optional env override: GMAIL_DEFAULT_USER=you@gmail.com.
Account resolution
--user <email|id>GMAIL_DEFAULT_USERusers.is_default- Sole connected account
- Else error — set a default
Commands
npm run gmail -- <command> …
| Command | Purpose | --reason |
|---|---|---|
accounts |
List mailboxes / set --default |
no |
list |
Search → id / from / subject | no |
read <id> |
Full headers + body | no |
summarize |
Compact digests for one or many (--ids or --query) |
no |
labels |
List label ids/names | no |
label <ids> --add/--remove |
Modify labels | required |
archive <ids> |
Remove INBOX |
required |
draft --to --subject --body |
Create a draft (never sends) | required |
forward <id> --to [--note] |
Forward-as-draft | required |
audit |
Show recent CLI audit rows | no |
Shared: --user, --json, --dry-run (mutations: no Gmail write; audit status=dry-run).
Aliases:
npm run list-messages -- … # → gmail list
npm run process-messages -- … # receipt backfill (see development.md)
Examples
npm run gmail -- list --query 'is:unread newer_than:3d' --max 40
npm run gmail -- read 18c0… --json
npm run gmail -- summarize --query 'in:inbox newer_than:7d' --max 15
npm run gmail -- label ABC,DEF --add receipts --reason "tag Grab receipts"
npm run gmail -- archive ABC --reason "newsletter: Product Hunt daily"
npm run gmail -- archive ABC --dry-run --reason "preview bulk archive"
npm run gmail -- draft \
--to colleague@example.com \
--subject "Re: Invoice" \
--body "Thanks — I'll review today." \
--reason "polite reply draft; user will send"
npm run gmail -- forward ABC \
--to accounting@example.com \
--note "Please book this receipt." \
--reason "forward Grab receipt to accounting"
npm run gmail -- audit --limit 30
npm run gmail -- audit --action archive --user you@gmail.com --json
Audit log
Every CLI action writes a row to SQLite audit_log (same apps/api/data/app.db):
actor=cliaction,mailbox,message_ids,payload(JSON),status(ok|error|dry-run)reason— required for mutations; optional elsewhere
Failures still write status=error. Receipt watcher success stays in PocketBase spendings.parsed + stdout; it is not mixed into this table.
Safety
- Never call send. Never trash/delete.
- Always pass a real
--reasonon mutations (explains intent in the audit log). - Ask the user before bulk archive (roughly >20 messages).
- Prefer
--dry-runwhen unsure. - Drafts stay in Gmail Drafts until the user sends them in the Gmail UI.
Ideas — what agents can do
These are workflows on top of the CLI, not extra product features.
- Inbox triage: list unread → summarize a batch → archive newsletters after labeling.
- Receipt desk: search provider subjects →
--add receipts→process-messagesinto PocketBase. - Draft, never send: reply drafts, declines, “please re-send invoice” — you hit Send in Gmail.
- Forward-as-draft: receipt or travel mail → draft to accounting/partner with
--note. - Label taxonomy:
travel,bills,need-reply,waiting— agents apply labels instead of inventing folders. - Weekly digest:
newer_than:7d is:unread→ summarize by sender → archive obvious noise. - Follow-up queue: find unanswered threads → draft a bump → leave in Drafts.
- Multi-mailbox: omit
--userfor the default; pass--userfor work vs personal.