Skip to main content
Ari Zilnik
Hardware, Developer ToolsOpen SourceDesigner, Builder

Claude Usage on a 240-Pixel Screen

Claude Usage on a 240-Pixel Screen

Claude Code has usage limits on a five-hour window and a weekly cap, and I kept discovering where I stood in the middle of something I didn’t want to stop. I wanted the answer to be ambient — a thing I glance at, not a thing I query.

So it lives on a $20 GeekMagic SmallTV Pro next to my keyboard, updated from my Mac every five minutes. One glance answers: how much runway do I have? Unplug it and it goes back to being a clock.

The display on a shelf between a copper rabbit ornament and a glass bird, showing PERSONAL at 78% five-hour and 88% weekly, WORK at 26% and 4%, with the time along the bottom
Two accounts, four bars, one clock. All the bars share a scale, so the comparison is real.

Two dashes are not zero percent

The most useful decision on the whole panel is what it does when it doesn’t know something.

-- means unknown. It is deliberately not 0%. A zero is an answer — it says you’ve used nothing and have everything left, which is the single most dangerous thing to tell someone about a rate limit when the truth is that the token expired an hour ago. Every failure the thing can have is named on the screen instead: not logged in, token expired, 52m old.

That last one matters more than it looks. A stale reading is not a broken reading, and it isn’t a fresh one either. Saying “52m old” lets you decide how much to trust the number, which is a decision the display has no business making for you.

An amber bar past 60 percent with '5h in 42m' in the header, showing when the window emptiesA weekly bar split into a muted sustainable portion and a brighter lit excessA panel reading 'not logged in' where the usage figures would otherwise be
Past 60% the bar goes amber and the reset time appears. Burning too fast, it splits — the sustainable part dims, the excess stays lit. Signed out, it says so.

Review it at actual size or don’t review it

Every state the renderer can produce gets rendered onto one contact sheet, and that sheet is shown at 240 pixels — actual size.

Reviewing a 240px design at 2× flatters it. The type looks crisp, the bars look precise, the color separation looks obvious. Then you put it on the shelf and squint. So the review happens at the size the thing actually is, which is the only honest way to look at it, and the same states feed the contrast tests — checked for a red-green colorblind viewer and after JPEG compression, because the device re-encodes what it’s sent.

A contact sheet of all fourteen display states rendered at actual size, four to a row
All fourteen states at 240px. Generated from the same list the contrast tests read.

The sheet and the tests read from one list of states, and that constraint does real work: a state that isn’t in the list is a state nobody has ever looked at. Adding a new failure mode without adding it to the list is possible, but you have to do it deliberately, and then it never appears on the contact sheet and you notice.

The thresholds are guesses, and the project says so

Amber starts at 60% and coral at 85%. Those are round numbers I picked by hand. Nothing derived them from how these accounts actually get used, and the daily volume underneath them has swung from $2 to $1,354 inside a fortnight — which is the shape a fixed cutoff fits worst.

The honest move would have been to either ground them or drop them. What I did instead was log every reading to a plain CSV, so the distribution can replace the guess later — median, p90, max, and how often 60% and 85% are actually reached, per account and per window.

The off switch is written in bash

The kill switch needs no virtualenv, no Python, and no valid config. It parses the device address out of the config file with sed and falls back to a hardcoded default if even that is missing.

That’s not stubbornness about tooling. The moment you most want to pull the plug is the moment something is broken, and a kill switch that imports the project it’s killing is useless exactly then. It’s idempotent, it waits for the system to actually drop the job rather than assuming, and if the device is offline it finishes the local teardown anyway and warns you the panel will still be showing a stale frame when it comes back.

It also refuses to edit ~/.claude/settings.json. If something in there references this project, it tells you to remove the line by hand rather than rewriting your config behind your back. A teardown script that quietly edits files it didn’t create is how you lose trust in a teardown script.

The repo is public under MIT.

Impact

240×240

The entire canvas, in pixels

14

Display states, every one reviewed at actual size

5 min

Refresh cadence, through reboots and sleep