🌸Spring 2026 Pebble App Contest — View the entries!

Changelog

Version 0.8.22026-10-02T08:41:20.57

## 0.8.2

- Opening the Shortcuts page and then tapping "Pick shortcuts" (or
  "Update metadata") straight away could collide: the second AppMessage send
  returned `APP_MSG_BUSY` and the screen showed "Send failed" with an empty
  picker, with no way forward but BACK. A busy outbox is now retried once
  after 300ms; only a second busy or a real send error is reported
- The fetch watchdog now fires on any request that never finished. Its
  previous check ("entries received >= expected") was also true before the
  first reply, so it bailed out in the worst stall — the phone dying before
  it ever sent the count
- "Update metadata" against a Home Assistant with no scripts or scenes now
  finishes and reports; the dialog used to sit on "Updating..." forever,
  waiting for entries that were never coming
- A pending send retry is cancelled when the picker closes

Version 0.8.12026-10-02T07:47:41.478

## 0.8.1

Hardening the two-page menu: no loading state, and no way for a fetch to
hang.

- Removed the "Fetching labels..." row hint and the state behind it. Nothing
  waits on the label list, and a flag that only cleared when a reply arrived
  meant an offline phone could leave the row claiming to fetch forever
- Fixed the first-install label warm-up: the watch now hands the stored
  config to the phone after a save (the JS only learned it on `ready`), so
  the labels request no longer fires against empty credentials. The refresh
  moved to the phone side — one message each way, instead of two back-to-back
  sends where the second could return `APP_MSG_BUSY` and be dropped
- Picker and "Update metadata" now have a fetch watchdog (25s, above the
  phone's own 20s request timeout). Every failed hop was already reported,
  but if the phone's JS stopped mid-chain nothing came back and the picker
  sat on "Fetching..." over a partial list; it now ends in "Fetch error"
- The phone also reports a browse that stops mid-chain, instead of logging it
  only
- A failed label fetch no longer replies with an empty list: the watch keeps
  its cached labels, so being away from home (or HA being down) cannot wipe
  the filter choices

## 0.8.0

The menu is two pages now, and the label filter loads itself.

- 3-dot menu split in two: **Shortcuts** (Pick shortcuts / Change Order /
  Update metadata / Label filter) and **Settings** (Automatic close /
  Info line / Vibrations) — everything that shapes the shortcut list sits
  together, the display and haptic settings sit together
- The label list is fetched when the Shortcuts page opens (labels only: one
  request, no entity dump) instead of waiting for a manual picker or
  "Update metadata" run, and it is cached in flash — so the row cycles your
  labels on the first open, right after a restart, and once settings are
  saved
- Picker row renamed to "Pick shortcuts" so the page and its first row are
  not both called "Shortcuts"; the row reads "Fetching labels..." while the
  list is on its way
- A failed label fetch replies with an empty list rather than nothing, so the
  row falls back to All instead of claiming to fetch forever
- Nothing to migrate: the stored label filter keeps working

Version 0.8.02026-10-02T07:45:09.548

## 0.8.1

Hardening the two-page menu: no loading state, and no way for a fetch to
hang.

- Removed the "Fetching labels..." row hint and the state behind it. Nothing
  waits on the label list, and a flag that only cleared when a reply arrived
  meant an offline phone could leave the row claiming to fetch forever
- Fixed the first-install label warm-up: the watch now hands the stored
  config to the phone after a save (the JS only learned it on `ready`), so
  the labels request no longer fires against empty credentials. The refresh
  moved to the phone side — one message each way, instead of two back-to-back
  sends where the second could return `APP_MSG_BUSY` and be dropped
- Picker and "Update metadata" now have a fetch watchdog (25s, above the
  phone's own 20s request timeout). Every failed hop was already reported,
  but if the phone's JS stopped mid-chain nothing came back and the picker
  sat on "Fetching..." over a partial list; it now ends in "Fetch error"
- The phone also reports a browse that stops mid-chain, instead of logging it
  only
- A failed label fetch no longer replies with an empty list: the watch keeps
  its cached labels, so being away from home (or HA being down) cannot wipe
  the filter choices

## 0.8.0

The menu is two pages now, and the label filter loads itself.

- 3-dot menu split in two: **Shortcuts** (Pick shortcuts / Change Order /
  Update metadata / Label filter) and **Settings** (Automatic close /
  Info line / Vibrations) — everything that shapes the shortcut list sits
  together, the display and haptic settings sit together
- The label list is fetched when the Shortcuts page opens (labels only: one
  request, no entity dump) instead of waiting for a manual picker or
  "Update metadata" run, and it is cached in flash — so the row cycles your
  labels on the first open, right after a restart, and once settings are
  saved
- Picker row renamed to "Pick shortcuts" so the page and its first row are
  not both called "Shortcuts"; the row reads "Fetching labels..." while the
  list is on its way
- A failed label fetch replies with an empty list rather than nothing, so the
  row falls back to All instead of claiming to fetch forever
- Nothing to migrate: the stored label filter keeps working

Version 0.7.02026-10-01T21:52:39.559

- New "Label filter" sub-menu row (SELECT cycles All → every Home Assistant
  label the last fetch saw); the picker then lists only scripts/scenes
  carrying the chosen label, and blank lists everything, as before
- The offered labels are the ones in use by scripts/scenes — the label
  registry itself is websocket-only — so the row fills up after a fetch
  (picker or "Update metadata") and cycles All ↔ the stored label until then
- The 32-shortcut cap now applies after filtering, so untagged entities can
  no longer crowd tagged ones out of the list
- Labels longer than 23 characters are not offered in the cycle: the row
  would have to clip the name, and a clipped name matches nothing, so the
  picker would empty with no visible reason
- A stored label that HA later renames or deletes stays on the row for one
  press and then cycles to All, instead of jumping to an arbitrary label
- While a filter is active, kept-but-untagged shortcuts are neither re-added
  to the picker as red rows nor marked missing (main screen included); clear
  the filter to manage them

Version 0.6.12026-08-23T08:53:51.545

- Touch ON by default — bare Touch toggle in the phone settings (no firmware-bug caveat text), watch-side default ON for fresh installs                                                                             
 - Pull-down to sub-menu (HeadeRSS pattern): arms only when the menu content is at its very top (real scroll offset, not the selection — same firmware quirk) and the finger starts in the top band; the 3-dot row   
   inverts as the armed cue; drag back up cancels; release-while-armed opens the sub-menu; rubber-band sheet + snap-back                                                                                             
 - Single tap fires a shortcut — CONFIRM shortcuts still stop at the UP+DOWN dialog (button-only: both pressed to arm, both released to execute, SELECT inert, BACK cancels — touch cannot confirm)                  
 - Version/changelog/README finalized in the feature commit

Version 0.6.02026-08-15T08:31:52.292

- Confirmation screen: shortcut icon above the prompt; confirm by pressing UP + DOWN together and releasing (BACK cancels)
- Watch vibrates on every shortcut launch and on every error/timeout
- New "Vibrations" sub-menu setting (ON/OFF) silences every haptic

Version 0.5.02026-08-15T06:06:07.393

- Picker now lists scenes alongside scripts (one merged list, same OFF / ON / CONFIRM cycling, same 32-shortcut cap)
- Execution routes by type: scene.turn_on / script.turn_on, entity-id based, so renames / duplicates / same-named scene+script pairs work
- Type visible at a glance: the main list's second line leads with a symbol — $ for scripts, a play triangle for scenes — then ·-joined area, tags and icon name; the symbol is always followed by a · divider and overflow truncates at the end, so the beginning of the line stays fixed
- New "Info line" sub-menu setting (SELECT cycles, like Automatic close): choose which fields the main-screen line shows — None, T·A·Tg·C, T·A·Tg, T·A, A·Tg·C, T·Tg·C, none - only name (only the name, 24pt bold and centered, no icon/subtitle) or none - big name (icon plus left-aligned name, 24pt, vertically centered, no subtitle) — persisted on the watch
- Fixed: scene subtitle had no divider/space between the play symbol and the area text (symbol touched the text); scripts already had $ · 
- Shortcut edit cards use a strict four-region label/value table: banner | top split (Type | Area) | state band | bottom split (Tags | Category) — muted bold labels, full-width rows, no fills, nothing overlaps the state band; full entity id as footer — same-named scene/script rows stay distinct
- Edit cards now respect dark/light mode: page, labels, values and footer follow the app theme instead of always being white
- The icon is only ever shown as the banner glyph — its mdi name is no longer rendered as text anywhere on the edit card
- Category row: HA categories (entity-registry scope mapping) are exposed only over WebSocket, which PebbleKit JS cannot use, so the row shows — until HA exposes them via REST/templates; the earlier values under "Category" were the entities' icon names, which is what made it confusing
- Category falls back to the HA domain default (script-text / palette) when an entity has no icon
- Scene/script pairs with the same key are independent shortcuts: launcher slots, reorder, removed-position restore and metadata refresh are all type-aware
- Old stored shortcuts migrate cleanly (all existing entries stay scripts)
- Fixed: browse parser no longer drops scene entities (was script-only)

Version 0.4.02026-08-15T05:56:17.559

- Picker now lists scenes alongside scripts (one merged list, same OFF / ON / CONFIRM cycling, same 32-shortcut cap)
- Execution routes by type: scene.turn_on / script.turn_on, entity-id based, so renames / duplicates / same-named scene+script pairs work
- Type visible at a glance: the main list's second line leads with a symbol — $ for scripts, a play triangle for scenes — then ·-joined area, tags and icon name; the symbol is always followed by a · divider and overflow truncates at the end, so the beginning of the line stays fixed
- New "Info line" sub-menu setting (SELECT cycles, like Automatic close): choose which fields the main-screen line shows — None, T·A·Tg·C, T·A·Tg, T·A, A·Tg·C, T·Tg·C, none - only name (only the name, 24pt bold and centered, no icon/subtitle) or none - big name (icon plus left-aligned name, 24pt, vertically centered, no subtitle) — persisted on the watch
- Fixed: scene subtitle had no divider/space between the play symbol and the area text (symbol touched the text); scripts already had $ · 
- Shortcut edit cards use a strict four-region label/value table: banner | top split (Type | Area) | state band | bottom split (Tags | Category) — muted bold labels, full-width rows, no fills, nothing overlaps the state band; full entity id as footer — same-named scene/script rows stay distinct
- Edit cards now respect dark/light mode: page, labels, values and footer follow the app theme instead of always being white
- The icon is only ever shown as the banner glyph — its mdi name is no longer rendered as text anywhere on the edit card
- Category row: HA categories (entity-registry scope mapping) are exposed only over WebSocket, which PebbleKit JS cannot use, so the row shows — until HA exposes them via REST/templates; the earlier values under "Category" were the entities' icon names, which is what made it confusing
- Category falls back to the HA domain default (script-text / palette) when an entity has no icon
- Scene/script pairs with the same key are independent shortcuts: launcher slots, reorder, removed-position restore and metadata refresh are all type-aware
- Old stored shortcuts migrate cleanly (all existing entries stay scripts)
- Fixed: browse parser no longer drops scene entities (was script-only)

Version 0.3.02026-08-14T18:04:49.036

- Stored shortcuts -> instant launch, no browsing
- Picker auto-fetches all HA scripts (names, areas, labels, icons) and refreshes the stored metadata; update it any time from the sub-menu
- Per-shortcut OFF / ON / CONFIRM; the confirm screen is a quick step — execution then runs from the main screen exactly like without it
- Missing scripts show a red !; SELECT deletes them right from the list, BACK keeps them (HA may be temporarily unreachable)
- Robust against renamed / duplicated / deleted scripts: execution uses script.turn_on by entity id, so entity-id renames and duplicates work; unavailable ghosts are never listed
- Icon clustering: 79 glyphs cover about half of Material Design Icons via concept clusters (all garage-* -> one garage, bed-* -> home, ...)
- Automatic close (Never/3s/5s/10s/15s/30s), set on the watch
- Touch-ready; dark/light themes + accent color
- Reorder that only commits when you drop; order never touched by updates
- Up to 32 shortcuts (comfortable for a watch; keeps the app lean)
- Fixed: CONFIRM flow freeze, invisible icons, missing labels/tags, exec-feedback text, 400-on-ghost-script execution

Version 0.2.02026-08-14T16:28:58.916

Initial release, yet more to come!