case study · 01

lithium

Mood stabilizer for your AI bill.

A local Rust daemon that polls every provider you pay, normalizes the bill into one SQLite store, and answers a single question: what's actually burning this month, fixed and variable, across everything?

lithium illustration

~ what shipped ~

Three numbers that matter.

metric · 01

5 providers

Anthropic, OpenAI, OpenRouter, Claude Max, ChatGPT Pro on day one. Adapter-per-crate so each new provider is a sibling crate, not a fork.

metric · 02

0 telemetry

Nothing leaves your machine. SQLite at ~/.local/share/lithium/usage.db. Network calls only to the provider APIs you configure.

metric · 03

Public Day 1

First commit shipped to a public GitHub repo with a finished README, hero image, and a working subcommand. Production packaging as a forcing function: nothing stays in a half-built state on main.

The shape

Three crates: lithium-core handles storage, types, projection. lithium-anthropic / lithium-openai / lithium-openrouter are the per-provider adapters. lithium-cli is the binary entry. Future adapters drop in as sibling crates without touching the core.

The pipeline

lithium poll runs every adapter on a schedule. Each adapter fetches that provider's usage API (admin keys for Anthropic and OpenAI; regular API key works for OpenRouter), normalizes per-day spend into a unified row shape, writes to SQLite. Read commands like lithium today and lithium month project from that table.

Live, mocked

The tile below is the production read-shape rendered with seeded mock values. Real data lives in the daemon on your machine. The site demos the readout you'd see piped into a status bar or menubar surface.

Phase plan

↳ each surface ships at finished quality before the next one starts. No half-built state in main.

~ on the workbench ~

The tooling.

~ counterfactual ~

What would have been worse.

Without it: a misconfigured automated run or a forgotten cron burns $200 in a day before anyone notices. Fixed-cost subscriptions and variable-cost API calls live in different mental buckets, both bills arrive at the end of the month, and the spreadsheet 'tracking' it is wrong by half. Cross-provider visibility is nobody's job until it is.

~ got something like this on the bench? ~

Pull the cord.

Start the conversation

/ lithium / built by hand / shipped to a working URL /