Notifications
Everything else on this device is something it fetches on a timer. Notifications are the other direction: you push, and the screen reacts immediately. A single HTTP request takes over the whole panel with an animation and a message, holds it for as long as you asked, and then puts back whatever was on screen before.
It was built for Claude Code sessions, waving when a session needs an answer and celebrating when a task finishes, but nothing about it is specific to that. Anything that can make an HTTP request can fire one: a backup script, a doorbell, a long compile.
Firing one
Section titled “Firing one”curl -X POST http://smalltv.local/api/notify \ -H 'Content-Type: application/json' \ -d '{"state":"done","ttl":20,"label":"nightly-backup"}'| Field | Meaning |
|---|---|
state | waiting draws a waving character over NEEDS YOU; done draws a jumping one over TASK DONE. Anything else is rejected. Required. |
ttl | How long to hold the screen, in seconds. Clamped to 2 to 120; defaults to 20. |
label | Optional line under the state word, up to 20 characters. |
A request that is understood answers {"ok":true}. An unknown state answers {"ok":false} with HTTP 400. A request with no body at all, or one whose body is not valid JSON, answers HTTP 400 with a plain-text reason rather than JSON, so a script checking the response should look at the status code and not assume it can parse what comes back.
Firing again while an overlay is up replaces it and restarts the clock, so a burst of events from several scripts shows the most recent one rather than queueing.
The label
Section titled “The label”Without a label the screen shows the state word on its own, which is enough when one machine fires the alerts. With several sources it is not: “TASK DONE” does not say which thing finished, and that is exactly when the alert matters. Put the project, host, or job name in label and it renders on its own line under the state word.
Twenty characters is the limit, from the panel width and the font size rather than an arbitrary cap. Longer labels are cut. Anything outside plain printable ASCII is dropped, so accents and emoji disappear rather than drawing as blanks.
What happens to the screen underneath
Section titled “What happens to the screen underneath”The overlay is not a mode. It cannot be selected in the Display tab and it never joins the carousel rotation; it simply pre-empts whatever is running, then hands back.
Handing back is careful about the carousel. The time the overlay spent on screen is credited back to the rotation timer, so if the ticker had four seconds left when the alert arrived, it still has four seconds left afterwards, on the same symbol. The underlying feature repaints from what it already had rather than re-fetching, so an alert costs no extra network traffic.
One edge to that: the credit counts from the most recent alert only. A burst that keeps replacing itself is credited just the last one, so the rotation still moves on while the panel was covered. Three twenty-second alerts fired twenty seconds apart hide the carousel for about a minute and give back about twenty seconds of it.
Nothing about a notification is saved. There is no history, and a reboot leaves no trace of one.
Worth knowing
Section titled “Worth knowing”- The feature underneath does not fetch while the overlay is up. At the default 20 seconds nothing is noticeable; a
ttlnear the 120-second maximum will delay a refresh. - Two states swallow the alert while still answering
{"ok":true}: a device in SETUP MODE, which keeps the hotspot screen up, and one sitting on the crash screen after a fault. Neither draws the overlay, so a script cannot read a success here as “it appeared”. - Night mode still applies. An alert that arrives with the night brightness at 0 animates behind a backlight that is off, which means it is invisible until morning. That is consistent with every other mode, but it does mean notifications are not a way to be woken up.
- The endpoint needs the web UI password when you have set one, so a script firing alerts has to send those credentials too.
Changing the animations
Section titled “Changing the animations”The two animations come from Clawdmeter’s own splash set and live in src/features/notify/notify_frames.h, generated by tools/extract_notify.py. That script regenerates the header from the upstream source and fails with a specific error rather than emitting broken data if the upstream format changes.