Sloths have one big idea: never do work you can make something else do.
So I built an app that does the one chore I'm worst at: honestly knowing how many reels I watched today.
The idea came from watching my parents. Almost all their free time was going to reels. Then I looked around and realised it isn't just them: babies, kids, millennials like me, parents, even grandparents. Everyone is scrolling in their spare moments. I don't think it's evil. But most of it isn't doing much for us, and most of us don't notice. So I built something that quietly shows you the number and says it out loud, kindly, or with a roast.
Scroll Sloth is an Android app that counts the short videos you watch in Instagram Reels, YouTube Shorts, and Facebook Reels. It shows daily, weekly and monthly totals, and gives you two scores: laziness and unproductivity, each with a "why this score" breakdown. Every night at about 00:30, while the phone is charging, a small Gemma model running on the phone writes a two-sentence verdict about your day. You pick the tone: gentle, or roast.
The lazy part: you don't log anything, you don't open anything, and the verdict is waiting in the morning. The only effort is the shame.
Download: signed APK (with SHA-256 checksum) on the latest release
The Play Store listing is still waiting on paperwork, so for now it installs straight from GitHub. On Android 13+ you first need App info > menu > Allow restricted settings before you can switch on the accessibility service. The onboarding screen walks you through it.
Scroll Sloth is an Android-only, on-device app for counting short-form video sessions in Instagram, YouTube Shorts, and Facebook Reels. The current build includes onboarding, rule-driven reel detection, daily/weekly/monthly statistics with laziness and unproductivity scores (with a "why this score" breakdown), on-device commentary (Gemma or templates), and the debug Rule Inspector used to collect the real UI structure that detection rules are built from.
Download:latest release (signed APK and its SHA-256 checksum)
Architecture overview
app: the only Android application module, written in Kotlin with Jetpack Compose and Material 3.
com.halfbloodcoder.scrollsloth.AppContainer: hand-written dependency container created by ScrollSlothApplication and shared by the activity and the accessibility service (one DataStore instance per process).
com.halfbloodcoder.scrollsloth.detect: supported platforms, the detection-rules schema, loader and repository, RulesUpdater/HttpRulesFetcher (rules fetch), AppStatuses (per-app status), RuleEngine (node tree → DetectorEvent), the pure-Kotlin ReelStateMachine (dwell, dedupe, resets), ReelDetector…
Privacy turned out to be the thing everyone cared about most. When I shared the app with friends for feedback, "wait, is this watching my phone?" was the first question every time. Fair question. So here are the honest answers.
Scroll Sloth counts your reels. It doesn't watch them.
It saves only the time, the app and how long you stayed. No captions, no names, no screen content. Everything stays on your phone. No server, nothing to sell. You can pause it, export it or delete it anytime. And the code is open for anyone to check.
What does it look at?
Only three apps: Instagram, YouTube and Facebook. Android itself enforces this. The app was never given permission to see anything else, so your messages, photos, banking apps and browser are out of its reach.
What does it look at inside those apps?
Only one thing: "Is a reel on the screen, and did it just change?" It doesn't read captions, comments, usernames or links. It can't tell what you watched. It only knows that you watched one.
What does it save?
Three small facts per reel: the time, which app, and how many seconds you stayed. That's all. It's like a tally mark on a wall.
What does it never save?
What the reel was about, who posted it, what it said, or what was on your screen.
Does anything leave my phone?
Your reel data, never. There is no server, so there's nowhere for it to go. The AI that writes your daily verdict (Gemma) runs on your phone too. The app makes only two internet requests, and both just download public files:
The AI model, once.
A small file of "how to spot a reel" rules, once a week. You can switch this off in settings.
Neither request carries your data. There is no analytics tool and no ad tool inside the app.
Can I stay in control?
Yes, all of this is in Settings:
Pause counting at any time.
Export your data, or delete all of it with one tap.
Turn off the app's permission in Android settings whenever you want.
Uninstall, and everything goes with it.
How do I know you're not fibbing?
Don't take my word for it. The whole app is open source, so anyone can read the code. The privacy rules are written in the README, and the app limits itself to those three apps in its own configuration file, not just in a promise.
One honest note.
Accessibility is a powerful Android permission, and you should always be careful about who you give it to. That's why I made the app open, kept it to three apps, and keep it fully on your phone. Only download it from the official link, and check the checksum on the release page if you want to be extra sure.
How I Built It
The rule: the model writes words, plain code does maths.
Every number in the app comes from a deterministic Kotlin engine. Laziness is a weighted sum of four things: how many reels (45%), how far above my own 28-day baseline (15%), how many were watched late at night (20%) and my longest unbroken session (20%). Unproductivity is minutes watched against a daily budget. Gemma never touches a number. It only gets a small JSON block of facts and is told to write two sentences using only those.
Then a checker called NumberGuard reads whatever Gemma wrote. Every number in the text (digits, percentages, even "seven") has to be in an allow-list built from the facts. If one isn't, Gemma gets one retry with the bad numbers named. If it fails again, a template engine writes the verdict instead. The card shows a badge, "Written by Gemma on your phone" or "Template", so I always know who to blame.
Counting reels in apps that don't tell you how they're built.
Instagram, YouTube and Facebook don't publish their UI structure, and I didn't want to guess view IDs from memory. So before writing any detection, I built a Rule Inspector: a draggable Capture button (an accessibility overlay, so it needs no extra permission) that saves the structure of the screen: view IDs, classes, sizes, and only whether text exists, never the text itself. I captured a reel screen and a home feed in each app on my Galaxy S24 Ultra, diffed them, and worked out the detection rules from what I could actually see, with GitHub Copilot as my pair for reading the captures. Facebook obfuscates its IDs, so its rule leans on class, size, and position instead.
The rules live in a versioned detection-rules.json, and the unit tests replay my real captures, so a rule change that stops matching them fails the build. The app checks for new rules weekly. When Instagram changes its layout (it will), I fix a JSON file instead of shipping a new APK. A reel counts after 2 seconds, loops are capped at 120 seconds, and scrolling back to a reel within 60 seconds doesn't count it twice.
Gemma 4 on the phone, and the bug that made it speak in tongues.
The writer is Gemma 4 E2B (instruction-tuned, about 1.9 GB, Apache 2.0, not gated) running through LiteRT-LM on the GPU, with greedy decoding and a 60-token cap. A verdict takes a few seconds on my phone.
The first outputs were fun for the wrong reasons: one sentence told me I had "watchedヒル closely". Mid-sentence, a Japanese word had wandered in. The cause turned out to be a known GPU issue in the public LiteRT-LM tracker (#3879), and Copilot helped me read the issue and turn it into a fix. Switching to FLOAT32 activations with a separate GPU cache directory solved it. I also taught NumberGuard to treat unexpected non-Latin letters as a sign of garbled output and fall back to a template.
The pipeline.
GitHub Actions runs the tests, validates the rules file on every pull request, builds the signed release APK on each tag, and deploys the landing page. Copilot also helped me fix a workflow that wouldn't run.
A tracker of my own habits has no business in someone else's cloud. Knowing when I scroll, for how long, and how late is about as personal as data gets. With an open-weight model on the phone, the model comes to the data, not the other way round. Nothing about my reel habit leaves the device.
Open weights meant zero friction. Gemma 4 E2B is Apache 2.0 and not gated, so there's no token or terms-acceptance step in the downloader. And once downloaded, it works on a plane for free, forever. There's no per-call bill for a tool that fires once a night.
Open issue trackers saved my afternoon. The garbled-output bug had a public issue with a matching symptom. That's the difference between "my model is broken" and "this is a known GPU precision problem, here's the workaround".
Open rules, open repo. Because detection is a JSON file in a public repo, anyone with a different phone or a newer Instagram can capture, fix and open a PR. The README has a step-by-step guide for it. And because the code is open, my privacy claims above are something you can check, not just believe.
Where closed worked better, honestly:
A cloud model would have been easier to set up and would run on any phone. Mine needs a capable GPU and about 2 GB of storage, and falls back to templates otherwise.
My promo video was made with ElevenLabs, a closed tool. It was easy and the result looks great. I'm not going to pretend an open pipeline would have been faster to get there.
The Lazy Payoff
Doing this by hand is exactly as annoying as it sounds. My calibration screen asks me to tap a +1 button for every reel I really watched so I can compare it to what the app counted. Scroll Sloth is the thing that makes that tap-by-tap tallying unnecessary.
I tested it on my own phone against my own thumb. Results of calibration runs (my manual count vs. the app's count):
App
My count
Scroll Sloth's count
Error
Instagram Reels
5
5
0%
YouTube Shorts
5
5
0%
Facebook Reels
6
6
0%
I knew, I watched a little insta reels before I went to sleep or when work was slow, but watching the actual numbers left me to wonder how much time I am wasting being unproductive. It was a wake-up call. I plan to decrease the amount of time I spend watching reels and maybe do something productive (like reading a book or learn to play guitar 😅)
I shared the app with my friends, and they liked it. But the immediate question that they asked was - "What about privacy?". So, I had to explain the whole project philosophy, and I won their trust finally.
What It Can't Do (Yet)
Android only. iOS has no equivalent of the accessibility service.
It depends on three apps' screen structure, which they can change in any update. The rules were calibrated on one phone (Galaxy S24 Ultra, Android 16), so other devices, app versions, or languages may need new rules.
Counting is close, not exact: picture-in-picture, split-screen, and reels inside DMs or Stories may be missed.
Prize Categories
Best Use of Gemma: Gemma 4 E2B writing every verdict on-device through LiteRT-LM, wrapped in a number checker so it can't invent stats.
Best Use of GitHub Copilot: Copilot helped me work out the detection rules for all three apps from my Rule Inspector captures, find the cause of the garbled Gemma output by reading an open GitHub issue, and fix a failing GitHub Actions workflow.
Best Use of ElevenLabs: The promo video above was made with ElevenLabs.
Now if you'll excuse me, I have a roast waiting for me in the morning. 🦥