mailroom is a local-first repository for Gmail operations: search, thread triage, reply drafting, reviewed cleanup actions, attachment cataloging, and controlled export. The native center of gravity is a Rust CLI/TUI with a single local operational store. The operator loop can also use Codex Gmail/GitHub plugin workflows where live inspection or ad hoc actions are still a better fit.
- Primary stack: Rust +
clap - Operator surfaces: CLI first, TUI inspection plus confirmed selected-thread workflow, draft, cleanup, and persisted automation actions second
- Local operational store: SQLite with migration-owned schema and FTS5-backed mailbox search
- Native Gmail foundation: OAuth login, active account persistence, live profile/label reads, one-shot mailbox sync, local search, thread-scoped workflow state, remote draft sync, reviewed cleanup actions, attachment catalog/export foundation, review-first automation rules, and a terminal operator shell
- Hardening surface: read-only label audits, readiness verification, and operator runbooks for safe real-mailbox rollout
- Versioned content: code, docs, examples, plans
- Ignored runtime content:
.mailroom/state, caches, exports, secrets, and attachment vaults - V1 milestone: search + thread workflow + draft/send + reviewed cleanup + controlled attachment export + review-first automation
src/: Rust entrypoints and workspace logicconfig/: tracked example configurationmigrations/: embedded SQL schema migrationsdocs/: architecture, decisions, operations, roadmap, and workflow docs.github/workflows/: CI for formatting, linting, and tests.mailroom/: ignored runtime workspace for local state
mailroom treats the git repo as the durable source of truth for design and code, and .mailroom/ as the local operational workspace:
.mailroom/auth/.mailroom/cache/.mailroom/state/.mailroom/vault/.mailroom/exports/.mailroom/logs/
These paths are intentionally ignored from git.
Repo-local overrides also live under .mailroom/:
.mailroom/config.toml.mailroom/automation.toml.mailroom/auth/gmail-oauth-client.json.mailroom/auth/gmail-credentials.json.mailroom/state/mailroom.sqlite3
The current binary can now resolve config, bootstrap the local store, manage Gmail auth, sync mailbox metadata, search the local cache, catalog inbound attachments, manage thread workflows, sync remote Gmail drafts, execute reviewed cleanup actions, and open a terminal operator shell:
cargo run -- workspace init
cargo run -- paths --json
cargo run -- doctor --json
cargo run -- audit labels --json
cargo run -- audit verification --json
cargo run -- config show --json
cargo run -- auth status --json
cargo run -- auth setup
cargo run -- auth setup --credentials-file /path/to/client_secret.json
cargo run -- auth login --no-browser
cargo run -- auth logout --json
cargo run -- account show --json
cargo run -- gmail labels list --json
cargo run -- store init --json
cargo run -- store doctor --json
cargo run -- sync run --json
cargo run -- sync run --full --recent-days 30 --json
cargo run -- sync run --profile deep-audit --json
cargo run -- search "project alpha" --label INBOX --limit 10 --json
cargo run -- tui
cargo run -- tui --search "project alpha"
cargo run -- attachment list --json
cargo run -- attachment show m-1:1.2 --json
cargo run -- attachment fetch m-1:1.2 --json
cargo run -- attachment export m-1:1.2 --json
cargo run -- attachment export m-1:1.2 --to ./exports/statement.pdf --json
cargo run -- automation rules validate --json
cargo run -- automation rules suggest --json
cargo run -- automation rollout --limit 10 --json
cargo run -- automation run --json
cargo run -- automation run --rule archive-newsletters --limit 25 --json
cargo run -- automation show 42 --json
cargo run -- automation apply 42 --execute --json
cargo run -- automation prune --older-than-days 30 --json
cargo run -- workflow list --json
cargo run -- workflow show thread-123 --json
cargo run -- triage set thread-123 --bucket urgent --note "reply today" --json
cargo run -- workflow promote thread-123 --to follow_up --json
cargo run -- workflow snooze thread-123 --until 2026-04-25 --json
cargo run -- draft start thread-123 --reply-all --json
cargo run -- draft body thread-123 --text "Thanks, sending details shortly." --json
cargo run -- draft attach add thread-123 --path ./notes/reply.txt --json
cargo run -- draft send thread-123 --json
cargo run -- cleanup archive thread-123 --json
cargo run -- cleanup archive thread-123 --execute --json
cargo run -- cleanup label thread-123 --add 0.To-Reply --remove INBOX --execute --json
cargo run -- cleanup trash thread-123 --json
cargo run -- roadmapAll --json commands now use one normalized envelope:
- success:
{ "success": true, "data": ... } - failure:
{ "success": false, "error": { "code": "validation_failed", "message": "use --until YYYY-MM-DD or --clear", "kind": "workflow.validation", "operation": "workflow.snooze", "causes": ["use --until YYYY-MM-DD or --clear"] } }
error.code is stable and operator-oriented. Current exit buckets are:
2: validation or config failure3: auth required4: not found5: conflict6: timeout, rate limit, or remote failure7: local storage failure10: internal failure
mailroom sync run is quota-aware by default. Full and incremental sync now:
- use Mailroom's built-in Gmail quota limiter instead of an external generic rate-limiter dependency
- budget Gmail read calls by quota units, not raw request count
- use
500-message list/history pages for fewer API round trips - keep message payload fetch concurrency bounded by default
- retry Gmail
429,5xx, and usage-limit403responses with truncated backoff
The named deep-audit preset is available when a deep bootstrap needs extra headroom:
cargo run -- sync run --profile deep-audit --jsonEquivalent explicit flags:
cargo run -- sync run --full --recent-days 365 --quota-units-per-minute 9000 --message-fetch-concurrency 3 --jsonOperator input mistakes on the workflow surface now stay in the validation bucket. Examples:
workflow snoozerequires exactly one of--untilor--cleardraft bodyrequires exactly one of--text,--file, or--stdindraft attach addtreats missing attachment files as validation failuresdraft attach removerejects ambiguous filename-only matches; use the stored attachment path when multiple attachments share a filename
Mailbox sync/search behavior, cursor fallback rules, and doctor field meanings
live in docs/operations/mailbox-sync-and-search.md.
Durable architectural ownership for the sync/search slice lives in
docs/decisions/0003-message-canonical-sync.md.
Attachment catalog, vault, and export behavior live in
docs/operations/attachment-catalog-and-export.md,
with the durable ownership captured in
docs/decisions/0005-attachment-canonical-model.md.
Thread workflow, remote draft, and cleanup behavior live in
docs/operations/thread-workflow-and-cleanup.md,
with the durable design captured in
docs/decisions/0004-unified-thread-workflow.md.
Review-first automation rules and persisted bulk-action snapshots live in
docs/operations/automation-rules-and-bulk-actions.md,
with the durable design captured in
docs/decisions/0006-review-first-automation-rules.md.
Read-only verification and hardening guidance live in
docs/operations/verification-and-hardening.md,
with the durable design captured in
docs/decisions/0007-verification-audit-hardening.md.
The terminal operator shell lives in
docs/operations/tui-operator-shell.md,
with the durable design captured in
docs/decisions/0008-read-only-tui-foundation.md,
docs/decisions/0009-tui-workflow-actions.md,
docs/decisions/0010-tui-draft-cleanup-flows.md,
and docs/decisions/0011-tui-automation-apply-rules.md.
Config precedence is:
- Built-in defaults
- User config via
directories::ProjectDirs - Repo-local
.mailroom/config.toml MAILROOM_environment overrides
For Gmail auth, the primary path is:
- Run
cargo run -- auth setup. - If Mailroom auto-discovers exactly one
client_secret_*.json, select it. Otherwise paste the Client ID and optional Client Secret directly into the CLI. - Advanced: if you already ran
gcloud auth application-default loginwith Gmail scopes, choose the ADC import option. - Let Mailroom import the client locally and continue into the browser consent flow or reuse the imported ADC refresh token.
Once imported, the repo-local OAuth client file becomes the authoritative Gmail
OAuth client for future login and token refresh flows. Legacy inline
gmail.client_id / gmail.client_secret config is only used when no imported
client file exists.
If you omit --credentials-file, Mailroom will try to auto-discover a single
client_secret_*.json file from the current directory or ~/Downloads, then
offer that path inside the setup wizard. The imported file is stored in the
standard Google Desktop app installed JSON shape under
.mailroom/auth/gmail-oauth-client.json.
Advanced manual overrides still work:
gmail.client_id- optionally
gmail.client_secret - leave the default
gmail.modifyscope unless you are intentionally testing a narrower mock configuration
docs/README.md: doc indexdocs/decisions/0001-foundation.md: foundational architecture decisiondocs/architecture/system-overview.md: system boundaries and responsibilitiesdocs/decisions/0003-message-canonical-sync.md: mailbox sync and search designdocs/decisions/0004-unified-thread-workflow.md: thread workflow, drafts, and cleanup ownershipdocs/decisions/0005-attachment-canonical-model.md: attachment catalog, vault, and export ownershipdocs/decisions/0006-review-first-automation-rules.md: review-first automation rules and persisted bulk-action snapshotsdocs/decisions/0007-verification-audit-hardening.md: read-only audit ownership and real-mailbox rollout posturedocs/decisions/0008-read-only-tui-foundation.md: read-only terminal shell ownershipdocs/decisions/0009-tui-workflow-actions.md: confirmed local workflow actions in the TUIdocs/decisions/0010-tui-draft-cleanup-flows.md: selected-thread draft and cleanup flows in the TUIdocs/decisions/0011-tui-automation-apply-rules.md: persisted automation run apply and editor-backed rules editing in the TUIdocs/operations/local-config-and-store.md: config precedence, store bootstrapping, and hardeningdocs/operations/gmail-auth-and-account.md: Gmail OAuth flow, credential storage, and account verificationdocs/operations/mailbox-sync-and-search.md: sync commands, search filters, and cursor behaviordocs/operations/attachment-catalog-and-export.md: attachment listing, vault fetch, and export commandsdocs/operations/thread-workflow-and-cleanup.md: triage, draft/send, snooze, and reviewed cleanup commandsdocs/operations/automation-rules-and-bulk-actions.md: rule validation, persisted run snapshots, and review-first bulk applydocs/operations/verification-and-hardening.md: deep-sync audit, label canonicalization, canary tests, and first-wave ruleset rolloutdocs/operations/tui-operator-shell.md: TUI usage, workflow action key bindings, and safety contractdocs/operations/plugin-assisted-workflows.md: how Codex Gmail/GitHub workflows fit alongside native commandsdocs/roadmap/v1-search-triage-draft-queue.md: first milestone scope
- Use the verification and hardening runbook to canonicalize labels, deepen the local audit corpus, and generate disabled starter rules with
automation rules suggest. - Use the TUI automation pane for validation, disabled suggestion review, persisted preview runs, saved-run candidate inspection, and high-friction saved-run apply.
- Improve automation ergonomics only after a few low-surprise micro-batch archive/label runs land cleanly.
- Add unsubscribe assistance only after the deeper sync proves out list-header coverage in the local cache.