sugarrush 2026.8.3

A terminal UI for viewing Nightscout CGM (blood glucose sensor) data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# sugarrush on the Quickshell bar

A bar widget for [Quickshell](https://quickshell.org). Unlike the assets in
[`waybar/`](../waybar/), which work on any compositor, this one targets a
specific host: the **Omarchy 4 shell** (`omarchy-shell`), which loads bar
widgets as plugins. Quickshell on its own has no bar to add a widget to — a
shell has to provide one — so a widget is only as portable as its host.

It shows the reading **with its unit**, the trend arrow and the delta, and
opens a panel with the rest of the day. It wears the bar's own colour until
the reading leaves your target range — see [Colours](#colours). The unit is there
because a bare number names nothing — `10.5` could be a load average; nothing
else on a desktop is reported in mmol/L:

| Interaction | What happens |
|---|---|
| left click | opens the panel — chart, time in range, patterns |
| right click | opens the sugarrush TUI in a floating terminal |
| middle click | fetches now, without waiting for the next poll |

On a vertical bar the pill stacks the reading over its trend arrow and drops
both the unit and the delta, which do not fit 28 pixels.

Against a sugarrush too old to send the reading in parts, the pill falls back
to the line that binary prints — no unit, but no breakage either.

## The panel

Clicking the pill opens a panel carrying what the bar line has no room for.
The wordmark leads, with refetch and open-the-dashboard on the right, then
chips switching between three views — **Glucose**, **Profile** and
**Settings**. Each view is a stack of cards that name the window they describe
— because "mean 8.8" under a six-hour chart is a 24-hour figure, and a panel
that does not say so invites the wrong reading.

Glucose:

- **Now** — the reading at display size beside where it lands in half an hour,
  both coloured by the band they fall in, with the trend and the delta. The
  forecast is sugarrush's own AR2 projection; during a sensor gap it is absent
  rather than guessed, and the arrow goes with it;
- **Last N hours** — the chart: your reading over a typical day for the same
  hours, the median dashed and the 25–75% band shaded, each alert threshold
  ruled and labelled on the value axis, the clock along the bottom.
  The line carries the state, changing colour as it crosses a threshold, and
  seeing tonight sit above the band is the point of it. Hovering the chart
  drops a crosshair on the nearest reading and prints its value and time —
  the reading itself, never an interpolation between two of them. Scroll the
  chart to pan back through `scrollbackHours` of history — at a quarter-hour
  step once past the finely-drawn window, from readings the snapshot already
  fetched for the patterns rather than a second request. The default stops at
  three days because a strip a few hundred pixels wide turns a fortnight into
  noise with a viewport box too small to grab; the strip underneath is that
  whole window with a box showing where you are, and clicking or dragging it
  jumps. Once panned, the card names the hours on screen and returns to live
  when tapped, so a chart showing 3am never claims to be showing now;
- **Last 24 hours** — the five time-in-range bands, with mean, GMI and CV.

Profile — the same window read as habit rather than as history:

- **Typical day · N days** — the ambulatory glucose profile: every day folded
  onto one 24-hour clock, the median line over the middle half and the outer
  5–95%. A bump here means "this happens at 3am", which the six-hour chart
  cannot say. It needs at least three days: with one, the median and the
  quartiles are the same number, and a chart that cannot tell a habit from a
  bad Tuesday should not be drawn. **Copy summary** puts the same clinical
  text `sugarrush export` writes on the clipboard, for the conversation that
  usually happens somewhere else;
- **Patterns · last N days** — the times of day where lows or highs keep
  happening, or a line saying nothing recurring stands out.

Under the cards runs a status strip — the alarm's own state as a chip, then
`sensor 9d 5h · 19h left`, with `updated 3m ago` on the right. The chip reads
`alarm armed`, `snoozed 12m`, or `not watching` in red when no daemon is
running, from `sugarrush health --json`: a panel can draw a perfect graph
while nothing is watching tonight, and that is exactly the state worth being
told about. Those describe the rig rather than the glucose, and they are the only things in the panel that do not change every
five minutes, so they sit apart from the cards rather than inside one. The
sensor turns amber inside its last day and red once it is past; the countdown
needs `sensor_days` and a site whose uploader logs "Sensor Start" / "Sensor
Change", and without either you get the age alone, or no strip at all.

The stack scrolls if it outgrows the room a popup is allowed, which four cards
can do on a short screen.

The panel calls `sugarrush snapshot`, which needs a sugarrush new enough to
have that command; the pill does not, and keeps working either way. If the
command is missing or too old the panel says so instead of drawing an empty
frame.

It fetches when opened, not on a timer, and reuses its last document for
`panelCacheMinutes`. So the heavy part — the multi-day history the patterns
need — is paid for only when someone is actually looking.

## Install

```bash
mkdir -p ~/.config/omarchy/plugins/sugarrush
cp manifest.json *.png *.svg *.qml ~/.config/omarchy/plugins/sugarrush/
omarchy-shell shell rescanPlugins
omarchy plugin enable sugarrush.glucose
```

`omarchy plugin enable` puts it on the bar; move it with
`omarchy bar move sugarrush.glucose --after omarchy.clock`, and remove it again
with `omarchy plugin disable sugarrush.glucose`.

The widget calls `sugarrush waybar`, so it needs `sugarrush` on `PATH` and a
configured site (`~/.config/sugarrush/config.toml`).

## Options

Set with `omarchy bar set <widget> <key> <value>`:

| Key | Default | What it does |
|---|---|---|
| `interval` | `60` | seconds between pill fetches |
| `showUnits` | `true` | print the unit after the reading; turn it off on a crowded bar |
| `showMascot` | `false` | put the sugar cube in front of the reading |
| `showSparkline` | `true` | draw the last hour as a trace after the reading |
| `showArrow`, `showDelta` || not widget options: switch them off in sugarrush's own `[bar]` config (or the settings screen), which every bar follows |
| `command` | `sugarrush waybar` | the command the pill reads a reading from |
| `onClick` | `omarchy-launch-floating-terminal-with-presentation sugarrush` | what the panel's "Open dashboard" runs, and the left-click fallback when the panel cannot load |
| `onRightClick` | the same, plus `--screen settings` | right click |
| `animations` | `true` | cross-fade when switching views; off makes every switch instant |
| `wideLayout` | `true` | two columns of cards on a horizontal bar; off gives the narrow single column |
| `panelHours` | `6` | how much of the overview the chart shows at once |
| `overviewHours` | `24` | how much history is drawn at full resolution (6-72) |
| `scrollbackHours` | `72` | how far the chart pans, and the span of the strip (6-336) |
| `insightDays` | `14` | history behind the patterns and the chart's typical-day band; `0` hides the patterns and skips the query |
| `panelCacheMinutes` | `5` | how stale the panel's document may be when it opens |
| `snapshotCommand` | `sugarrush snapshot` | the command the panel reads its document from |

`showUnits` and `showSparkline` can only take something away. sugarrush's own
`[bar]` config decides what the payload carries in the first place — turn
`units` or `sparkline` off there and the pill drops them whatever these say,
along with every other bar you run.

```bash
omarchy bar set sugarrush.glucose interval 30
omarchy bar set sugarrush.glucose onClick "foot -a sugarrush-float sugarrush"
```

Two notes on those:

- The option is `command`, not `exec`. The bar treats any widget carrying
  `exec`, `source` or `type` as one of its own built-in command/QML modules and
  never loads the plugin.
- `omarchy plugin disable` drops the widget's options along with its place on
  the bar, so set them again after re-enabling.

## Colours

In range, the pill is the bar's own foreground — one more thing on the bar
rather than a green light asking to be looked at. Colour is spent on the case
worth spending it on: **only the reading itself** takes the alert colour, and
only when it is out of range, or when a forecast crossing is coming (the
sparkline's end dot goes hollow for that one, since nothing has happened yet).
The unit, the arrow, the delta and the trace stay in the bar's foreground
throughout. Stale data is carried by the leading `?` alone.

The alert colour is the `color` field of `sugarrush waybar` — the state colour
from your sugarrush theme, including the colourblind palette. Nothing to theme
here, and no stylesheet to keep in sync, unlike the Waybar module's CSS
classes. Against an older sugarrush that doesn't emit `color`, it falls back to
the bar's urgent colour.

The panel follows the same theme, from the `theme` object in
`sugarrush snapshot`: the chart, the profile bands, the time-in-range bar, the
sensor countdown and the alarm chip are all painted from your five configured
colours rather than from a copy of the defaults. Switch on the colourblind
preset and the whole panel switches with it.

## Settings in the panel

The chips under the wordmark swap the panel between **Glucose** and
**Settings** — glucose rather than "now", since that view carries six hours of
chart and fourteen days of patterns as well as the reading, and rather than
"dashboard", which is what this panel's own button opens.
The settings view edits two different things, and says so by grouping them:

- **Alarm thresholds**, **Alarm** and **Status bar** write
  `~/.config/sugarrush/config.toml` through `sugarrush config`, the same
  serializer and atomic write the dashboard's settings screen uses. A value the
  app would have quietly repaired — crossed thresholds, mostly — is refused,
  and the refusal appears under the rows rather than in a log. **Status bar**
  switches the parts of the reading off one at a time; it is sugarrush's own
  `[bar]` config, so it applies to every bar sugarrush feeds, not only this
  pill, which is why it is not under "This panel". The pill refetches as soon
  as the write lands rather than waiting out the poll.
- **This panel** writes the widget's own options in the bar's config through
  `omarchy bar set`.

Everything else — sites, tokens, quiet hours, themes — stays in the dashboard.

## Carbs and insulin

Anything logged on your Nightscout site inside the chart's window is drawn in a
lane along the foot of the chart: a dot for carbs, sized by the amount, and a
triangle for insulin, with the amounts labelled wherever the markers are far
enough apart to read. The card's own title carries the totals — `Last 6 hours ·
45g · 5.7u`.

They are deliberately not drawn at the reading's own height: a marker sitting
on the line would be read as a reading. The two take the graph and forecast
colours from your theme rather than the alert ladder, since neither is a
glucose state, and both are told apart by shape as well as colour so the
colourblind preset still separates them.

Entries with no amount — notes, finger sticks, sensor changes, which Nightscout
keeps in the same collection — are left out. A site that logs nothing simply
has no lane.

## A fortnight, one bar per day

The Profile view draws time in range as one stacked bar per day, oldest on the
left, under the typical-day chart. The bands are in the same order as the
time-in-range bar on the Glucose view, so a column here and that bar are read
the same way round.

Days are grouped at **local midnight** in the site's timezone, not UTC — a
night split across a UTC boundary would be reported as two days the person did
not have.

A day whose bar is computed from too few readings is drawn faded. One thin
morning after a sensor change is 100% in range on a technicality, and drawn
solid it would read as the best day of the fortnight.

## Thresholds as a band

The Settings view draws the four alarm thresholds as one band with a handle at
each, in the same colours the reading is drawn in — so it doubles as a legend
for the rest of the panel. Drag a handle to move a threshold; they clamp
against their neighbours and cannot cross, which makes the crossed
configuration `sugarrush config` refuses unreachable rather than rejected.

One config write happens when a handle is released, not while it moves. There
are no stepper rows any more: a handle lands on a tenth of a mmol/L in about
two pixels at panel width, so the card is now the shape it describes.

## While it is open

The panel refetches at the pill's own poll interval (`interval`, 60s by
default) for as long as it is on screen, and stops when it closes. The header
counts down to the next fetch; the refresh button restarts that countdown along
with the fetch.

It used to read once on open and cache for five minutes, so a panel left open
went quietly out of date while the pill behind it kept moving.

## Two columns

On a horizontal bar the panel is wide enough for two columns of cards: the
reading beside the last 24 hours, the clinical summary beside the alarms.
Everything that wants the room — the six-hour chart, last night's trace, the day
strip, the profile — keeps a full row to itself.

Paired cards take the taller one's height, so a row has a single bottom edge.

It is a `Flow`, not a second layout: a card given half the width shares its row,
and a card at full width takes its own. There is no wide-mode tree to keep in
step with the narrow one.

A vertical bar keeps the single column, where it is the right answer, and
`omarchy bar set sugarrush.glucose wideLayout false` returns the narrow panel
on any bar.

## Last night

The Glucose view leads with the night just gone — 23:00 to 07:00 in the site's
timezone, since a night is a local thing. The trace is deliberately not the
six-hour chart shrunk: no axes and no clock, because it answers one question.
Underneath it, time in range, the lowest reading, and how many alarms fired,
each listed with what the delivery did.

Every excursion below range is marked, not just the lowest point: two separate
lows at 3am and 5am is a different night from one long one.

Before 07:00 the card says **tonight so far** and ends at the current reading.
A night reported as finished before it has finished is a claim about hours that
have not happened.

## What the alarm did

The Profile view lists recent alarm episodes from `sugarrush alerts` — the
local record `alertlog.rs` keeps — with the reading each began at and how long
it lasted. An episode still running says `still going` rather than reporting a
duration it does not have.

Underneath, in red, any episode whose delivery failed: `04:55 · push never
arrived`. That is the most important line in the log and was the least visible
— it means an alarm was raised and nobody was told. Failures are attached to
the episode they happened in, because "a push failed at 04:55" means nothing on
its own.

An empty list reads as "No alarms in this window", which is a good fortnight
rather than a card that failed to load.

## An hour of the profile

The typical-day chart draws a median and two envelopes, which is what a clinic
reads — and which hides the individual days by design. **Tap an hour** and the
days behind it appear as dots, with the caption naming the median, the spread,
and how many of them fell out of range:

```
20:07 · median 7.1 · spread 5.1–13.0 · 1 of 13 days out of range
```

Tapping the same hour again clears it. Only one hour is ever drawn: all of them
at once is the scatter plot the envelope exists to replace.

## The clinical summary

The Profile view renders the same figures `sugarrush export` writes — mean,
GMI, CV, and the five bands with their boundaries in your own units — over the
history window. **Copy summary** puts the exported text on the clipboard; the
card is so that you have read it first.

## Today against your own baseline

Under the time-in-range bar, four figures are read against the whole history
window rather than left on their own: time in range, time below range, mean and
CV, each with the change named.

The colour answers "is this better", which is the only reason to print two
numbers instead of one — green for an improvement, amber for the other way.
Mean is deliberately never coloured: a lower average bought with more lows is
not an improvement, so the change is stated and left to be read.

The baseline comes from `baseline` in `sugarrush snapshot`, computed over
whatever `--days` fetched, and the card names the span it covers.

## Acting from the panel

Under the reading are the two things worth doing at 3am. **Snooze 15m** and
**1h** run `sugarrush snooze`, and while a snooze is running they collapse into
`Wake now · 12m left`, which runs `sugarrush snooze off`. The countdown comes
from `sugarrush health --json`, so a snooze set from the Omarchy menu, the
dashboard or another machine is reflected here as well. If no watcher is
running the buttons are disabled and the panel says so — silencing an alarm
that is not armed would be a button that lies.

**Log** opens a small form — carbs and insulin, nothing else — and **Review in
terminal** hands those amounts to `sugarrush treatment` in a terminal window.
The panel never writes the record itself: the command prints what it is about
to write and asks for the person's name first, and that confirmation is the
guard on a health record rather than a formality to route around. Cancel, or
closing the panel, clears the form.

**The Log button only appears on a site with a treatment write token** — a
separate, write-capable Nightscout token, set under Site in the dashboard's
settings. `sugarrush treatment` refuses a site without one, so the panel shows
no button rather than a permanently dead one. If Log is missing and you expected
it, that token is what is missing.

Carbs and insulin are the only fields because they are the two the chart draws
and the two the command needs. A meal remembered three hours late wants
`--at`, which needs a date picker to offer honestly — that one belongs in the
terminal.
A panel that dismisses when focus moves is the wrong place to type a token.

## Keys

| Key | What it does |
|---|---|
| `1` `2` `3` | jump to Glucose, Profile, Settings |
| `` `` | step between views |
| `r` | fetch now |
| `d` | open the dashboard |
| `Esc` | close |
| `?` | show or hide this list, in the panel |

## Omarchy menu entries

[`omarchy-menu.jsonc`](omarchy-menu.jsonc) has a sugarrush submenu — dashboard,
snooze 15m/1h, the current reading as a notification, export, settings — to
merge into `~/.config/omarchy/extensions/omarchy-menu.jsonc`. The shell watches
that file, so an edit takes effect without a restart, and every entry is gated
on `command -v sugarrush` so the menu stays clean on a machine without it.

## Editing the widget

The shell compiles plugin QML once per process. Editing an installed
`BarWidget.qml` — or `omarchy plugin disable` / `enable` — will not pick up
your changes; restart `omarchy-shell` to load them.

## Without the plugin

If you would rather not install a plugin, the bar's own command module can run
sugarrush directly. It has no popup or tooltip beyond the text, but it needs no
QML. In `~/.config/omarchy/shell.json`:

```json
{
  "bar": {
    "layout": {
      "right": [
        {
          "id": "sugarrush",
          "type": "command",
          "exec": "sugarrush waybar",
          "interval": 60,
          "onClick": "omarchy-launch-floating-terminal-with-presentation sugarrush"
        }
      ]
    }
  }
}
```