InboxSweeper
Clean years of junk out of your inbox — for free, without handing your email to anyone.
InboxSweeper deletes old promotions and newsletters in bulk and unsubscribes you from the noise. Built for Gmail today, with experimental support for Yahoo and other IMAP inboxes (see the note below). It runs entirely on your own computer; your email is never uploaded anywhere. Deleted mail goes to Trash, so you can always get it back.
- 🆓 Free and open source — no account, no subscription, no catch.
- 🔒 Private — everything happens on your machine; nothing is sent to a company.
- 🧹 Cleans by who sent it — clears the junk without touching your receipts, orders, or bookings.
- ✉️ Actually unsubscribes — it uses the real one-click unsubscribe, not just delete-and-hope.
- ♻️ Safe — deletions go to Trash (recoverable), and bank, security, and government email is protected automatically.
- 🖱️ Four ways to use it — a double-click web app, a one-file Windows
.exe, your AI assistant (Claude / Codex), or the terminal.
⬇️ Get it: Download the app (ZIP) then double-click the launcher inside · or the one-file Windows .exe — or scroll to the Claude & Codex / terminal options.
How this is different from other "inbox" cleaners
There are a lot of inbox tools — browser extensions, Gmail-only add-ons, cloud services. Most ask you to "Sign in with Google" and hand a company ongoing access to your mailbox. InboxSweeper is built the opposite way:
- No OAuth / no "Sign in with Google". You paste a scoped app password once (stored in your OS keychain), never grant a third party access to your account. Revoke it anytime and the tool stops instantly.
- Not a browser extension. Nothing installs into your browser; it's open-source code you run yourself and can read line by line. No extension that can change hands or silently update what it does.
- Nothing is uploaded — not even a token. Your mail, credentials and tokens never leave your machine. No cloud copy of your inbox, no server holding your access. (The only thing sent is an anonymous, opt-out sweep counter — counts + version, never addresses or content.)
- Works beyond Gmail. Gmail fully supported, plus experimental Yahoo and any IMAP inbox — not locked to one provider.
- Focused, not bloated. Clean by sender, real one-click unsubscribe, deliberate report-spam — and nothing gimmicky bolted on.
- Free and open source, no strings. MIT, no signup, no OTP, no phone number, no subscription.
⚠️ Read the built-in safety rules before you run a sweep. The one rule that matters most: recognize a sender → unsubscribe; don't recognize it → report spam, never unsubscribe. Clicking unsubscribe on real spam confirms your address is live and gets you more spam.
⚡ Three cleaning modes — you pick the aggression
The heart of InboxSweeper: one dial from cautious to ruthless. The wizard asks which mode you want before it touches anything. Banks, security, payments, receipts and government mail stay protected in every mode — the dial only changes how far back it reaches and how many senders it clears per run.
| Mode | 🦥 Sloth | 🧹 Normal | 🔥 MadMax |
|---|---|---|---|
| safest | recommended | aggressive | |
| Reaches | mail older than 2 years | mail older than 1 year | all promo mail, incl. recent |
| Senders / run | 25 | 50 | 100 |
python3 inboxsweeper.py wizard # asks you to pick a mode
python3 inboxsweeper.py sweep --mode madmax # or set it directly on any command
Every sweep goes to Trash (recoverable ~30 days) and previews the count before anything moves. Hit the per-run cap? It tells you exactly how many senders remain — just run it again to clear the next batch.
🎯 Three actions — and when to use each
The mode above decides how far back to reach. Once you've scanned, you choose what to do with a sender. There are three, and picking the right one matters:
| Action | Use it when… | What it does |
|---|---|---|
| ✉️ Unsubscribe | you recognize the sender | Real one-click / mailto unsubscribe — stops it at the source |
| 🗑️ Move to Trash | you're just done with it | Clears the backlog to Trash (recoverable ~30 days) |
| 🚩 Report spam | you don't recognize it | Trains your provider's filter so future mail auto-junks |
The one rule that matters most: recognize a sender → unsubscribe; don't recognize it → report spam, never unsubscribe. Clicking unsubscribe on real spam confirms your address is live and gets you more spam. That's why Report spam is a separate, deliberate action — in the app it's its own tab that starts with nothing selected, and in the terminal it's the
spamcommand (or option 2 in the wizard). It never runs in bulk by accident, and it can never touch a financial/security/government sender.
Four ways to use it
Pick the one that fits you:
| You are… | Path | In short |
|---|---|---|
| Anyone — no tech needed (recommended) | 🖱️ Web app | Download the ZIP, double-click the launcher. Opens in your browser. → Web app |
| On Windows, want zero setup | 📦 One-file .exe | Download InboxSweeper.exe, double-click. → Windows .exe |
| A Claude Code / Codex user | 🤖 Claude skill | Install the skill and just ask. → AI agent |
| A coder | ⌨️ Terminal | Clone, install one dep, run one command. → Terminal |
🖱️ The web app (for everyone)
Works on Mac, Windows, and Linux, always runs the latest version — nothing to compile.
- Download the app: on the GitHub page, click the green Code button → Download ZIP (or use this direct link).
- Unzip it — double-click on Mac; right-click → Extract All on Windows.
- Open the unzipped folder and double-click the launcher for your computer:
- 🍎 macOS →
InboxSweeper.command(first time only, macOS will block it once — here's the one-time unlock.) - 🪟 Windows →
InboxSweeper.bat - 🐧 Linux →
InboxSweeper.command(or runpython3 inboxsweeper.py serve)
- 🍎 macOS →
- A small window opens and InboxSweeper appears in your web browser. Keep that window open while you use it.
It installs its one dependency automatically. Don't have Python? The launcher opens the download page and walks you through the free, one-time install — then just double-click again. From there it's all clicking: paste an app password once (it shows you exactly how to get one), Scan, tick the junk senders, and hit Move to Trash or Unsubscribe. Nothing is uploaded; deletions go to Trash.
📦 Windows .exe (nothing else to install)
Prefer a true one-file download with no Python step at all? On Windows:
- Download InboxSweeper.exe. Chrome/Edge may block the download itself ("isn't commonly downloaded") → open the Downloads bar, click the ⋮ next to the file → Keep → Keep anyway.
- Double-click it. Windows SmartScreen may warn (free/unsigned) → click More info → Run anyway.
- It opens in your web browser — pick Gmail or Yahoo and follow the on-screen steps.
Want proof it's really from this repo? Every release is built by a public GitHub Actions workflow that records signed build provenance. With the GitHub CLI:
gh attestation verify InboxSweeper.exe --repo elixir-bash/inboxsweeper
That confirms the exact file you downloaded was built from this source, by that workflow — which is most of what a code-signing certificate would tell you, without the $99/year.
🚧 First run: what your computer will say
InboxSweeper isn't code-signed — a certificate costs $99/year and this is free — so your browser and OS treat it as an unknown app. Nothing is wrong. Each wall and the one button past it:
| What you see | Where | What to click |
|---|---|---|
| "isn't commonly downloaded" / "can't be downloaded securely" | Chrome/Edge, during download | Downloads bar → ⋮ → Keep → Keep anyway |
| "Windows protected your PC" | Windows, first launch | More info → Run anyway |
| "Apple could not verify…" / "unidentified developer" | Mac, first launch | Click Done, then System Settings → Privacy & Security → Open Anyway |
Mac note — this changed in macOS 15. The old advice you'll find everywhere (right-click → Open) was removed by Apple in Sequoia. On macOS 15 and newer, including macOS 26, do this instead:
- Double-click
InboxSweeper.command. macOS blocks it and offers Move to Trash or Done — click Done. (Don't pick Move to Trash; that deletes the launcher.) - Open System Settings → Privacy & Security, scroll down to Security. You'll see "InboxSweeper.command was blocked to protect your Mac" → click Open Anyway and authenticate.
- Double-click the launcher again → Open. That's it, once ever.
On macOS 14 Sonoma and older, the old route still works: right-click (or Control-click)
InboxSweeper.command → Open → Open.
Fastest route if you're comfortable in Terminal (any macOS version) — this removes the "downloaded from the internet" flag, so the launcher just opens:
xattr -d com.apple.quarantine ~/Downloads/inboxsweeper-main/InboxSweeper.command
Hit something not listed here? Open an issue with your OS, browser and the exact wording — that's the fastest way to get it fixed.
AI coding agents (Claude Code, Codex, Jules, Cursor…)
This repo ships ready-made instructions so an AI coding agent can drive the tool for you. See
integrations/ for the full map — in short:
- Claude Code — install as a skill (bundles the script so it's self-contained):
mkdir -p ~/.claude/skills/inboxsweeper cp integrations/claude-code/SKILL.md inboxsweeper.py ~/.claude/skills/inboxsweeper/
Then just ask Claude: "declutter my gmail" / "unsubscribe from these senders" / "report these as spam". - Codex, Jules, Cursor, Gemini CLI & other agents — they all read
AGENTS.mdautomatically. Dropinboxsweeper.py+AGENTS.mdin your project (or run the agent from this repo) and just ask. It documents the commands, the safety rules, and the recommended flow.
The terminal (for coders)
If you just want a clean inbox and don't care how it works:
git clone https://github.com/elixir-bash/inboxsweeper && cd inboxsweeper
pip install -r requirements.txt
python3 inboxsweeper.py wizard # Gmail
python3 inboxsweeper.py wizard --provider yahoo # Yahoo
The wizard walks you through everything, in plain language:
- First it asks what you want to do: Clean up (unsubscribe + move to Trash) or Report spam.
- If it's your first run, it prints the exact steps to create an app password and asks you to paste it once (hidden). It's stored securely (macOS Keychain, or a locked file).
- It scans your mailbox and shows your noisiest bulk senders.
- Clean up asks — in y/N prompts — whether to unsubscribe (first) then move that mail to Trash. Report spam starts with nothing selected and asks which senders to flag. Nothing happens without your yes, and it always previews counts before moving anything.
That's the whole journey. Everything below is for people who want the individual commands.
1. Prerequisites
- Python 3.9+
pip install -r requirements.txt(onlyrequests, and only forunsub-run)- A Gmail or Yahoo account with 2-Step Verification ON (required for app passwords)
⚠️ Yahoo / other IMAP is experimental. It works, but with a big caveat: Yahoo's IMAP only exposes your ~10,000 most-recent messages per folder — older mail simply isn't reachable, and Yahoo's server-side search is limited. For a large Yahoo backlog, use Yahoo's own web unsubscribe (Yahoo Mail → Settings → More Settings → Subscriptions), which isn't capped. Gmail has no such limits — that's the primary, fully-supported target.
Setup (if you still want it): create an app password at login.yahoo.com/account/security → Create app password under "External connections", confirm IMAP is on (Settings → More Settings → Mailboxes), then add
--provider yahooto any command.
2. Create a Gmail app password (step by step)
You never give this tool your real Google password. You create a scoped app password.
(Or skip this section entirely and let python3 inboxsweeper.py setup walk you through it.)
- Turn on 2-Step Verification: myaccount.google.com/security → 2-Step Verification → follow the steps. (App passwords don't exist without it.)
- Go to myaccount.google.com/apppasswords.
- App name:
inboxsweeper→ Create. - Google shows a 16-character password like
abcd efgh ijkl mnop. Copy it. (You can always revoke it later from that same page — the tool stops working instantly.) - IMAP is already enabled on modern Gmail (no toggle). If you have an old account: Gmail → ⚙️ See all settings → Forwarding and POP/IMAP → Enable IMAP → Save.
3. Store the credentials
Option A — macOS Keychain (recommended on Mac). The value is prompted and never echoed:
security add-generic-password -U -s gmail_cleanup -a you@gmail.com -w # paste app pw, hidden
security add-generic-password -U -s gmail_cleanup_addr -a account -w you@gmail.com
Option B — environment variables (any OS). Put spaces-removed password here:
export GMAIL_ADDR="you@gmail.com"
export GMAIL_APP_PASSWORD="abcdefghijklmnop"
The tool checks env vars first, then Keychain.
4. Use it
# 1. See where the noise is
python3 inboxsweeper.py counts
# 2. Rank the noisiest bulk senders (default query = the safe bulk set)
python3 inboxsweeper.py profile --top 40
# 3. Preview a deletion (DRY RUN — nothing moves)
python3 inboxsweeper.py sweep --senders linkedin.com
# 4. Actually move them to Trash (30-day recovery)
python3 inboxsweeper.py sweep --senders linkedin.com --yes
# 5. See each sender's unsubscribe method, then unsubscribe from specific ones
python3 inboxsweeper.py unsub-list --top 40
python3 inboxsweeper.py unsub-run --domains "email-marriott.com,mail.zillow.com,uber.com"
Commands
| Command | Purpose |
|---|---|
wizard |
Start here. Guided: first pick Clean up (unsubscribe + Trash) or Report spam |
setup |
Store credentials for a provider (prints the app-password steps) |
counts |
Landscape of your mailbox (sizes by category / bulk) |
profile --top N |
Tally the noisiest bulk senders |
unsub-list --top N |
Senders + unsubscribe method (1click/mailto/weblink/none) |
sweep [--senders a.com,b.com] [--days 365] [--yes] |
Move a sender's old mail to Trash. Dry-run unless --yes. |
unsub-run --domains a.com,b.com |
Execute unsubscribe (one-click POST or mailto/SMTP) |
spam --senders a.com,b.com [--yes] |
Report specific senders as spam (trains your filter). Deliberate & opt-in — never bulk. Dry-run unless --yes. |
Add --provider gmail (default) or --provider yahoo to any command. sweep targets by
sender (the safe way — see the built-in safety rules); omit --senders to target every
non-protected bulk sender. Protected senders (financial/security/gov/transactional) are always
skipped.
5. Recommended flow
counts→ find the mass (often it'scategory:updates, which hides receipts).profile→ rank bulk senders.- Classify each into PROTECT / DELETE / KEEP-BY-DEFAULT using the built-in safety rules.
sweep(dry-run →--yes) the DELETE set. Verify a sample in Gmail → Bin.unsub-list→unsub-runthe recognized DELETE senders.- Unrecognized/spammy senders: report spam in Gmail — don't unsubscribe.
- Add Gmail filters for the worst repeat offenders so the backlog can't rebuild.
The story behind it
I have a habit of pointing a bit of code at the everyday annoyances in my life. For the better part of 15 years, my inbox was the one that never stayed solved. It started the way these things always do: a small IMAP script to nuke the obvious promotions. Then another for newsletters. Then a cron job, once a month, to hold the pile back while I wasn't looking.
The trouble is email never sits still. Every so often something underneath would shift — Google
killed off "less secure app" access and I had to move everything onto 2-factor and app passwords;
the special folders never behaved the same across providers ([Gmail]/Trash here, "Bin" there);
IMAP search would quietly change what it returned; Yahoo would only hand back your ten thousand
most-recent messages; a provider would tighten rate limits or rotate a port. The cron would break,
usually silently, and I'd only notice weeks later when the clutter had crept back in. So I patched.
Year after year, one more fix stacked on the last.
But the part I could never fully automate away was the careful bit — the plumbing and cleaning. Bulk-deleting email is easy; bulk-deleting only the junk and never once touching what matters is hard. A bank statement, a flight confirmation, a receipt I'd need at tax time — those can't land in Trash by accident. So most of my years of tinkering weren't about deleting faster; they were about drawing the line ever more carefully: expanding the list of protected senders, teaching it to recognize a financial or government domain, making sure even the most aggressive sweep still stepped around anything critical.
This year, working with AI, I finally stopped patching the symptoms and fixed the core. The fragile scripts became a real app — the cleaning modes, the safe-by-default sweeps that always go to Trash, the automatic shield around bank, security and government mail, real one-click unsubscribe, a browser UI. The whole construct I'd carried in my head for a decade, done properly. And then the step I'd never gotten around to alone: making it open source, so anyone can clean their inbox the same careful way — for free, and without ever handing their mail to a company.
That's what InboxSweeper is: years of doing this the hard way, finally turned into something anyone can use.
How it works
- Connects over IMAP and searches with Gmail's
X-GM-RAWextension, so any Gmail search query works server-side. - "Delete" = IMAP
MOVEto the Trash/Bin folder (auto-detected via the\Trashspecial-use flag), which is Gmail's 30-day-recoverable trash — not a permanent delete. - Unsubscribe reads the message's
List-Unsubscribe/List-Unsubscribe-Postheaders:- one-click → HTTP
POSTwith bodyList-Unsubscribe=One-Click(RFC 8058). - mailto → sends an unsubscribe email via SMTP using your app password.
- weblink-only → reported for manual handling (never auto-clicked; could be a tracker).
- one-click → HTTP
FAQ
Will I still get receipts/order confirmations after unsubscribing? Yes. Unsubscribing only cancels a marketing list; transactional mail is a separate, CAN-SPAM-exempt stream.
Is it safe? Deletions go to Bin (recoverable). Unsubscribes use one-click/mailto only. The tool never permanently deletes and never clicks arbitrary web links.
Does it work with non-Gmail IMAP? It's built for Gmail (uses X-GM-RAW and Gmail
categories). Other providers need query changes.
Is this the Chrome extension / Gmail add-on that asks to sign in with Google? No — different project. This one has no OAuth and no browser extension. You use an app password over IMAP, entirely on your own machine, and it's open source so you can read exactly what it does before you run it.
Do I have to grant Google account access? No. You paste a scoped app password once; you never click through a "Sign in with Google" consent screen handing anyone access to your account.
Anonymous usage stats
To show how many people we've helped — and to catch problems — the tool sends anonymous
counters: a random install ID, your OS, the tool version, and totals (emails cleaned, MB
freed, unsubscribes). It never sends your email address, senders, subjects, or any message
content — your mail still never leaves your machine. Turn it off completely with
INBOXSWEEPER_NO_TELEMETRY=1. The live totals appear on the website.
Security
- Uses an app password, never your Google password. Revoke it anytime at apppasswords and the tool dies instantly.
- Nothing is hardcoded; credentials come from Keychain or env vars.
.gitignorekeeps local credential files out of the repo.
License
MIT — see LICENSE. Personal tool; use at your own risk. Always dry-run first.
Author
Built by Mukundan Govindaraj — LinkedIn · GitHub. If InboxSweeper helps you, a ⭐ on the repo or a hello on LinkedIn is genuinely appreciated.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file inboxsweeper-0.1.3.tar.gz.
File metadata
- Download URL: inboxsweeper-0.1.3.tar.gz
- Upload date:
- Size: 30.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29633672df02559402c7ada4eb2e67dfd7eeda348db1a9f17405ec4bf69ecee0
|
|
| MD5 |
513d68c0711a99e1a2c9428e4b76c577
|
|
| BLAKE2b-256 |
b4b44091a1387e803e4b90fed79cc1d6eb0e9d46cab03096e273e3a74f99581f
|
Provenance
The following attestation bundles were made for inboxsweeper-0.1.3.tar.gz:
Publisher:
publish.yml on elixir-bash/inboxsweeper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inboxsweeper-0.1.3.tar.gz -
Subject digest:
29633672df02559402c7ada4eb2e67dfd7eeda348db1a9f17405ec4bf69ecee0 - Sigstore transparency entry: 2439886321
- Sigstore integration time:
-
Permalink:
elixir-bash/inboxsweeper@5b771134a2715759d080c9016b3d0172d3c30f4c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/elixir-bash
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5b771134a2715759d080c9016b3d0172d3c30f4c -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file inboxsweeper-0.1.3-py3-none-any.whl.
File metadata
- Download URL: inboxsweeper-0.1.3-py3-none-any.whl
- Upload date:
- Size: 30.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e34b3c8a565e50acdb75d128165f90208b5b6edac946c57e5f18e8d64a5f0fb
|
|
| MD5 |
cf9969bda370bda09fa9d7d3bafd04cb
|
|
| BLAKE2b-256 |
f424923777d06718c1cfbd1a89beef2f91af47ba6a9fa2e3628730e53e7b5905
|
Provenance
The following attestation bundles were made for inboxsweeper-0.1.3-py3-none-any.whl:
Publisher:
publish.yml on elixir-bash/inboxsweeper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inboxsweeper-0.1.3-py3-none-any.whl -
Subject digest:
7e34b3c8a565e50acdb75d128165f90208b5b6edac946c57e5f18e8d64a5f0fb - Sigstore transparency entry: 2439886365
- Sigstore integration time:
-
Permalink:
elixir-bash/inboxsweeper@5b771134a2715759d080c9016b3d0172d3c30f4c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/elixir-bash
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5b771134a2715759d080c9016b3d0172d3c30f4c -
Trigger Event:
workflow_dispatch
-
Statement type: