Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Claude Usage Dashboard — ESP32-S3-Zero

ESP32-S3-Zero PlatformIO OLED WiFi claude.ai License

A tiny physical dashboard that shows your Claude.ai usage limits on a 0.96" OLED. Built for the Waveshare ESP32-S3-Zero — a 23.5×18 mm board — driving a two-color (yellow/blue) SSD1306. Shows the current 5-hour session usage, 7-day cap, a live countdown to reset, and an animated face that reacts to how close you are to your limit. No API key required.


Hardware

Component Notes
ESP32-S3-Zero Waveshare, ESP32-S3FH4R2: 4 MB flash, 2 MB PSRAM (PSRAM unused), native USB-C
SSD1306 OLED 128×64, I2C Two-color variant: top 16 px yellow, bottom 48 px blue (a plain mono SSD1306 works too)
USB-C cable Flashing + power
Breadboard + 4 jumper wires No resistors — SSD1306 breakout modules have onboard I2C pull-ups

The two-color panel is electrically identical to a monochrome SSD1306 — the yellow/blue split is just a dye band on the glass, with a small unlit seam at the boundary (~rows 14–16). The layout is designed around that seam so nothing important lands in it.


Wiring

OLED         ESP32-S3-Zero
────         ─────────────
VCC    →     3V3
GND    →     GND
SDA    →     GPIO 8
SCL    →     GPIO 7
  • GPIO 8 / GPIO 7 are used for I2C. GPIO 9 is avoided (flash-adjacent on this module) and GPIO 21 is reserved for the onboard WS2812 LED (not used by this firmware).
  • Pins are centralized in src/config/config.h — change PIN_SDA / PIN_SCL there if you wire differently.

Breadboard notes

Each breadboard row of 5 holes is one shared electrical node, so you can run 4 direct point-to-point jumpers with no power rails at all:

  1. Seat the S3-Zero across the center gap, USB-C port overhanging one edge.
  2. 3V3 → OLED VCC, GND → OLED GND, GPIO8 → OLED SDA, GPIO7 → OLED SCL.
  3. Verify each pin by the silkscreen label, not just position — header order varies by seller/batch. Cross-check against the espboards.dev pinout.
  4. Only power on over USB-C once all four jumpers are seated (avoids shorting VCC/GND through a half-placed wire).

Display Layout

Current OLED layout

Live capture from GET /api/screen, rendered in the panel's two colors.

  • Yellow strip: centered CLAUDE USAGE title + a full-width progress bar for your primary metric.
  • Blue area: the large primary percentage (5-hour if your plan has one, else 7-day), the animated face top-right, then the 7-day cap with its days countdown, then the live reset countdown.

Every row is individually toggleable in the web portal under Display Settings.

The Face

A small face lives top-right in the blue area. It winks every 7 seconds (left eye, then right, then they reopen in the same order), and its mouth follows your usage — same metric as the primary %:

< 30% 30–60% 60–80% > 80%
Smile Open Flat Sad
Smile Open Flat Sad

If the face looks sad, you're about to hit your cap.


Software Requirements


Build & Flash

  1. Clone or download this repo and open the folder in VS Code (PlatformIO detects platformio.ini automatically).
  2. Click Build (checkmark) — first build downloads the toolchain (~5 min).
  3. Connect the S3-Zero via USB-C.
  4. Click Upload (arrow).

If upload fails or the board "beeps" in a reset loop

The S3-Zero has no auto-reset-into-bootloader circuit. If flashing can't connect, or the board rapidly connects/disconnects (audible USB "beep-beep" loop), put it in download mode manually:

Hold BOOT, tap RESET, then release BOOT.

Then click Upload again. After a successful flash it resets into the app normally.

Reflashing an already-configured device: if an update changes the settings storage format (noted in that update's changelog/commit), the device wipes its saved settings once on first boot after the flash — you'll redo First-Time Setup below. This is a one-time reset per format change, not a routine reflash behavior.


First-Time Setup

After flashing, the device starts a WiFi access point named ESP32-Claude-Dashboard. The OLED shows ! ERROR / Set WiFi SSID until configured — that's expected.

Step 1 — Get your Claude session cookie

Do this before connecting to the device AP, while on your normal WiFi:

  1. Open claude.ai in Chrome, logged in.
  2. Open DevTools (F12) → Network tab.
  3. Refresh, click any request to claude.ai.
  4. In Request Headers, find Cookie and copy its entire value.
Cookie: sessionKey=sk-ant-...; __cf_bm=...; other=...
        ^^^^^ copy this entire value

The ESP32 impersonates a logged-in browser session. The cookie is valid as long as you stay logged in to claude.ai. If you log out or it expires, repeat this step.

Step 2 — Configure the device

  1. Connect to WiFi ESP32-Claude-Dashboard (password: dashboard1).
  2. Open http://192.168.4.1.
  3. Under Connection Settings → Add a Network, click Scan for Networks, click your network in the dropdown, and enter its password when prompted — it's saved immediately as a known network. (Hidden network? Type its name + password into the fields below the scan button instead.)
  4. Paste your Claude cookie under Claude Cookie Header.
  5. Click Save Settings.

The device connects and fetches live data within ~10 seconds. The OLED updates automatically.


Taking the Device Somewhere Else

The device remembers up to 5 WiFi networks (like a phone) and auto-connects to whichever one is actually in range — no need to reconfigure every time you move it.

  • Add more networks anytime: connect to the ESP32-Claude-Dashboard AP (it's always reachable, regardless of which — if any — known network is currently in range) and repeat the scan-and-add step above for each new location.
  • Bring it to a known network: power it on there and it reconnects on its own, usually within 30 seconds — nothing to do.
  • Forget a network: click Forget next to it in the Known WiFi Networks list in the portal.

Under the hood, the device always keeps its own hotspot in plain AP mode by default, and only switches into AP+STA mode when a scan actually confirms a saved network is in range — so a stale or out-of-range network can never make the portal unreachable. Retries happen on a bounded 30-second schedule, never continuously.


Web Portal

Connect to the ESP32-Claude-Dashboard AP and open http://192.168.4.1.

Section Description
Live Preview Canvas rendering of the current OLED layout, updates every 30 s
Display Settings Toggle each row on/off
Connection Settings Known WiFi networks (add/forget, up to 5), session cookie, refresh interval, AP password
Refresh Data Force an immediate fetch
Reset Defaults Wipe all settings back to factory defaults

Bonus: GET /api/screen returns the raw 1024-byte SSD1306 framebuffer — the exact pixels currently on the OLED.


Settings Reference

Setting Default Description
Refresh interval 30 000 ms How often to poll claude.ai
AP password dashboard1 Password for the device WiFi AP
Session cookie (empty) Full Cookie header from claude.ai DevTools
Known WiFi networks (empty, up to 5) Auto-connects to whichever is in range — see "Taking the Device Somewhere Else"

Troubleshooting

Board rapidly connects/disconnects ("beep-beep" loop), flash won't take

  • Enter download mode manually: hold BOOT, tap RESET, release BOOT, then Upload.

Boot loops with partition table / Failed to verify partition table on serial

  • The board definition defaulted to an 8 MB partition scheme but this chip has 4 MB. This repo already pins the fix in platformio.ini (board_upload.flash_size = 4MB and board_build.partitions = default.csv) — make sure those lines are present.

OLED shows nothing

  • Check wiring: SDA → GPIO 8, SCL → GPIO 7, VCC → 3V3 (not 5V).
  • Verify the I2C address is 0x3C; some modules use 0x3D — edit config.h.

Content clipped at the yellow/blue boundary

  • That's the physical seam (~rows 14–16). The layout avoids it by design; if you re-position elements, keep the yellow content at y ≤ 13 and blue content at y ≥ 17.

OLED shows Set WiFi SSID / Set session key

  • Configure the device at http://192.168.4.1 (see First-Time Setup).

Hotspot appears in WiFi lists but won't let you in / 192.168.4.1 won't load

  • Fixed as of the multi-network update: earlier firmware kept retrying a single fixed SSID indefinitely in the background, which could destabilize the AP's own radio channel if that network was out of range or misspelled. The device now only attempts STA connections on a bounded 30-second schedule, gated by an actual scan confirming a known network is present — the AP itself should now always be reachable regardless of WiFi state. If you're still on older firmware, reflash to pick up the fix.

OLED shows API Error

  • The session cookie likely expired — repeat Step 1. Open the Serial Monitor (115200 baud) for HTTP error codes.

Build fails with cc1plus.exe: CreateProcess: No such file or directory

  • Corrupted toolchain download. Run in PowerShell, then rebuild:
    Remove-Item -Recurse -Force "$env:USERPROFILE\.platformio\packages\toolchain-xtensa-esp-elf"

Using a Different Board

The firmware compiles for any ESP32-family board. Typically only three things change: the board line, the PSRAM/USB build flags, and the I2C pins.

1. platformio.ini

Board board = value build_flags notes
ESP32 classic (Wemos D1 Mini32, NodeMCU-32S) esp32dev remove -DARDUINO_USB_CDC_ON_BOOT=1
ESP32-S3 (8 MB+ devkit, PSRAM) esp32-s3-devkitc-1 add -DBOARD_HAS_PSRAM; drop the 4 MB partition lines
ESP32-S3-Zero (this build) esp32-s3-devkitc-1 keep board_upload.flash_size = 4MB + board_build.partitions = default.csv
ESP32-S2 esp32-s2-saola-1 —
ESP32-C3 esp32-c3-devkitm-1 remove -DARDUINO_USB_CDC_ON_BOOT=1
ESP32-C6 esp32-c6-devkitc-1 remove -DARDUINO_USB_CDC_ON_BOOT=1
  • -DBOARD_HAS_PSRAM — only add it if your module has PSRAM and you need it. This firmware doesn't, so it's omitted even though the S3-Zero's chip physically has 2 MB.
  • Partition sizing is the #1 gotcha on small-flash boards: if your chip's flash is smaller than the board definition assumes, the bootloader rejects the partition table and crash-loops. Pin board_upload.flash_size and board_build.partitions to match.

2. src/config/config.h — I2C pins

#define PIN_SDA  8   // ← change to match your wiring
#define PIN_SCL  7   // ← change to match your wiring

Any free GPIO works. Common defaults: ESP32 classic 21/22, ESP32-S3/S2 8/9, ESP32-C3 8/9, ESP32-C6 6/7.

Not supported without a rewrite

  • ESP8266 — different WiFiClientSecure API (TLS often fails against Cloudflare), no NVS Preferences, and WIFI_AP_STA behaves differently.
  • Non-ESP MCUs (Uno, STM32, etc.) — the project needs WiFi + HTTPS/TLS, ~50 KB free RAM, and the Arduino framework. Boards like the Uno R4 WiFi or RP2040 W are possible in principle but require porting the WiFi/TLS/storage layers.

Architecture

claude.ai  ──HTTPS──>  ESP32-S3-Zero  ──I2C──>  OLED
             (session cookie)
                  |
                  └──WiFi AP──>  Browser (192.168.4.1)

The ESP32 calls claude.ai/api/organizations/{org}/usage directly using your browser session cookie. No backend server, no API key, no cloud service. The org UUID is auto-discovered on first fetch and cached in flash (NVS).


Security Notes

  • Change the default AP password. Ships as dashboard1; anyone in WiFi range who knows it can open the portal and read/replace your cookie. Set a strong one under Connection Settings → AP Password.
  • No TLS certificate verification. The device uses setInsecure() (loading a full CA bundle costs too much flash), so a machine-in-the-middle on your local network could intercept the cookie. Low risk on a trusted network.
  • Credentials live only on the device. Session cookie, WiFi password, and AP password are stored in the ESP32's NVS — never in source or config files.
  • The settings portal is HTTP, not HTTPS. Use it only while connected to the device's own AP.

License

MIT

About

A physical dashboard that displays your Claude.ai usage limits on a 128×64 OLED screen. Shows the current 5-hour session usage, 7-day cap, and live countdown to reset — updated automatically. No API key required.

Topics

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages