Skip to content

feat(ccusage): add Gemini CLI usage support#1021

Merged
ryoppippi merged 8 commits into
mainfrom
feature/gemini-cli-usage
May 19, 2026
Merged

feat(ccusage): add Gemini CLI usage support#1021
ryoppippi merged 8 commits into
mainfrom
feature/gemini-cli-usage

Conversation

@ryoppippi
Copy link
Copy Markdown
Owner

@ryoppippi ryoppippi commented May 17, 2026

Try This PR

bunx -p https://pkg.pr.new/ryoppippi/ccusage@1021 ccusage gemini daily --help

Summary

  • add Gemini CLI as a ccusage data source with focused daily/monthly/session reports
  • parse local Gemini JSON/JSONL logs from GEMINI_DATA_DIR / ~/.gemini/tmp
  • preserve cache, reasoning, and tool token metadata and compute Gemini pricing
  • wire Gemini into CLI commands, all-agent reports, schema, docs, and tests

Validation

  • pnpm run format
  • pnpm typecheck
  • pnpm run test
  • pnpm --filter ccusage build
  • pnpm --filter docs build

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Gemini CLI as a supported data source for token usage tracking and cost analysis
    • Supports daily, monthly, and session reports with configurable options
    • Automatically processes usage logs with token breakdown and cost calculations
  • Documentation

    • Added comprehensive Gemini CLI integration guide with setup and troubleshooting
    • Updated configuration and environment variable documentation to include Gemini
    • Extended all-reports documentation to list Gemini as a supported source

Review Change Stack

Add a Gemini CLI adapter that discovers JSON and JSONL chat logs under GEMINI_DATA_DIR, defaulting to ~/.gemini/tmp. The parser normalises Gemini token records into ccusage rows, separates cache-inclusive input into cache read tokens, keeps reasoning and tool token metadata, and supports daily, monthly, and session reports.

Wire the gemini namespace into unified agent detection, focused commands, config schema generation, and docs. Pricing uses LiteLLM Gemini entries, including Google, Vertex AI, and OpenRouter prefixes, and applies Gemini 128k input/output tiers when available.

Update table rendering to use explicit source total tokens when adapters provide them, so hidden reasoning tokens remain reflected in totals without inflating visible output tokens.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

Caution

Review failed

Pull request was closed or merged during review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds Gemini CLI support to ccusage. It extends the configuration schema, CLI commands, and adapter infrastructure to discover and parse Gemini logs, calculate token usage and estimated costs, and include Gemini data in all-agent reports. Documentation is updated throughout to describe the new Gemini data source.

Changes

Gemini CLI Integration

Layer / File(s) Summary
Configuration schema (JSON + Rust)
apps/ccusage/config-schema.json, rust/crates/ccusage/src/config_schema.rs
JSON schema definitions for GeminiConfig and GeminiCommandsConfig, top-level gemini property with SharedOptions for defaults and per-command settings, Rust config structs, generated schema examples, and schema validation tests.
CLI command parsing
rust/crates/ccusage/src/cli.rs
Adds Command::Gemini enum variant, parser parse_gemini_command, agent command validation, and CLI tests verifying gemini daily/monthly/session commands.
Gemini adapter core
rust/crates/ccusage/src/adapter/gemini.rs
New module discovering *.json/*.jsonl logs under GEMINI_DATA_DIR, parsing direct and stats records, normalizing cached-input overlap, calculating costs via LiteLLM pricing with model candidate matching, and includes unit tests for discovery and JSONL token aggregation.
All-agent integration
rust/crates/ccusage/src/adapter/all.rs
Imports Gemini adapter, extends Session/Daily loading branches, and implements load_gemini_rows to convert Gemini entries into aggregated report rows.
CLI dispatch and progress
rust/crates/ccusage/src/main.rs, rust/crates/ccusage/src/config.rs, rust/crates/ccusage/src/progress.rs, rust/crates/ccusage/src/adapter/mod.rs
Routes Command::Gemini to adapter in main, recognizes "gemini" in agent detection, adds UsageLoadAgent::Gemini with display label, and declares adapter module.
User documentation
docs/guide/gemini/index.md, docs/.vitepress/config.ts, docs/guide/{index,all-reports,configuration,config-files,environment-variables}.md, apps/ccusage/README.md
New Gemini guide covering data directory layout, token fields (cached/reasoning), cost computation, troubleshooting; sidebar navigation; and updates to supported sources, environment variables, config examples across all guides.
Formatting and supporting changes
rust/crates/ccusage/src/{claude_loader,codex_loader,commands/mod,pricing}.rs, rust/crates/ccusage-terminal/src/lib.rs, rust/crates/ccusage/src/adapter/{codex,copilot,opencode/}.rs
Test assertions and import refactoring, closure/expression style, dedup logic refactor in claude_loader, codex_loader usage path expansion, and formatting updates without behavioral changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ryoppippi/ccusage#1000: Introduces the multi-agent all-agent reporting framework that this PR extends to support Gemini as an additional agent loader.
  • ryoppippi/ccusage#977: Establishes the native Rust CLI dispatcher and adapter infrastructure that Gemini command/adapter/config wiring plugs into.
  • ryoppippi/ccusage#1058: Introduces the Rust JSON schema generator that this PR extends with new Gemini config definitions.

Suggested labels

enhancement

Poem

🐰 A rabbit hops through Gemini logs,
Parsing tokens with perfect precision,
Cache overlaps vanish, costs align,
And unified reports now shine—
Hopping toward better usage insight! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.68% 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 clearly and concisely summarizes the main change: adding Gemini CLI as a new usage data source for ccusage, which is the primary focus of this PR.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/gemini-cli-usage

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.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 17, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ccusage-guide 4aeb9e8 Commit Preview URL

Branch Preview URL
May 19 2026, 01:02 PM

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/ccusage/test/snapshots/cli-output/all-agent-daily-table.txt (1)

5-5: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add Gemini test fixtures to verify agent detection.

The test setup in cli-output.test.ts initializes a GEMINI_DATA_DIR directory (lines 33–46), but no actual Gemini log files exist in the fixture directory. This explains why the snapshot shows detected agents as "Amp, Claude, Codex, OpenCode, pi-agent" without Gemini. To properly test Gemini agent support, create at least one Gemini fixture file so the agent detection snapshot includes Gemini in the output.

🤖 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 `@apps/ccusage/test/snapshots/cli-output/all-agent-daily-table.txt` at line 5,
The test fixtures are missing Gemini log files so agent detection in
cli-output.test.ts (the GEMINI_DATA_DIR setup) never finds Gemini; add at least
one representative Gemini fixture file into the directory initialized by
GEMINI_DATA_DIR (using the same filename pattern and content structure the
detection logic expects) so the detection code that reads GEMINI_DATA_DIR will
include "Gemini" in the snapshot; ensure the new fixture is committed to the
test fixtures and that any test setup that copies or points GEMINI_DATA_DIR to
the fixtures uses that file.
🧹 Nitpick comments (1)
apps/ccusage/test/cli-output.test.ts (1)

200-207: ⚡ Quick win

Add one Gemini direct CLI snapshot test now that GEMINI_DATA_DIR is wired.

This file now provides Gemini env setup, but the integration suite still doesn’t assert a Gemini command path/output shape. A minimal gemini daily --offline --json snapshot would reduce regression risk.

🤖 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 `@apps/ccusage/test/cli-output.test.ts` around lines 200 - 207, Add a minimal
snapshot test in apps/ccusage/test/cli-output.test.ts that uses the existing
createAgentCliEnv function (which now wires GEMINI_DATA_DIR) to run the CLI
command "gemini daily --offline --json" and assert its stdout shape via a Jest
snapshot; specifically, invoke the CLI runner used elsewhere in this test file
with the environment returned by createAgentCliEnv(fixturePath) (ensuring
GEMINI_DATA_DIR is present), capture the command output, and add a snapshot
assertion so future changes to gemini command wiring will be caught.
🤖 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 `@apps/ccusage/src/adapter/gemini/paths.ts`:
- Around line 18-25: The Promise.all in discoverGeminiLogFiles currently lets
any collectFilesRecursive rejection abort detection; update probes that call
collectFilesRecursive (and analogous hasFileRecursive calls) to use byethrow's
Result.try to catch per-path errors and map failures to safe defaults (empty
array for discoverGeminiLogFiles and false for hasFileRecursive usage), so each
getGeminiPaths().flatMap(...) item is wrapped in Result.try(...).then(r =>
r.unwrapOr([])) or unwrapOr(false) as appropriate before awaiting Promise.all,
preserving successful probes and sorting the flattened results with
compareStrings.

In `@docs/guide/gemini/index.md`:
- Around line 30-35: The directory tree example in the
docs/guide/gemini/index.md currently shows only "*.jsonl" but Line 24 states the
system reads both JSON and JSONL; update the example tree to reflect both file
types (e.g., show both "*.json" and "*.jsonl" under chats/) so the docs match
the documented "JSON + JSONL support" statement and ensure any surrounding text
that references the tree also mentions both formats.

---

Outside diff comments:
In `@apps/ccusage/test/snapshots/cli-output/all-agent-daily-table.txt`:
- Line 5: The test fixtures are missing Gemini log files so agent detection in
cli-output.test.ts (the GEMINI_DATA_DIR setup) never finds Gemini; add at least
one representative Gemini fixture file into the directory initialized by
GEMINI_DATA_DIR (using the same filename pattern and content structure the
detection logic expects) so the detection code that reads GEMINI_DATA_DIR will
include "Gemini" in the snapshot; ensure the new fixture is committed to the
test fixtures and that any test setup that copies or points GEMINI_DATA_DIR to
the fixtures uses that file.

---

Nitpick comments:
In `@apps/ccusage/test/cli-output.test.ts`:
- Around line 200-207: Add a minimal snapshot test in
apps/ccusage/test/cli-output.test.ts that uses the existing createAgentCliEnv
function (which now wires GEMINI_DATA_DIR) to run the CLI command "gemini daily
--offline --json" and assert its stdout shape via a Jest snapshot; specifically,
invoke the CLI runner used elsewhere in this test file with the environment
returned by createAgentCliEnv(fixturePath) (ensuring GEMINI_DATA_DIR is
present), capture the command output, and add a snapshot assertion so future
changes to gemini command wiring will be caught.
🪄 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: dbb97763-c0ac-4cb8-9bd5-b9e243c92a01

📥 Commits

Reviewing files that changed from the base of the PR and between 2c28474 and c2efa65.

📒 Files selected for processing (22)
  • apps/ccusage/config-schema.json
  • apps/ccusage/src/adapter/gemini/index.ts
  • apps/ccusage/src/adapter/gemini/parser.ts
  • apps/ccusage/src/adapter/gemini/paths.ts
  • apps/ccusage/src/adapter/gemini/pricing-macro.ts
  • apps/ccusage/src/adapter/gemini/pricing.ts
  • apps/ccusage/src/adapter/gemini/schema.ts
  • apps/ccusage/src/adapter/index.ts
  • apps/ccusage/src/adapter/types.ts
  • apps/ccusage/src/commands/agent.ts
  • apps/ccusage/src/commands/all.ts
  • apps/ccusage/src/commands/index.ts
  • apps/ccusage/test/cli-output.test.ts
  • apps/ccusage/test/snapshots/cli-output/all-agent-daily-table.txt
  • apps/ccusage/tsdown.config.ts
  • docs/.vitepress/config.ts
  • docs/guide/all-reports.md
  • docs/guide/configuration.md
  • docs/guide/environment-variables.md
  • docs/guide/gemini/index.md
  • docs/guide/index.md
  • packages/terminal/src/table.ts

Comment thread apps/ccusage/src/adapter/gemini/paths.ts Outdated
Comment thread docs/guide/gemini/index.md
Address CodeRabbit review feedback for the Gemini CLI adapter follow-up.

The all-agent CLI fixture now includes a representative Gemini JSONL log so detection snapshots exercise the new adapter. A direct Gemini daily JSON snapshot verifies command routing, cache-read normalization, and reasoning token JSON output.

Gemini path discovery now treats individual recursive file probes as best-effort with byethrow Result handling, so one unreadable data root does not abort detection for other configured roots. The Gemini docs tree also shows both JSON and JSONL files to match parser support.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/ccusage/test/cli-output.test.ts (1)

525-526: ⚡ Quick win

Use ccusage-testing fixtures for the new Gemini CLI test path.

This newly added test continues using fs-fixture directly; please switch this path to the repo’s ccusage-testing fixture utilities for consistency with test infra conventions.

As per coding guidelines apps/ccusage/**/*.{test,spec}.{ts,tsx,js,jsx}: Use ccusage-testing package for in-source Vitest, snapshots, fixtures, Claude models, and LiteLLM pricing tests.

🤖 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 `@apps/ccusage/test/cli-output.test.ts` around lines 525 - 526, The test "runs
Gemini daily JSON through the main ccusage namespace" is still creating fixtures
via the repo's fs-fixture helpers (createFixture and createAgentFixtureTree);
replace those with the repo-standard ccusage-testing fixture utilities by
importing the fixture helpers from 'ccusage-testing' and using them in place of
createFixture(createAgentFixtureTree()). Update the test to call the
ccusage-testing fixture factory (the package's fixture/agent fixture helper) and
adjust any returned API or teardown usage to match ccusage-testing's utilities
so the test uses the in-repo fixture conventions.
🤖 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.

Nitpick comments:
In `@apps/ccusage/test/cli-output.test.ts`:
- Around line 525-526: The test "runs Gemini daily JSON through the main ccusage
namespace" is still creating fixtures via the repo's fs-fixture helpers
(createFixture and createAgentFixtureTree); replace those with the repo-standard
ccusage-testing fixture utilities by importing the fixture helpers from
'ccusage-testing' and using them in place of
createFixture(createAgentFixtureTree()). Update the test to call the
ccusage-testing fixture factory (the package's fixture/agent fixture helper) and
adjust any returned API or teardown usage to match ccusage-testing's utilities
so the test uses the in-repo fixture conventions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c01bb9f8-db81-4308-92dd-2bb17d496028

📥 Commits

Reviewing files that changed from the base of the PR and between c2efa65 and 67d204d.

📒 Files selected for processing (6)
  • apps/ccusage/src/adapter/gemini/paths.ts
  • apps/ccusage/test/cli-output.test.ts
  • apps/ccusage/test/snapshots/cli-output/all-agent-daily-json.txt
  • apps/ccusage/test/snapshots/cli-output/all-agent-daily-table.txt
  • apps/ccusage/test/snapshots/cli-output/gemini-direct-daily-json.txt
  • docs/guide/gemini/index.md
✅ Files skipped from review due to trivial changes (2)
  • apps/ccusage/test/snapshots/cli-output/gemini-direct-daily-json.txt
  • docs/guide/gemini/index.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/ccusage/src/adapter/gemini/paths.ts

@ryoppippi
Copy link
Copy Markdown
Owner Author

@coderabbitai The latest nitpick about switching this new Gemini CLI test to a ccusage-testing fixture package/helper looks invalid for this repo.

I checked the repo-local ccusage-testing guidance and it explicitly says to use fs-fixture with createFixture() for simulated agent data directories. There is no ccusage-testing dependency or fixture factory in package.json; fs-fixture is the configured test fixture dependency.

The earlier actionable comments are addressed in 67d204d:

  • Gemini fixture data is now present in createAgentFixtureTree() and all-agent detection snapshots include Gemini.
  • gemini daily --offline --json has a direct file snapshot.
  • Gemini path discovery now catches per-probe filesystem failures with Result.try.
  • The docs tree now shows both *.json and *.jsonl.

Validation run locally:

  • pnpm run format
  • pnpm typecheck
  • pnpm run test
  • pnpm --filter ccusage build
  • pnpm --filter docs build

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check package.json for ccusage-testing and fs-fixture
rg -n "ccusage-testing|fs-fixture" --type json apps/ccusage/package.json 2>/dev/null || echo "apps/ccusage/package.json not found"
# Also check root package.json
rg -n "ccusage-testing|fs-fixture" --type json package.json 2>/dev/null || echo "root package.json not found"
# Confirm fs-fixture usage in tests
rg -n "fs-fixture|createFixture" --type ts apps/ccusage/test/ -l 2>/dev/null

Length of output: 103


@ryoppippi You're absolutely right — confirmed. fs-fixture (via catalog:testing) is the designated test fixture dependency in this repo, and createFixture() is the correct helper for simulated agent data directories. My suggestion to switch to a ccusage-testing fixture package was invalid; there is no such dependency here. Apologies for the noise.

Thanks for the thorough summary of 67d204d — all the previously raised actionable items are addressed. The PR looks good to go! 🐇✨


✏️ Learnings added
Learnt from: ryoppippi
URL: https://github.com/ryoppippi/ccusage/pull/1021

Timestamp: 2026-05-17T11:50:36.698Z
Learning: In the `ryoppippi/ccusage` repository, the correct test fixture dependency for simulated agent data directories is `fs-fixture` (declared as `"fs-fixture": "catalog:testing"` in `apps/ccusage/package.json`). Tests use `createFixture()` from `fs-fixture`. There is no `ccusage-testing` package or fixture factory in this repo — do not suggest switching to one.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Add a timeout to the LiteLLM pricing dataset fetch used by pricing macros so CI builds do not hang indefinitely when GitHub raw pricing fetches stall.

Also register Gemini in the config schema generator agent list so generated configuration schema uses the same gemini namespace shape as other focused agent commands instead of top-level gemini:* command keys.
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 17, 2026

Open in StackBlitz

npx https://pkg.pr.new/ryoppippi/ccusage@1021

commit: 56f51df

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 17, 2026

ccusage performance comparison

This compares the PR build against the base branch build on the same CI runner.

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Runtime: package ccusage bin from apps/ccusage/package.json through bun -b, --offline --json, measured by hyperfine with 2 warmups and 7 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude daily --offline --json 0.00 MiB 53.4ms 53.6ms 1.00x 0.03 MiB/s 0.03 MiB/s
claude session --offline --json 0.00 MiB 53.4ms 53.7ms 1.00x 0.03 MiB/s 0.03 MiB/s
codex daily --offline --json 0.00 MiB 53.0ms 53.6ms 0.99x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 53.2ms 53.7ms 0.99x 0.02 MiB/s 0.02 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Runtime: package ccusage bin from apps/ccusage/package.json through bun -b, --offline --json, measured by hyperfine with 0 warmups and 1 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude --offline --json 1.01 GiB 1.348s 1.361s 0.99x 765.04 MiB/s 757.60 MiB/s
codex --offline --json 1.01 GiB 1.657s 1.803s 0.92x 622.26 MiB/s 571.71 MiB/s

Package size

Package artifact Base PR Delta Ratio
packed ccusage-*.tgz 67.58 KiB 70.46 KiB +2.88 KiB 0.96x

Lower medians and smaller packed package sizes are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/ccusage/scripts/generate-json-schema.ts (1)

245-245: ⚡ Quick win

Avoid duplicated agent source-of-truth in schema properties.

AGENT_NAMES is already the canonical list, but the properties section still hardcodes each agent key. Generating that block from AGENT_NAMES will prevent future drift when adding/removing agents.

♻️ Suggested refactor
+	const agentProperties = Object.fromEntries(
+		AGENT_NAMES.map((agent) => [agent, createAgentJsonSchema(agent, agentCommandSchemas[agent])]),
+	) as Record<AgentName, JsonSchemaNode>;
+
 	return {
 		$ref: '`#/definitions/ccusage-config`',
 		definitions: {
 			'ccusage-config': {
 				type: 'object',
 				properties: {
 					$schema: {
 						type: 'string',
 						description: 'JSON Schema URL for validation and autocomplete',
 						markdownDescription: 'JSON Schema URL for validation and autocomplete',
 					},
 					defaults: {
 						...defaultsJsonSchema,
 						description: 'Default values for all-agent reports and legacy Claude commands',
 						markdownDescription: 'Default values for all-agent reports and legacy Claude commands',
 					},
 					commands: commandsJsonSchema,
-					claude: createAgentJsonSchema('claude', agentCommandSchemas.claude),
-					codex: createAgentJsonSchema('codex', agentCommandSchemas.codex),
-					opencode: createAgentJsonSchema('opencode', agentCommandSchemas.opencode),
-					amp: createAgentJsonSchema('amp', agentCommandSchemas.amp),
-					pi: createAgentJsonSchema('pi', agentCommandSchemas.pi),
-					gemini: createAgentJsonSchema('gemini', agentCommandSchemas.gemini),
+					...agentProperties,
 				},
 				additionalProperties: false,
 			},
 		},
🤖 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 `@apps/ccusage/scripts/generate-json-schema.ts` at line 245, The properties
block is hardcoded for each agent; instead iterate AGENT_NAMES to build the map
so the schema stays in sync. Replace the explicit entries (e.g., gemini:
createAgentJsonSchema('gemini', agentCommandSchemas.gemini)) with a dynamic
construction that maps AGENT_NAMES to createAgentJsonSchema(agentName,
agentCommandSchemas[agentName]) (or agentCommandSchemas.get(agentName) depending
on its type) and uses that resulting record as the properties value where the
schema is assembled; update any typing to reflect the dynamic Record<string,
...> if needed.
🤖 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.

Nitpick comments:
In `@apps/ccusage/scripts/generate-json-schema.ts`:
- Line 245: The properties block is hardcoded for each agent; instead iterate
AGENT_NAMES to build the map so the schema stays in sync. Replace the explicit
entries (e.g., gemini: createAgentJsonSchema('gemini',
agentCommandSchemas.gemini)) with a dynamic construction that maps AGENT_NAMES
to createAgentJsonSchema(agentName, agentCommandSchemas[agentName]) (or
agentCommandSchemas.get(agentName) depending on its type) and uses that
resulting record as the properties value where the schema is assembled; update
any typing to reflect the dynamic Record<string, ...> if needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 20a64a9b-3b19-4238-a5f1-257d5cdd08b2

📥 Commits

Reviewing files that changed from the base of the PR and between 67d204d and 2d677af.

📒 Files selected for processing (3)
  • apps/ccusage/config-schema.json
  • apps/ccusage/scripts/generate-json-schema.ts
  • packages/internal/src/pricing-fetch-utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/ccusage/config-schema.json

Avoid slow source-level Gemini pricing macro fetches in CLI output snapshot child processes. The tests still preserve existing Codex and Amp pricing snapshot coverage while keeping Gemini fixture costs at zero for the synthetic test model.
@ryoppippi
Copy link
Copy Markdown
Owner Author

@coderabbitai review it

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

@ryoppippi Sure, I'll review the latest changes now!

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Add Gemini CLI to the README supported-source summary and example commands so the PR documentation matches the new adapter surface.
@ryoppippi
Copy link
Copy Markdown
Owner Author

@coderabbitai README update pushed in 08139fc. Please review it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Fetch commit details for 08139fc
gh api repos/ryoppippi/ccusage/commits/08139fc --jq '.commit.message'
echo "---DIFF---"
gh api repos/ryoppippi/ccusage/commits/08139fc | jq -r '.files[] | "FILE: \(.filename)\nSTATUS: \(.status)\nPATCH:\n\(.patch // "(binary or no patch)")'

Length of output: 553


🏁 Script executed:

#!/bin/bash
# Fetch the diff for commit 08139fc with fixed jq syntax
gh api repos/ryoppippi/ccusage/commits/08139fc > /tmp/commit_data.json
jq -r '.files[].filename' /tmp/commit_data.json
echo "---"
jq -c '.files[]' /tmp/commit_data.json | while IFS= read -r file; do
  fname=$(echo "$file" | jq -r '.filename')
  status=$(echo "$file" | jq -r '.status')
  patch=$(echo "$file" | jq -r '.patch // "(no patch)"')
  echo "FILE: $fname"
  echo "STATUS: $status"
  echo "PATCH:"
  echo "$patch"
  echo "=========="
done

Length of output: 1619


@ryoppippi The README changes in commit 08139fc look clean and complete. Here's a quick summary of the review:

apps/ccusage/README.md — 3 targeted additions, all consistent:

  1. Supported Sources description — "Gemini CLI" correctly appended to the agent list alongside Claude Code, Codex, OpenCode, Amp, and pi-agent. ✅
  2. CLI examples blockbunx ccusage gemini daily added in a logical position (after amp session, before pi daily), matching the actual CLI surface (gemini:daily) wired up in this PR. ✅
  3. Feature bullet — "Unified CLI Reports" bullet updated to mention Gemini CLI, keeping it in sync with the description change above. ✅

The "Gemini CLI" naming is consistent with the docs sidebar entry and the dedicated guide page added in this PR. Nothing is missing — all three user-facing touchpoints in the README (description, example, feature list) have been updated. LGTM! 🐇✨

@ryoppippi
Copy link
Copy Markdown
Owner Author

@cubic-dev-ai review it

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented May 17, 2026

@cubic-dev-ai review it

@ryoppippi I have started the AI code review. It will take a few minutes to complete.

Replace the inline agent label conditional in the schema generator with a small exhaustive switch helper. This keeps future agent-specific labels out of nested ternaries and makes the config schema label rules easier to extend.
@ryoppippi
Copy link
Copy Markdown
Owner Author

@coderabbitai review it

@ryoppippi
Copy link
Copy Markdown
Owner Author

@cubic-dev-ai review it

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented May 17, 2026

@cubic-dev-ai review it

@ryoppippi I have started the AI code review. It will take a few minutes to complete.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

@ryoppippi Sure, I'll kick off a fresh review of the latest changes now!

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Register the gemini namespace with config loading so gemini defaults and per-report overrides are applied consistently with the generated schema and command registration.
@ryoppippi
Copy link
Copy Markdown
Owner Author

@coderabbitai review it

@ryoppippi
Copy link
Copy Markdown
Owner Author

@cubic-dev-ai review it

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented May 17, 2026

@cubic-dev-ai review it

@ryoppippi I have started the AI code review. It will take a few minutes to complete.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

@ryoppippi Sure, I'll kick off a fresh review of the latest changes now!

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Merge the current main Rust CLI migration into the Gemini PR and replace the old TypeScript Gemini adapter with a Rust implementation.

The Rust adapter discovers JSON and JSONL logs from GEMINI_DATA_DIR or ~/.gemini/tmp, parses direct Gemini events and stats records, preserves cached-input overlap normalization, maps reasoning/tool tokens, and deduplicates direct JSONL updates by id.

Also wires Gemini into direct reports, all-agent reports, progress labels, config schema, CLI parsing, README, and docs.
@ryoppippi
Copy link
Copy Markdown
Owner Author

@coderabbitai review

Updated this PR to merge current main and port Gemini CLI support to the Rust CLI implementation.

This now wires Gemini into direct reports and all-agent reports, reads JSON/JSONL logs from GEMINI_DATA_DIR/default ~/.gemini/tmp, preserves cached-input overlap normalization, maps reasoning/tool tokens, and deduplicates direct JSONL updates by id.

Local validation passed:

  • nix develop --command cargo test --manifest-path rust/Cargo.toml --workspace gemini
  • nix develop --command pnpm run format
  • nix develop --command cargo test --manifest-path rust/Cargo.toml --workspace
  • nix develop --command pnpm typecheck
  • nix develop --command pnpm run test

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

@ryoppippi Got it! The Rust CLI port for Gemini is a meaningful new scope — I'll kick off a fresh review covering the new Rust implementation (direct/all-agent reports, GEMINI_DATA_DIR discovery, cached-input normalization, reasoning/tool token mapping, and JSONL deduplication by id) as well as the merged-main changes now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ryoppippi ryoppippi merged commit 4a7c880 into main May 19, 2026
28 of 29 checks passed
@ryoppippi ryoppippi deleted the feature/gemini-cli-usage branch May 19, 2026 13:05
@github-actions
Copy link
Copy Markdown

ccusage performance comparison

PR SHA: 4aeb9e8868cf
Base SHA: edb439221918

This compares the Rust PR release binary against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new edb439221918 744.0ms 354.8ms 35.0ms 3
PR pkg.pr.new 4aeb9e8868cf 812.1ms 595.6ms 33.8ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: edb439221918; PR package: 4aeb9e8868cf. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 687.4ms 685.7ms 1.00x 1.46 GiB/s 1.47 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 867.4ms 864.7ms 1.00x 1.16 GiB/s 1.16 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 690.0ms 1.46 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 653.9ms 1.54 GiB/s 1
claude --offline --json Workspace release binary 1.01 GiB 723.8ms 1.39 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 909.6ms 1.11 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 823.0ms 1.22 GiB/s 1
codex --offline --json Workspace release binary 1.01 GiB 822.3ms 1.22 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude daily --offline --json 0.00 MiB 31.1ms 4.1ms 7.68x 0.05 MiB/s 0.38 MiB/s
claude session --offline --json 0.00 MiB 31.3ms 3.9ms 7.92x 0.05 MiB/s 0.39 MiB/s
codex daily --offline --json 0.00 MiB 30.9ms 3.6ms 8.48x 0.03 MiB/s 0.24 MiB/s
codex session --offline --json 0.00 MiB 30.8ms 3.7ms 8.39x 0.03 MiB/s 0.23 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude --offline --json 1.01 GiB 674.5ms 719.6ms 0.94x 1.49 GiB/s 1.40 GiB/s
codex --offline --json 1.01 GiB 844.0ms 806.1ms 1.05x 1.19 GiB/s 1.25 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 8.90 KiB 8.96 KiB +0.06 KiB 0.99x
installed native package binary 3096.24 KiB 3096.24 KiB +0.00 KiB 1.00x
Rust release binary rust/target/release/ccusage - 2763.68 KiB - -

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@github-actions
Copy link
Copy Markdown

ccusage performance comparison

PR SHA: 4aeb9e8868cf
Base SHA: edb439221918

This compares the PR package against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new edb439221918 494.5ms 484.6ms 34.1ms 3
PR pkg.pr.new 4aeb9e8868cf 545.1ms 654.8ms 34.4ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: edb439221918; PR package: 4aeb9e8868cf. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 684.3ms 691.9ms 0.99x 1.47 GiB/s 1.46 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 869.9ms 882.9ms 0.99x 1.16 GiB/s 1.14 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 678.8ms 1.48 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 647.0ms 1.56 GiB/s 1
claude --offline --json Workspace release binary 1.01 GiB 730.2ms 1.38 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 859.7ms 1.17 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 828.8ms 1.21 GiB/s 1
codex --offline --json Workspace release binary 1.01 GiB 819.5ms 1.23 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude daily --offline --json 0.00 MiB 32.7ms 32.6ms 1.00x 0.05 MiB/s 0.05 MiB/s
claude session --offline --json 0.00 MiB 33.8ms 32.8ms 1.03x 0.05 MiB/s 0.05 MiB/s
codex daily --offline --json 0.00 MiB 32.4ms 32.3ms 1.00x 0.03 MiB/s 0.03 MiB/s
codex session --offline --json 0.00 MiB 32.7ms 33.6ms 0.97x 0.03 MiB/s 0.03 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude --offline --json 1.01 GiB 693.2ms 680.7ms 1.02x 1.45 GiB/s 1.48 GiB/s
codex --offline --json 1.01 GiB 865.4ms 872.0ms 0.99x 1.16 GiB/s 1.15 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 8.90 KiB 8.96 KiB +0.06 KiB 0.99x
installed native package binary 3096.24 KiB 3096.24 KiB +0.00 KiB 1.00x
Rust release binary rust/target/release/ccusage - 2763.68 KiB - -

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

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