Back to Projects
Demo

Token Usage Tracker

Jun 2026Stable, in daily useSolo build, standard library only

A local observability tool tracking LLM API spend across Claude Code, Gemini/Antigravity, and custom scripts, with a live dashboard and zero external dependencies.

PythonOTLPObservabilityLLM
15s demo

By the numbers

0
external dependencies
~5s
capture latency
3
telemetry sources
4
independent processes
1.2k
lines of source
3
token buckets priced

Architecture

Claude Code
OTLP push
Antigravity
local RPC
Any script
log_usage()
JSON-lines log
the contract
Aggregate
sessions, cache split
Dashboard
vanilla JS

Four processes, one append-only file, no broker between them.

Overview

Token Usage Tracker answers a question that is surprisingly hard to answer otherwise: where did the tokens go? It captures spend in real time across Claude Code, Gemini via Antigravity, and any custom script, using nothing but the Python standard library.

Claude Code usage arrives by push rather than poll. A local OTLP/HTTP receiver ingests the editor's native OpenTelemetry export, logging every prompt within about five seconds with no polling loop and no transcript scraping. The receiver always answers 200, deliberately, because an OTLP exporter treats a non-2xx as failure and starts backing off, and a telemetry sink should never apply backpressure to the workload it is measuring.

Gemini usage is harder, and estimating it from character counts is guesswork dressed as data. Instead the tracker discovers Antigravity's local language server by scanning for its process and CSRF token, confirms the pairing with a heartbeat RPC, and pulls exact per-call backend usage: what was actually billed, deduplicated by response ID so a restart never double-counts. Anything else can report through a generic adapter that duck-types Anthropic, OpenAI, and Gemini response shapes and degrades to zeros rather than raising, because a meter must never break the thing it measures.

Cache accounting is where naive trackers go wrong. With prompt caching, a 30,000 token request can be 29,562 tokens of cache reads, billed at roughly a tenth of the fresh input rate. Cache reads and cache writes are kept separate from fresh input on every record, so the difference between a nine-cent estimate and a 1.3-cent reality is visible rather than averaged away.

Everything lands in one append-only JSON-lines file, which is the entire integration contract between four independent processes. A second standard-library server aggregates it into per-model totals, an hourly timeline, and sessions inferred from ten-minute gaps in activity, then serves a single-page vanilla JS dashboard with no build step, no framework, and no bundler.

Why It Matters

LLM spend is opaque and easy to overshoot, especially across several tools and providers with different pricing models and different caching rules. By the time a bill arrives, the sessions that caused it are weeks in the past.

Local telemetry gives immediate visibility into cost per session and per model without shipping prompt contents to a third-party service, which is the trade most observability vendors ask you to make silently.

It is also a demonstration that good observability does not require a heavyweight stack. A push receiver, a cost model that respects caching, an append-only log, and a parser that degrades instead of raising add up to trustworthy visibility in about 1,200 lines with nothing installed.

Stack

Python 3.10+ · stdlib HTTP servers · OTLP/JSON · local RPC · vanilla JS · zero dependencies

View on GitHub