Skip to content

iBrewerRoot/Clawdmeter-Standalone

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

103 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Clawdmeter

🍴 Fork — standalone, no companion script

This is a fork of HermannBjorgvin/Clawdmeter. The original relies on a companion script (a daemon / tray app) running on your computer: it reads your Claude token, polls the API, and pushes the numbers to the device over Bluetooth. I didn't want that — a machine that has to stay on running a background process. So this fork makes the device fully autonomous: it joins your WiFi and talks to the Anthropic API by itself. Nothing runs on your PC.

What this fork changes

  • No host daemon — the device polls the Anthropic API directly over WiFi and refreshes its own login token (~every 8 h).
  • On-device setup — first boot opens a Clawdmeter-setup WiFi hotspot with a web form to enter WiFi and sign in with your Claude account (OAuth). No cable, no app, no PC.
  • Re-open setup anytime with a triple-click on the BOOT button — change WiFi / clock / login without wiping.
  • Idle wall-clock when plugged in and idle (configurable time zone + style).
  • Top button sends Enter to validate Claude Code prompts (was Space).
  • Bluetooth kept only for the side-button HID keyboard.
  • Extra usage views — additional pace / history-sparkline / active-limit pages.

Everything below documents this autonomous build. To pull future changes from the original, see Keeping in sync with upstream.

A small ESP32 dashboard I made for my desk to keep an eye on Claude Code usage.

It runs on a Waveshare ESP32-S3-Touch-AMOLED-2.16 as well as a few other alternative boards. It is fully standalone: it joins your WiFi, queries the Anthropic API directly, and refreshes its own login — no PC, no companion app, no background daemon. The splash screen plays pixel-art Clawd animations that get busier when your usage rate climbs, and the side buttons act as a Bluetooth keyboard for Claude Code shortcuts.

Usage meter Clawd animation screen
Usage meter Clawd animation screen

The Clawd animations come from claudepix, @amaanbuilds's library of pixel-art Clawd sprites, check it out, it's lovely.

Screens

The device boots into the splash. Tap the screen anywhere to switch to the Usage view; tap again to flip back to the splash.

Splash Usage
Splash Usage
Splash; touch-toggle anytime Session and weekly utilization

While the splash is up, the middle (PWR) button cycles animations. The firmware also auto-rotates animations every 20 s within the current usage-rate group, so a long stretch on the splash isn't just one Clawd on loop.

When plugged into USB and idle (Claude "Ready", no active usage for ~1 min), the Usage view can switch to an idle clock instead — see Idle clock.

Hardware

Boards supported out of the box:

PSRAM is required. Because the device queries the Anthropic API itself, every refresh runs a TLS handshake whose buffers (~32 KB) live in PSRAM — without it the handshake runs out of internal RAM and usage never loads. Only PSRAM-equipped ESP32-S3 boards are supported. (An earlier ESP32-C6 port was dropped when the firmware went WiFi-autonomous, since the C6 has no PSRAM.)

Please check if a pull request exists for your alternative hardware port before opening a new one — QA feedback and testing on the same hardware is more valuable than duplicate pull requests.

Porting to another board. The firmware is a thin HAL with per-board folders under firmware/src/boards/: drop in a new folder and a new PlatformIO env — main.cpp, ui.cpp, and splash.cpp never need to change. A viable target needs:

  • an ESP32-S3 with OPI PSRAM (the TLS/usage path depends on it — see above);
  • a QSPI AMOLED panel with a driver in GFX Library for Arduino (CO5300, SH8601, NV3041A, …);
  • an I2C touch controller (any driver you can compile);
  • at least the BOOT button (a second button and an AXP2101 PMU / QMI8658 IMU / IO expander are optional).

See docs/porting/adding-a-board.md for the walk-through and docs/porting/hal-contract.md for the interfaces a port must implement.

Prerequisites

  • PlatformIO CLI on Linux, macOS, or Windows — only needed to build and flash the firmware.
  • A 2.4 GHz WiFi network (the ESP32 has no 5 GHz radio).
  • A phone or laptop with a browser, for the one-time setup.
  • A Claude account with an active subscription — you sign in on the device during setup.

That's it. There is no host-side software to install or keep running.

Flash the firmware

The board env name is either waveshare_amoled_216 or waveshare_amoled_18.

# macOS  (auto-detects /dev/cu.usbmodem*, or pass an explicit port)
./flash-mac.sh waveshare_amoled_216
./flash-mac.sh waveshare_amoled_18 /dev/cu.usbmodem1101

# Linux  (defaults to /dev/ttyACM0, or pass an explicit port)
./flash.sh waveshare_amoled_216
./flash.sh waveshare_amoled_18 /dev/ttyACM1
# Windows — use your device's COM port
pio run -d firmware -e waveshare_amoled_216 -t upload --upload-port COM5

Run the helper script (or pio run -d firmware) with no env to list the available boards.

Setup (WiFi + Claude sign-in)

On its first boot (nothing provisioned yet) the device starts an open WiFi access point called Clawdmeter-setup and shows a "Setup" hint on screen.

  1. Join the AP. Connect your phone or laptop to Clawdmeter-setup. A captive page should pop up automatically; if not, open http://192.168.4.1/.
  2. WiFi. Enter your 2.4 GHz network name and password, then Save & connect. The device joins your WiFi (it stays an AP at the same time so the page keeps working).
  3. Sign in with Claude. Click Open the Claude login page, sign in on Anthropic's own site, approve access, then copy the code it shows you and paste it back into the form. Your password / SSO / MFA happen entirely on Anthropic's pages — the device never sees them. It receives its own OAuth tokens and from then on refreshes them itself.
  4. Idle clock (optional). Enable it and pick a time zone + style if you want a clock when the device is plugged in and idle.

Once WiFi and sign-in are both done the portal closes by itself, the screen switches to the Usage view, and it refreshes every 60 seconds.

The sign-in uses the same OAuth flow as claude login (Authorization Code + PKCE). The endpoints and client id are undocumented, so a future Anthropic change could require a firmware update.

Re-opening setup later — triple-click BOOT (no wipe)

To change WiFi, sign in again, or adjust the clock on an already-configured device, triple-click the BOOT button (three quick presses). That re-opens the same setup portal without erasing anything. Triple-click again — or just wait for the safety timeout — to close it.

Two side notes: while the portal is open the Bluetooth keyboard is temporarily off (its RAM is reused for the secure connection), and because each BOOT press is also an Enter, a quick triple-click sends three Enters to whatever has focus.

Factory reset

To wipe the stored WiFi + tokens and start over, open the USB serial console at 115200 baud and send wipe. (Clock and brightness settings are kept.)

Pair the buttons (Bluetooth)

The side buttons reach your computer as a Bluetooth HID keyboard. Pair it once from your OS Bluetooth settings — it advertises as Clawdmeter. This is completely separate from the usage data (which travels over WiFi), so the dashboard works whether or not anything is paired. To clear the pairing and re-advertise, hold the PWR button for 3 seconds then release.

Idle clock

When the device is on USB power and Claude has been idle ("Ready", no active usage) for about a minute, the Usage view can swap to a clock. Enable it and configure it in setup step 4:

  • Time zone — the dropdown is preselected from your browser's zone; DST is handled on the device (it stores a POSIX TZ rule).
  • StyleTime only, Time + date, or Time + creature (a small sleeping Clawd).

It reverts to live usage the moment activity resumes, and never shows on battery (so it can't keep the panel lit overnight).

Physical buttons

The buttons are a standard BLE HID keyboard, so the keystrokes land in whatever window has focus on the paired host — not just Claude Code. Layout depends on the board:

Button GPIO Function
Top (BOOT) GPIO 0 Press → Enter (submit Claude prompts). Triple-click → open/close setup portal.
Middle (PWR) AXP2101 PKEY On splash: cycle animations. On usage: cycle brightness. Hold 3 s + release: clear BLE pairing.
Right GPIO 18 Press → Shift+Tab (Claude Code mode toggle). 2.16 boards only.

The AMOLED-1.8 has only the BOOT and PWR buttons (no third button).

How it works

  1. On first boot the device hosts a WiFi setup portal (SoftAP Clawdmeter-setup). You enter your WiFi and sign in with your Claude account over OAuth — the login runs on Anthropic's pages, so your password never touches the device. It stores its own access + refresh tokens in flash (NVS).
  2. Every 60 s it makes a minimal call to api.anthropic.com/v1/messages over your WiFi — one token of Haiku, basically free. The usage numbers come straight out of the response headers (anthropic-ratelimit-unified-5h-utilization and friends).
  3. It refreshes its own OAuth access token (~every 8 h, or immediately on a 401), so it stays autonomous indefinitely with no PC and no re-login.
  4. It tracks the rate of change of session % over a few-minute window and picks splash animations from the matching mood group; the status line shows playful "working" words during active usage and Ready when idle.
  5. Bluetooth is used only for the HID keyboard — the side buttons send keystrokes directly to the paired host.

TLS note: the Arduino libs build mbedTLS with internal-only allocation, which can't fit the handshake alongside WiFi + BLE, so the firmware pins Anthropic's root CAs and routes the TLS buffers to PSRAM. Relevant if you port to a board without PSRAM.

Bluetooth

BLE now carries only the standard HID keyboard service (0x1812, advertised as Clawdmeter); usage data travels over WiFi, so the old custom GATT data service is gone. Pair the device once from your OS Bluetooth settings to enable the side buttons.

Recompiling fonts

The firmware/src/font_*.c files are pre-compiled LVGL bitmap fonts.

npm install -g lv_font_conv

Generate each one (one at a time — lv_font_conv doesn't like loop-driven invocations) with --no-compress (required for LVGL 9):

# Tiempos Text (titles, 56px)
lv_font_conv --font assets/TiemposText-400-Regular.otf -r 0x20-0x7E \
  --size 56 --format lvgl --bpp 4 --no-compress \
  -o firmware/src/font_tiempos_56.c --lv-include "lvgl.h"

# Styrene B (large numbers 48, panel labels 28, small text 24, minimal 20)
for size in 48 28 24 20; do
  lv_font_conv --font assets/StyreneB-Regular.otf -r 0x20-0x7E \
    --size $size --format lvgl --bpp 4 --no-compress \
    -o firmware/src/font_styrene_${size}.c --lv-include "lvgl.h"
done

# DejaVu Sans Mono (32px, with spinner Unicode chars)
lv_font_conv --font assets/DejaVuSansMono.ttf \
  -r 0x20-0x7E,0xB7,0x2026,0x2722,0x2733,0x2736,0x273B,0x273D \
  --size 32 --format lvgl --bpp 4 --no-compress \
  -o firmware/src/font_mono_32.c --lv-include "lvgl.h"

Important: lv_font_conv v1.5.3 outputs LVGL 8 format. Each generated file must be patched for LVGL 9 compatibility:

  1. Remove #if LVGL_VERSION_MAJOR >= 8 guards around font_dsc and the font struct
  2. Remove the .cache field from font_dsc
  3. Add .release_glyph = NULL, .kerning = 0, .static_bitmap = 0 to the font struct
  4. Add .fallback = NULL, .user_data = NULL to the font struct

Without these patches, fonts compile but render as invisible.

CJK support

firmware/src/font_cjk_16.c covers the full CJK Unified Ideographs basic block (U+4E00–U+9FFF, ~20k glyphs) plus ASCII, CJK punctuation, and halfwidth/fullwidth forms. Generated from Noto Sans CJK SC (SIL OFL 1.1) at 16px, 2bpp:

lv_font_conv --font NotoSansCJKsc-Regular.otf --size 16 --bpp 2 \
  --no-compress --format lvgl --lv-include 'lvgl.h' \
  -r '0x20-0x7E,0xB7,0x2014,0x2018-0x2019,0x201C-0x201D,0x2026,0x3000-0x303F,0x4E00-0x9FFF,0xFF00-0xFFEF' \
  -o firmware/src/font_cjk_16.c

Then apply the four LVGL 9 patches above. Because the font has >65k of glyph bitmap data, the build needs -DLV_FONT_FMT_TXT_LARGE=1 in platformio.ini build flags so font descriptor offsets switch from 16-bit to 32-bit.

The CJK font is used for the Activity screen's user-prompt row and todo content rows. The headline (28pt Styrene B) and titles stay ASCII-only to preserve the brand font — Chinese text in those slots renders as empty boxes. Add a font_cjk_28.c if full coverage is needed (~1MB more flash).

Converting Lucide icons

The UI uses a small set of Lucide icons (bluetooth + battery states) converted to RGB565 / RGB565A8 C arrays for LVGL.

node tools/png_to_lvgl.js assets/icon_bluetooth_48.png icon_bluetooth_data ICON_BLUETOOTH_WIDTH ICON_BLUETOOTH_HEIGHT

Default tint is white (0xFFFFFF); Lucide PNGs ship as black-on-transparent and would render invisible against the dark UI without it. Pass --no-tint for pre-coloured artwork like the logo. Battery icons use RGB565A8 (alpha plane) so they blend cleanly over the splash; the rest are baked RGB565 over the panel colour. Paste the converter output into firmware/src/icons.h.

Splash animations

The animations come from claudepix.vercel.app, a library of Clawd sprites. tools/scrape_claudepix.js evaluates the site's JavaScript in a Node VM to pull out frame data and palettes, then tools/convert_to_c.js turns everything into RGB565 C arrays and writes firmware/src/splash_animations.h.

To re-pull (e.g. when the source library updates):

node tools/scrape_claudepix.js
node tools/convert_to_c.js
pio run -d firmware -t upload

See tools/README.md for details.

Keeping in sync with upstream

This repo is a fork of HermannBjorgvin/Clawdmeter. To pull later changes from the original into your fork:

git remote add upstream https://github.com/HermannBjorgvin/Clawdmeter.git   # once
git fetch upstream
git merge upstream/main          # or: git rebase upstream/main

Credits

  • Pixel-art Clawd animation by @amaanbuilds, sourced from claudepix.vercel.app. Frame data and palettes scraped + converted by the tooling in tools/.
  • Lucide icon set (lucide.dev, MIT) for bluetooth and battery UI glyphs.
  • macOS flash helper (flash-mac.sh) ported by Chris Davidson (@lorddavidson). Thanks Chris!
  • Anthropic brand fonts (Tiempos Text, Styrene B) — see licensing warning below.

Licensing gray area warning

The software in this repository uses and adheres to the Anthropic brand guidelines and uses the same proprietary fonts that Anthropic has a license for but this software uses without permission as well as using assets from Anthropic such as the copyrighted Clawd mascot so even though the code in this repo is non-proprietary I will not license it myself under a copyleft license since this repo includes proprietary fonts and copyrighted assets. Please be aware of this if you fork or copy the code from this repo. You have been warned!

About

ESP32 desk dashboard that shows Claude Code usage — standalone over WiFi, no companion app

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • C 92.0%
  • C++ 7.1%
  • Other 0.9%