Skip to content

[codex] add provider coverage parity#133

Merged
ya-nsh merged 3 commits into
mainfrom
codex/tokscale-competitive-analysis
May 26, 2026
Merged

[codex] add provider coverage parity#133
ya-nsh merged 3 commits into
mainfrom
codex/tokscale-competitive-analysis

Conversation

@ya-nsh

@ya-nsh ya-nsh commented May 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add local/cache-only providers for Codebuff, Droid, Kimi, Kilo CLI, Mux, Crush, Goose, Antigravity, Zed Agent, Kiro, Trae, and Synthetic.
  • Wire the new provider keys through registry exports, CLI aliases/listing, TUI, MCP defaults, and renderer/TUI color maps.
  • Make Hermes SQLite ingestion tolerant of optional schema differences while preserving provider-reported costs, and document provider overrides/limitations in the README.

Validation

  • bun test packages/registry/src/providers/provider-parity.test.ts
  • bun test packages/cli/src/cli.test.ts
  • bun run check
  • bun run test
  • bun run build

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for 12 new AI assistant providers: Codebuff, Droid, Kimi, Kilo, Mux, Crush, Goose, Antigravity, Zed, Kiro, Trae, and Synthetic.
    • Provider paths are now customizable via TOKENLEAK_*_DIR environment variables for enhanced configuration flexibility.
  • Documentation

    • Comprehensive documentation added for all newly supported providers.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@ya-nsh, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 49 minutes and 23 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b844942a-09df-49ac-ab6e-f97e65e4588a

📥 Commits

Reviewing files that changed from the base of the PR and between e71f374 and a843767.

📒 Files selected for processing (17)
  • README.md
  • packages/cli/src/cli.test.ts
  • packages/cli/src/cli.ts
  • packages/mcp/src/resources/overview.ts
  • packages/mcp/src/shared/provider-load.ts
  • packages/mcp/src/tools/compare-periods.ts
  • packages/mcp/src/tools/get-cost-breakdown.ts
  • packages/mcp/src/tools/get-daily-usage.ts
  • packages/mcp/src/tools/get-efficiency-advice.ts
  • packages/mcp/src/tools/get-receipt-lines.ts
  • packages/mcp/src/tools/get-streaks-and-habits.ts
  • packages/mcp/src/tools/get-usage-summary.ts
  • packages/registry/src/index.ts
  • packages/registry/src/providers/hermes.ts
  • packages/registry/src/providers/provider-parity.test.ts
  • packages/registry/src/providers/zed.ts
  • packages/tui/src/lib/data.ts
📝 Walkthrough

Walkthrough

This PR adds support for 12 new AI agent providers (Codebuff, Droid, Kimi, Kilo, Mux, Crush, Goose, Antigravity, Zed, Kiro, Trae, Synthetic) to the TokenLeak registry. Each provider implementation parses local cache or database files, extracts token usage within a date range, and normalizes to a common record format. Provider classes are exported, wired into CLI/MCP, assigned UI colors, tested comprehensively, and documented.

Changes

Multi-provider expansion

Layer / File(s) Summary
12 new provider implementations
packages/registry/src/providers/codebuff.ts, droid.ts, kimi.ts, kilo.ts, mux.ts, crush.ts, goose.ts, antigravity.ts, zed.ts, kiro.ts, trae.ts, synthetic.ts
Each provider reads local cache/database, parses session/message/usage rows, filters by date range, computes token totals, and returns normalized usage records via buildProviderData with provider metadata and colors.
Hermes schema adaptability
packages/registry/src/providers/hermes.ts
Added schema-aware helpers to discover table columns via PRAGMA and generate dynamic SELECT/WHERE clauses so Hermes handles optional cost/token fields missing in some database versions.
Registry and public exports
packages/registry/src/providers/index.ts, packages/registry/src/index.ts
Re-exports all 12 new provider classes to make them available to CLI, MCP, and TUI consumers.
CLI and MCP service registration
packages/cli/src/cli.ts, packages/mcp/src/server.ts
Imports and registers all 12 new providers; extends PROVIDER_ALIASES, PROVIDER_ALIAS_GROUPS, and PROVIDER_COLORS for alias-aware discovery and color-consistent rendering; updates registerBuiltInProviders and createDefaultRegistry to instantiate all providers.
UI and TUI color mappings
packages/renderers/src/live/wrapped-live-template.ts, packages/renderers/src/svg/wrapped-single-page.ts, packages/tui/src/lib/data.ts, packages/tui/src/lib/theme.ts
Adds provider-to-color entries so new providers display with consistent brand colors in CLI focus output, SVG reports, and TUI dashboard; wires providers into TUI registry via createRegistry.
Provider parity tests and validation
packages/cli/src/cli.test.ts, packages/registry/src/providers/provider-parity.test.ts
Adds comprehensive parity tests for each of the 12 providers validating token extraction and date filtering; extends CLI tests to verify new providers appear in --list-providers and resolveTabbedDashboardProviders with correct filtering; adds Hermes variant test for missing cost columns.
Provider documentation
README.md
Expands provider overview table with 12 new rows, adds detailed provider sections describing data sources/file locations/schemas, documents environment variable overrides (TOKENLEAK_*_DIR) for each provider, and lists aliases and configuration notes.

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • ya-nsh/tokenleak#91: Documentation-only README updates expanding provider coverage and listing aliases/env-var overrides, directly related to this PR's documentation expansion.
  • ya-nsh/tokenleak#41: Modifies CLI provider selection/filtering in packages/cli/src/cli.ts (alias handling, --list-providers), directly related to this PR's provider aliasing and discovery system.
  • ya-nsh/tokenleak#93: Extends the same CLI/MCP provider-wiring code (imports, PROVIDER_ALIASES, PROVIDER_COLORS, registry registration), but adds the Cursor provider instead of these 12 non-Cursor providers.

🐰 Twelve new agents hop into the warren,
From Codebuff to Synthetic, each with their warren,
Token trails parsed in SQLite and JSON arrays,
Colors assigned for dashboards and layers.
The registry grows—more voices to hear! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.59% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[codex] add provider coverage parity' accurately describes the main change: expanding local provider support across 12 new providers and integrating them throughout the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/tokscale-competitive-analysis

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ya-nsh ya-nsh marked this pull request as ready for review May 26, 2026 18:57
Comment thread packages/cli/src/cli.ts
Comment thread packages/registry/src/providers/zed.ts Outdated
Comment thread packages/registry/src/providers/hermes.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/registry/src/providers/hermes.ts`:
- Line 125: rowToRecord is still dropping rows with zero tokens even when
signalPredicate now includes non-zero-cost rows, so update rowToRecord (and any
downstream filtering it uses) to preserve records that have cost > 0 regardless
of token count: change the token-count-based discard logic in rowToRecord to
check for cost (e.g., keep if row.cost && row.cost > 0) before skipping, ensure
the returned Record includes the cost field so cost-only sessions survive
query-time inclusion, and remove or adjust any other filters that assume zero
tokens means drop.

In `@packages/registry/src/providers/kilo.ts`:
- Around line 29-31: The resolveDbPath function currently returns
process.env['TOKENLEAK_KILO_DIR'] verbatim which breaks if callers pass a
directory; change resolveDbPath to detect when TOKENLEAK_KILO_DIR (or the
optional dbPath arg) is a directory and if so append the expected DB filename
(use the basename from DEFAULT_DB_PATH) and return the joined path; implement
detection using path and fs (e.g., fs.existsSync +
fs.statSync(...).isDirectory() or fallback to checking trailing path separator)
and normalize with path.resolve/path.join so DB open later receives a full file
path.

In `@packages/registry/src/providers/kiro.ts`:
- Around line 103-107: The current DB load uses JSON.parse on each row's history
inside the flatMap, which lets one malformed history throw and abort the entire
load; update the logic around the rows iteration (where rows is produced and
processed into parseKiroSessionObject) to try/catch JSON.parse and/or
objectValue per row, skip rows whose history fails to parse, and continue
parsing valid rows; reference the same symbols: keep using db.query(...).all(),
objectValue(JSON.parse(...)), stringValue(row['id']), and parseKiroSessionObject
but wrap the JSON.parse/objectValue/parseKiroSessionObject call in a per-row
try/catch, optionally logging the row id or error, and return [] for errored
rows so other rows are still ingested.

In `@packages/registry/src/providers/provider-parity.test.ts`:
- Around line 549-554: The test checks a floating-point sum with exact equality
(expect(data.totalCost).toBe(0.036)) which is brittle; change the assertion to a
tolerant matcher such as Jest's toBeCloseTo (e.g.,
expect(data.totalCost).toBeCloseTo(0.036, 3)) so the MuxProvider.load result's
totalCost is compared with a tolerance rather than strict IEEE-754 equality.
Target the assertion for data.totalCost in the provider-parity.test (the
MuxProvider.load result) and adjust the precision as appropriate.

In `@packages/registry/src/providers/synthetic.ts`:
- Around line 35-37: The hf: branch returns the whole string when there is no
slash (e.g., "hf:deepseek-r1"), so update the branch that checks if
(lower.startsWith('hf:')) to extract the last segment and then strip the "hf:"
prefix if present: compute const last = lower.split('/').at(-1) ?? ''; if
(last.startsWith('hf:')) return last.slice(3); else return last; this ensures
both slash-separated IDs and single-segment hf: IDs normalize correctly
(referencing the existing lower variable and the hf: branch in
providers/synthetic.ts).

In `@packages/renderers/src/svg/wrapped-single-page.ts`:
- Line 85: The dark-mode color for the "kimi" provider in the color palette
object is inconsistent; update the "kimi" entry in wrapped-single-page.ts so its
dark value is "`#111827`" (matching the other renderers) instead of "`#9ca3af`" to
ensure uniform rendering across wrapped-live-template and theme mappings.

In `@README.md`:
- Line 3: The intro sentence lists the provider name as "Kimi" but other
references use "Kimi CLI"; update the string in the intro (the list of providers
in README.md) to "Kimi CLI" so it matches the provider table and details
sections (search for the literal "Kimi" in that provider list and replace it
with "Kimi CLI").
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0af5362b-7065-427c-894e-1b86970a434a

📥 Commits

Reviewing files that changed from the base of the PR and between 7acd6f8 and e71f374.

📒 Files selected for processing (24)
  • README.md
  • packages/cli/src/cli.test.ts
  • packages/cli/src/cli.ts
  • packages/mcp/src/server.ts
  • packages/registry/src/index.ts
  • packages/registry/src/providers/antigravity.ts
  • packages/registry/src/providers/codebuff.ts
  • packages/registry/src/providers/crush.ts
  • packages/registry/src/providers/droid.ts
  • packages/registry/src/providers/goose.ts
  • packages/registry/src/providers/hermes.ts
  • packages/registry/src/providers/index.ts
  • packages/registry/src/providers/kilo.ts
  • packages/registry/src/providers/kimi.ts
  • packages/registry/src/providers/kiro.ts
  • packages/registry/src/providers/mux.ts
  • packages/registry/src/providers/provider-parity.test.ts
  • packages/registry/src/providers/synthetic.ts
  • packages/registry/src/providers/trae.ts
  • packages/registry/src/providers/zed.ts
  • packages/renderers/src/live/wrapped-live-template.ts
  • packages/renderers/src/svg/wrapped-single-page.ts
  • packages/tui/src/lib/data.ts
  • packages/tui/src/lib/theme.ts

Comment on lines +99 to +100
sessionId: `${dbPath}:${row.id}`,
projectId: dirname(dbPath).split(/[\\/]/).at(-1),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid leaking absolute filesystem paths in sessionId.

Line 99 includes full dbPath, which can expose local usernames and host-specific paths in exported/reporting data.

💡 Proposed fix
 function rowToRecord(dbPath: string, row: CrushSession, range: DateRange): LocalUsageRecord | null {
+  const dbId = dirname(dbPath).split(/[\\/]/).slice(-2).join('/');
   const timestamp = timestampToIso(row.updated_at || row.created_at);
   const date = timestamp ? extractDate(timestamp) : null;
   if (!timestamp || !date || !isInRange(date, range)) return null;
@@
-    sessionId: `${dbPath}:${row.id}`,
+    sessionId: `${dbId}:${row.id}`,
     projectId: dirname(dbPath).split(/[\\/]/).at(-1),
   };
 }

Comment thread packages/registry/src/providers/hermes.ts
Comment on lines +29 to +31
function resolveDbPath(dbPath?: string): string {
return dbPath ?? process.env['TOKENLEAK_KILO_DIR'] ?? DEFAULT_DB_PATH;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle directory-style TOKENLEAK_KILO_DIR values correctly.

Line 30 returns the override verbatim. If users provide a directory path, Line 86 passes availability, but DB open later fails and returns empty data.

💡 Proposed fix
 function resolveDbPath(dbPath?: string): string {
-  return dbPath ?? process.env['TOKENLEAK_KILO_DIR'] ?? DEFAULT_DB_PATH;
+  const candidate = dbPath ?? process.env['TOKENLEAK_KILO_DIR'] ?? DEFAULT_DB_PATH;
+  return candidate.endsWith('.db') ? candidate : join(candidate, 'kilo.db');
 }

Also applies to: 85-87

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/registry/src/providers/kilo.ts` around lines 29 - 31, The
resolveDbPath function currently returns process.env['TOKENLEAK_KILO_DIR']
verbatim which breaks if callers pass a directory; change resolveDbPath to
detect when TOKENLEAK_KILO_DIR (or the optional dbPath arg) is a directory and
if so append the expected DB filename (use the basename from DEFAULT_DB_PATH)
and return the joined path; implement detection using path and fs (e.g.,
fs.existsSync + fs.statSync(...).isDirectory() or fallback to checking trailing
path separator) and normalize with path.resolve/path.join so DB open later
receives a full file path.

Comment on lines +103 to +107
const rows = db.query('SELECT id, history FROM conversations_v2').all() as Array<Record<string, unknown>>;
return rows.flatMap((row) => {
const history = objectValue(JSON.parse(String(row['history'] ?? '{}')));
return history ? parseKiroSessionObject(history, stringValue(row['id']) ?? 'kiro-sqlite', range) : [];
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Malformed SQLite history in one row drops the entire Kiro DB load.

A single bad history JSON currently aborts parsing for all rows in that database. Handle parse failures per row so valid rows are still ingested.

Suggested fix
-    return rows.flatMap((row) => {
-      const history = objectValue(JSON.parse(String(row['history'] ?? '{}')));
-      return history ? parseKiroSessionObject(history, stringValue(row['id']) ?? 'kiro-sqlite', range) : [];
-    });
+    return rows.flatMap((row) => {
+      try {
+        const history = objectValue(JSON.parse(String(row['history'] ?? '{}')));
+        return history
+          ? parseKiroSessionObject(history, stringValue(row['id']) ?? 'kiro-sqlite', range)
+          : [];
+      } catch {
+        return [];
+      }
+    });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const rows = db.query('SELECT id, history FROM conversations_v2').all() as Array<Record<string, unknown>>;
return rows.flatMap((row) => {
const history = objectValue(JSON.parse(String(row['history'] ?? '{}')));
return history ? parseKiroSessionObject(history, stringValue(row['id']) ?? 'kiro-sqlite', range) : [];
});
const rows = db.query('SELECT id, history FROM conversations_v2').all() as Array<Record<string, unknown>>;
return rows.flatMap((row) => {
try {
const history = objectValue(JSON.parse(String(row['history'] ?? '{}')));
return history
? parseKiroSessionObject(history, stringValue(row['id']) ?? 'kiro-sqlite', range)
: [];
} catch {
return [];
}
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/registry/src/providers/kiro.ts` around lines 103 - 107, The current
DB load uses JSON.parse on each row's history inside the flatMap, which lets one
malformed history throw and abort the entire load; update the logic around the
rows iteration (where rows is produced and processed into
parseKiroSessionObject) to try/catch JSON.parse and/or objectValue per row, skip
rows whose history fails to parse, and continue parsing valid rows; reference
the same symbols: keep using db.query(...).all(), objectValue(JSON.parse(...)),
stringValue(row['id']), and parseKiroSessionObject but wrap the
JSON.parse/objectValue/parseKiroSessionObject call in a per-row try/catch,
optionally logging the row id or error, and return [] for errored rows so other
rows are still ingested.

Comment on lines +549 to +554
const data = await new MuxProvider(root).load(RANGE);

expect(data.provider).toBe('mux');
expect(data.totalTokens).toBe(20);
expect(data.totalCost).toBe(0.036);
expect(data.events?.[0]?.projectId).toBe('workspace-a');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use a tolerant matcher for totalCost float assertions

Line 553 uses exact equality for a summed decimal (expect(data.totalCost).toBe(0.036);), which can be brittle under IEEE-754 rounding. Use a tolerance-based assertion instead.

Suggested fix
-    expect(data.totalCost).toBe(0.036);
+    expect(data.totalCost).toBeCloseTo(0.036, 6);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const data = await new MuxProvider(root).load(RANGE);
expect(data.provider).toBe('mux');
expect(data.totalTokens).toBe(20);
expect(data.totalCost).toBe(0.036);
expect(data.events?.[0]?.projectId).toBe('workspace-a');
const data = await new MuxProvider(root).load(RANGE);
expect(data.provider).toBe('mux');
expect(data.totalTokens).toBe(20);
expect(data.totalCost).toBeCloseTo(0.036, 6);
expect(data.events?.[0]?.projectId).toBe('workspace-a');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/registry/src/providers/provider-parity.test.ts` around lines 549 -
554, The test checks a floating-point sum with exact equality
(expect(data.totalCost).toBe(0.036)) which is brittle; change the assertion to a
tolerant matcher such as Jest's toBeCloseTo (e.g.,
expect(data.totalCost).toBeCloseTo(0.036, 3)) so the MuxProvider.load result's
totalCost is compared with a tolerance rather than strict IEEE-754 equality.
Target the assertion for data.totalCost in the provider-parity.test (the
MuxProvider.load result) and adjust the precision as appropriate.

Comment on lines +35 to +37
if (lower.startsWith('hf:')) {
return lower.split('/').at(-1) ?? lower.slice(3);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

hf: model normalization fails for single-segment IDs.

For values like hf:deepseek-r1, the current branch keeps the hf: prefix, which can break model normalization consistency.

Suggested fix
 function normalizeSyntheticModel(model: string): string {
   const lower = model.toLowerCase();
   if (lower.startsWith('hf:')) {
-    return lower.split('/').at(-1) ?? lower.slice(3);
+    const withoutPrefix = lower.slice(3);
+    return withoutPrefix.split('/').at(-1) ?? withoutPrefix;
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/registry/src/providers/synthetic.ts` around lines 35 - 37, The hf:
branch returns the whole string when there is no slash (e.g., "hf:deepseek-r1"),
so update the branch that checks if (lower.startsWith('hf:')) to extract the
last segment and then strip the "hf:" prefix if present: compute const last =
lower.split('/').at(-1) ?? ''; if (last.startsWith('hf:')) return last.slice(3);
else return last; this ensures both slash-separated IDs and single-segment hf:
IDs normalize correctly (referencing the existing lower variable and the hf:
branch in providers/synthetic.ts).

cursor: { dark: '#7c5cbf', light: '#6a4aaa' },
codebuff: { dark: '#2563eb', light: '#1d4ed8' },
droid: { dark: '#f97316', light: '#c2410c' },
kimi: { dark: '#9ca3af', light: '#374151' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Kimi provider color inconsistency detected.

The dark-mode color for kimi is #9ca3af here, but wrapped-live-template.ts (Line 65) and theme.ts (Line 33) both use #111827. This inconsistency will cause the Kimi provider to render with different colors in live HTML output vs. single-page SVG vs. TUI dashboard, creating a confusing user experience.

🎨 Proposed fix to align with other renderers
-  kimi:          { dark: '`#9ca3af`', light: '`#374151`' },
+  kimi:          { dark: '`#111827`', light: '`#374151`' },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
kimi: { dark: '#9ca3af', light: '#374151' },
kimi: { dark: '`#111827`', light: '`#374151`' },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/renderers/src/svg/wrapped-single-page.ts` at line 85, The dark-mode
color for the "kimi" provider in the color palette object is inconsistent;
update the "kimi" entry in wrapped-single-page.ts so its dark value is "`#111827`"
(matching the other renderers) instead of "`#9ca3af`" to ensure uniform rendering
across wrapped-live-template and theme mappings.

Comment thread README.md
# Tokenleak

See where your AI tokens actually go. Tokenleak reads usage data from **Claude Code**, **Codex**, **Cursor**, **Gemini**, **GitHub Copilot**, **Amp**, **Qwen**, **Roo Code**, **Kilo Code**, **OpenClaw**, **Hermes**, **Pi (`pi-mono`)**, and **OpenCode**, then renders terminal dashboards, heatmaps, compare reports, explain/focus reports, and shareable image cards from the CLI.
See where your AI tokens actually go. Tokenleak reads usage data from **Claude Code**, **Codex**, **Cursor**, **Gemini**, **GitHub Copilot**, **Amp**, **Codebuff**, **Droid**, **Qwen**, **Roo Code**, **Kilo Code**, **Kimi**, **Kilo CLI**, **Mux**, **Crush**, **OpenClaw**, **Hermes**, **Goose**, **Antigravity**, **Zed Agent**, **Kiro**, **Trae**, **Synthetic**, **Pi (`pi-mono`)**, and **OpenCode**, then renders terminal dashboards, heatmaps, compare reports, explain/focus reports, and shareable image cards from the CLI.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent provider name: "Kimi" should be "Kimi CLI".

The intro line lists "Kimi" but the provider table (line 24), the provider details section (line 652), and all other references consistently use "Kimi CLI" as the display name.

📝 Proposed fix
-See where your AI tokens actually go. Tokenleak reads usage data from **Claude Code**, **Codex**, **Cursor**, **Gemini**, **GitHub Copilot**, **Amp**, **Codebuff**, **Droid**, **Qwen**, **Roo Code**, **Kilo Code**, **Kimi**, **Kilo CLI**, **Mux**, **Crush**, **OpenClaw**, **Hermes**, **Goose**, **Antigravity**, **Zed Agent**, **Kiro**, **Trae**, **Synthetic**, **Pi (`pi-mono`)**, and **OpenCode**, then renders terminal dashboards, heatmaps, compare reports, explain/focus reports, and shareable image cards from the CLI.
+See where your AI tokens actually go. Tokenleak reads usage data from **Claude Code**, **Codex**, **Cursor**, **Gemini**, **GitHub Copilot**, **Amp**, **Codebuff**, **Droid**, **Qwen**, **Roo Code**, **Kilo Code**, **Kimi CLI**, **Kilo CLI**, **Mux**, **Crush**, **OpenClaw**, **Hermes**, **Goose**, **Antigravity**, **Zed Agent**, **Kiro**, **Trae**, **Synthetic**, **Pi (`pi-mono`)**, and **OpenCode**, then renders terminal dashboards, heatmaps, compare reports, explain/focus reports, and shareable image cards from the CLI.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
See where your AI tokens actually go. Tokenleak reads usage data from **Claude Code**, **Codex**, **Cursor**, **Gemini**, **GitHub Copilot**, **Amp**, **Codebuff**, **Droid**, **Qwen**, **Roo Code**, **Kilo Code**, **Kimi**, **Kilo CLI**, **Mux**, **Crush**, **OpenClaw**, **Hermes**, **Goose**, **Antigravity**, **Zed Agent**, **Kiro**, **Trae**, **Synthetic**, **Pi (`pi-mono`)**, and **OpenCode**, then renders terminal dashboards, heatmaps, compare reports, explain/focus reports, and shareable image cards from the CLI.
See where your AI tokens actually go. Tokenleak reads usage data from **Claude Code**, **Codex**, **Cursor**, **Gemini**, **GitHub Copilot**, **Amp**, **Codebuff**, **Droid**, **Qwen**, **Roo Code**, **Kilo Code**, **Kimi CLI**, **Kilo CLI**, **Mux**, **Crush**, **OpenClaw**, **Hermes**, **Goose**, **Antigravity**, **Zed Agent**, **Kiro**, **Trae**, **Synthetic**, **Pi (`pi-mono`)**, and **OpenCode**, then renders terminal dashboards, heatmaps, compare reports, explain/focus reports, and shareable image cards from the CLI.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 3, The intro sentence lists the provider name as "Kimi"
but other references use "Kimi CLI"; update the string in the intro (the list of
providers in README.md) to "Kimi CLI" so it matches the provider table and
details sections (search for the literal "Kimi" in that provider list and
replace it with "Kimi CLI").

@ya-nsh ya-nsh merged commit f50bd62 into main May 26, 2026
1 of 2 checks passed
@ya-nsh ya-nsh deleted the codex/tokscale-competitive-analysis branch May 26, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant