PRJ

Claude Code Usage on My Wrist (Garmin Fenix 7X)

13 June 2026
SPECPROJECT
RoleDesign & build (personal project)
Date13 June 2026
Stack
Monkey CConnect IQ SDKPythonGitHub GistAnthropic APIClaude Code
13 June 2026 ·Design & build (personal project)
Monkey CConnect IQ SDKPythonGitHub GistAnthropic APIClaude Code

Background

I wanted to prove something to myself: that Claude Code can take an idea all the way to a working utility — not a throwaway proof-of-concept that demos once and rots, but something I’d actually keep on my wrist. I also have a long-running hobby of building software for the devices I already own, and a Garmin Fenix 7X is the device I look at most.

The concrete itch was small but real. I live inside Claude Code, and Anthropic meters usage against a rolling 5-hour session window. Checking how much of that window I’d burned meant breaking flow to look it up. I wanted the number glanceable on my wrist — no app to open, no phone to tap, just a watch face. The interesting constraint: a Garmin watch can’t talk to my laptop, and it certainly can’t hold my Claude credentials. So the real problem wasn’t drawing a ring — it was getting a private number from my machine onto the watch safely.

What I built

Two cooperating pieces and a deliberately boring relay between them.

  1. A Windows sidecar daemon (usage_pusher.py) that runs on my laptop. It reads the OAuth token Claude Code already stores locally, polls Anthropic’s usage endpoint, compacts the response to a ~140-byte JSON snapshot (5-hour %, 7-day %, reset timestamps), and PATCHes it onto a secret GitHub Gist every five minutes.
  2. A Connect IQ watch face for the Fenix 7X, written in Monkey C. A background service fetches the Gist through Garmin Connect Mobile over Bluetooth; the foreground renders a “Pixel Ring” design — 24 blocks around the bezel, one per 12.5 minutes of the 5-hour window, filling clockwise from twelve o’clock. The in-progress block blinks, an original pixel-art mascot walks along the bottom, and time, date, and step count sit in the middle.
  3. A Gist as the dead drop. The watch reads a public raw URL; the laptop is the only thing that writes. My Claude token never leaves the laptop, and the watch never touches Anthropic.

If the feed goes stale (older than 30 minutes), the ring dims and the label shows --% — so a dead pipeline never lies to me.

Outcome

The whole thing is built, validated, and running on real hardware:

  • End-to-end flow proven in the Connect IQ simulator first — sidecar → live Gist → background fetch → on-screen render — then sideloaded to a physical Fenix 7X over USB.
  • On-watch fetches succeed through the phone: the background temporal event pulls the Gist, gets a 200, stores the snapshot, and the ring fills to match live usage.
  • The sidecar is a single self-contained Python module; the watch app is three small Monkey C classes (app lifecycle, background networking, and the Pixel Ring view) plus the design resources.
  • The snapshot payload is orders of magnitude under the watch’s 8 KB background hand-off cap, so parsing and battery cost are negligible.

Stack rationale

Monkey C + Connect IQ SDK, because that’s the only way onto the watch. The platform’s constraints shaped every decision. Watch faces can’t make web requests from the foreground, so all networking lives in a background ServiceDelegate registered for a temporal event — which the runtime caps at a 5-minute minimum. The 280×280 transflective display renders only 64 colours (RGB222) with no anti-aliasing, which is exactly why a pixel-art ring and mascot look native here rather than like a compromise. Animations (the walking mascot, the blinking block) run only during the brief high-power window after a wrist-raise; in always-on mode everything freezes to stay inside the power budget.

A GitHub Gist instead of a server, because the cheapest moving part is the one you don’t run. The watch needs an HTTPS URL it can reach through Garmin Connect Mobile; a secret Gist gives me that for free, with the laptop as the sole writer. No hosting, no auth surface of my own to secure.

Anthropic’s OAuth usage endpoint, not the /v1/messages header-probe trick. An alternative way to read usage is to send a throwaway message and inspect the rate-limit headers — but that spends token quota. The usage endpoint returns the same numbers for free, so the monitor never costs me the very budget it’s monitoring. The sidecar reuses the credentials Claude Code already wrote, so there’s no separate login to build.

Where the experiments happened. I first explored the look as HTML/CSS prototypes across five directions — pixel blocks, a skyline bar chart, an arcade HP-bar HUD, a rising-tide fill, and the pixel ring — and locked in the ring. The build had its detours: the simulator initially returned null for the app’s configured URL, so I shipped a hardcoded fallback to keep the plumbing moving, then removed it once I’d verified the settings layer reads its default reliably. Sideloading to the real watch was its own small adventure — the Fenix mounts over MTP, not as a USB drive, so the .prg goes into GARMIN\Apps through the device’s media interface rather than a copy-paste to a drive letter.

The result is the thing I set out to prove: an idea, end-to-end, into a working tool I actually wear.


Personal project. The Claude usage data is Anthropic’s; the watch face, the relay, and the pixel mascot are mine.

← All projects