Search

↑↓ to move↵ to openesc to closetop 6 documentation results

Book a demoTry TokenTriage

In development · Explore the product preview. Join the launch list or book a walkthrough.

Browse docs

The dashboard

A web UI your binary already contains, reading the same ledger the CLI reads. What it is for, and where each screen is documented.

ExplanationLast updated

On this page

You have a decision ledger with a line per request, and reading it with tokentriage top works but does not scale to the questions people actually ask: which team spent that, why did this request go to the expensive model, is the saving I reported measurable. The dashboard is those questions as screens.

It ships inside the binary you already downloaded. No separate service, no database, no build step, no network call to anyone. Turn it on and it serves a web UI on the admin port over the same file the CLI reads, so the two cannot disagree about a total.

This page is the section’s front door: what the dashboard is, what it is not, and how the rest of these pages are organised. If you want to see it before reading about it, tokentriage demo boots the whole thing against synthetic traffic with no credentials.

One ledger, two front ends

The CLI and the dashboard are readers of the same decision log. Neither computes a number the other cannot; a dollar on a screen came from the same row, priced against the same pricing snapshot, as the dollar the CLI prints. Where the dashboard adds value is in what a file is bad at: filtering, grouping, drilling from a total into the rows that produced it, and watching rows arrive.

Two properties follow from shipping it inside the binary, and both matter operationally.

It sits on the admin plane, not the request path. Your data plane (server.listen, default 127.0.0.1:8787) proxies traffic. The dashboard is served from the admin listener (server.admin, default 127.0.0.1:9090) alongside /health and /metrics. A dashboard query, a slow chart, even a crashed browser tab cannot touch a request in flight. If the admin listener fails to bind at boot, the proxy keeps serving and the banner says the dashboard is unavailable.

It fetches nothing. The web app is compiled into the executable and served with a strict content-security policy that permits same-origin requests only. No CDN, no font host, no telemetry. That is what makes it work unchanged in an air-gapped deployment, and it is why the whole UI is one go:embed directory rather than a docker-compose file.

localhost:9090/ui/Demo data
The Overview surface over a populated ledger: spend to date and projected period-end as dollar tiles, a savings-vs-baseline verdict, spend over time, and top spend broken down by routing tier, agent and model. A mixed-snapshot chip warns that totals span two pricing snapshots.The Overview surface over a populated ledger: spend to date and projected period-end as dollar tiles, a savings-vs-baseline verdict, spend over time, and top spend broken down by routing tier, agent and model. A mixed-snapshot chip warns that totals span two pricing snapshots.
Overview, over the demo ledger. The chips beside each panel report how many rows the figure came from, how many were estimated, and how many carried no price (real dashboard, demo mode).

What it is not

A short negative list saves more time than a feature tour.

It is not a place to configure your proxy by hand. Every write goes through the same config-as-contract loop the CLI uses: the surface composes YAML, you validate it, diff it against what is running, then apply it under a compare-and-set guard. The dashboard never mutates config behind your back, and a rejected apply shows the server’s error rather than a friendly summary of it.

It is not a monitoring system. It reads your ledger; it does not scrape, store time series, or page anyone. Prometheus and OTLP are how the gateway joins the monitoring you already run, and Observability & tracing owns that.

It is not multi-tenant SaaS. There is no organisation model, no seat billing, and no hosted copy of your data. Access control is three roles on one instance, plus read-only share links for a frozen query.

It is not the system of record. The ledger is. Everything on screen is derived from it through a SQLite read model you can delete at any time, which is the subject of the read model.

How this section is organised

Most of what you see on a dashboard screen has a meaning that belongs to a subsystem: a cost figure means what Cost & attribution says it means, a verdict chip means what the honesty model says it means. Duplicating those definitions here would give you two places to be wrong.

So this section documents the application — turning it on, getting into it, what decides which screens exist, and the rules every screen obeys — and sends the meaning of any number to the section that owns it. One page carries the map: the surface index lists every screen with the question it answers, the setting that makes it appear, and a link to the concept behind it.

If you are looking at a screen right now and want to know what it is, start there. If you are setting the dashboard up, the pages run roughly in the order you need them: turn it on, see what a new instance shows, work out why your sidebar is shorter than the screenshots, then sign in properly before you expose it to anyone.

What it costs to run

The dashboard is off in a config file and on in the zero-config quickstarts, which surprises people often enough to be worth stating twice. dashboard.enabled defaults to false, so a config-file deployment adds two lines to get a UI. tokentriage run --anthropic and --simple/--complex turn it on for you, and --no-dashboard opts back out.

Running it costs one SQLite file, a bounded query budget, and a small amount of memory for the live-stream fan-out. It reads your ledger continuously to keep the index current. It does not add latency to proxied requests, because it is not on that path.

What the dashboard adds to a deployment, item by item
  • A read-model index at dashboard.index.path, defaulting to ~/.tokentriage/index/decisions.sqlite. Derived from the ledger, rebuildable, disposable.
  • A state directory at dashboard.state_dir, defaulting to ~/.tokentriage/dash, holding the users file, token hashes, saved views, the audit log and the event ring.
  • An HTTP surface on the admin listener: the UI at /ui/ and the management API at /tt/api/v1.
  • A bounded query budget: dashboard.query.deadline (10s), row_cap (1000) and max_concurrent (2), so one expensive filter cannot monopolise the instance.
  • A live stream with dashboard.stream.client_queue (1024) and max_clients (32).

Every one of those has a default, and the defaults are what a two-line dashboard: block gets you.

Where to go next

Turning it on takes one setting; the page below covers the ports, the container, and the demo. If you would rather understand the shape first, the surface index is the map of every screen, and reading a number is the one page that pays off on every other screen.