runrate
A local-first dashboard for AI coding-agent token, cache, session, model, and cost telemetry from local usage artifacts.
Why this exists
AI coding agents changed my development loop, but they also introduced a new blind spot. A session can be technically productive and still be operationally noisy. It can drag a huge context forward, repeatedly miss cache, bounce between models, or burn through a rolling window while the terminal only shows a narrow slice of what happened.
Runrate is a local-first instrument panel for that work. It reads usage artifacts from the machine, normalizes sessions, estimates cost, and makes the pattern visible while the work is still fresh. The point is not billing precision. The point is operational judgment.
Local-first by design
Coding-agent telemetry is sensitive because it sits close to private work. Even when prompts are not stored directly, workspace names, file paths, session timing, and model behavior can reveal what someone is building. A hosted analytics product would create a new trust problem for a tool whose purpose is introspection.
Runrate keeps the default loop local. Local artifacts come in, local rollups are computed, and the dashboard runs beside the editor. That design makes it easier to inspect cost and behavior without turning engineering workflow metadata into another remote dataset.
What it watches
The dashboard focuses on signals that change behavior: model mix, token volume, cache reads, cache writes, session totals, workspace totals, estimated cost, and expensive checkpoints. These are the signals that help decide whether a prompt is too broad, a session should be restarted, a cheaper model is enough, or cache is actually helping.
The useful view is not one big number. It is the relationship between numbers. A high token count with strong cache behavior means something different from a high token count with repeated fresh input. A short session with a costly model mix means something different from a long session that stayed cheap and predictable.
Estimates and honesty
Cost dashboards can become misleading when they pretend estimates are invoices. Provider pricing changes, logs differ, cache accounting varies, and local artifacts may be incomplete. Runrate handles this by treating numbers as operating signals, not authoritative billing records.
That honesty matters. If a dashboard says a session is expensive, the useful next action is to inspect the session, the model, the cache pattern, and the prompt shape. The exact total can be refined, but the behavior is already visible enough to improve the workflow.
Where it helps
Runrate is useful for people who run long agent sessions, compare models, manage rolling windows, or want a better sense of how prompts and repository context affect usage. It is also useful for teams trying to normalize agent usage without turning the conversation into anecdotes.
The broader idea is simple: AI-assisted engineering needs observability too. Not the heavy kind with traces and dashboards for production traffic, but a local operating surface that helps builders see what their tools are doing and decide when to adjust.
Usage samples
Install
Runrate is intended to stay local. Install it into the workspace where you want to inspect agent usage.
npm install -D @crup/runrate Start the local dashboard
Point the dashboard at local usage artifacts and keep it open beside the editor during long agent sessions.
npx runrate dev \
--source ~/.codex/usage \
--workspace ~/Projects/rajender.pro Generate a local usage report
Use a time window when you want a shareable local summary without uploading private prompts or workspace metadata.
npx runrate report \
--since 24h \
--group-by workspace,model \
--format markdown \
--output ./runrate-report.md Read normalized events in another tool
The adapter boundary lets another local script consume normalized usage records without depending on provider-specific files.
import { readUsageEvents, rollupBySession } from "@crup/runrate";
const events = await readUsageEvents({
source: "~/.codex/usage",
since: "7d",
});
const sessions = rollupBySession(events);
for (const session of sessions) {
console.log(session.workspace, session.model, session.estimatedCostUsd);
}