> ## Documentation Index
> Fetch the complete documentation index at: https://continuum-three-olive.vercel.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Analytics

> Local spend history across every provider, repo, and time window — parsed from the agent CLIs' own logs, priced offline, never uploaded.

Continuum's analytics layer is a Swift re-implementation of the ideas behind [`ccusage`](https://github.com/ryoppippi/ccusage) by [@ryoppippi](https://github.com/ryoppippi). It parses the same kinds of local agent logs, applies the same deduplication logic for Claude, and prices tokens with the same LiteLLM snapshot.

Parsing and pricing run on your Mac, against files the agent CLIs already wrote there. No usage data leaves the device unless you explicitly turn on Mac → iPhone sync or link the Mac to an organization. The one column that arrives from elsewhere is Continuum-hosted inference, which has no local log to read.

**`ccusage daily` is the ground truth.** If Continuum's numbers diverge from `ccusage`, ccusage is correct.

## What gets parsed

The loader walks each provider's own on-disk logs. A provider whose store isn't there — because you don't use it, or its CLI isn't installed — is skipped cleanly rather than treated as an error, and providers you've turned off in **Settings → Providers** get no column at all.

| Provider             | Source                                                                                                                                                                                                                                                                      |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Claude               | `~/.claude/projects/**/*.jsonl`                                                                                                                                                                                                                                             |
| Codex                | `~/.codex/sessions/**/*.jsonl`                                                                                                                                                                                                                                              |
| Antigravity / Gemini | `~/.gemini/antigravity/conversations/*.{pb,db}` (desktop IDE) plus `~/.gemini/antigravity-cli/conversations/*.db` (the `agy` CLI). Tokens are estimated from each conversation's brain directory. macOS and iOS only.                                                       |
| OpenCode             | `~/.local/share/opencode/opencode.db` (SQLite, WAL mode; honors `OPENCODE_DATA_DIR`). macOS only.                                                                                                                                                                           |
| Cursor               | Cursor Agent transcripts (`~/.cursor/projects`), hook logs (`~/Library/Application Support/Cursor/logs`), and the agent KV state DB. On macOS, the Cursor dashboard's billing events (with authoritative `chargedCents`) are preferred over local estimates when available. |
| Grok                 | Continuum's own harness ledger for precise per-turn ACP usage, plus the Grok CLI's `signals.json` files under `~/.grok/sessions`.                                                                                                                                           |
| Z.ai Coding          | Same OpenCode database. Z.ai GLM Coding Plan rides the OpenCode connector, so its rows are split out of the shared store by provider id and given their own column — priced from the underlying GLM model.                                                                  |
| Continuum (hosted)   | **Not parsed from disk.** There is no local rollout for models Continuum serves itself, so this column is fed by the usage envelope from your account and stays empty on a device that only reads local logs. See [Hosted inference](/docs/features/hosted-inference).           |

<Note>
  The parsed-source list grows as Continuum adds providers. Every column except Continuum-hosted comes from a log the agent CLI wrote on your own machine — Continuum reads those files, it does not instrument the CLIs.
</Note>

### Deduplication

Claude's JSONL frequently repeats the same assistant turn across files when a session resumes. Continuum collapses those on the message's `id` — with the top-level `requestId` as an optional qualifier when present. (Recent Claude Code builds dropped `requestId`, so requiring both would double-count resumed history; keying on `message.id` matches ccusage's outcome.) Cross-file duplicates are caught at merge time, not just within a file.

Codex carries a cumulative `total_token_usage` snapshot rather than per-turn counts, so Continuum computes per-turn **deltas** by subtracting the previous cumulative. Zero-delta heartbeats are dropped, and a non-monotonic drop (a session reset mid-file) is treated as a fresh baseline rather than a negative delta. Codex records carry no dedup key — the delta math is the dedup.

## Multi-account aggregation

You can add a second account on **every** provider (see [multi-account](/docs/features/multi-account)), but only **Claude and Codex** contribute extra history to this loader. Those two write their logs under a per-instance config directory (`$CLAUDE_CONFIG_DIR/projects`, `$CODEX_HOME/sessions`), so the loader merges each account's root into the Claude and Codex passes alongside the default account and the history rolls into the same aggregate totals.

The other providers isolate accounts by other means — an API key at spawn, an isolated `HOME`, an `XDG_DATA_HOME` — which routes and bills the session correctly but produces no second on-disk log root to walk. Their spend still lands in analytics; it just isn't split by account.

The extra roots are re-read on every refresh, so an account you add in Settings joins the totals on the **next** refresh without rebuilding the store or relaunching the app.

<Note>
  Totals are aggregated **across** accounts in this version — there is no per-account spend breakdown yet. See [Providers](/docs/providers/overview) for the multi-account setup flow.
</Note>

## Time windows

| Window   | Alignment                            |
| -------- | ------------------------------------ |
| Today    | Current calendar day, local timezone |
| Past 7d  | 7 calendar days, local timezone      |
| Past 30d | 30 calendar days, local timezone     |
| All time | Full history                         |

Windows are calendar-day aligned in your local timezone, matching ccusage's `daily` default. UTC bucketing was evaluated and rejected — it diverges from ccusage near midnight.

The tokens-by-model breakdown on the Usage tab is windowed slightly differently (it also exposes a trailing-90d view), but the dollar totals and per-repo split use the four windows above.

## Repo identity

Continuum walks up the directory tree from each record's working directory to find the canonical git repository, so every branch and worktree of one repo rolls up to a single row. It handles:

1. **Regular git directory** — the directory containing `.git` is the repo root.
2. **Worktree pointer file** — reads the `gitdir:` line (resolving a relative pointer against the `.git` file's own parent) and buckets under the **main** worktree.
3. **Conductor workspace** (`<…>/conductor/workspaces/<repo>/<branch>`) — introspects a live sibling branch's `.git` pointer to discover the underlying main repo, falling back to a stable per-repo bucket.
4. **Claude Code worktree** (`<repo>/.claude/worktrees/<branch>`) — collapses every worktree of a repo into one bucket.
5. **Sole-git-child descent** — if a directory isn't itself a repo but contains exactly one child that is, it collapses to that child (covers launching an agent from a parent folder).

A cwd that resolves to none of these collapses to a shared **"Other"** row, and a record with no cwd at all collapses to **"(unknown)"**. This keeps random UUID folders, home directories, and abandoned workspace IDs out of the repo list.

## Pricing

Token costs are calculated from a **bundled LiteLLM pricing snapshot**, so analytics work offline and totals are reproducible. Tiered pricing — rates that change above a prompt-size threshold — is applied per model. Models that aren't in the snapshot are tracked under "unpriced model tokens" so their token counts still appear even when no dollar figure can be attached.

A second bundled file of **manual overrides** is merged on top of the snapshot and wins per key. It exists for rates LiteLLM hasn't shipped yet — newly released frontier models, xAI and Z.ai GLM ids, and the models Continuum hosts itself — and doubles as an audit trail: each manual entry carries a note recording the source of the rate and the date it was verified.

Contributors can refresh the snapshot with `tools/refresh-pricing.sh`, which fetches the current LiteLLM table, filters it to the model families Continuum tracks (`claude-*`, `gpt-*`, `o[0-9]*`, `chatgpt-*`, `gemini-*`, `gemma-*`, `grok-*`, `xai/*`), then re-applies the manual overrides on top.

## Cache

Parsed results cache to the app's container, falling back to:

```
~/Library/Application Support/Clawdmeter/analytics-cache.json
```

The cache is schema-versioned. When you update Continuum and the schema changes, old caches are treated as empty and re-parse on first load — nothing stale survives an upgrade. Entries are keyed by file path and hold that file's per-day, per-repo, and per-model token totals along with its dedup keys.

A file is reused from cache only when its mtime **and** size match. The newest-mtime file per provider always bypasses the cache — the active session may still be appending mid-walk. Cold reparses checkpoint after each provider's corpus, so an interrupted re-parse (quit, sleep, crash) resumes instead of restarting from zero.

## Mac → iPhone sync

The Mac writes a usage snapshot to iCloud key-value storage under the key `cloud.analytics.v1`. iPhone picks it up when iCloud reports the change and renders the same totals, chart, and per-repo split. Nothing leaves the device except through this key.

<Warning>
  Personal-team Apple Developer accounts cannot sign the iCloud entitlement. On those builds, the iPhone analytics surface falls back to "waiting for Mac sync." Upgrading to a paid Apple Developer Program membership resolves it.
</Warning>

<Note>
  If this Mac is linked to an organization, detailed per-repo analytics are never mirrored to personal iCloud — the snapshot is suppressed and any snapshot written before the link is cleared, so an employee's repo names don't end up in personal iCloud while their usage reports to the org. See [Privacy](/docs/privacy) and [Organization](/docs/features/organization).
</Note>

## Loader performance

The loader walks every provider directory in parallel, parsing files at background priority so a multi-gigabyte cold reparse doesn't starve the rest of the app. Overlapping refresh requests coalesce — a second caller awaits the first's result instead of starting a parallel walk — and a lightweight mtime probe lets the store skip a refresh entirely when nothing on disk changed since the last load.

## Related

* [Usage](/docs/surfaces/usage) — the live quota gauges and the analytics panel below them.
* [Providers](/docs/providers/overview) — connecting subscriptions and adding multiple accounts.
* [Hosted inference](/docs/features/hosted-inference) — where the Continuum column's numbers come from.
* [Mobile](/docs/surfaces/mobile) — iCloud sync to iPhone.
* [Privacy](/docs/privacy) — what stays local and what (with opt-in) leaves the device.
