Automatically organize your Gmail inbox by filing messages from specific senders (or entire domains) into labeled folders. Perfect for managing newsletters, notifications, marketing emails, and bulk email organization. Rules are stored in a JSON config file and can be discovered automatically from your existing label structure or added manually via a Gmail side-panel UI.
Gmail's native filters are powerful but clunky — they require manual rule-by-rule configuration and lack automation for common patterns. Inbox Cleaner provides a simpler, faster alternative:
| Feature | Gmail Filters | Inbox Cleaner |
|---|---|---|
| Auto-discover rules from existing labels | ❌ | ✅ |
| Visual rule editor & management | ❌ | ✅ |
| Bulk cleanup in one click | ❌ | ✅ |
| Test changes before applying (dry run) | ❌ | ✅ |
| Track filing stats over time | ❌ | ✅ |
Built on Google Apps Script, this add-on integrates seamlessly with Gmail without plugins or third-party services.
- 🔍 Auto-Discovery – Email automation that scans your existing labels and learns sender → label mappings automatically
- 🧹 Bulk Cleanup – Perform bulk email organization by sweeping your inbox and filing all matching threads in one pass
- 🌐 Domain Wildcards – Use
@company.compatterns for rule-based filing that matches everyone from a domain - 📋 Rule Editor – View, search, edit, and delete rules from the UI with pagination
- 🔄 Smart Consolidation – Automatically detects and merges similar rules to keep config lean
- ⚡ Quick File – One-click rule creation from the currently viewed email
- 🔍 Dry Run – Preview what cleanup would do before moving any threads
- 🚫 Exclusion List – Whitelist senders/domains to never auto-file, even if rules match
- 🔑 Keyword Rules – Match on subject-line keywords in addition to sender rules
- 📊 Filing Stats – Track how many threads each rule has filed over its lifetime
- ⏰ Trigger Management – Enable/disable hourly inbox automation and daily discovery from the UI
- 📦 Import/Export – Backup and restore your email organization rules as timestamped Drive files
- 🎨 Label Color Themes – Apply consistent colors to label hierarchies for better email management
- ♻️ Label Migration – Rename/reorganize labels and automatically update your email filtering rules
- ⚡ Optimized – Batch API calls and timeout protection prevent script failures
For newsletter junkies:
- Automatically file newsletters from Substack, Medium, Patreon, and Medium into a
Newsletterslabel - Use keyword rules to catch digest emails that don't always come from the same sender
For notification management:
- Route GitHub notifications, CI/CD alerts, and monitoring emails into separate labels
- Enable automated hourly cleanup to keep your inbox free of operational clutter
For teams managing multiple email accounts:
- Set up rules that match entire domains (
@company.com,@partner.org) - Use bulk cleanup for periodic inbox maintenance across different label hierarchies
For label power users:
- Migrate and reorganize your label structure without losing email organization rules
- Use the dry run feature to preview changes before committing to bulk operations
- A Google account with Gmail
- Google Apps Script CLI (clasp) installed (optional, for local development)
- Go to script.google.com
- Create a new project
- Copy the contents of
Code.jsandappsscript.jsoninto your project - Enable the Gmail API advanced service:
- Click ⚙️ Project Settings → Services
- Add Gmail API v1
# Clone this repo
git clone https://github.com/zmongeau/Inbox-Cleaner.git
cd Inbox-Cleaner
# Log in to Google
clasp login
# Create a new Apps Script project
clasp create --title "Inbox Cleaner" --type standalone
# Push the code
clasp push- In the Apps Script editor, click Deploy → Test deployments
- Select Install to enable the add-on in your Gmail
- Open Gmail and look for the Inbox Cleaner icon in the right sidebar
Built with Google Apps Script and the Gmail API, Inbox Cleaner automates email filtering through three core phases:
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Discovery │ ----> │ Config File │ ----> │ Cleanup │
│ │ │ (JSON rules) │ │ │
└─────────────┘ └──────────────┘ └─────────────┘-
Discovery Phase (
discoverRules())- Scans up to 30 recent threads per label
- Extracts sender email from the first message
- Builds a JSON map:
{ "sender@domain.com": "LabelName" }
-
Cleanup Phase (
runGlobalCleanup())- Fetches all inbox threads
- Checks each sender against rules (exact match → domain wildcard → keyword)
- Respects exclusion list — excluded senders are never filed
- Applies label + archives matching threads
- Tracks filing stats per rule
-
Manual Additions (
addNewRule())- Add one-off rules from the UI
- Immediately files existing inbox threads for that sender
When multiple rules could match a thread, the following priority applies:
- Exclusions — If sender/domain is excluded, skip entirely
- Exact email —
john@acme.commatches first - Domain wildcard —
@acme.commatches any sender from that domain - Keyword rules — Subject-line keyword matches (lowest priority)
Open Gmail → Click the Inbox Cleaner icon in the right sidebar.
When viewing an email, the add-on shows the sender's email and whether a rule already exists:
- File Sender — Create a rule for the exact sender email
- File @domain — Create a rule for the entire domain
- Both buttons use the target label you enter
- Sender Email: Enter
john@acme.comor@acme.comfor a domain wildcard - Target Label: Enter
Work/Invoices(use/for sub-labels) - Click Add & Clean Now to save the rule and file existing threads
- View Rule Stats – See count of exact email rules, domain rules, keyword rules, and exclusions
- View/Edit/Delete Rules – Browse all rules with search, pagination, and filing stats:
- 📧 = exact sender email
- 🌐 = domain wildcard rule
- Filing count shown next to each rule
- Edit button to change the target label
- Delete button to remove rules
- Search – Filter rules by sender email or label name
- Consolidate Similar Rules – Merge redundant or similar rules automatically
- Small Labels (< 200 threads): Use Auto Move to rename and update config
- Large Labels:
- Manually rename the label in Gmail sidebar
- Use Sync Rules Only to update the JSON config
- Sync Rules from Labels – Runs discovery across all your labels
- Run Full Inbox Sweep – Processes your entire inbox
- Refresh Label Colors – Applies color themes to top-level labels
- 🔍 Dry Run Preview – See what cleanup would do without moving anything, then optionally proceed
- 🚫 Manage Exclusions – Add/remove senders and domains that should never be auto-filed
- 🔑 Keyword Rules – Add/remove subject-line keyword matching rules
- ⏰ Trigger Settings – Enable/disable hourly cleanup and daily discovery automation
- 📦 Import / Export – Backup rules to Drive, import from backup files, view/reset filing stats
Before running a full sweep, preview what would happen:
- Click 🔍 Dry Run Preview in the Advanced section
- See a summary grouped by target label (thread count + sender count)
- Click ▶ Run Full Sweep Now to proceed, or go back to cancel
Prevent specific senders or domains from ever being auto-filed:
- Click 🚫 Manage Exclusions
- Enter an email (
boss@company.com) or domain (@company.com) - Click Add Exclusion
Excluded senders are skipped during:
- Full inbox sweeps (
runGlobalCleanup) - Immediate filing when adding new rules (
addNewRule)
Rules for excluded senders are preserved — remove the exclusion to resume filing.
Match emails by subject line instead of sender:
- Click 🔑 Keyword Rules
- Enter a keyword (case-insensitive substring match)
- Enter a target label
- Click Add Keyword Rule
Priority: Keyword rules have the lowest priority. Sender and domain rules are always checked first. An email is only matched by keyword if no sender/domain rule applies.
Example:
- Keyword:
invoice→ Label:Finance/Invoices - Any email with "invoice" in the subject gets filed (unless a sender rule matches first)
Automate cleanup and discovery without leaving Gmail:
- Click ⏰ Trigger Settings
- Inbox Cleanup — Toggle hourly automatic sweeps
- Rule Discovery — Toggle daily automatic label scanning
Status shows whether each trigger is active or inactive. Triggers run in the background using Apps Script's time-based trigger system.
Back up your rules and restore them:
- Click 📦 Import / Export
- Click 📤 Export to Drive
- A timestamped JSON backup file is created in your script's Drive folder
- Enter the backup filename (e.g.,
mail-rules-backup-2026-02-28_1430.json) - Merge Import — Adds new rules, updates existing ones (doesn't delete anything)
- Replace All — Overwrites all rules with the imported file
- View lifetime filing counts across all rules
- Reset Filing Stats to clear counters
Click View/Edit/Delete Rules to access the rule editor:
- Displays rules in pages of 10 (with Previous/Next navigation)
- Shows sender → label mappings with filing counts
- Icons: 📧 for exact emails, 🌐 for domain rules
- Search box to filter by sender email or label name
- Click Edit next to any rule
- Update the target label name
- Click Save Changes to apply
- The rule updates immediately and files matching inbox threads
- Click Delete next to any rule
- Rule is removed from config and logs
- Future emails from that sender will no longer be filed
Clean up your rules by merging similar patterns. Click 🔄 Consolidate Similar Rules to:
Type 1: Redundant Rules 🗑️
- Exact emails already covered by domain rules
- Example:
alice@company.comis removed if@company.com→ same label exists
Type 2: Domain Merging 🔀
- Multiple subdomains that can merge to parent
- Example:
@sub1.company.com,@sub2.company.com→@company.com - Also: 3+ exact emails from same domain → single domain rule
- Example:
alice@co.com,bob@co.com,charlie@co.com→@co.com
- Click 🔄 Consolidate Similar Rules
- Review the consolidation opportunities shown
- Click ✓ Apply All Consolidations to merge rules
- Config is updated and logs show each change
Before:
{
"alice@one.gmail.com": "Personal",
"bob@two.gmail.com": "Personal",
"charlie@three.gmail.com": "Personal",
"@one.gmail.com": "Personal",
"@two.gmail.com": "Personal"
}After Consolidation:
{
"@gmail.com": "Personal"
}Changes Made:
- 🗑️ Removed exact emails (redundant)
- 🔀 Merged subdomains to parent domain
- Result: 5 rules → 1 rule
Run functions directly from the Apps Script editor for advanced workflows:
// Discover rules from existing labels
discoverRules();
// Clean the inbox based on current rules
runGlobalCleanup();
// Dry-run preview (returns array of matches without filing)
const preview = runGlobalCleanup(true);
// Add a single rule manually
addNewRule('newsletter@example.com', 'Newsletters');
// Add a domain wildcard rule
addNewRule('@github.com', 'Dev/GitHub');
// Get all rules (optionally filtered)
const allRules = getRules(); // all rules
const filtered = getRules('github'); // search for 'github'
// Get rule statistics
const stats = getRuleStats();
// { totalRules: 47, exactRules: 32, domainRules: 15, exclusionCount: 3, keywordCount: 5 }
// Find and apply consolidation opportunities
const opportunities = findConsolidationOpportunities_();
consolidateRules(opportunities);
// Manage exclusions
addExclusion('boss@company.com'); // never file this sender
addExclusion('@personal.com'); // never file this domain
removeExclusion('boss@company.com');
const excluded = getExclusions();
// Manage keyword rules
addKeywordRule('invoice', 'Finance/Invoices');
addKeywordRule('shipping confirmation', 'Orders');
deleteKeywordRule('invoice');
const keywords = getKeywordRules();
// Filing stats
const filingStats = getFilingStats(); // { "user@co.com": 42, "@domain.com": 128 }
resetFilingStats();
// Import/export
const backupFile = exportRulesToDrive();
importRulesFromFile('backup.json', false); // merge
importRulesFromFile('backup.json', true); // replace all
// Trigger management
enableCleanupTrigger(); // hourly cleanup
disableCleanupTrigger();
enableDiscoveryTrigger(); // daily discovery
disableDiscoveryTrigger();
// Migrate a label (small)
migrateLabel('Old Label', 'Work/New Label');
// Update rules after manual rename (large labels)
syncJsonAfterManualRename('Old Label', 'Work/New Label');
// Apply color themes
autoColorLabels();
// Delete a specific rule
deleteRule('old@email.com');const CONFIG_FILENAME = 'mail-rules.json'; // Rules file name
const THREAD_LIMIT_PER_LABEL = 30; // Threads inspected per label
const MAX_DISCOVERY_TIME_MS = 5 * 60 * 1000; // 5-minute timeout
const AUTO_CONSOLIDATE = false; // Auto-consolidate after adding rulesNote on AUTO_CONSOLIDATE:
- Set to
trueto automatically consolidate rules after eachaddNewRule()call - Set to
false(default) to review consolidation opportunities before applying them - Recommended: Keep disabled and use the Consolidate Similar Rules button to review changes first
Stored in the same Drive folder as your Apps Script project:
{
"alice@example.com": "Work/Clients",
"bob@company.org": "Projects/Alpha",
"@newsletter.com": "Subscriptions",
"@github.com": "Dev/GitHub"
}- Exact matches take priority over domain wildcards
- Domain wildcards start with
@
Exclusions, keyword rules, and filing stats are stored in UserProperties (via PropertiesService), keeping the main config file clean and backward-compatible:
| Property Key | Format | Description |
|---|---|---|
exclusions |
JSON array | ["boss@co.com", "@personal.com"] |
keyword_rules |
JSON object | {"invoice": "Finance", "shipping": "Orders"} |
filing_stats |
JSON object | {"@github.com": 142, "keyword:invoice": 28} |
Edit the THEMES object in autoColorLabels() to customize:
const THEMES = {
'@Shopping': { bg: '#fb4c2f', txt: '#ffffff' }, // Red
'@Work': { bg: '#4a86e8', txt: '#ffffff' }, // Blue
// ... add your own parent labels here
};- In Apps Script editor: Triggers (clock icon)
- Add trigger:
- Function:
runGlobalCleanup - Event:
Time-driven→Hour timer→Every hour
- Function:
- Repeat for
discoverRules(run daily or weekly)
Manage triggers directly from the Gmail side panel:
- Click ⏰ Trigger Settings in the Advanced section
- Toggle Hourly Cleanup — runs
runGlobalCleanupevery hour - Toggle Daily Discovery — runs
discoverRulesevery 24 hours
Status indicators show whether each trigger is active or inactive.
The add-on requests these OAuth scopes:
| Scope | Purpose |
|---|---|
gmail.addons.execute |
Run as a Gmail Add-on |
gmail.readonly |
Read message metadata |
gmail.modify |
Apply labels and archive |
gmail.addons.current.message.metadata |
Access current message sender for Quick File |
drive |
Access the config file and import/export backups |
script.container.ui |
Display the side panel |
script.locale |
Detect user locale for formatting |
- Use only the hex codes from the official Gmail palette (see
THEMESinautoColorLabels())
- Reduce
THREAD_LIMIT_PER_LABELto15or lower - The script saves progress when hitting
MAX_DISCOVERY_TIME_MS
- Check the config file exists in Drive (same folder as the script)
- Run
loadConfig_()and check logs for JSON parse errors - Verify sender email format (check logs after
extractEmail_()) - Check if the sender is in the exclusion list (
getExclusions())
- Quick File only appears when viewing an individual email
- Check that
appsscript.jsonhas bothhomepageTriggerandcontextualTriggers
- Go to Deploy → Test deployments → Install
- Check that
appsscript.jsonhas theaddOnssection correctly configured
- Keywords match as case-insensitive substrings on the subject line only
- Sender and domain rules always take priority over keyword rules
- Check that the sender isn't in the exclusion list
Contributions welcome! Areas for improvement:
- Batch processing for extremely large inboxes
- Regex-based sender and keyword matching
- Undo log for recent filing actions
- Gmail filter import (convert native Gmail filters to rules)
- Multi-action rules (mark read, star, forward)
- Integration with Google Workspace admin features
MIT License – See LICENSE file for details.
Community-maintained open-source project.
This project was conceived and directed by a human, with the implementation written entirely using AI assistance (Claude). The codebase reflects iterative refinement through AI-guided development, testing, and documentation.