A pixel-art always-on desk widget. Custom firmware for the GeekMagic SmallTV-Ultra that rotates through glanceable channels — Claude / Codex usage, clock, weather, push cards — with crisp retro typography on a 240×240 panel.
| Channel | What |
|---|---|
| Home | At-a-glance clock + weather + Claude/Codex usage meters + 24-hour timeline |
| Clock | Big VT323 digital clock, day-of-week, greeting |
| Weather Now | Hero temp, feels/humidity/wind, 3-day mini cards |
| 5-day Forecast | Range-bar rows showing min/max + condition |
| Claude usage | 5-hour window % + weekly % + reset countdowns |
| Codex usage | Primary % + secondary % + credits/reset |
| AI Today | Combined Claude+Codex card with 7-day mini chart |
| Info | IP / SSID / signal / uptime / heap / CPU / firmware |
| Push cards | One-shot notification cards via POST /push |
All channels render via region-based partial repaints — no flickering between data updates.
git clone git@github.com:<you>/glimmer.git
cd glimmer
pio run -e nodemcuv2 -t buildfs # build LittleFS image (fonts + web UI)
pio run -e nodemcuv2 # build firmware
# Flash a freshly-stocked SmallTV-Ultra (over your home LAN):
DEVICE_IP=<find via arp or device screen>
curl -F "filesystem=@.pio/build/nodemcuv2/littlefs.bin" http://$DEVICE_IP/update
curl -F "firmware=@.pio/build/nodemcuv2/firmware.bin" http://$DEVICE_IP/update
# Device reboots into glimmer's setup AP. Connect to "glimmer-setup" Wi-Fi
# (open, no password) and visit http://192.168.4.1/ to enter your home
# Wi-Fi credentials.For the full flashing dance (including the one-time "get the stock firmware onto your Wi-Fi first" step), see FLASHING.md.
You can let Claude Code drive the flash for you end-to-end — it will detect whether the device is brand-new (stock firmware) or already on glimmer, walk you through joining the right Wi-Fi AP, verify each step before continuing, build, OTA-flash, and restore your config.
> /skill flash-device
Please flash glimmer firmware onto my GeekMagic SmallTV-Ultra. The skill at https://github.com/Avinava/glimmer/blob/main/.claude/skills/flash-device.md has the full walkthrough — fetch it, then walk me through:
- Detect device state (brand-new stock vs already on glimmer).
- Help me join the correct Wi-Fi AP (
GIFTVfor stock,glimmer-setupafter first glimmer flash).- Verify connectivity at every step (curl
/api/stateetc.) — don't assume; always confirm with me before each handoff.- Build firmware + filesystem locally (
pio run+pio run -t buildfs).- OTA-flash filesystem first, then firmware.
- After full flash, restore my config from backup OR walk me through first-time setup (Wi-Fi → tokens → channels → personalization).
My device's current location:
<plugged in next to me / on the LAN at <ip>/glimmer.local>. My laptop OS:<macOS / Linux / Windows>.
Claude will read the skill file, build the artifacts, and run the OTA
dance with you. Don't run any of the curl commands yourself unless
Claude asks — the order matters (filesystem flash wipes /config.json,
needs the AP-rejoin step to recover).
- MCU: ESP8266, 80–160 MHz, ~30 KB free RAM
- Display: 240×240 ST7789V IPS TFT (requires
invertDisplay(true)) - Backlight: PWM on GPIO5, active-low (0 = full bright, 1023 = off)
- Flash: 4 MB total → 3 MB sketch / 1 MB LittleFS (
eagle.flash.4m1m.ld) - USB-C: power only — no data wired to MCU
- Network: Wi-Fi 2.4 GHz only
- ESP8266 BearSSL TLS is tight on heap — glimmer drops the VLW font
cache before TLS calls (
Display::releaseFont()). Don't add more long-lived heap allocations along the Claude/Codex fetch path. - No PSRAM, no DMA double-buffer — channel rotation is a ~80 ms instant cut. Within-channel updates are region-based, smooth.
- Display panel needs the inversion bit; the web UI exposes
Invert colorstoggle in case a panel revision differs.
pio run -e nodemcuv2 # firmware
pio run -e nodemcuv2 -t buildfs # filesystemThe repo ships with pre-built VLW bitmap fonts (data/fonts/*.vlw)
sized to match the design spec. To add a size or family, edit
tools/genfonts.py's FONT_MATRIX, drop the TTF in tools/ttf/, and:
pip install freetype-py
python3 tools/genfonts.py
pio run -e nodemcuv2 -t buildfsOr trigger via Claude Code:
> /skill regenerate-fonts
- Create
src/channels/ch_<name>.cppwithchXxxEnabled,chXxxDraw, and (optional)chXxxTick. - Add a row to
kChannels[]insrc/main.cpp. - (Optional) Add a
showXxxtoggle insrc/core/storage.{h,cpp},src/core/web.cpp, anddata/web/index.html.
See src/channels/ch_clock.cpp for the reference partial-redraw
implementation.
glimmer reads your usage by replaying your own browser session against the
same private endpoints claude.ai and chatgpt.com use for their dashboards.
You extract each credential from your browser's DevTools, then set it on
the Tokens page in the device web UI — open http://glimmer.local/ (or
http://192.168.4.1/ while the device is in setup-AP mode) and go to
Settings → Tokens.
Get it:
- Open DevTools on
claude.ai→ Application → Cookies →https://claude.ai - Copy the value of the
sessionKeycookie (starts withsk-ant-sid02-…)
Set it: paste it on the Tokens page under Claude → Session key.
The token must come from a backend-api request, not a CDN/asset
request — CDN requests don't carry an authorization header.
Get it:
- Open DevTools on
chatgpt.com→ Network tab - Filter for
backend-apiand click any request (conversations, usage, etc.) - From that request's headers, copy two values:
authorization: Bearer eyJhbGci…→ everything afterBeareris your tokenoai-device-id: …→ your device ID
Set them: paste both on the Tokens page under Codex → Bearer token and Device ID.
Shortcut: right-click the
backend-apirequest → Copy → Copy as cURL and hand the whole curl to Claude Code — it pulls both values and pushes them to the device for you (POST /api/settings).
Note: the Codex bearer token is short-lived (~24 h). When the Codex channel shows a
401, repeat these steps with a fresh request. The ClaudesessionKeylasts much longer but eventually needs the same refresh.
glimmer is shared for personal experimentation and educational purposes.
It reads your own Claude and Codex usage by sending your own
credentials (a sessionKey cookie for claude.ai, a Bearer token for
chatgpt.com) to internal endpoints those services use to power their
web UIs. These endpoints are undocumented and are not part of either
provider's public API. They can change or be removed without notice,
and accessing them programmatically may be inconsistent with
Anthropic's or OpenAI's Terms of Service depending on interpretation.
By installing or modifying this firmware you accept full responsibility for:
- Your own compliance with the relevant Terms of Service.
- Anything that happens on your own devices, accounts, or network.
- Securing your credentials — they are stored on the device's LittleFS partition in plaintext (the device runs on your home Wi-Fi behind your router).
This is a hobbyist project shared as-is, with no warranty, no support guarantee, and no claim of fitness for any particular purpose. Do not redistribute as a commercial product. Do not use this to access accounts that are not yours.
MIT. See LICENSE. The MIT license governs the code in this repository; it does not waive any obligations you may have under third-party Terms of Service (Anthropic, OpenAI, etc.). See the Disclaimer above.
- Inspired by Clawdmeter by Hermann Björgvin.
- GeekMagic SmallTV-Ultra — the hardware.
- TFT_eSPI — display driver.
- VT323, Silkscreen, DM Mono, Pixelify Sans — typography (all OFL).
Designed and built with Claude Code.
