Concepts
A blip is one live item: a stat, a running agent session, a game score. An
extension can emit several blips (each with its own key) from one update() call.
Blipbar’s Claude Code extension emits one per agent session.
A layout is the shape of a blip’s data: stat, progress, session, list,
score, countdown, or meter (Builders: one per layout). You pick one per blip; the Mac app’s renderer owns
every pixel. There’s no view to design: the same blip shows as an ear beside the camera, a
row, a tile and an opened item, because it’s data, not a view.
A state is what’s happening right now. Every layout supports every state, and the renderer decides how each looks (color, motion, whether it peeks). You never pick a color: you pick the state that’s actually true, and the look follows from that.
| State | Means | How it shows |
|---|---|---|
idle |
Nothing happening | Calm |
running |
Work in progress | Calm, with progress or elapsed time |
attention |
Needs a decision or input from the person | Amber. The only state that plays the notch’s attention animation, and it reminds again while it waits |
stalled |
No progress for too long | Amber |
success |
Finished well | Green, then settles back to calm after a few seconds |
failure |
Finished badly, or something’s wrong | Red, then settles back to calm after a few seconds |
stale |
The data is old | Dimmed, with when it was last updated |
offline |
No connection | Dimmed, with when it was last updated |
empty |
Nothing to show yet | Calm |
Entering attention, stalled, success or failure can peek the notch open briefly.
A state with a color also has a shape (!, ✓, ×), so color is never the only signal.
The host owns the lifecycle. Your extension doesn’t run a server, a cron job, or
a setInterval. The app decides when your code runs: on launch, on the manifest’s
interval, when a webhook arrives, when a watched file changes, when someone presses an
action. The Node runtime that hosts your code checks your declared permissions and
validates everything you emit before it reaches the app. This is deliberate, not a
limitation: it’s how Blipbar keeps idle CPU near zero, and why your manifest (which Blipbar
shows people before they install) can say what your extension does without anyone reading
your code.
A tool is the other thing an extension can offer: a small utility the user opens from the notch’s tool tray and runs on demand (look up a package, decode a token). Tools declare their inputs and return typed output; the same kit draws them as Blipbar’s own. See Tools.
Full snapshots, not diffs. ctx.emit() sends everything about a blip every time,
not just what changed. The app can join late, drop a message, or reconnect and still
render correctly, with no “catch up” logic anywhere. Emit a blip’s complete state, always,
even the fields that didn’t change since last time.