A desk-side Claude Code usage monitor running on an Espressif ESP32-S3-BOX.
Connects to WiFi and polls the Anthropic API directly - no host daemon, no companion app. OAuth tokens are obtained and refreshed on-device via a QR-code pairing flow.
The splash screen plays pixel-art Clawd animations sourced from claudepix. Animation intensity tracks your live usage rate.
| Splash | Usage | Network | Settings |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Screen | Description |
|---|---|
| Splash | Boot screen with Clawd pixel-art animation, UTC clock, usage rate ticker |
| Usage | 5h session % and 7d weekly % with progress bars, reset timers, live clock |
| Network | WiFi state, IP address, OAuth status, Reset config zone |
| Settings | Brightness, auto-standby, night mode schedule, timezone offset |
Press BOOT to cycle screens. Tap anywhere on the splash to hide/show it. Long-press BOOT (>5 s) to factory reset.
All three Espressif ESP32-S3-BOX variants are supported:
| Variant | Display | Touch | Backlight GPIO |
|---|---|---|---|
| ESP32-S3-BOX (original, ~2022) | ILI9342C 320×240 IPS | TT21100 | GPIO 45 |
| ESP32-S3-BOX-Lite (~2022, no touch) | ST7789 320×240 IPS | none | GPIO 45 |
| ESP32-S3-BOX-3 (~2023, latest) | ILI9342C or ST7789 | GT911 or TT21100 | GPIO 47 |
BOX-3 display driver and touch controller are detected at runtime via I2C probe (mirrors the Espressif BSP auto-detect logic).
The ESP32-S3-BOX family is an official Espressif product - not a third-party board. This means a stable, well-documented BSP, long-term availability, and a known-good hardware reference for all three variants.
The more important reason for a desk monitor, though, is the display technology.
IPS LCD, not AMOLED. All BOX variants use IPS LCD panels. Competing ESP32 display boards (such as the Waveshare AMOLED series) use AMOLED. For a device that sits on your desk and is on most of the day, this matters:
| IPS LCD (this device) | AMOLED | |
|---|---|---|
| Burn-in / image retention | None - backlight is uniform, pixels do not age unevenly | Organic pixels degrade under sustained static content; logos and progress bars burn in over months |
| Brightness decay | Negligible over years of use | Organic emitters dim measurably over thousands of hours |
| Always-on viability | Yes | No - requires aggressive screen savers, short timeouts, or content rotation to slow degradation |
| Replacement cost | Low - commodity panel | Higher - proprietary AMOLED module |
A usage monitor is by definition static content: the same layout, the same progress bars, the same clock position, always in the same spot on your desk. That is exactly the workload that ages AMOLED panels fastest. IPS LCD has no organic emitters and no burn-in mechanism - it will look the same in three years as it does on day one.
The auto-standby and night-mode features (Settings screen) exist to reduce unnecessary backlight hours, but the display is fundamentally safe to leave on indefinitely.
- USB-C cable for flashing
- PlatformIO CLI
- Active Claude Code / Anthropic subscription (OAuth tokens obtained via on-device QR flow)
Select the environment matching your hardware:
# ESP32-S3-BOX (original)
pio run -d firmware -e s3box -t upload --upload-port /dev/ttyACM0
# ESP32-S3-BOX-Lite
pio run -d firmware -e s3box_lite -t upload --upload-port /dev/ttyACM0
# ESP32-S3-BOX-3
pio run -d firmware -e s3box3 -t upload --upload-port /dev/ttyACM0- Fresh flash → device starts AP
Clawdbox-setup(open, no password). - Connect to the AP; captive portal opens at
http://192.168.4.1/. - Enter SSID and WiFi password. Submit → device reboots into STA mode.
- Device connects to WiFi and shows a QR code plus a LAN URL (
http://<device-ip>/pair) on screen. - Scan the QR →
claude.aiOAuth authorization page opens. Authorize. - After authorizing, the callback page shows a
CODE#STATEstring. Copy it. - Navigate to
http://<device-ip>/pair(shown on screen), paste theCODE#STATE, submit. - Device exchanges the code for tokens (PKCE), saves them to NVS, and reboots.
- From now on the device refreshes tokens autonomously (~every 15 min).
| Setting | Description |
|---|---|
| Backlight | PWM brightness slider |
| Auto-standby | Turns off the display after the configured idle timeout. Must be enabled for any standby to occur. |
| Night only | Restricts auto-standby to a configured hour range (e.g. 22h-7h local time). Requires Auto-standby to also be enabled. When both are on, the display turns off after the idle timeout only if the current local time falls within the night window. Device auto-wakes when the window ends. |
| Timezone | UTC offset (±h); auto-detected from IP on first WiFi connect via ip-api.com. Used by the Night only window. |
Standby logic summary:
| Auto-standby | Night only | Behaviour |
|---|---|---|
| off | any | Display never turns off |
| on | off | Display turns off after idle timeout, at any hour |
| on | on | Display turns off after idle timeout, only within the night window |
The original Clawdmeter uses Bluetooth to receive usage data relayed from the host machine. This approach has a fundamental architectural flaw: the device is completely dependent on the host being awake, unlocked, and running a companion daemon. The moment you lock your screen, close the lid, or switch machines, the link breaks and the monitor goes stale. It also requires installing software on every machine you use.
This project takes a radically different approach: the device connects directly to the Anthropic API over WiFi, with no host involvement whatsoever.
| WiFi - this device | Bluetooth - original Clawdmeter | |
|---|---|---|
| Host dependency | None - polls Anthropic directly | Requires companion app on every host |
| Works when host sleeps | Yes - always live | No - goes dark when host locks |
| Works when host is off | Yes | No |
| Multi-machine | Yes - follows your account, not your laptop | No - tied to the one paired host |
| Rate-limit data source | Official API response headers - authoritative | Scraped from CLI - fragile, breaks on updates |
| Token refresh | On-device, autonomous | Host must relay credentials |
| Setup friction | One-time portal + OAuth QR scan | Pair per machine, install and maintain daemon |
| Licensing overhead | None | Bluetooth product qualification requires Bluetooth SIG membership and royalties |
The Bluetooth SIG requires that any product using the Bluetooth trademark or standard undergo a qualification and listing process. For commercial products this involves fees; even for open-source projects, the compliance burden (QDID, Declaration ID, listing) is non-trivial and constrains redistribution.
WiFi with direct API polling sidesteps all of that. The only trade-off is that WiFi requires network access and OAuth tokens are stored on the device. See the Security note below.
- Connects to WiFi; NTP syncs the clock.
- Timezone auto-detected via
http://ip-api.com/jsonon first connect; saved to NVS. - Every 60 s (while active): POST 1-token probe to
https://api.anthropic.com/v1/messages, read rate-limit headers (anthropic-ratelimit-unified-5h-utilization,-5h-reset,-7d-utilization,-7d-reset). Polling pauses while the display is in standby; on wake, a fresh poll fires immediately. - OAuth token nearing expiry → POST to
https://console.anthropic.com/v1/oauth/tokenwith refresh token; rotated pair persisted to NVS. - Splash animation group selected by current usage-rate (usage % change over sliding window).
| Button | GPIO | Function |
|---|---|---|
| BOOT | 0 | Cycle screens; long-press >5 s → factory reset |
| Mute slider | 1 | Manual poll trigger |
All HTTPS connections verify against root CA certificates in firmware/src/anthropic_ca.h. This file is auto-generated at build time by firmware/tools/fetch_ca.py - you never edit it by hand.
| Endpoint | Root CA |
|---|---|
api.anthropic.com |
GlobalSign Root CA (via GTS Root R4) |
console.anthropic.com |
ISRG Root X1 (Let's Encrypt) |
The pre-build script follows the AIA chain from each endpoint to locate the correct root CA, downloads it, verifies the fingerprint, and writes the PEM bundle before compilation. If Anthropic rotates their CA, rebuilding with network access picks up the new cert automatically.
OAuth tokens are stored in NVS in plaintext. Anyone with USB access can extract them with esptool.py read_flash. Before lending, gifting, or recycling the device: long-press BOOT >5 s (or tap Reset config on the Network screen) and revoke the token at https://claude.ai/settings/claude-code.
Fonts are pre-compiled LVGL 9 bitmap files in firmware/src/font_*.c. To regenerate:
npm install -g lv_font_conv
for size in 28 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"
doneEach generated file needs LVGL 9 patching: remove #if LVGL_VERSION_MAJOR >= 8 guards, drop .cache, add .release_glyph, .kerning, .static_bitmap, .fallback, .user_data.
node tools/scrape_claudepix.js # fetch sprites → tools/claudepix_data/*.json
node tools/convert_to_c.js # → firmware/src/splash_animations.hnode tools/png_to_lvgl.js <input.png> <symbol> [W_MACRO] [H_MACRO] [--tint=RRGGBB | --no-tint]Default tint is white. Pass --no-tint for pre-coloured artwork.
This project is an independent, unofficial, non-commercial community tool created for personal use. It is not affiliated with, endorsed by, sponsored by, approved by, or in any way connected to Anthropic, PBC or any of its subsidiaries or affiliates.
This project was developed independently, without access to any non-public information, internal APIs, or proprietary documentation belonging to Anthropic, PBC. All API usage is based solely on Anthropic's publicly documented interfaces.
Claude™ and Anthropic™ are registered trademarks of Anthropic, PBC. All rights are reserved by their respective owners. References to these names in this repository are made solely for the purpose of nominative fair use - to accurately describe interoperability with Anthropic's publicly available API - and constitute neither a claim of association nor an implied licence of any kind. No sponsorship, endorsement, or affiliation is suggested or implied.
The pixel-art animations included in this firmware are fan-made, community-created works sourced from claudepix.vercel.app and attributed to @amaanbuilds. They are not official Anthropic assets and are reproduced here solely for non-commercial, personal use under fair use principles. The author of this project asserts no ownership over these works and makes no representations regarding their intellectual property status. Use of this firmware does not grant any rights to the underlying artwork.
This device makes real API calls to api.anthropic.com every 60 seconds while active. Each poll sends a minimal 1-token probe to claude-haiku solely to read rate-limit response headers - actual token consumption is negligible (≈ 2 tokens/minute while awake). Polling is suspended automatically while the display is in standby, so no API calls are made while the device is idle overnight. You are solely and exclusively responsible for any charges, quota consumption, rate-limit violations, or Terms of Service violations arising from your use of this firmware. Review Anthropic's Usage Policy before deploying. The author accepts no liability for any costs incurred.
OAuth tokens are stored unencrypted in the device's NVS flash. You are solely and exclusively responsible for the physical security of the device and for revoking credentials promptly if the device is lost, stolen, transferred, resold, or discarded. To revoke: visit https://claude.ai/settings/claude-code. The author accepts no liability for unauthorised access to your Anthropic account resulting from use of this firmware.
This software is provided "as is", without warranty of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the author be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including but not limited to procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise), arising in any way out of the use of this software, even if advised of the possibility of such damage. See the full MIT License.
- Inspired by Clawdmeter by @HermannBjorgvin.
- Pixel-art Clawd animations by @amaanbuilds via claudepix.vercel.app.
- Lucide icon set (lucide.dev, MIT).




