Skip to content

Add support for a new AI coding agent (usage provider) — architecture & contribution guide #115

Open

Description

@chattymin

What this is

PokeTokenBar tracks usage across AI coding tools. This is a standing invitation to add a new usage source and a guide to integrating it with the existing architecture.

Want to add a specific agent? Either:

  • Open a separate issue referencing this one (for example, Add <agent> usage tracking), so each agent can be tracked independently; or
  • Open a PR directly using the repository PR template and linking back here.

Already supported on main

Last checked against 9be4ea95 on October 6, 2026. This list describes merged code, not a promise that every change is in the latest release.

Tool Provider ID
Claude Code claude_code
Codex codex
Gemini gemini
Antigravity antigravity
OpenCode opencode
Hermes Agent hermes
Cursor cursor
Grok grok
Copilot copilot
Kiro kiro
Pi pi
oh-my-pi (omp) omp
Aside aside
Kimi Code kimi_code

Recent merged work includes Pi support (#189), omp support (#214), Kiro CLI 2.20+ JSONL support (#238), Cursor dashboard fallback (#197), Aside support (#283), cost provenance and unavailable-cost handling (#289), selected-language localization (#290), Kimi Code local usage (#403, closes #386), and Russian UI localization (#372). Pi and omp are separate providers; support for one does not automatically update the other.

Core integration

Read docs/reference/provider-extension.md and CLAUDE.md before implementing a source.

  1. Implement the UsageProvider protocol defined in Sources/PokeTokenBar/Core/UsageProvider.swift: use a unique, stable id, a displayName, fetchDaily(), and fetchEnrichment(). The protocol also exposes reportsCost (default true).
  2. Register the provider in the default providers: array in Core/UsageStore.swift.
  3. Add the reader, cache integration, scan roots, and tests needed by the actual source format. The provider and registration array are the core extension points, not a two-file limit.

Use official source documentation or versioned upstream writer code to establish the file format, token semantics, model identity, and cost meaning. Include that evidence and sanitized fixtures in the PR. Do not assume a fork has identical storage or accounting semantics.

Reuse the existing data path

  • For established JSONL sources, see LocalUsageProvider.swift, LocalUsageReader.swift, and LocalUsageCache.swift.
  • For a new local file/DB source, start with LocalAdditionalSource, a reader, and LocalAdditionalUsageCache in LocalAdditionalUsageProvider.swift. Reuse its shared scan and merge behavior; document a concrete reason if a different cache path is necessary.
  • Assemble block/week/month/daily-series enrichment with ProviderEnrichment.local(entries:now:). Use LocalUsageReader.enrichmentScanStart(now:) for scan windows so week and month boundaries are covered.
  • For append-only SQLite stores, reuse LocalAdditionalUsageReader.scanIncrementalStores where its assumptions match the source. Test resets/recreation and stable entry identity for that source.
  • When changing persisted parsing semantics, review the relevant parser/cache version and test loading a cache produced by the previous parser, not only an empty cache.

Architecture and integration checklist

  • Keep universal aggregation provider-agnostic. Today/week/month totals, burn rate, and companion activity must flow through the shared snapshot aggregation. Do not add provider-ID branches to these calculations. Keep the unknown-provider parity tests in UsageStoreTests green.
  • Keep provider-specific behavior at its own integration point. Official rate limits and authentication are separate capabilities, not implied by local usage support. Existing official-limit integrations include Claude, Codex, Antigravity, and Cursor (feat(cursor): show remaining included usage from dashboard limits API #273).
  • Integrate custom scan folders. Read customScanRoots.<providerID> in the source's root resolver, use CustomScanRoots.union to preserve default roots, and add the matching defaults to CustomScanRoots.curatedRoots(for:) so Settings counts the same locations the reader scans. Test with injected roots instead of the contributor's real home directory.
  • Share install-path discovery. Additional version-manager directories belong in BinaryLocator.commonToolDirectories().
  • Preserve cost provenance. Distinguish source-reported costs, estimates, and unpriced usage as implemented in fix: distinguish estimated and unavailable usage costs #289. Missing price data must not be presented as a measured $0, and a token-price estimate must not be described as an actual invoice. Subscription/API-key support alone does not establish the meaning of a recorded cost.
  • Describe failure semantics. State when fetchDaily returns nil, throws, or returns data, and when enrichment OK flags remain false. Check how UsageStore.refresh handles each outcome; no data and a read failure are not interchangeable.
  • Localize new user-facing text. Use the existing localization mechanism for explanatory strings and errors. Current app languages are English, Korean, Japanese, Spanish, French, Brazilian Portuguese, German, and Russian. Brand/model names can remain their official names.
  • Status pages are optional. If the tool has a compatible statuspage.io endpoint, add the exact relevant component to StatuspageStatusProvider.endpoints. The current integrations are Claude Code and Codex. Usage tracking does not require a status page.

Definition of done

  • Provider implementation and registration, with source-format evidence and sanitized fixtures.
  • Correct token buckets, model attribution where supported, and cost provenance.
  • Shared cache and custom-root integration, including Settings root counts.
  • Tests exercise the provider through its cache and cover relevant incremental/repeated reads, source changes, and previous-cache behavior.
  • No-data and failure behavior verified through the consuming store.
  • Provider-agnostic today/week/month/burn aggregation and monthly daily-series behavior remain covered.
  • ./scripts/test-gate.sh passes; inspect coverage for newly added branches rather than relying only on the total percentage.
  • New explanatory UI/error strings use the supported localization mechanism.
  • Update the provider list and applicable setup instructions in README.md, README.ko.md, and README.ja.md.
  • PR description follows .github/PULL_REQUEST_TEMPLATE.md, reports actual validation, and includes before/after evidence for UI changes.

PR titles, descriptions, and commit messages should be in English. Keep this standing issue open for future agents; individual source requests and fixes should be tracked separately.

Pinned by chattymin

Activity

  1. chattymin commented on Jul 24, 2026

    @chattymin
    OwnerAuthor

    Already supported on main

    Pi and omp are separate providers. OMP per-model usage display (#276) is merged; its model-price cost is presented as an estimate, not universally billed cost. Official-limit integrations include Claude, Codex, Antigravity, and Cursor (#273). Russian UI localization (#372) is also merged. #289 updated cost provenance and unavailable-cost handling; the issue body now covers the shared cache/enrichment paths, scan-folder integration, localization, and current contribution requirements.

    Updated October 6, 2026, checked against 9be4ea95. This tracks merged main, not release availability. This standing invitation remains open for additional agents.

  2. added a commit that references this issue on Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions