// Gmail

Auto-archive old emails on a schedule with Apps Script.

Keep your Gmail inbox shallow without losing anything. A daily trigger archives every thread older than 30 days that isn't starred — archived threads stay searchable in All Mail.

I want my inbox to stop growing. Anything older than a month should fall off the front page automatically.

The script

copy · paste · trigger
autoArchiveOld.gs
Apps Script
// Archive Gmail threads older than 30 days that are still in the inbox.
// Daily trigger keeps the inbox shallow; archived threads stay
// searchable in All Mail (nothing is deleted).
function autoArchiveOld() {
  const query = 'older_than:30d in:inbox -is:starred';
  const threads = GmailApp.search(query, 0, 100);
  threads.forEach(t => t.moveToArchive());
}

Need a variant? Gnaw writes a custom version from one sentence — fields, triggers, edge cases handled.

Walkthrough

How it works

GmailApp.search runs the same query you'd type into Gmail's search bar. `older_than:30d in:inbox -is:starred` selects every inbox thread older than 30 days, excluding ones you starred to keep visible.

The result is capped at 100 threads per run. moveToArchive() flips Gmail's "Inbox" label off the thread without deleting anything — searches and labels still find it.

Idempotency comes free: a thread that's already archived no longer matches `in:inbox`, so re-running is harmless.

How to schedule it

Open the Apps Script editor, go to Triggers (clock icon), and add a time-based trigger that fires autoArchiveOld() daily. Pick an off-hours slot — early morning works because the script needs ~30 seconds at most.

If your inbox volume is heavy and 100 threads/run isn't enough, raise the GmailApp.search() page size up to 500, or schedule the trigger hourly instead of daily.

Common pitfalls

Quota: GmailApp.moveToArchive counts against a 250 calls/execution limit. The query cap (100) keeps you under it. Don't remove the cap unless you also batch.

Starred messages: the `-is:starred` guard saves anything you flagged. If you use a different signal (a label like "Pinned"), swap to `-label:Pinned`.

Authorization: first run prompts for Gmail modify scope. Approve once; subsequent triggers run without prompting.

Want a custom version?

Describe your sheet and the rule you want. Gnaw writes the Apps Script — fields, triggers, edge cases — in one shot.

FAQ

4 questions
How do I exclude specific senders?
Add `-from:vip@example.com` to the query. You can chain multiple `-from:` clauses or use a label like `-label:keep` if you want a sticky exclusion list.
Will this delete the emails?
No. Archive only removes the Inbox label. The threads stay in All Mail forever (until you manually delete them).
Can I run different rules for different labels?
Yes. Run a separate function per label with a tailored query, then schedule each on its own trigger. Apps Script supports up to 20 triggers per script.
How do I undo a bad run?
Open Gmail, search `label:archived after:<the date>` (Gmail keeps a `label:archived` synthetic label), select all, and add the Inbox label back. The bulldo.gs generator can scaffold the recovery script too.