Skip to main content
Continuum’s analytics layer is a Swift re-implementation of the ideas behind ccusage by @ryoppippi. It parses the same local log files, applies the same deduplication logic, and prices tokens with the same LiteLLM snapshot. ccusage daily is the ground truth. If Continuum’s numbers diverge from ccusage, ccusage is correct.

What gets parsed

ProviderSource files
Claude~/.claude/projects/*.jsonl
Codex~/.codex/sessions/*.jsonl
AntigravityConversation DB and brain-dir state (macOS and iOS only)
OpenCodeOpenCode session logs
Events are deduplicated by messageId:requestId pair, matching ccusage’s dedup behavior. Codex usage undergoes cumulative-to-delta conversion.

Time windows

WindowAlignment
TodayCurrent calendar day, local timezone
Past 7 days7 calendar days, local timezone
Past 30 days30 calendar days, local timezone
All timeFull history
Windows are calendar-day aligned in Calendar.current (your local timezone), matching ccusage’s daily default. UTC bucketing was evaluated and rejected — it diverges from ccusage near midnight.

Repo identity

RepoIdentity.normalize(cwd) walks up the directory tree to find .git. It handles three cases:
  1. Regular git directory — uses it directly.
  2. Worktree pointer file — reads gitdir: and resolves to the main worktree.
  3. Conductor workspace (~/conductor/workspaces/<repo>/<branch>) — introspects a live sibling’s .git pointer to discover the underlying main repo.
Non-git paths (UUIDs, home directories) collapse to RepoKey.other, which appears as “Other” in the repo breakdown.

Pricing

Token costs are calculated from a bundled LiteLLM pricing snapshot at apple/ClawdmeterShared/Sources/ClawdmeterShared/Analytics/pricing.json. Tiered Claude pricing is handled in Pricing.swift. Refresh the snapshot anytime:
./tools/refresh-pricing.sh
The script fetches the current LiteLLM pricing and filters it to claude-*, gpt-*, and o[0-9]+* models.

Cache

Parsed results cache to:
~/Library/Application Support/Clawdmeter/analytics-cache.json
The cache is schema-versioned (currently v8). Per-file shape:
byDayByRepo: [Date: [RepoKey: TokenTotals]]
dedupKeys: [String]
unpricedModelTokens: [String: TokenTotals]
When you update Continuum and the schema version changes, old caches re-parse on first load. The version constant lives in UsageHistoryLoader.swift — bump it whenever the schema changes.

Mac → iOS sync

The Mac writes a UsageHistorySnapshot to iCloud KV under the key cloud.analytics.v1. iOS reads it on didChangeExternallyNotification.
Personal-team Apple Developer accounts cannot sign the iCloud entitlement. On those builds, the iOS Analytics tab shows “iCloud not enabled” or “Waiting for Mac sync”. Upgrading to a paid Apple Developer Program membership resolves this.

Loader performance

UsageHistoryLoader is an actor. loadAll() walks both provider directories in parallel via withTaskGroup. Parsers are nonisolated static so the task group genuinely parallelizes. The newest-mtime file per provider bypasses the file-mtime cache — the active session may still be appending.
  • Usage — live quota gauges and the analytics panel below them.
  • Mobile — iCloud KV sync to iPhone.