This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady.
Somewhere on your laptop there's a folder that looks like this:
Screenshot 2026-10-03 at 13.04.11.png
Screenshot 2026-10-03 at 13.04.11 (2).jpg
Screenshot 2026-10-06 at 22.17.40.png
Screenshot 2026-10-09 at 10.02.55.png
IMG_4821.PNG
...
Every one of those was taken on purpose, to keep something. A receipt for a refund. The error message you meant to paste into an issue. The train ticket. Then they all got the same useless name, and now finding the receipt means opening forty files.
Sorting that folder is the purest kind of chore: low stakes, mildly gross, and always postponed. In honour of International Sloth Day, I built something that does it while I lie down.
What I Built
Screenshot Sloth reads every screenshot in a folder with an open-source vision model, inside your browser tab, and proposes a plan:
-
Rename each file for what's on it:
Screenshot 2026-10-03 at 13.04.11.pngbecomes2026-10-03-receipt-tandoor-express.png, andIMG_4821.PNGbecomes2026-10-11-ticket-shatabdi-express-12002.png. - File them into folders: Receipts, Chats, Errors, Code, Tickets, Maps, Documents, Photos.
-
Flag the ones holding a one-time code, card number, Aadhaar, PAN, UPI ID or password, and put them in one
_Review (sensitive)folder so you can look once and delete. -
Catch duplicates (that
(2).jpgyou saved twice) and set the extras aside.
You see the whole plan before anything moves. Fix any name, untick anything you want left alone, then apply. In Chrome and Edge it moves the files in place and logs every move, so Undo puts every file back where it was. Other browsers get a sorted .zip, and your originals stay put.
It's for anyone with a Desktop full of screenshots, which is everyone. It's especially for people whose screenshots are mostly UPI receipts, OTP messages and WhatsApp chats, which is a lot of us in India.
Demo
Try it: https://tarunvashishth.github.io/screenshot-sloth/
Click Try the demo desktop to run it on 12 synthetic screenshots drawn in the page: a food-delivery receipt, a build error, a chat, an OTP SMS, a train ticket, a test credit card, a map, a saved-twice duplicate and more. All of it is fake data, so you can watch the whole flow without pointing it at your own files.
The first run downloads the model once (about 350 MB, then cached). After that the demo goes like this:
| Before | After |
|---|---|
Screenshot 2026-10-03 at 13.04.11.png |
Receipts/2026-10-03-receipt-tandoor-express.png |
Screenshot 2026-10-06 at 22.17.40.png |
Errors/2026-10-06-error-build-failed.png |
Screenshot_20261008-191502_WhatsApp.jpg |
Chats/2026-10-08-chat-whatsapp-rohan.jpg |
Screenshot 2026-10-09 at 10.02.55.png |
_Review (sensitive)/β¦ flagged One-time code β’β’β’β’β’β’
|
Screenshot 2026-10-12 at 09.12.31.png |
_Review (sensitive)/β¦ flagged Card number β’β’β’β’ 1111
|
Screenshot 2026-10-03 at 13.04.11 (2).jpg |
_Duplicates/2026-10-03-receipt-tandoor-express.jpg |
Code
tarunvashishth
/
screenshot-sloth
Sorts your screenshots folder: an open-source vision model (Florence-2) reads each one in your browser, renames and files it, and flags OTPs and card numbers. Nothing is uploaded.
Screenshot Sloth π¦₯
Your screenshots folder, sorted while you lie down.
Try it: https://tarunvashishth.github.io/screenshot-sloth/ (Chrome or Edge to sort in place; any browser for the demo)
Point it at a folder full of Screenshot 2026-10-03 at 14.22.01.png files. An open-source vision model
reads every one in your browser tab, then proposes a plan:
-
Rename each file for what's on it:
2026-10-03-receipt-tandoor-express.png,2026-10-06-error-build-failed.png - File them into folders: Receipts, Chats, Errors, Code, Tickets, Maps, Documents, Photos
-
Flag the ones holding one-time codes, card numbers, Aadhaar, PAN, UPI IDs or passwords, and put them together
in
_Review (sensitive)so you can look once and delete -
Catch duplicates (the same screenshot saved twice) and set the extras aside in
_Duplicates
You see the whole plan first, can fix any name or untick anything, then apply. Every move is logged to
.screenshot-sloth-undo.json in the folder, and Undo puts every file back.
Nothing isβ¦
TypeScript and Vite, with no backend. The model runs in a Web Worker; rules.ts holds everything that decides names, folders and flags, and it has its own tests.
How I Built It
The model reads; plain code decides
Florence-2-base-ft is Microsoft's MIT-licensed vision model, small enough (0.23B parameters) to run in a browser through Transformers.js on WebGPU, with a WASM fallback. I used it for my Week 1 entry too, and it's very good at one thing I needed here: <OCR_WITH_REGION>, which returns every line of text with its bounding box.
The boxes turned out to be the most useful part. A screen's title is almost always its biggest text, so the name comes from the tallest line that isn't phone chrome: not the clock, not the battery, not a "Start navigation" button. Filenames carry the rest. macOS and Windows names hold the date, and Android ones hold the app (Screenshot_20261008-191502_WhatsApp.jpg).
I deliberately didn't ask the model to "categorise this screenshot". A 0.23B model's free-text guess is unpredictable, while OCR text plus small, testable rules is something I can debug. When a screenshot lands in the wrong folder, I can see why and write a test for it.
Tall screenshots get read in strips
Florence squashes every input to 768Γ768. A 1179Γ2556 phone screenshot squashed that far loses all its small text, so each screenshot is read as up to three square-ish strips from the top down, and the boxes are mapped back to full-image coordinates so the "tallest line" comparison still works across strips.
Sensitive data: a pattern isn't enough, so check the checksum
Screenshots are full of long numbers: order IDs, phone numbers, amounts. Flagging every 16-digit number would cry wolf, so each finding has to pass a real check:
- Cards must pass the Luhn checksum.
- Aadhaar numbers must pass the Verhoeff checksum, which UIDAI uses for the last digit.
- PAN must match its actual structure (the fourth letter is the holder type).
- OTPs only count when a 4β8 digit code sits next to words like "OTP" or "verification code".
Findings are always shown masked (β’β’β’β’ 1111), so the review screen doesn't become a second leak.
My favourite bug: the demo's OTP message wasn't flagged. The model had read "Your OTP for login is 482913." perfectly. My regex refused to match 482913 because a full stop followed it, and I'd written that check to skip decimals like 1299.50. The model was fine; my rule was the bug. That's the argument for keeping the model's job small: the mistakes end up in code you can test.
Duplicates: "looks alike" is useless for screenshots
My first version used a 64-bit perceptual hash (dHash), the textbook way to find near-duplicate images. On the demo it declared 8 of 12 screenshots copies of each other.
The reason is obvious in hindsight. dHash encodes whether each pixel is brighter than its neighbour. A screenshot is mostly a flat white page with a little text, and a sunset photo is a smooth vertical gradient. Both hash to roughly zero. To a perceptual hash, all screenshots look the same.
The fix was to require two signals: a duplicate has to look alike (mean pixel difference on a 32Γ32 thumbnail) and read alike (at least 80% overlap in the OCR'd words). A re-saved JPEG of the receipt passes both. A chat that happens to be equally white doesn't.
Moving files without losing any
The File System Access API lets a web page work inside a folder you pick. Screenshot Sloth uses FileSystemFileHandle.move() where the browser has it, and otherwise copies, checks the size, then removes the original. Every move goes into .screenshot-sloth-undo.json in the folder, which is written even if a run stops halfway. Undo replays it backwards, and only removes folders it created if they're empty. I tested both paths against the browser's origin-private file system (same API, no real files at risk), including name collisions and folders that already existed.
The Lazy Payoff
On the 12-screenshot demo desktop, on my Mac's GPU:
- Machine time: between 1 min 21 s and 2 min 13 s to read all 12 across my runs (after the one-time model download)
- My time: looking over the plan and clicking Apply
- By hand: about 10 seconds a file to open it, read it, think of a name, type it and drag it, so 2 minutes for 12. A folder of a few hundred screenshots is an hour of that, which is exactly why nobody ever does it.
So it isn't faster than you, at about 7β11 seconds per screenshot. But a sloth doesn't need to be fast; it needs to be doing the work so you aren't. You start it, go make tea, and come back to a sorted folder.
Why Does Open Innovation Matter?
Because screenshots are the most private files you own, and the only way to sort them without handing them to someone else is a model you can run yourself.
Think about what's in that folder: OTPs, bank balances, card numbers, Aadhaar scans, boarding passes, private chats. You took them to keep something important, which is exactly why they're sensitive.
Other people have scratched this itch. One screenshot organizer sends each image to GPT-4V. It works, but every OTP and card number in the folder then goes to an API, and the cost grows with every screenshot. OrganizeShots runs in the browser and sorts by OCR into a zip. Screenshot Sloth builds on the same no-upload idea, adds content-based names, in-place moves with undo and checksum-verified flags, and is open all the way down: the code and the model doing the reading.
That openness matters for four concrete reasons:
- Nothing leaves the tab. After the one-time download, the model works with Wi-Fi off. Your screenshots are never uploaded, because there's nowhere to upload them to.
- You can check that. The model is MIT-licensed with published weights, and the app is MIT-licensed on GitHub. "Your files stay on your device" is something you can verify by reading the code or watching the network tab, not a promise you have to trust.
- It costs nothing per screenshot. 12 or 1,200 cost the same, which makes it reasonable to just run it on everything.
- It's forkable. Your screenshots aren't my screenshots. If yours are mostly Figma frames or Grafana dashboards, the categories are a small, readable rules file, and you can swap in a bigger Florence model or a different one entirely.
A closed API could probably name the odd screenshot more cleverly. But the job here isn't to be clever about one screenshot. It's to be trusted with all of them.
My Agent Session
I built Screenshot Sloth pairing with Claude Code. The first idea on our shortlist was an automatic subtitle syncer, until I remembered my own Cuelatch already does that, so we switched to this. The agent did most of the implementation and helped draft this post. The bugs in it are real ones from the build: the dHash false positives and the missed OTP both showed up on the first demo runs and were fixed with tests. The timings come from actual runs, and the move-and-undo code was tested against the browser's sandboxed file system before anything touched a real folder.
What's next
- Searching by content ("that error with
ECONNRESET") using the text it already read - Reading past the third strip of very long scrolling screenshots
- A watch mode, so the folder stays sorted as new screenshots land


Top comments (0)