Skip to content
SuperAngryMonkeyPublic

About

Per-API-key Anthropic spend meter on an M5Stack Core2 — live token burn on your desk.

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

6 Commits

Folders and files

Repository files navigation

obol

ναῦλον τῷ πορθμεῖ. Fare for the ferryman.

A desk meter for your Anthropic API spend. Per-API-key, real dollars, updated live over BLE. Runs on an M5Stack Core2 for AWS with a Python daemon on your Mac.

obol on the desk

What it does

  • Polls the Anthropic Admin API every minute, broken out by API key and model
  • Computes exact dollar cost from tokens × rate-card, same way the Console UI does internally
  • Streams the numbers over BLE to a 320×240 screen on your desk
  • Lights the 10-LED bezel ring green / amber / red against your monthly budget
  • The three cap-touch buttons send BLE HID keystrokes (Space, Shift+Tab, Cmd+Esc) to whichever Mac app has focus
  • Doesn't talk to anything except Anthropic's API. No proxy, no LXC, no tailnet, no telemetry.

Why "obol"?

In ancient Greek, an obol (ὀβολός) was the small coin paid to Charon, the ferryman of the dead, as fare for passage across the Styx. The name fits because:

  • Real API spend per call is tiny — pennies, not drachmas. Obols.
  • The meter weighs passages — every API call is a small crossing, and the obol tracks the fare.
  • Paired conceptually with the planned Ferryman project. Ferryman is Charon; obol is what he gets paid.

Screens

Four screens, swipe left/right to navigate.

Total

The headline number — month-to-date spend, gauge against your budget, today, burn rate, projection, key count.

Total screen

Today

Today only — total spent, burn rate, top active key.

Today screen

Plan

Real-time utilization of your Claude subscription's 5-hour rolling window (and weekly cap, when applicable). Reads via the Claude Code OAuth token; works for any active subscription tier.

Plan screen

Status

BLE state, daemon health, firmware version, uptime, billing period.

Status screen

How it's built

┌─────────────────────────┐                  ┌─────────────────────────┐
│ Mac: obold              │  BLE GATT        │ Core2 for AWS: obol fw  │
│                         │ ──────────────▶  │                         │
│ - Polls Anthropic Admin │  CBOR usage      │ - 4 screens (M5GFX)     │
│   /v1/organizations/    │  every 2s        │ - SK6812 ring driver    │
│   usage_report/messages │                  │ - 3-button HID          │
│ - Computes cost via     │ ◀──────────────  │ - NimBLE composite      │
│   rate-card (pricing.py)│  BLE HID kbd     │   (HID + GATT)          │
│ - Admin key in macOS    │  (Space,         │                         │
│   Keychain              │   Shift+Tab,     │                         │
│                         │   Cmd+Esc)       │                         │
└─────────────────────────┘                  └─────────────────────────┘
  • Firmware: PlatformIO project, ESP32 Arduino + M5Unified + NimBLE + FastLED. No LVGL (M5GFX direct draw — the two collide because M5GFX bundles its own LVGL).
  • Daemon: Python 3.11+, bleak for BLE, httpx for the Anthropic Admin API, cbor2 for the wire format.
  • Wire format: CBOR over a custom BLE GATT service. Hand-rolled decoder on device (~300 lines, no library).
  • Auth: Admin API key lives in macOS Keychain (security add-generic-password). Never on disk, never in env vars.

Quick start

git clone https://github.com/SuperAngryMonkey/obol.git
cd obol
./install.sh           # one-time: venv, deps, plist scaffold
source daemon/.venv/bin/activate
obold setup            # interactive: admin key, Claude Code, launchd
obold                  # run the meter

The obold setup wizard walks you through generating an Anthropic admin key, storing it in Keychain, verifying it works, checking Claude Code is logged in (for the Max-plan screen), and optionally installing the launchd auto-start plist. End to end in about two minutes.

Full step-by-step: INSTALL.md. Operational details: docs/OPERATIONS.md.

Hardware

M5Stack Core2 for AWS — ESP32-D0WDQ6-V3, 320×240 IPS, FT6336U cap touch, 10× SK6812 LED ring on the bezel, ATECC608B secure element, AXP192 PMIC, 390 mAh battery, USB-C (UART-only, not native USB).

Roughly $40 from M5Stack or Amazon. Yellow case.

The standard (non-AWS) Core2 will almost work — same ESP32, same screen, same touch — but it lacks the LED ring and ATECC608B, and the firmware's ring driver is behind a BOARD_HAS_AWS_LEDS compile flag. So far obol is AWS-edition only; the standard variant would need a small build tweak.

Repo layout

obol/
├── README.md  INSTALL.md  HANDOFF.md  CHANGELOG.md  SECURITY.md
├── install.sh                Mac daemon installer
├── docs/
│   ├── DESIGN.md             screens, palette, LED modes
│   ├── OPERATIONS.md         deep-dive operational manual
│   ├── PROTOCOL.md           BLE GATT spec, CBOR schema
│   └── screenshots/
├── firmware/                 PlatformIO, M5Stack Core2 for AWS
│   ├── platformio.ini
│   └── src/
│       ├── main.cpp
│       ├── ui/               M5GFX direct draw
│       ├── ble/              NimBLE GATT + HID composite + CBOR
│       └── ring/             SK6812 driver
└── daemon/                   Python 3.11+
    ├── pyproject.toml
    ├── config.toml.example
    ├── obol/
    │   ├── main.py
    │   ├── config.py         Keychain integration
    │   ├── pricing.py        Anthropic rate card
    │   ├── ble_client.py     bleak + GATT writes
    │   └── sources/
    │       └── per_key_cost.py
    └── launchd/
        └── com.obol.daemon.plist

License

MIT. See LICENSE.

Lineage

This project was previously called cyranometer (Rostand-themed, candle metaphor). Renamed to obol at v1.0 when the scope locked to a numeric per-key cost dashboard. Pre-rename history lives under the cyranometer-final git tag.

About

Per-API-key Anthropic spend meter on an M5Stack Core2 — live token burn on your desk.

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages