# Usage — agent Gmail toolbox How Cursor agents (and you) operate connected Gmail accounts via CLI. The web UI is a reader only. ## Prerequisites 1. Sign in via the web UI at least once **per** mailbox (`gmail.modify` scope — see [development.md](development.md#change-google-api-permissions-gmailmodify)). 2. Set a default if more than one account is connected: ```bash npm run gmail -- accounts npm run gmail -- accounts --default you@gmail.com ``` Optional env override: `GMAIL_DEFAULT_USER=you@gmail.com`. ## Account resolution 1. `--user ` 2. `GMAIL_DEFAULT_USER` 3. `users.is_default` 4. Sole connected account 5. Else error — set a default ## Commands ```bash npm run gmail -- … ``` | Command | Purpose | `--reason` | |---|---|---| | `accounts` | List mailboxes / set `--default` | no | | `list` | Search → id / from / subject | no | | `read ` | Full headers + body | no | | `summarize` | Compact digests for one or many (`--ids` or `--query`) | no | | `labels` | List label ids/names | no | | `label --add/--remove` | Modify labels | **required** | | `archive ` | Remove `INBOX` | **required** | | `draft --to --subject --body` | Create a draft (**never sends**) | **required** | | `forward --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: ```bash npm run list-messages -- … # → gmail list npm run process-messages -- … # receipt backfill (see development.md) ``` ### Examples ```bash 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` = `cli` - `action`, `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 `--reason` on mutations (explains intent in the audit log). - Ask the user before bulk archive (roughly >20 messages). - Prefer `--dry-run` when 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-messages` into 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 `--user` for the default; pass `--user` for work vs personal.