I built myself a Chrome extension called ScrollGuard that tracks how long I spend on sites I choose and, once I pass the limit, covers the page with an overlay that will not go away until I type a password I set in advance. It exists to break my own YouTube Shorts habit. Two things came out of it, neither especially technical — the password is a speed bump against impulse rather than a security control, and building a Chrome extension is the entry point I recommend for anyone starting with Claude Code.
I am the first to fall for the algorithmic manipulations of social platforms. They simply got too good.
Where this started
Reading the Israeli philosopher Micah Goodman’s Hebrew book on attention, מהפכת הקשב, got me to the realization that I am handing over my presence itself to predatory corporations that cynically sell it to the highest bidder. That is, in my view, the single biggest problem facing modern people, and I am not exaggerating.
So I went on a detox. Luckily I never got around to being addicted to Instagram or Twitter, and I deleted Facebook long ago because it stopped being cool.
That left YouTube, which joined the dark side and went from a lonely island of real full-length content to another human force-feeding plant of artificial pixelated garbage, known as Shorts.
Why YouTube needs a tool and not a decision
Here is the structural difference I had not noticed before. On every other network, quitting is a single act: you delete the account in a moment of clarity and forget about it once and for all. The door closes behind you.
YouTube is freely accessible. There is no user to delete, no point at which you are done. The door is open in every new tab, and a good decision does not survive that — it has to be made again twenty times a day.
So I made myself a guard — not to decide for me, but to delay me long enough for the decision I already made to catch up.
What the extension actually does
ScrollGuard is Manifest V3, no build step and no bundler — what you install is what Chrome runs. No server, no account, no network code anywhere in the codebase. Everything lives in chrome.storage.local.
- It tracks time per domain (
www.stripped) and counts only while the tab is actually visible — one-second ticks, flushed to storage every ten seconds. - Each domain gets two independent limits, daily and session. The defaults are 60 and 30 minutes.
- A limit of
0in either field blocks the domain outright, no time budget at all. - When a limit is hit, a content script covers the page and disables scrolling.
- The correct password unlocks that domain for five minutes — hardcoded. Time keeps accruing while unlocked, so the moment those five minutes expire the next tick puts the overlay straight back.
- A popup shows today’s total; a dashboard shows a donut chart and a date picker for the last 30 days. An hourly alarm deletes daily stats older than that and clears expired unlocks.
The password I chose for myself is iamaloser. That is part of the design.
The settings page is minimal: a domain (https:// and www. get stripped, a dot is required), then the two limits in minutes. Both are editable inline in the rules table afterwards and save on every change. The password is four characters minimum, typed twice. One trap: set a rule without setting a password and the overlay still appears at the limit, with no password field on it — you have to open Settings from the overlay itself, set a password or delete the rule, and reload. It looks like a bug the first time. It is exactly what the code says.
On permissions, know what you are granting. Beyond storage, tabs and alarms, the extension asks for access to every http and https site — the tracking loop runs on every page, because it has to know when you land on a domain you configured. I allow it only because I know what is in the code; for a blocker off the store I would ask the same question.
What it is not, and why that is in the README
The password is stored in cleartext — not hashed, not encrypted. Anything that can read the extension’s storage, like the service worker console from chrome://extensions, reads it in seconds.
That is a deliberate trade-off, not an oversight I am hiding. The threat model here is me, at 1am, wanting to scroll, and a password prompt is exactly enough friction to interrupt that. It is not a parental control, and not something to point at someone else’s browsing.
What I did fix: the cleartext password never leaves the service worker. In an earlier version GET_ALL_STATS handed it back to any extension page that asked, and the content script read it out of storage on every blocked page load. Both are gone; the only thing about the password that leaves the worker now is a hasPassword boolean, and the comparison happens only there.
And the gaps that remain, because writing them down beats discovering them:
- The overlay is a
divin the page. Deleting the node in devtools, disabling the extension, or opening the site in another profile bypasses it completely. - The “session” limit never resets by itself. Only a manual button press clears it, and it survives tab closes and reboots — in practice a second cumulative budget, which is the biggest gap between the name and the behaviour.
- The day rolls over at UTC midnight, because the date key comes from
toISOString(). In Israel the daily counter resets at 02:00 or 03:00 local time. - Limits overshoot by up to about ten seconds, since the check only runs when the buffer flushes.
- The same domain open in two visible windows double-counts, because tracking is per-tab.
- The page is visible for a moment before the overlay lands on it, and there is no throttling on wrong password guesses.
And the best irony: rules match whole hostnames only. No wildcards, no path rules, so I cannot limit youtube.com/shorts — only YouTube entirely. I set out to break up with Shorts and built a tool that also blocks the thing I liked there in the first place.
Chrome extensions are the new Hello World
This is the part that matters even if you do not care about Shorts.
If you have never tried Claude Code, extensions are where to start. You describe in plain language what you want to happen and which site it should affect. It writes the extension without much fuss and drops the files in the folder Chrome loads them from. Zero to a working product — local, admittedly — literally in one prompt.
It works because the format is small: a manifest, a service worker, a content script. The browser supplies the infrastructure, so all that is left to describe is the behaviour you want. No deployment, no other users, no cloud storage.
Installing is where people get stuck, so: open chrome://extensions, turn on Developer mode, click Load unpacked, pick the folder with the manifest in it. Mine has no icon files, so Chrome gives it the generic puzzle piece — which has never stopped it working.
For the more advanced: ask Claude Code to install chrome dev-tools before you start. Then it can visit the site you want the extension to work on and explore it for itself. You can also watch it move things around there in real time, which is very cool.
The takeaway
The most useful tool you build for yourself this year probably will not be technically impressive. It will be small, ugly, and it will solve one problem that only you have — which is why nobody was ever going to build it for you. The cost dropped low enough that it is worth building even when it is only a speed bump, and even when it does not quite live up to the name you gave it.
That is what I try to unlock inside organizations — not another system, but people who can build themselves the small missing piece. Here is how the process works.