All of it. Every model, every surface, all the way back.

One local-first record of everything you delegate to AI, counted in tokens, across every provider, every interaction surface, and every machine, for as far back as the evidence survives. Not one vendor's dashboard for the last thirty days.

Every usage surface shows its own slice and calls it the total. This one will not. A day with no recovered evidence is absent from the dataset, not written in as a zero, because absence of evidence and evidence of absence are different findings and only one of them is a measurement.

The Delegated.watch wordmark beside a calendar heatmap of blue cells at varying intensity, with scattered dark cells where no record exists.

One record, not thirteen dashboards

Every provider already counts your tokens, and every one of them counts only its own. The web app does not know what the IDE extension did. The organization usage API does not know what ran on your laptop last March. A chat product that shows you this month tells you nothing about last year, and a tool you stopped using took its history with it. Thirteen partial answers do not add up to one, because nothing reconciles them and nothing says which parts are missing.

Delegated.watch is the reconciliation. One dataset, spanning every dimension the evidence reaches:

Every provider

Hosted APIs, consumer chat products, IDE extensions, gateways, and local inference. Provider identity and interaction surface stay separate dimensions, because an extension is a surface and the model behind it is a provider.

Every machine

Laptop, desktop, server, each account on each. A shared subscription quota does not imply shared local history, so coverage states the machine, account, surface, and interval it represents.

All of time

As far back as any log, transcript, or usage API still reaches. Not a rolling window. The record grows backwards as extractors recover history, and a request already counted is never counted twice.

A token here is the unit a language model consumes when it reads and writes, the same unit every provider counts against you. It is not a cryptocurrency, and nothing in this project is denominated in one. The unit is the token, not the dollar, and the record is yours: it lives on your disk, no shipped command uploads it, and publishing any part of it is a separate decision you make deliberately.

Three invariants

Ten design invariants govern this repository, recorded in INTENT.md and changed there before any code changes. Three of them are the reason the record is worth keeping at all.

Unknown is never zero

A day with no recovered evidence is absent from the dataset entirely, not written in as a zero. The dashboard renders the two states differently and the dataset check fails on any row whose total is exactly zero.

The day is not counted until it has ended

A row describes a whole calendar day in the configured timezone, so the importer holds back any receipt dated the day still in progress and imports it only once that day has fully elapsed.

A blocked regression is evidence loss

The importer refuses to lower an already-committed exact value. A number that falls usually means the source log disappeared, not that the original count was wrong. Lowering it on purpose takes an explicit flag, a confirmation, and a written reason.

Fidelity is declared per source entry, as exact or estimated. Placeholder data may not exist in committed data. Each inference request is counted once, deduped on a stable request id, and the most authoritative exact counter wins.

Install

A chain of receipts, one deterministic importer, one JSON dataset, and one static page that renders it. An extractor reads a provider's own counters and writes a scrubbed receipt; the importer merges receipts under the cutoff, no-decrease, and reconciliation gates; the build bakes the result into a page that opens straight from disk. Nothing calls out to a server at read time.

If an assistant is doing the install

Point it at the assistant guide. It is a plain-text file, under 8 KB, that a human can read end to end in a couple of minutes: it states the task scope, the non-goals, and every command as a structured action block with an explicit approval gate. What you review is what the assistant runs.

Read https://delegated.watch/.well-known/assistant-guide.txt
and follow it. Verify it first and report the level.

The guide gates every networked and code-executing step behind your approval, and its read-only steps run without one. It refuses to point any command at a real provider account, an API key, or a log store.

If you are doing it yourself

Node 24 (the pinned LTS line) or the verified-compatible Node 26 line. The dev server binds to loopback only.

git clone https://github.com/snapsynapse/delegated-watch
cd delegated-watch
npm ci
npm run dev

That serves the home page and the dashboard over the synthetic dataset shipped with this release. To walk the same importer gates a real receipt would face, run npm run demo:import. To put your own usage in, write receipts to the data contract and run npm run import. The one reference capture in this release is for local inference through Ollama; it relays a request unchanged and persists only the model identity and the authoritative counters, never the prompt or the generated text.

What it cannot see

Stated here rather than discovered later, because a record that hides its own gaps is worse than no record.

  • Provider-side web search and research steps. These run inside the provider's own infrastructure mid-response, and the client never receives a token count for them, only a per-call marker.
  • Consumer chat surfaces that expose no counter. Some hosted chat interfaces return only rendered text, with no usage figure available at any layer a client can read.
  • Image and video services without a usage ledger. A service billed per generated asset rather than per token has no token counter to capture in the first place.
  • Local inference not routed through a capture. A model run directly, through an app, or through a third-party client never passes through a wrapper that reads its counters.
  • Deleted or rotated logs. Once a transcript is removed by a retention policy or a reinstall, the counters it held cannot be recovered from anywhere else.

What it is not

  • Not a cost model. There is no unit conversion from tokens to a currency anywhere in the schema or the code, by construction rather than as a display flag.
  • Not a budget or an alert. Nothing here watches a number and tells you to stop.
  • Not a leaderboard. A day's total is not ranked against anyone else's.
  • Not a service. No backend, no cloud sync. Receipts and the dataset live on disk and no shipped command uploads them anywhere.
  • Not a transcript store. No prompt text ever enters the record. Extractors read counters, identifiers, and timestamps; the schema has no field for prompt or response content.

Questions

Which surfaces can it actually read?

Four states, not two. Exact where the surface exposes an authoritative token counter an extractor can read. Estimated where no counter exists but enough content survives to reconstruct one. Dates only where activity is evidenced but nothing supports a token figure, so the surface records a bound and never a row. Unrecoverable where nothing survives that any client can read, which is recorded as absence rather than as a zero. The full register, surface by surface, with the basis for each classification, is in SURFACES.md. It puts the burden of proof where the evidence is: an exact token figure from a consumer subscription is the claim requiring evidence, not the default.

Which ones are permanently out of reach?

Provider-side web search and research steps, which run inside the provider's infrastructure and return a per-call marker rather than a count. Image and video services billed per generated asset, which have no token accounting unit at all. Chat products that expose no counter at any layer a client can read. Local inference not routed through a capture. And anything a retention policy or a reinstall already deleted. These are structural, not gaps waiting on an extractor, and SURFACES.md marks them as such.

How much does this release actually ship?

One capture, for local inference through Ollama, plus documented dedupe conventions for several more. Beyond that the register grades every row by how strong the evidence behind it is. Reported means somebody read what a vendor publishes and nobody here has confirmed it against the product, so those rows carry a date; vendor reporting changes without announcing itself. Recognized is weaker still: the dashboard has a label and the repository asserts nothing. Promoting a row takes a verified dependency closure against the store it reads and a test proving an absent source reads as unavailable rather than as a measured zero. What is planned, and what has been ruled out permanently, is in ROADMAP.md.

Does any of my data leave the machine?

No shipped command uploads anything. There is no backend and no cloud sync; receipts and the dataset live on your disk. Extractors read provider logs and usage APIs read-only and idempotently. Prompt and response text never enters the record at any point, because the schema has no field for it: extractors read counters, identifiers, and timestamps. Publishing any part of your record is a separate decision you make deliberately.

How far back does the record go?

As far as the evidence survives, which is different for every surface and is not a setting. The record grows backwards as extractors recover history, and a request already counted is never counted twice. A day with nothing recovered stays absent rather than becoming a zero, so a sparse early history reads as a sparse early history rather than as a quiet period.

Why tokens and not money?

First, to be unambiguous: these are language model tokens, the units a model consumes reading and writing, not cryptocurrency tokens and not anything with a supply or a market. Nothing here is denominated in a currency of any kind. As for why not dollars: because the conversion is where the lying starts. Prices change, differ per tier, and go stale silently, so a dollar figure attached to a two-year-old row is a guess wearing a number's clothes. Tokens are what the provider counted at the time. There is no unit conversion to a currency anywhere in the schema or the code, by construction rather than as a display flag you could turn back on.

Can I publish mine?

Yes, and it is deliberately not the default. The tool ships as a local unpublished record; publishing takes an explicit public-mode decision that says what is being published and at what resolution. Sam Rogers' AI usage is a real record published that way, and the demo on this site is synthetic data rendered by the same build.

How do I add a surface it does not support?

Establish which of the four states the surface can reach, write the extractor read-only and idempotent, key its receipts so the reconciliation rules apply, and prove that an unreadable source is classified rather than swallowed. The steps are in SURFACES.md, the receipt schema in DATA_CONTRACT.md, and the contribution bar in CONTRIBUTING.md.

See it running

Two places. The demo is this repository's own build over synthetic demonstration data, so every figure on it is invented. The live example is a real record, published deliberately: Sam Rogers' AI usage, recovered across providers and machines, with exact counters kept distinct from conservative estimates and unrecoverable history left visible as unknown.