skills/gmail-multi-inbox/SKILL.md
Set up and maintain Gmail Multiple Inboxes with auto-discovered sender filters. Scans the user's Gmail to discover senders, suggests inbox categories, generates a Google Apps Script that creates labels and filters. Use this skill for: organizing Gmail, setting up multiple inboxes, managing Gmail labels and filters, categorizing email senders, updating inbox filters with new senders, or unsubscribing from noisy emails. Trigger phrases: "Gmail sections", "inbox categories", "email organization", "sender filters", "multiple inboxes", "clean up my inbox".
npx skillsauth add apocohq/skills gmail-multi-inboxInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Gmail's Multiple Inboxes displays up to 5 custom sections alongside the main inbox. Each section shows emails matching a search query. This skill uses a label + filter approach: label-based sections get Gmail filters that auto-label incoming mail by sender domain. The output is always a Google Apps Script the user pastes into script.google.com.
The generated script is idempotent — safe to re-run after adding or removing senders. When senders are removed from the lists, setupAll() automatically deletes the corresponding Gmail filters.
This skill requires a Gmail MCP connector (e.g. search_gmail_messages) to scan the user's inbox. Gmail does not have an official MCP server — the user must have a third-party Gmail connector configured. If no Gmail connector is available, the skill can still work in a limited way: skip the scanning steps and let the user provide sender domains manually, or import from an existing script.
The skill stores its current configuration in assets/config.json inside this skill's directory. This file tracks:
Always read assets/config.json before starting. If it exists, this is a returning user — go to Update Mode. If it doesn't exist, check if the user has an existing script (see Import Existing Script). Otherwise, this is a new user — go to Initial Setup.
If the user already has a Gmail Multi-Inbox Apps Script (set up manually or from a previous run before config tracking existed), ask them to paste it. Parse the script to extract:
var xxxSenders = [...] declarations, extract the domain lists and map each to its label namecreateLabelIfNeeded('...') calls to identify the label names__MULTI_INBOX_CONFIG__ comment block or any section query/name commentsBuild assets/config.json from the parsed data and confirm the reconstructed config with the user before proceeding to Update Mode.
Search the user's Gmail history using search_gmail_messages to build a comprehensive picture of who emails them. Run multiple queries and merge the results — the goal is to discover all non-personal sender domains.
Broad sweep (most important — do this first):
newer_than:6m — all emails from the last 6 months. Paginate through results to collect as many senders as possible.newer_than:1m — recent emails, captures current high-frequency sendersCategory-based (catches things the broad sweep may paginate past):
category:promotions — marketing, newsletterscategory:updates — notifications, shipping, orderscategory:social — social media notificationscategory:forums — mailing lists, digestsSignal-based:
unsubscribe — anything with an unsubscribe link (broad, catches most automated mail)from:noreply OR from:no-reply OR from:notifications OR from:info@ — automated sendersLocalized subject searches (adapt based on user's language):
subject:order OR subject:invoice OR subject:receipt OR subject:shipping OR subject:confirmationsubject:objednávka OR subject:faktura OR subject:potvrzení OR subject:doručeníAggregate results: collect all sender addresses, extract domains, group by domain, count frequency. Ignore generic providers (gmail.com, outlook.com, yahoo.com, hotmail.com, icloud.com, seznam.cz, etc.) — these are personal contacts, not automated senders.
Based on the scan results, propose up to 5 sections. Start with these defaults and adjust based on what the scan actually found:
| # | Name | Query | Label | Description |
|---|------|-------|-------|-------------|
| 1 | Important | (is:starred OR is:important) | (none — query-based) | Starred and important emails |
| 2 | Work | label:work in:inbox | work | Emails from the user's company domain |
| 3 | Newsletters | label:newsletter in:inbox | newsletter | Subscriptions, digests, marketing |
| 4 | Orders | label:orders in:inbox | orders | E-shops, shipping, travel, invoices |
| 5 | (available) | | | Suggest based on scan or leave empty |
Present the proposed sections with the discovered sender domains grouped under each category. Ask the user to:
For section 1 (Important): this is query-based, no label or filters needed.
Read the template from scripts/gmail-multi-inbox-template.js in this skill's directory.
Fill in the placeholders:
__SENDER_ARRAYS__ — one var array per label-based section with the confirmed sender domains__LABEL_CONFIGS__ — createLabelIfNeeded('labelname', { backgroundColor: '#hex', textColor: '#hex' }) calls for each label-based section. The color object is optional — if the section has a color in the config, pass it; otherwise omit the second argument. Only Gmail's predefined hex colors are allowed (see template comments).__STALE_FILTER_CLEANUP__ — a removeStaleFilters([...]) call listing all managed label/sender pairs. This lets the script detect and delete Gmail filters whose sender was removed from the lists. Example:
removeStaleFilters([
{ senders: workSenders, label: 'work' },
{ senders: newsletterSenders, label: 'newsletter' }
]);
__FILTER_CREATION__ — for each label-based section: loop over its sender array calling createFilterIfNeeded(sender, label). Do NOT include retroLabel calls here — those go in __RETRO_LABEL__.__RETRO_LABEL__ — for each label-based section: call retroLabel(senderArray, label). If the section has matchToAndCc in the config, pass it as { matchToAndCc: [...] }. This is placed inside the separate retroLabelAll() function.__MULTI_INBOX_CONFIG__ — comment block listing each section's query and name for the user to enter in Gmail SettingsSave the generated script as assets/gmail-multi-inbox-setup.js inside this skill's directory.
Write assets/config.json with the full configuration:
{
"sections": [
{ "name": "Important", "query": "(is:starred OR is:important)", "label": null },
{ "name": "Work", "query": "label:work in:inbox", "label": "work", "senders": ["companydomain.com"], "matchToAndCc": ["companydomain.com"], "color": { "backgroundColor": "#4a86e8", "textColor": "#ffffff" } },
{ "name": "Newsletters", "query": "label:newsletter in:inbox", "label": "newsletter", "senders": ["substack.com", "beehiiv.com"], "color": { "backgroundColor": "#fad165", "textColor": "#000000" } },
{ "name": "Orders", "query": "label:orders in:inbox", "label": "orders", "senders": ["amazon.com", "ups.com"], "color": { "backgroundColor": "#16a766", "textColor": "#ffffff" } }
],
"lastScan": "2026-02-18"
}
Tell the user:
Part A — Run the script:
setupAll() and authorize when prompted — this creates labels, updates filters, and retro-labels existing emailsPart B — Configure Multiple Inboxes manually:
The Gmail API does not expose Multiple Inboxes settings, so this part must be done by hand in Gmail.
In Gmail: Settings (⚙️) → See all settings → Inbox tab
Set Inbox type to Multiple Inboxes
For each section, enter the Search query and Section name exactly as listed in the script's header comment. Present these to the user in a clear table, e.g.:
| Section | Search query | Section name |
|---------|-------------|--------------|
| 1 | is:starred OR is:important | Starred / Important |
| 2 | label:work in:inbox | Work |
| 3 | label:newsletter in:inbox | Newsletters |
| 4 | label:orders in:inbox | Orders |
| 5 | (leave empty) | |
Set Multiple Inbox position to "Right of inbox" (recommended)
Click Save Changes
Always present the full table with the actual section values from the config — do not just say "see the script header".
When assets/config.json exists:
assets/config.json. If any senders were removed, explicitly list them with their section names and ask the user to confirm. The generated script will delete the corresponding Gmail filters when run — make sure the user understands this. Do NOT generate the script until the user confirms the removals.assets/gmail-multi-inbox-setup.jsassets/config.jsonsetupAll() (this handles filters and retro-labeling in one go)When the user asks for inbox cleanup or unsubscribe suggestions:
Search Gmail for senders that pollute the inbox. Focus on:
from:domain.com (total) vs is:unread from:domain.com (unread) to estimate open rate.from:domain.com -in:sent has the same count as from:domain.com, meaning the user never interacts with this sender.Use broad queries to discover candidates:
unsubscribe newer_than:6m — anything with an unsubscribe link in the last 6 months (widest net)category:promotions — marketing and newsletterscategory:updates — transactional notificationscategory:social — social media digests and notificationsfrom:noreply OR from:no-reply OR from:notifications — automated senderssubject:newsletter OR subject:digest OR subject:weekly OR subject:monthlyThen for each discovered domain, measure engagement:
from:domain.com newer_than:6mis:unread from:domain.com newer_than:6mfrom:domain.com vs from:domain.com -in:sentExclude senders already managed in the config (they're already categorized).
Group the noisy senders into tiers:
For each sender, show:
in:inbox to section queries ensures archived mail doesn't appear in sections.from:domain.com matches any @domain.com address and subdomains.#000000 or #ffffff text for contrast):
#fb4c2f, #e66550, #cc3a21, #ac2b16, #822111, #f6c5be, #efa093#ffad47, #ffbc6b, #eaa041, #cf8933, #a46a21, #ffe6c7, #ffd6a2#fad165, #fcda83, #f2c960, #d5ae49, #aa8831, #fef1d1, #fce8b3#16a766, #44b984, #149e60, #0b804b, #076239, #b9e4d0, #89d3b2, #43d692, #68dfa9, #3dc789, #2a9c68, #1a764d, #c6f3de, #a0eac9#4a86e8, #6d9eeb, #3c78d8, #285bac, #1c4587, #c9daf8, #a4c2f4#a479e2, #b694e8, #8e63ce, #653e9b, #41236d, #e4d7f5, #d0bcf1#f691b3, #f7a7c0, #e07798, #b65775, #83334c, #fcdee8, #fbc8d9#000000, #434343, #666666, #999999, #cccccc, #efefef, #f3f3f3, #fffffftesting
Tracks Architecture Decision Records (ADRs) in docs/adrs/. Creates, lists, and updates ADRs following project conventions. TRIGGER when: user wants to record, review, or update an architectural decision.
development
Create a PRD through user interview, codebase exploration, and module design, then submit as a GitHub issue after user approval. Use when user wants to write a PRD, create a product requirements document, or plan a new feature. Always present the PRD for user approval before submitting.
development
Morning review and prioritization of Things todos. Use this skill every morning, or whenever the user asks to review, triage, categorize, or prioritize their Things tasks. Also trigger when the user says things like 'what should I work on today', 'organize my todos', 'morning routine', or 'daily review'.
testing
Use when completing tasks, implementing major features, or before merging to verify work meets requirements