Skip to content

Releases: niclasvestlund-YT/vibepulse

v0.7.0 — Codex on the glass, live data on any Wi-Fi

Choose a tag to compare

@niclasvestlund-YT niclasvestlund-YT released this 22 Aug 23:41
3b3f20c

Codex Needs You on the VibePulse panel   Codex recommended question on the panel   Codex safe command approval on the panel

Real 480×480 captures from the shared LVGL firmware renderer—the same layout and pixels sent to the panel, not design mockups.

VibePulse can now show supported Claude Code and Codex decisions on the panel,
move to a new Wi-Fi from a phone, and keep its numbers current when the panel
and computer are on completely different networks.

The Mac or PC still needs to be awake, online, and running tokenserver. The
panel does not need to be in the same home or on the same Wi-Fi, and the user
never has to reconfigure the router. Both sides make normal outbound internet
connections through the optional Cloudflare relay.

Wi-Fi setup from a phone

VibePulse looking for a saved 2.4 GHz network   Phone-scannable VibePulse Wi-Fi setup   The connected Wi-Fi mark on a normal panel page

Adding Wi-Fi is now a phone task, not a firmware-editing task. The panel opens
a temporary VibePulse-setup network and shows a phone-scannable QR code.
Choose a visible 2.4 GHz network, enter that network's normal password, and the
panel saves it only after a successful connection. Existing networks remain as
recovery choices.

On normal app pages, the top-right Wi-Fi mark has two clear states: a complete
fan means connected; the same full-size fan with a slash means offline.
Full-screen setup covers the normal-page mark while setup is active.

What is new

  • Codex on the glass. Codex uses the same large Needs You design as Claude
    Code. Supported recommendations and a narrow safe-command set can be answered
    from the panel; uncertain or unsafe actions stay on the computer.
  • Live numbers on any Wi-Fi. Claude/Codex quotas, reset times, Max Tracker,
    and optional GitHub numbers can travel through an outbound-only Cloudflare
    relay. The panel and computer may be on unrelated networks.
  • A strongly consistent numbers relay. One SQLite-backed Cloudflare Durable
    Object merges concurrent publishers atomically, with zero KV operations on
    the active request path.
  • Claude data self-recovers. When local Claude credentials are renewed, the
    tokenserver notices promptly and immediately publishes the first fresh values
    instead of leaving the panel stale behind the normal relay write ceiling.
  • Optional remote approvals and activity. Encrypted Needs You approvals and
    minimized live activity are separate features. Both remain off by default.
  • Private by default. When the encrypted interaction relay is enabled,
    question text, commands, project names, activity, and verdicts are end-to-end
    encrypted. Cloudflare handles ciphertext and delivery metadata, not plaintext.
  • Open-source friendly switches. Claude, Codex, interaction detail, numbers
    relay, encrypted approvals, encrypted live status, and GitHub can each be
    enabled or disabled independently. GitHub stays off unless enabled.

Reliability and safety

  • The LVGL memory pool is pinned and guarded at 256 KiB, fixing the stale
    96 KiB configuration that could wedge glyph rendering while the display lock
    was held.
  • Panel verdicts are authenticated against the live provider, request, and exact
    displayed view, with expiry and one-time resolution enforced. Encrypted-relay
    verdicts additionally bind the random challenge and message direction.
  • Approval text must fit the loaded font and physical screen bounds before a
    panel approval is offered.
  • Wi-Fi reconnect ordering, setup/OTA ownership, stale-data recovery, replay,
    expiry, HTTP limits, setup transactions, and subprocess cleanup have
    dedicated regression coverage.

Setup in plain English

  1. Teach the panel a 2.4 GHz network from the phone setup screen.
  2. Run python3 tools/vibepulse_setup.py install on the Mac or PC and choose
    Claude, Codex, both, or neither.
  3. Enable the numbers relay if the panel should receive quotas and tracker data
    away from the local network.
  4. Separately enable the encrypted interaction relay only if remote approvals
    are wanted.
  5. Separately enable encrypted live status only if remote Claude/Codex activity
    is wanted.

Direct LAN remains preferred whenever it works. The cloud features above are
optional and independently switchable.

Honest limits

The ESP32-S3 uses 2.4 GHz Wi-Fi. On iPhone, enable Maximize Compatibility
for a personal hotspot. Captive portals, offline networks, TLS interception,
and networks that block Cloudflare Worker domains are not solved. Remote data
and decisions stop when the computer or tokenserver is off.

Verification status

  • PR #25 is merged at
    3b3f20c; every GitHub check is green, including ESP32-S3 firmware, the full
    host gate, macOS/Ubuntu/Windows tokenserver suites, and both Worker suites.
  • Full host gate: 763 tests, plus the portable C, firmware wiring, privacy,
    setup, and security checks.
  • After this commit was installed, the physical panel completed phone Wi-Fi
    onboarding, showed the corrected
    two-state Wi-Fi mark, restored GitHub/Codex data, and cleared stale Claude
    data after credential recovery.
  • The live numbers relay was verified end to end across unrelated networks.
  • Publishing this GitHub release does not flash firmware or write ota_0.

v0.6.0 — Needs You: answer Claude from the panel

Choose a tag to compare

@niclasvestlund-YT niclasvestlund-YT released this 16 Aug 16:44

The shelf panel stops being a monitor and becomes an input device. When
Claude Code blocks on a question or a permission, the whole screen turns into
a takeover — and a tap on the glass answers it, in the same live session, no
window to switch to. The alert you already had now closes the loop it was
pointing at.

Attract: a mascot in a depleting countdown ring   Decision: the question and Claude's recommended answer   Payoff: a short ON IT beat

Attract → decision → done. Every frame is an unmodified 480×480 simulator render — the same pixels as the panel.

What it does

  • Tap to answer. A held prompt surfaces as a mascot in a depleting
    countdown ring (attract). A tap reveals the question and Claude's
    recommended answer (decision). APPROVE commits it; LEAVE IT hands it
    back to the terminal. The flow closes on a short "ON IT" beat.
  • Signed on the glass. Every verdict is signed with a device key that
    lives only on the panel (HMAC-SHA256). It grants exactly one thing: the
    ability to answer a prompt this Mac was already going to ask about.
  • Fail-safe. Walk away and nothing happens — an unanswered prompt falls
    back to the normal terminal prompt, and the tokenserver being down is an
    instant terminal fallback too.
  • Opt-in. Off by default. Needs a device key, the --interactions bridge,
    and two Claude Code hooks. Full setup in docs/agent-setup.md.

Also in this release

  • Freeze fix. A silent intermittent hang on the panel is fixed: LVGL's
    memory pool sat in internal RAM and starved the display-flush DMA block
    below its threshold. Moved to PSRAM (internal free 22 → 147 KB). Story in
    docs/lessons.md.
  • Decision-screen polish. A long question now steps its font down and
    stays above the recommendation card instead of overwriting it.
  • KEY3 ergonomics. While the OTA maintenance window is open, any KEY3
    release closes it.

Hardware-verified end-to-end on a real panel: tap → signed verdict → Claude
answered.

v0.5.0 — the value multiple and the GitHub star pulse

Choose a tag to compare

@niclasvestlund-YT niclasvestlund-YT released this 15 Aug 14:15

Release: the value multiple and the GitHub star pulse (2026-08-15)

Two optional features reach the glass, side by side. One answers the question
every subscriber has standing every month — am I getting my money's worth?
by pricing the tokens your agents already logged against what you pay. The
other lets the panel carry a public repo's star count and celebrate a new
star, by name. Neither is on by default; each is something you turn on.

Enable / disable — this is opt-in, both halves

  • The GitHub star pulse is entirely opt-in, via three independent,
    default-off flags in secrets.h (a fresh clone stays Claude/Codex-only
    until you set them):

    • TK_GITHUB_SCREEN_ENABLED — the star + fork screen (one swipeable tile).
    • TK_GITHUB_NOTIFICATIONS_ENABLED — the full-screen popup when a new star
      lands.
    • TK_GITHUB_SOUND_ENABLED — sound on that popup (a third, separate opt-in).

    Plus point the tokenserver at a repo: --github-repo owner/repository
    (and TK_GITHUB_URL in secrets.h). Leave any flag at 0 and that part
    simply isn't built. See docs/github-pulse.md.

  • The value multiple is opt-in by declaration. It shows nothing confident
    until you tell the tokenserver what you actually pay. Declare it and the
    tile lights up; leave it out and the page shows the dollars but dashes the
    multiple rather than guess. See docs/value-multiple.md.

The value multiple

  • What it is. Your month-to-date agent usage, priced at published list API
    rates and divided by your subscription cost. "$516 of Codex value against a
    $100 plan — 5.16×."
    Same data as the Usage page, aimed at a different
    question. Turn it on by stating your real costs:
    --plan claude=200 --plan codex=100 (dollar overrides), or the named tiers
    --claude-plan {pro,max5x,max20x} / --codex-plan {plus,pro}.
  • It refuses to guess. A model the price table doesn't know becomes
    unpriced tokens; past a small tolerance the whole multiple degrades to a
    dash rather than show a confident wrong number. Rates are generated from a
    maintained public catalogue, never hand-typed.
  • The Codex overcount, fixed. The Codex half read $8,296 for a month
    that was 10% of a weekly quota. The rate was never wrong ($0.67/Mtok, right
    next to Claude's) — the token count was inflated ~16×. codex resume,
    fork and subagent-spawn each replay the parent conversation's entire
    token_count history, re-timestamped, under the same session_id; summing
    every rollout counted one conversation once per resume (a real ~/.codex
    held a single conversation across 113 files). Now grouped by session_id
    and counted once, from the most-complete rollout. $8,296 → $516.

The GitHub star pulse

  • What it is. The Mac tokenserver polls a public repo's star and fork
    count (TLS, rate-limiting and backoff all live on the computer) and
    republishes one flat LAN payload on /api/github; the panel shows a tile
    and, when a new star lands, a full-screen celebration. The display never
    talks to GitHub.
  • The name, read-only. The celebration names who just starred. Reading
    that used to fall back to "someone": GitHub gates the REST stargazers list
    behind a write permission. It now reads the newest star from the public
    events feed (WatchEvent), which needs only metadata=read — so a
    fine-grained, public-repositories, read-only token resolves the name
    with the least privilege possible. No token still works; it just shows
    "someone" as before. The token lives in git-ignored secrets.h
    (#define TG_GITHUB_TOKEN "…"), never committed.

Both on one panel

The value tile and the GitHub tile now coexist in the swipeable usage strip —
eight tiles: the Claude/Codex quota and tracker views, then GitHub, then the
value multiple. Neither replaces the other; you swipe between them.

Verified

Host suite green; the firmware built once and was delivered over the air with
consent on the glass; the panel reports both tiles live and the value figure
at the corrected $516. The read-only token was proven against the real repo
(HTTP 200, name resolves) before going live.

v0.4.0 — The OTA platform: self-updating firmware with consent on the glass

Choose a tag to compare

@niclasvestlund-YT niclasvestlund-YT released this 14 Aug 13:11

Release: the OTA platform (2026-08-14)

One day, one arc: from a frozen panel at dawn to a screen that updates
itself over the air, asks permission with big buttons on the glass, and
rolls back bad images on its own.

Highlights

  • The freeze diagnosed and fixed. A companion app's RAM load plus the
    OTA foundation's boot footprint starved the panel flush's DMA bounce
    buffer (largest free block < 11,520 B ⇒ endless NO_MEM). The companion
    is now explicit opt-in (-DTORGET_WITH_BUDDY=ON), mirrored in the
    simulator, pinned by tests.
  • A/B over-the-air updates, proven in ten live deliveries. A 3-second
    KEY3 hold or a tap on the UPDATE pill opens a ten-minute maintenance
    window; a bearer token, SHA-256 and a metadata gate guard the upload;
    the image lands in the inactive slot; a boot-health gate must approve
    within 15 seconds or the bootloader rolls back. USB-C is never written
    by an OTA and remains the rescue path.
  • The UPDATE READY notice. The tokenserver announces the newest build
    on the existing quota poll; the screen takes over with the waiting
    version and two large buttons — UPDATE NOW / LATER. Hourly reminders
    until installed, silence when versions match, and never a takeover
    while an update is already running.
  • The OTA ring. READY (a clockwise-draining egg timer with mm:ss),
    INSTALLING (clockwise fill, percent, the incoming image's own version),
    VERIFYING (SHA-256), RESTARTING. Physically reviewed and refined over
    three rounds.
  • The boot screen. The wordmark over WIFI → TIME → DATA, each lit by
    its real signal, torn down the moment the first fetch lands. No more
    NO DATA flash at power-on. Physically approved.
  • A bulletproofed tokenserver. Dead OAuth tokens are never resent; a
    machine-wide probe lock allows at most one upstream prober per Mac; the
    429 penalty persists across restarts; used-today is computed from
    cached cycle timestamps and survives blackouts; scoped weekly pools
    show whenever they hold real usage; 15 calls/hour baseline.
  • Sender gates. The binary is chosen at the moment of upload, its
    embedded version is read from the app descriptor and always announced,
    and -dirty builds are refused without TG_OTA_ALLOW_DIRTY=1 — the
    lesson from the archived ghost build that froze the glass.
  • Attention alarms breathe for 45 seconds (4.8 s was missed in
    practice); DONE cards pulse their whole visibility window.
  • Documentation. docs/ota.md (the full loop and consent model), a
    README section, new symptom-table rows in the agent runbook, and
    CLAUDE.md ground rules.

Verified on the physical device

Ten OTA deliveries (including the first touch-consented and the first
fully chained one), a PENDING_VERIFY boot with the health gate live and
approving at 9.1 s (console-logged), automatic window re-arm after OTA,
the rollback net armed, and both the boot and OTA screens reviewed on
glass.

Known remaining

  • The value page (page seven) is being reworked — not part of this
    release.
  • A CI bridge in the pusher (refuse builds without green CI) — ordered,
    next session.
  • The ring's breathing pulse awaits its motion review.
  • A pusher daemon so the UPDATE tap always has a deliverer.

v0.2.1 — the probe survives reality

Choose a tag to compare

@niclasvestlund-YT niclasvestlund-YT released this 13 Aug 20:14
45cbc9b

What changed

Server fixes, all verified live on a real installation the same evening:

  • The probe survives reality. The tokenserver tries every token source and
    falls back on 401/403, so a stale Claude Desktop process token can no longer
    block a fresh keychain login. And it no longer requires an active 5-hour
    session window: between windows the weekly and per-model figures flow on
    their own, while the session field honestly shows a dash.
  • Rate limits are handled, not fed. On HTTP 429 the probe stops the cycle
    at once and rests at least ten minutes (honouring Retry-After). Repeated
    failures slow the cadence from 120 s to 480 s, so a dead credential idles at
    six requests an hour instead of sixty.
  • The status tells the whole story. claudeProbe preserves the usage
    outcome and appends the fallback result instead of overwriting it, and the
    root endpoint reports rev + startedAt — "the wrong code is running" is
    now one curl, not an evening of process archaeology.
  • Firmware: stale alerts stay out of your face. Full-screen alerts now
    require the state change to be under two minutes old after boot too, so
    hours-old waiting states rediscovered after a server outage stay in the
    header. Reaches your device on its next flash.

Known

  • The alert's pulse phase draws no motion yet — an actual pulse is gated
    behind the AMOLED review protocol.

Upgrading

git pull, then restart the service:
launchctl kickstart -k gui/$UID/se.torget.tokenserver.
Reflash the board when you want the alert fix on the panel.

v0.2.0 — VibePulse only

Choose a tag to compare

@niclasvestlund-YT niclasvestlund-YT released this 13 Aug 13:45
e353371

What changed

One app. VibePulse is now the only app in this repository, and the screen
boots into it. The maintainer's other screens moved to their own repos and are
compiled in only if you happen to have them checked out. A fresh clone builds
exactly one thing.

Corrections. The README described a "5-hour session" page that does not
exist — the firmware builds six: Claude heaviest-model week, Claude all-models
week, Codex week, burn rate, and a Max Tracker per provider. The privacy
section was too narrow: the screen also receives coarse status (project name,
model, effort), and a lost screen carries your Mac's LAN hostname alongside
your WiFi credentials.

Setup. secrets.h.example ships the VibePulse URLs active with a
placeholder instead of commented out — an undefined URL compiles the fetch out
entirely and leaves a screen that boots happily and shows dashes forever. New
docs/agent-setup.md is a runbook for coding agents: a verification after
every step, and a symptom→fix table.

Build. Companion apps resolve during ESP-IDF early expansion and their
paths are cache variables, so a present companion is never silently dropped.
The host gate links libm and checks fread returns, so all 307 tests — SDL
landmark captures included — now run headless on Linux as well as macOS.

Upgrading

Git history was rewritten in this cycle. An existing clone will not
fast-forward: re-clone, or git fetch origin && git reset --hard origin/main.

To update a board: pull and reflash. Flash in download mode with the panel
dark, and run the screen from its own power supply.

v0.1.0 — first public release

Choose a tag to compare

@niclasvestlund-YT niclasvestlund-YT released this 13 Aug 07:01

A shelf screen for your Claude Code and Codex usage: quota pages with reset countdowns, a live agent monitor with a full-screen NEEDS YOU alert, burn-rate forecasts, and the Max Tracker daily heatmap with coding streaks.

ESP32-S3 AMOLED firmware, a pure-stdlib macOS service, and a pixel-identical SDL simulator. Everything stays on your LAN.

To update: pull and reflash (flash in download mode; run the screen from its own power supply).

This is an ongoing project. Expect rough edges and frequent commits.