Skip to content

ALENOC/Clawdbox

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Clawdbox

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.


Screenshots

Splash Usage Network Settings
Splash Usage Network Settings

Photos

Device


Screens

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.


Hardware

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).

Why ESP32-S3-BOX

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

Prerequisites

  • PlatformIO CLI
  • Active Claude Code / Anthropic subscription (OAuth tokens obtained via on-device QR flow)

Flash

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

First-boot setup

  1. Fresh flash → device starts AP Clawdbox-setup (open, no password).
  2. Connect to the AP; captive portal opens at http://192.168.4.1/.
  3. Enter SSID and WiFi password. Submit → device reboots into STA mode.
  4. Device connects to WiFi and shows a QR code plus a LAN URL (http://<device-ip>/pair) on screen.
  5. Scan the QR → claude.ai OAuth authorization page opens. Authorize.
  6. After authorizing, the callback page shows a CODE#STATE string. Copy it.
  7. Navigate to http://<device-ip>/pair (shown on screen), paste the CODE#STATE, submit.
  8. Device exchanges the code for tokens (PKCE), saves them to NVS, and reboots.
  9. From now on the device refreshes tokens autonomously (~every 15 min).

Settings (Network screen)

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

Why WiFi, not Bluetooth

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.


How it works

  1. Connects to WiFi; NTP syncs the clock.
  2. Timezone auto-detected via http://ip-api.com/json on first connect; saved to NVS.
  3. 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.
  4. OAuth token nearing expiry → POST to https://console.anthropic.com/v1/oauth/token with refresh token; rotated pair persisted to NVS.
  5. Splash animation group selected by current usage-rate (usage % change over sliding window).

Physical buttons

Button GPIO Function
BOOT 0 Cycle screens; long-press >5 s → factory reset
Mute slider 1 Manual poll trigger

TLS

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.


Security note

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.


Recompiling fonts

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"
done

Each generated file needs LVGL 9 patching: remove #if LVGL_VERSION_MAJOR >= 8 guards, drop .cache, add .release_glyph, .kerning, .static_bitmap, .fallback, .user_data.

Splash animations

node tools/scrape_claudepix.js   # fetch sprites → tools/claudepix_data/*.json
node tools/convert_to_c.js       # → firmware/src/splash_animations.h

Converting icons

node 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.


Disclaimer

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.

Independence

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.

Trademarks

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.

Artwork

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.

API usage and costs

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.

Security

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.

No warranty / limitation of liability

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.


Credits

About

ESP32-S3-BOX desk monitor for Claude Code API usage - polls Anthropic rate-limit headers over WiFi, no host daemon

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors