This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
On Sunday night I sat with my phone and deleted WhatsApp forwards by hand. Thirty-five minutes later I had thrown away 1,641 pictures, videos and screenshots, 1.89 GB of them. My phone also holds a lot of my mom's and dad's photos, so every swipe was a small bet that I was not binning one of theirs.
Then I plugged the phone into my laptop and let an open model go through the same phone, one picture at a time: the ones I had kept, and the ones I had just thrown away. This post is what it found, and how it compares with my 35 minutes.
The narrator is Amazon Polly (the "Arjun" voice), not me, and the pictures in the video are samples, not my phone's.
What I Built
Good Morning Sweep clears junk off a phone without uploading anything. You plug the phone into a laptop. The laptop copies the WhatsApp pictures, WhatsApp videos, screenshots and camera photos, and then Gemma 4, an open AI model running on the laptop itself, looks at them one by one. When it is done, you get one page that shows what it would delete and why. You tap anything you want to keep, then press "Delete from phone".
I built it for my mom's phone, which is where the Good Morning flood really lands. The first real run was on mine, which holds plenty of her photos and my dad's too. When I showed them what it does, their verdict was: "This is great, it will save so much time."
For each picture, Gemma says what it is (a greeting, a quote, a meme, forwarded news, an ad, a real photo, a document, a screenshot or an accidental shot) and copies out the words printed on it. Then plain rules, written by me, decide what to suggest:
| What the page suggests | How it decides | Ticked to delete? |
|---|---|---|
| WhatsApp forwards | Gemma reads the words; the rules look for greeting and forward words in Hindi, English and seven other Indian scripts | yes |
| Exact copies | same file twice; one copy always stays | yes |
| Blurry or black photos | the code measures blur and brightness, and Gemma must agree it was a mistake with nobody in it | yes |
| Almost the same photo | the sharper one stays | no |
| Old screenshots of one-time codes, payments, deliveries | older than 30 days | no |
| Your call | Gemma thinks it is a forward, but real people may be in it | no |
Photos of people, documents such as bills, prescriptions and IDs, and anything Gemma is unsure about are never suggested. Nothing leaves the laptop. Nothing is deleted until you have scrolled past it on the page, and just before each deletion the phone itself checks that the file is exactly the one backed up on the laptop.
The rule I kept coming back to: it reads before it deletes. Every red tile says why, in words you can check against the picture: Forwarded greeting. It reads: "शुभ प्रभात आपका दिन मंगलमय हो".

From the public demo, with sample cards I made: Gemma reads Hindi word for word.
Demo
Try the review page yourself: good-morning-sweep.vercel.app. It is the real page with sample pictures (stock photos and cards I made), because the real run's pictures stay on my laptop. Tap a picture to keep it. The "Your call" group at the bottom is the trap described below.

The trap: Gemma calls this a greeting, but says real people may be in it, so it is my call, and it is not ticked.
Code
itssaharsh / good-morning-sweep
Frees a parent's phone of WhatsApp Good Morning forwards, copies and mistakes, with Gemma 4 running on the family laptop. It reads before it deletes.
Good Morning Sweep
Frees a parent's phone from WhatsApp "Good Morning" forwards, duplicate copies and accidental shots, using an open model (Gemma 4) that runs on the family laptop. It reads every picture before it suggests deleting one, and nothing is deleted until a person has looked at the pile.
Built for the Hacktoberfest Open-Source AI Challenge, Week 3: Slow and Steady The repository was started on 24 October 2026, inside the challenge window.
What it does
Plug the phone into a laptop over USB. sweep run copies the phone's WhatsApp Images, WhatsApp Video, Screenshots and Camera folders to the laptop (that copy is the backup), then works through them slowly, one picture at a time, with Gemma 4 E2B running locally through llama.cpp. When it is done, sweep review opens a page that groups what it would remove and says why on every picture:
| Group | Who decides | Ticked |
|---|
The rules are in sweep/guard.py, each with a test. The question Gemma is asked is in sweep/model.py. The comparison with my 35 minutes is eval/compare.py, and its results, counts only, are in eval/results.md.
How I Built It
The pieces are small on purpose. Gemma 4 E2B is the smallest Gemma 4 that can see pictures, and it runs on the laptop's processor through llama.cpp, with no graphics card, no cloud and no account. Everything else is Python: adb to talk to the phone, a small database to remember every answer, one web page for the review, and Temporal to keep the overnight run going.
Gemma gets the same instructions for every picture and answers with one line:
{"kind": "greeting", "words": "शुभ प्रभात आपका दिन मंगलमय हो", "people": false, "screen": ""} I give each picture the smallest size Gemma 4 accepts (70 tokens), which is still enough to read a greeting card word for word. That brought one answer from about 14 seconds down to 5.0 seconds on average, over 1,947 real pictures on my laptop's i7.
Slow is the point. A phone with a few thousand WhatsApp pictures is a night's work for a laptop. So every answer is saved the moment it arrives, the biggest files go first (forwarded videos are where the gigabytes are), and identical files are asked about once. The scan runs as a Temporal workflow: if the model crashes, each picture is retried until it gets an answer, and if the laptop sleeps, running the command again carries on from the next picture.

The scan of my phone, 31 minutes in. It finished with 1,137 pictures looked at.
My 35 minutes against Gemma
The gallery app does not really delete anything for 30 days. It hides the file and keeps it. So after my 35 minutes the phone still held every picture I had thrown away, and I could copy those too and ask Gemma about them, without it ever seeing my choices. The model was the same for both sets, and each set was scanned once.
| Pictures | Gemma alone would delete | Gemma + the rules, ticked | Shown on the page at all | |
|---|---|---|---|---|
| What I kept | 1,124 | 207 | 5 | 50 |
| What I had deleted by hand (random sample) | 823 | 94 | 6 | 21 |
The first row matters most. Of the pictures I had decided to keep, Gemma on its own would have deleted 207, including an electricity receipt and an Aadhaar notice. With the rules, five are ticked, and I looked at every one.
Then I labelled a random 100 of those 207 myself, as junk or keep. I called all 100 junk. So on my phone, Gemma alone was right more often than my rules gave it credit for: they ticked 3 of those 100 and showed 17. I am keeping the rules that careful anyway, because the phone this is for is my mom's, and she keeps every receipt.
The second row surprised me. Of the 823 pictures I had deleted by hand, Gemma called 554 "photo", 88 screenshots and 57 documents. Most of my 35 minutes was not forwards at all. It was me deciding about photos, which no tool should decide for me. On my phone the sweep is a second pair of eyes after the clean-up. On my mom's phone, where the forwards are the flood, it is the clean-up.
Things that went wrong
On my own phone, it wanted to delete my electricity recharge receipt. My test pictures were greeting cards and stock photos. My real phone was not. Among the pictures I had kept, the first version ticked 134 for deletion, including an electricity recharge receipt, a food order, an Aadhaar notice, a maths problem I had sent, a Bubble Sort quiz, a letter addressed to me that began "Congratulations! On behalf of the entire team", and birthday posts I had sent. Gemma had read every one of them correctly. It had just called them "ad" or "quote", and my rule trusted "an ad with words on it" to be a forward.
I changed three rules. A forward now needs a forward word (sale, offer, free, good morning, share and so on). Anything that reads like a bill, receipt, order, ID, ticket, bank card, letter or exam question is kept, whatever Gemma called it. Anything in WhatsApp's Sent folder is never ticked, because I chose to send it. Ticked went from 134 to 10, and I looked at all ten: a gambling ad, a meme, two forwarded quotes, a photo of the floor and five black frames from my pocket. These rule changes came after I had seen my kept pictures, so the numbers for that set are after fixes found on it. The pictures I had deleted by hand were scored after that, once.
Gemma started thinking out loud. Once the instructions were long enough to be useful, every answer came back as paragraphs that began "The user wants me to analyze an image…", with no answer in sight. One setting in the request, "enable_thinking": false, turned 14 seconds of rambling into an answer in about 3.
It nearly deleted a family photo because it looked like a greeting card. To save time, I first asked Gemma about one picture from each group of look-alikes and copied the answer to the rest. On my test set, a plain photo got the answer meant for the same photo with "Happy Diwali from the Sharmas" written on it, and landed in the forwards pile. Now an answer is only shared between files that are byte-for-byte identical, and that case is a test.
The review page could delete pictures nobody saw. A second AI agent reviewed the code before it touched a phone. It found that the page showed only the first 600 pictures of a group but would delete every ticked one, and that deletion checked only file sizes. Now a picture counts as seen only once it has loaded on screen, and the phone checks each file's fingerprint (its SHA-1 hash) against the backup before removing it.
Android 14 said "Permission denied" at 3 a.m. The check that the phone can compute those fingerprints read a system file that Android 14 does not allow. It would have refused every deletion. It now hashes a known word instead, and I found out on my own phone, not my mom's.
The faster answer format was the wrong one. A shorter answer format saved about a second per picture. On my test set it also called landscapes "people" and a chat screenshot a "greeting". I went back. Over a night, a second per picture is two hours, but one wrong deletion is a photo you don't get back.
What one run costs. Both sets together were 2.7 hours of laptop time. At a rough 45 W and ₹8 a unit, that is about ₹1 of electricity (an estimate, not a meter reading), and ₹0 in API fees.
Why Does Open Innovation Matter?
Because the pictures are a family's. My WhatsApp folder, and my mom's, holds the last few years: people, prescriptions, a photo of the electricity bill, a cousin's wedding card. I was not going to upload 1,947 of them to someone's server to find out which ones are roses. With an open model, the whole job runs on a laptop I already own.
It is not about the money, and I want to be straight about that. I priced it: sending about 7,000 pictures to a cheap closed vision model costs somewhere between about ₹81 (OpenAI's gpt-6-luna, by my estimate) and ₹345 (Google's gemini-3.5-flash-lite at its default image size) per run. That is less than one month of the ₹130 Google One 100 GB plan. What it really costs is the upload. On the laptop it costs about ₹1 of electricity and a night, nothing leaves the house, and next month it is the same model, because Gemma 4 is a 3 GB file under the Apache 2.0 licence.
And it is fixable. When something went wrong, I could see exactly why, change a few lines and add a test. The model, the rules and the page are all open, so anyone with a phone and a laptop can run it, read why each picture was picked, and change the rules for their own family's groups.
My Agent Session
I built this with Claude Code as my pair, over one long weekend. It wrote most of the code and tests from a plan we agreed on, and a second agent reviewed the delete path before it touched a phone. I chose what the product is for, decided that nothing is deleted without a review, and ran it on my phone overnight.
The Lazy Payoff
- By hand: 35 minutes for 1,641 pictures, videos and screenshots (1.89 GB), about 47 a minute, and I had to look at every one.
- With the sweep: the laptop read 1,947 pictures in 2.7 hours while I slept, 5 seconds each. My part was labelling 100 pictures with two keys and one scroll through the review page. Among the pictures I had kept, it found ten I had missed: a gambling ad, a meme, two forwarded quotes, a photo of the floor and five black pocket shots (24 MB). The three I scrolled past were deleted after the phone confirmed each file matched the laptop's backup.
- What it did not do: decide about photos. That part of my 35 minutes is still mine.
- My parents: "This is great, it will save so much time." Their phones are next.
On my phone, 35 minutes of tapping and second-guessing became a few minutes of looking, while the laptop did the reading overnight. On my mom's phone, where nobody is going to sit through 35 minutes, it is the difference between "phone full" and a phone she can take photos with again.
Prize Categories
- Best Use of Gemma: Gemma 4 E2B reads every WhatsApp picture, video frame and screenshot on the laptop, and its answer (what it is, the words on it, whether real people may be in it) is what every suggestion is built on.
- Best Use of Temporal: the overnight scan of my phone ran as a Temporal workflow, so a crashed model is retried and a closed laptop picks up where it left off.


