Ongoing Gmail inbox management via scheduled runs. Archives known noise, flags urgent items, drafts replies in-thread (never auto-sends), and catches stale follow-ups.
assistant skills install inbox-managementCompanion to inbox-cleanup. Cleanup drains the backlog once. Management keeps the inbox clean on a schedule — archiving noise, flagging urgents, drafting replies, and catching stale follow-ups.
Runs as a scheduled task (via the schedule skill). Each run should be silent unless something is worth interrupting the user for.
Default posture: high recall on noise archiving, high precision on user interruption. Archive aggressively on known-safe patterns. Ping sparingly. Never auto-send a reply. When unsure, flag instead of archiving.
A single wrong archive of an important email kills trust. Earn autonomy in stages:
| Stage | Archive behavior | Draft behavior | Alerts |
|---|---|---|---|
| 0 — Flag-only (default) | Nothing archived. All archive calls use --dry-run. Summary shows what would be archived for user review. | Drafts created in-thread, listed in summary. | Urgent scan active. |
| 1 — Standard | Silent archive of known-safe categories only (calendar responses, no-reply, newsletters). Cold outreach still flagged. Batches > 1,000 ops auto-dry-run. | Drafts created in-thread, summarized per run. | Urgent scan active. |
| 2 — Aggressive | Above + cold outreach archived by LLM judgment (default archive, flag only when relevant to user). All ops logged for reversal. | Same as Stage 1. | Urgent scan active. |
Graduation requires the user to explicitly say "graduate me" or equivalent. Do not infer from silence.
Never auto-send a draft. No toggle for this rule.
Before anything else, explain what the user is opting into. Be direct:
"Here's what inbox management does: on a schedule you choose (e.g. every few hours on weekdays), I'll scan your inbox and take action based on a trust level you control.
Stage 0 (where everyone starts): I watch but don't touch. I'll tell you what I would archive, show you draft replies I wrote, and flag urgent items — but I won't move or delete anything. This lasts until you explicitly tell me to graduate.
Stage 1 (you opt in): I silently archive obvious noise — calendar responses, no-reply senders, newsletters. Everything else is still flagged for your review.
Stage 2 (you opt in): I also archive cold outreach using my judgment. Higher autonomy, slightly higher risk of a wrong call.
At every stage: I will never send an email on your behalf. I create drafts for you to review. You can pause or stop this at any time."
Wait for explicit confirmation before proceeding. If the user hesitates or asks clarifying questions, answer them — don't rush past this step.
Start at Stage 0. Store via gmail-prefs.ts --action set-management-config --stage 0.
Ask for senders/domains that may look like outreach but matter. Seed categories:
Store via gmail-prefs.ts --action add-safelist --emails "...". The safe-list is shared with inbox-cleanup.
Default urgency bar for alerts:
Store threshold level via gmail-prefs.ts --action set-management-config --interrupt-threshold "default".
Create a recurring schedule via schedule_create:
0 */3 * * 1-5 (every 3 hours on weekdays)"Load the inbox-management skill and run the inbox management pipeline."executereuse_conversation: true for context accumulation across runsConfirm cadence with user. Overnight: urgent-scan only.
Run messaging_analyze_style on the user's recent sent mail. Store the style profile in the Personal Knowledge Base for draft generation.
Confirm the user wants drafts generated. Some prefer flag-only forever.
Each step is silent unless something qualifies for interrupt. Run these in order.
Resume interrupted runs first. Before starting a new pipeline pass, check bun run scripts/gmail-runs.ts list. If the most recent run has status: "interrupted", resume it via bun run scripts/gmail-archive.ts archive --resume "<run-id>" before proceeding. Also run bun run scripts/gmail-runs.ts prune to clean up logs older than 30 days.
Read the last-run timestamp via gmail-prefs.ts --action get-management-config. If last-run is more than 2x the scheduled interval ago (e.g. >6 hours for a 3-hour schedule), notify the user:
Then update last-run to now via gmail-prefs.ts --action set-management-config --last-run "..." before continuing.
Run these queries via gmail-archive.ts --action archive --query "..." and bulk archive results:
subject:(Accepted: OR Declined: OR Tentative: OR "has accepted" OR "has declined") in:inbox
from:(noreply OR no-reply OR donotreply) in:inbox
subject:("newsletter" OR "weekly digest" OR "monthly digest") in:inbox
Cross-check the safe-list before each batch. Use gmail-prefs.ts --action list to load the safe-list. Remove any safe-listed sender from the batch before archiving.
Stage 0: Collect results but do not archive. Include in summary with "would archive" label.
Use gmail-scan.ts --action outreach-scan to identify cold outreach senders. For each result, judge: is this person/offer potentially relevant to the user?
Search in:inbox is:unread newer_than:1d. Scan each for urgency signals:
| Signal | Why |
|---|---|
| "past due", "overdue", "final notice", "balance due" | Financial consequence |
| "will be suspended", "service interruption", "account closure" | Operational consequence |
| "signature required", "agreement", "DocuSign pending" from real sender | Legal action needed |
| .gov domain, "IRS", "state of", "department of" | Regulatory |
| Safe-list sender with deadline language | Known-important, urgent framing |
If any qualify, send one alert:
🚨 urgent email — count + per-item bullets (sender · subject · why)Search in:inbox is:unread newer_than:7d. Filter out anything caught by Steps 1-2, calendar responses, receipts, no-reply senders, one-way FYIs.
For each remaining email from real humans expecting a response:
list_drafts, filter results by thread ID. If draft exists, skip.get_thread.gmail-email.ts draft --thread-id "..." --in-reply-to "...". Draft must be fully written in the user's voice (use Personal Knowledge Base style profile), substantive, no placeholders. Never auto-send.After the pass, send one summary:
[N] drafts ready for review: + per-item bulletsSearch in:sent newer_than:14d. For each thread where the user sent the last message and no reply has arrived:
Ask: did this email clearly expect a response? Only flag if 2+ signals are present:
Do not flag: cold outreach the user sent, intros where silence is normal, thank-yous, FYIs, one-line acknowledgments, or threads where the user's last message was itself a reply to a no-reply sender.
If yes, alert with: recipient, subject, date sent, and a ready-to-send follow-up draft.
At Stage 0, send one end-of-day summary (last scheduled run of working hours):
📬 Today's inbox (flag-only mode):
Would archive ([N]):
• [category]: [count] — [sample sender/subject]
Cold outreach flagged ([N]):
• [sender] · [subject] · relevant: [y/n]
Drafts ready ([N]):
• [sender] · [subject] — [one-line summary]
Follow-ups suggested ([N]):
• [recipient] · [subject] · sent [date]
User responds with:
Capture every correction — add protected senders to safe-list immediately.
name@domain) and domain-level (example.com) matches.inbox-cleanup — both skills read/write the same store via gmail-prefs.ts.inbox-cleanup first. Management assumes the backlog is drained.gmail-auto-filters.ts generate to propose Gmail filters for safe categories (no-reply, calendar, sketchy TLDs, confirmed newsletters). The user confirms before any filter is created. These filters prevent re-accumulation immediately — management Step 1 handles only what slips through.gmail-prefs.ts.