Skip to content

Repository files navigation

AI Usage Observatory

Version Runtime Language Privacy

AI Usage Observatory is a local-first analytics workspace for people who want to understand and improve how they use AI coding agents.

Provider dashboards can show how much capacity remains. The Observatory connects that usage to the work behind it: projects, sessions, models, token composition, reasoning effort, and changes over time. It creates a practical feedback loop for measuring current habits, investigating changes or outliers, and making more informed decisions about model choice, effort, and workflow.

The analysis runs on your machine against data already stored there. No separate cloud account or telemetry service is required.

Questions the Observatory helps answer

Question Evidence available
How is my usage changing? Daily, weekly, monthly, per-session, and five-hour activity, with comparable date ranges.
Which work is driving it? Cross-provider attribution to projects and sessions, including model breakdowns.
How are model and effort choices shifting? Token composition, API-equivalent cost, model mix, and provider-recorded reasoning effort beside the model family that recorded it, where available.
How much provider capacity remains? Optional provider-reported allowance windows, headroom, resets, credits, and locally observed quota history.
Which activity deserves closer review? Outlier sessions, allowance-capture and efficiency signals, transcript context, tool activity, and patch summaries.

The Observatory does not treat higher or lower usage as inherently better. It provides a consistent record so you can establish a baseline, change how you work, and evaluate the result over time.

Run locally

Requires Bun 1.3 or newer.

bun install
bun run dev

Open http://127.0.0.1:5173.

For a production build:

bun run build
bun run start

Open http://127.0.0.1:4318.

To update a clone, run git pull followed by bun install. A downloaded copy must be replaced with a newer one.

Inside the Observatory

Click any screenshot to open it at full size. The gallery reflects the current application; release changelogs preserve version-specific captures.

Overview dashboard with provider allowance windows, headroom, reset timing, and usage trajectory

Overview — provider allowance, headroom, reset timing, and usage trajectory

Usage Explorer with provider activity and model distribution Explorer — activity over time and model distribution; quota/reset info from quota-service Session ledger with transcript context, tool activity, and patch details Sessions — transcript context, tool activity, and patch detail
Project analysis with daily activity, model mix, and change trail Projects — daily activity, model mix, and change trail Model analysis comparing usage, cost, output, cache behavior, and reasoning effort Models — usage, cost, output, cache behavior, and effort
Data view with provider-specific allowance intelligence and usage findings Data — allowance intelligence, usage findings, and provenance Appearance settings for signal colors, text size, and scene effects Appearance — signal colors, text size, and scene effects

Still frame of the visual status animation showing usage headroom by provider

Visual status — a still from the provider-headroom animation

Download the 18-second visual-status recording (MP4). GitHub serves this repository-tracked MP4 as a download rather than an inline player, so the README uses an explicitly labeled still preview.

Maintaining the screenshot gallery

To refresh the Data screenshot without a personal Chrome profile or existing browser tabs, run bun run screenshot:data. The command captures the Data view at a fixed 1558 × 1072 CSS-pixel viewport.

Before a release, preserve the reviewed image with bun run screenshot:archive -- vX.Y.Z. The changelog must reference that archived copy rather than the rolling README image.

For Projects captures, open ai-usage-observatory and scroll it into view so myessentials-ui and PEF-Main-WP remain outside the screenshot frame.

Designed for ongoing analysis

Six connected views — Overview, Explorer, Sessions, Projects, Models, and Data — use the same collected dataset. Date, agent, path, and cache controls carry analytical context between the views that support each filter.

  • Track usage daily, weekly, monthly, by session, by project instance, and by reconstructed five-hour block with pinned ccusage@20.0.17.
  • Separate input, output, cache-read, and cache-creation tokens, or exclude cache traffic when it would obscure the comparison.
  • Compare API-equivalent cost, model mix, and provider-recorded reasoning effort as model family x effort — the unit an effort label is actually comparable in — without presenting missing effort labels as known data.
  • Trace work across Claude Code and Codex from session to project and model.
  • Apply glob or regular-expression path rules retroactively to the indexed history.
  • Add durable session tags and notes to preserve your own analytical context.
  • Review allowance capture, efficiency signals, and outlier sessions in the experimental Data analysis.
  • Refresh on startup, every 60 seconds, or on demand; if collection fails, the last successful result remains available and is marked stale.

How the data is assembled

Signal Source Role
Tokens and API-equivalent cost Pinned ccusage analytics Produces usage rollups and reconstructed activity blocks from local records.
Session and project attribution Local Claude Code and Codex session files Recovers native session identifiers and working directories through a metadata-only path index.
Model x effort Optional derived index of local session files Reads provider-recorded effort labels beside the model that recorded them and stores categorical aggregates, never reasoning text.
Session verdict You A rating you record yourself. It is never inferred, and it is the only signal in the app that does not come from a local record or a provider.
Provider capacity Optional quota-service instance Supplies provider-reported allowance windows, resets, credits, and status without changing local usage totals.

Important

The current data model assumes one Claude Code account and one Codex account per machine. If you switch accounts within a provider, their local activity is combined rather than attributed separately. See Measurement boundaries.

Privacy model

Usage records, derived indexes, annotations, and application state remain on the machine running the Observatory. The server binds to localhost, sends no telemetry, and does not upload prompts, responses, or usage records. ccusage may retrieve current pricing data; that request does not contain your usage records.

The default path index is metadata-only. It reads only the opening bytes of each session file — enough to recover the native session ID and working directory.

Reasoning-effort indexing is separate, opt-in, and disabled by default. When enabled in Data, it scans transcripts incrementally and stores only session/date/provider/model/effort categories, token buckets, observation counts, parser offsets and hashes, and quality counters. Session verdicts are stored alongside your existing tags and notes and stay on this machine too. It never stores prompts, responses, reasoning text, commands, tool arguments or results, file contents, or transcript fragments. Disabling the index stops new processing and excludes retained rows from analysis; Data can delete all derived effort observations without touching transcripts, annotations, or ccusage snapshots.

Session detail is the one place where your own prompts and sampled assistant output appear. When you open a session, the server reads its file on demand and returns recent user prompts plus bounded assistant-visible text samples so you can identify the work. Reasoning, tool arguments, and tool results are excluded. The response is sent only to your localhost browser and is not stored in the database. The server does not retain the transcript read after serving it.

Session-detail action menus can reveal a transcript or listed changed file in Finder, open it in Visual Studio Code, or send it to the macOS default text editor. Each action requires an explicit click. The server resolves the target from its indexed session record and never executes a browser-supplied shell command.

Application state is stored in .usage-observatory/data.db, which Git ignores. Set USAGE_OBSERVATORY_DB to move the database. Set QUOTA_SERVICE_URL to use a different quota-service base URL.

Measurement boundaries

  • Local activity and provider-reported allowance percentages are separate evidence sources. They are presented together for context, not treated as values that should reconcile one-for-one.
  • Every figure assumes one account per provider. Session indexing reads one local Claude Code session tree and one local Codex session tree; quota-service reads one signed-in credential per provider — the macOS Keychain item written by Claude Code and ~/.codex/auth.json. Activity from multiple accounts on the same provider is displayed as one combined stream.
  • Historical cost comes exclusively from ccusage. It is an API-equivalent estimate, not a subscription bill. Models without a current rate card are identified in the interface and excluded from cost totals rather than counted as free.
  • Allowance figures come from the optional quota-service and are labeled as provider-reported in the interface.
  • Five-hour blocks are reconstructed locally by ccusage and currently cover Claude Code only.
  • Effort labels are shown as recorded after trimming and lowercasing. They are not inferred from model names or reasoning-token counts, and they are not a quality score or recommendation. One observation represents one Claude assistant usage event or one Codex turn context.
  • Effort is only comparable beside the model that recorded it, so the unit of comparison is model family x effort. High on two different families is two different cohorts, not one.
  • Tokens and observations are attributable to a family x effort combination. Session cost, efficiency findings, and verdicts are not: they describe whole sessions, and are reported only over sessions a single combination uniquely led by attributed tokens. Sessions with no unique leader contribute volume and no outcome. These are observed cohort differences — they do not control for task difficulty and are not a recommendation to change model or effort.
  • Reasoning share is reported only where the provider reports reasoning tokens. A provider-reported zero is shown as zero; a provider that reports nothing is shown as not reported, never as zero.
  • Session verdicts are yours. Nothing in the app infers one, and a rate is shown only once a cohort has at least five ratings.

Provider allowance data

The Observatory is useful with or without live quota data. Most installations use one of these two modes.

Run without a quota service

No additional setup is required. Tokens, API-equivalent cost, sessions, projects, models, reasoning-effort analysis, and locally reconstructed Claude Code activity blocks remain available. The Observatory does not invent an allowance estimate when no provider source is connected, so live headroom and current reset or credit details remain unavailable. Quota-event markers and history-dependent allowance analysis also require a previously collected, compatible quota-history database.

Use the provided quota-service

The supported companion is quota-service, a separate local-first service for provider-reported allowance data. It currently targets macOS, reads existing local provider credentials and preferences, enables Codex and Anthropic by default, and can include Warp when configured.

git clone https://github.com/anobjectn/quota-service.git
cd quota-service
bun install
cp .env.example .env
bun run serve

With the service running at its default http://127.0.0.1:8787 address, the Observatory connects automatically. Set QUOTA_SERVICE_URL only when the service uses another base URL.

The provided service supplies provider-reported allowance windows and reset times, from which the Observatory derives current headroom. It also supplies Anthropic usage-credit spend; Codex account and banked-reset credits; optional Warp request-pool status; source freshness; and locally observed quota history. Claude Web prepaid and promotional credits can be added as an explicitly user-entered snapshot because Claude Code credentials cannot read those browser-session endpoints.

Provider collection is read-only: it does not consume credits, purchase anything, or modify provider accounts. The service does write observations to its local SQLite database. The Claude Web import writes only the values entered by the user to that local database; it receives no browser cookies or account credentials and does not contact Claude Web on the user's behalf.

The Observatory reads ~/.quota-service/quota.db directly and read-only for historical quota percentages, observed reaches, and inferred reset-credit use. The provided service retains 90 days of history by default while always keeping the latest row for each provider. Changing its QUOTA_RETENTION_DAYS setting changes how much historical analysis is available.

BYOQS — Bring Your Own Quota Service (advanced compatibility contract)

If you are building or adapting a different collector, set QUOTA_SERVICE_URL to its base URL. Custom quota data remains optional and never replaces locally derived usage totals.

Connection requirements

The Observatory requests /usage, /resets, and /status concurrently with a four-second timeout per request. Each endpoint must return a successful response containing valid JSON; otherwise the live quota source is marked unavailable. /status participates in that connection-health check and may return any JSON value.

GET /usage

Return a numeric generatedAt and a providers array. A provider entry requires:

  • provider: anthropic, codex, or warp.
  • status: ok, stale, unavailable, or unknown.
  • source: a string or null identifying the collection method.
  • snapshot: a window snapshot, pool snapshot, or null.
  • error: an optional status explanation.

dataAgeMs is an optional age duration in milliseconds; capturedAt is an optional Unix-millisecond timestamp for the collection. manualEntries and anthropicWebCredits are also optional. A service that does not provide an optional field can omit it.

A window snapshot supports Anthropic and Codex. Percentages use a 0–100 scale, not a 0–1 fraction; all timestamps are Unix milliseconds:

{
  "kind": "window",
  "fiveHour": { "usedPercent": 36, "resetsAt": 1763912400000 },
  "weekly": { "usedPercent": 12, "resetsAt": 1764499200000 },
  "modelWindows": {
    "example-model": { "usedPercent": 18, "resetsAt": null }
  },
  "usageCredits": {
    "enabled": true,
    "spentAmount": 8.5,
    "limitAmount": 40,
    "currency": "USD",
    "resetsAt": 1767225600000
  },
  "codexCredits": {
    "hasCredits": true,
    "unlimited": false,
    "balance": 1000
  }
}

fiveHour and weekly are required but may be null. modelWindows, usageCredits, and codexCredits are optional and may be omitted; the two credit objects are normally relevant only to their corresponding provider. For usageCredits, spentAmount is numeric, limitAmount and resetsAt may be null, and monetary values use major currency units. For codexCredits, hasCredits and unlimited are booleans and balance may be null; balances are provider-defined credits, not money. A snapshot may also expose an array at extra.rawLimits for the Data provenance view.

A pool snapshot supports a Warp-style request allotment:

{
  "kind": "pool",
  "pool": {
    "used": 42,
    "limit": 100,
    "usedPercent": 42,
    "refreshesAt": 1767225600000,
    "cadence": "Monthly"
  }
}

used, limit, and usedPercent are numeric. refreshesAt may be null, and cadence is optional.

The complete optional Claude Web credit structure is defined by AnthropicWebCredits. Supplying it is not required for live allowance integration.

GET /resets

Return {} or { "codexBankedResetCredits": null } when no banked-reset report is available. Otherwise, use this shape:

{
  "codexBankedResetCredits": {
    "availableCount": 1,
    "totalEarnedCount": 3,
    "status": "ok",
    "credits": [
      {
        "id": "credit-123",
        "title": "Extra reset",
        "status": "available",
        "expiresAt": "2026-12-31T00:00:00.000Z"
      }
    ]
  }
}

The counts may be numeric or null. Credit expiresAt may be null. Only credits whose individual status is exactly available appear in the current banked-reset list; id, title, and expiresAt supply the displayed details. The provided service also returns top-level generatedAt, windows, and pools fields; the current Observatory does not read them. Additional top-level and per-credit reset fields are ignored safely.

Optional Claude Web import

To support the Observatory's manual Claude Web credit workflow, implement POST /anthropic-web-import. The request contains capturedAt, currency, currentBalance, promoRemaining, promoGranted, promoExpiresAt, campaignId, campaignGranted, autoReloadEnabled, purchasedThisMonthAmount, monthlyCapAmount, purchasesResetAt, and maxDiscountPercent. Numeric form values may arrive as numeric strings, and blank optional fields may arrive as empty strings.

Return JSON with a 2xx status after storing a valid snapshot; return a non-2xx JSON error without changing the previous snapshot when validation fails. On the next /usage response, expose the normalized snapshot as the Anthropic provider's anthropicWebCredits value. The Observatory forwards the import result and refreshes quota data after success. This endpoint is not required for the three-GET live quota connection; without it, only the manual Claude Web credit workflow is unavailable.

Optional local history

History is not fetched through the HTTP contract. The Observatory opens a compatible SQLite database at QUOTA_DB_PATH; when the quota URL hostname is 127.0.0.1 or localhost and that variable is unset, it uses ~/.quota-service/quota.db. For any other hostname, history stays disabled unless QUOTA_DB_PATH is set explicitly.

Compatibility requires the snapshots table fields provider, status, captured_at, and snapshot_json, plus the reset_credits fields status, captured_at, and credits_json. snapshot_json must contain the window shape described above, and credits_json must contain an array of reset-credit objects. Only ok and stale rows are analyzed. A quota reach is counted once per reset cycle at the first observation of usedPercent >= 100. Reset-credit use is inferred when a credit is reported as used, consumed, or redeemed, or when an available credit disappears without evidence that it expired.

Sources and acknowledgments

  • ccusage v20.0.17 by ryoppippi (MIT) supplies local usage analytics and API-equivalent price estimates.
  • Local Claude Code and Codex session files supply session identifiers and working-directory metadata during indexing, recent prompts and bounded assistant-output samples on demand, and opt-in categorical effort metadata.
  • quota-service optionally supplies provider-reported allowance windows, resets, credits, and status. It is a separate localhost service, not a bundled dependency.

Current scope and potential enhancements

The current product deliberately excludes additional theme packs, wallpaper engines, and a desktop wrapper.

Under consideration, with no committed timeline: git-aware worktree canonicalization, touched-file indexing, task classification, filesystem watching, native provider collectors, and multi-account attribution within a provider.

Updating is the most likely next improvement. Today a new version means replacing a downloaded copy or running git pull in a clone; a built-in check that reports a new release and applies it in place would remove that step.

Suggestions welcome

There is room for improvement here, and suggestions are welcome. If something is missing, awkward, or wrong for the way you work, open an issue — including questions, corrections, and ideas that fall outside the current scope.

About

Local-first dashboard for AI coding usage. Reads ccusage analytics and local session metadata to chart tokens, cost, sessions, and per-project attribution across Claude Code and Codex. No new cloud login or service — nothing leaves your machine.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages