Skip to content

feat: support Antigravity CLI agent log tracking#1178

Closed
kexi wants to merge 2 commits into
ryoppippi:mainfrom
kexi:feat/support-antigravity-cli
Closed

feat: support Antigravity CLI agent log tracking#1178
kexi wants to merge 2 commits into
ryoppippi:mainfrom
kexi:feat/support-antigravity-cli

Conversation

@kexi
Copy link
Copy Markdown

@kexi kexi commented May 28, 2026

Summary

Adds support for tracking usage from the Antigravity CLI as a new agent source in ccusage. Antigravity stores per-conversation transcripts under ~/.gemini/antigravity-cli/brain/<id>/.system_generated/logs/transcript.jsonl, which ccusage now discovers, parses, and surfaces through the unified report model plus a focused ccusage antigravity namespace (daily, monthly, session).

What Changed

  • rust/crates/ccusage/src/adapter/antigravity/ — new adapter with paths, parser, loader, and report modules that read the transcript jsonl format, estimate token usage from character counts (Antigravity does not record raw token counts), and feed the unified loader.
  • rust/crates/ccusage-cli/ — registers the antigravity subcommand, root-help listing, and snapshots.
  • rust/crates/ccusage/src/adapter/all/ — wires Antigravity into the unified all loader/report.
  • rust/crates/ccusage/src/config*.rs and apps/ccusage/config-schema.json — adds antigravity-scoped configuration and updates the generated JSON schema.
  • docs/guide/antigravity/index.md and docs/.vitepress/config.ts — new docs guide and nav entry; docs/guide/index.md and source-support-qa.md updated to mention Antigravity.

Why

Antigravity CLI is a new Gemini-based coding agent and users have local transcripts but no built-in way to estimate cost or token usage. Adding it as a first-class source keeps parity with the other supported agents (Claude Code, Gemini CLI, Codex, etc.).

Notes

  • Token counts are character-count estimates (1.5 tokens/char). This is documented as beta in the guide.
  • Pricing falls back to google/gemini-1.5-flash when the recorded model cannot be mapped via LiteLLM.
  • ANTIGRAVITY_DATA_DIR (single dir or comma-separated list) overrides the default location.

Testing

  • cargo test (via pre-push hook in the Nix dev shell)
  • cargo fmt --check
  • CLI help snapshot updated

🤖 Generated with Claude Code


Summary by cubic

Adds Antigravity CLI as a tracked agent in ccusage, reading transcript.jsonl logs to estimate token and cost data. Antigravity usage now appears in unified reports and via ccusage antigravity daily|monthly|session.

  • New Features
    • New Antigravity adapter discovers ~/.gemini/antigravity-cli/brain/*/.system_generated/logs/transcript.jsonl, parses events, and estimates tokens from character counts (1.5 tokens/char), including reasoning tokens from thinking.
    • Pricing maps to Gemini models via LiteLLM with a fallback to google/gemini-1.5-flash.
    • CLI namespace antigravity with daily, monthly, and session commands; included in the unified all loader/report by default.
    • Config: added antigravity defaults and per-command options; updated JSON schema.
    • Docs: new Antigravity guide and nav entry.

Written for commit ae6b230. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Antigravity CLI as a supported data source.
    • Added configuration options supporting daily, monthly, and session reporting views.
    • Added support for discovering and reading transcript log files.
  • Documentation

    • Updated documentation to list Antigravity CLI as a supported data source.
    • Added Antigravity CLI configuration and troubleshooting guide.

Review Change Stack

@kexi
Copy link
Copy Markdown
Author

kexi commented May 28, 2026

@coderabbitai review
@cubic-dev-ai review

@github-actions
Copy link
Copy Markdown
Contributor

This PR was auto-closed. Only contributors approved with lgtm can open PRs. Open an issue first.

Maintainers review auto-closed issues and reopen worthwhile ones. Issues that do not meet the quality bar in CONTRIBUTING.md may not be reopened or receive a reply.

If a maintainer replies lgtmi, your future issues will stay open. If a maintainer replies lgtm, your future issues and PRs will stay open.

See CONTRIBUTING.md.

@github-actions github-actions Bot closed this May 28, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 35bd41cc-f295-4c2c-9a79-7ef264ea953f

📥 Commits

Reviewing files that changed from the base of the PR and between 284899c and ae6b230.

⛔ Files ignored due to path filters (2)
  • rust/crates/ccusage-cli/src/snapshots/ccusage_cli__tests__root_help.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__config_schema__tests__snapshots_schema_agent_specific_option_edges.snap is excluded by !**/*.snap
📒 Files selected for processing (22)
  • apps/ccusage/config-schema.json
  • docs/.vitepress/config.ts
  • docs/guide/antigravity/index.md
  • docs/guide/index.md
  • docs/guide/source-support-qa.md
  • rust/crates/ccusage-cli/src/cli-commands.json
  • rust/crates/ccusage-cli/src/parser.rs
  • rust/crates/ccusage-cli/src/tests.rs
  • rust/crates/ccusage-cli/src/types.rs
  • rust/crates/ccusage/src/adapter/all/loader.rs
  • rust/crates/ccusage/src/adapter/all/report.rs
  • rust/crates/ccusage/src/adapter/antigravity/README.md
  • rust/crates/ccusage/src/adapter/antigravity/loader.rs
  • rust/crates/ccusage/src/adapter/antigravity/mod.rs
  • rust/crates/ccusage/src/adapter/antigravity/parser.rs
  • rust/crates/ccusage/src/adapter/antigravity/paths.rs
  • rust/crates/ccusage/src/adapter/antigravity/report.rs
  • rust/crates/ccusage/src/adapter/mod.rs
  • rust/crates/ccusage/src/config.rs
  • rust/crates/ccusage/src/config_schema.rs
  • rust/crates/ccusage/src/main.rs
  • rust/crates/ccusage/src/progress.rs

📝 Walkthrough

Walkthrough

This PR adds Antigravity CLI as a supported local data source in ccusage. The change includes transcript discovery and parsing, cost estimation with model selection detection, CLI command routing, configuration schema definitions, and user documentation for the new feature.

Changes

Antigravity CLI Integration

Layer / File(s) Summary
Configuration schema and command type definitions
rust/crates/ccusage-cli/src/types.rs, rust/crates/ccusage/src/config_schema.rs, apps/ccusage/config-schema.json
Adds Command::Antigravity(AgentCommandArgs) enum variant and defines AntigravityConfig / AntigravityCommandsConfig Rust types with daily/monthly/session command groups and shared options, mirrored in JSON schema.
CLI command parsing and validation
rust/crates/ccusage-cli/src/parser.rs, rust/crates/ccusage-cli/src/cli-commands.json, rust/crates/ccusage-cli/src/tests.rs
Adds antigravity match arm in command dispatcher, extends validation helpers (is_command, is_agent_command, agent_report_supported, agent_display_name), defines CLI command pages for daily/monthly/session subcommands, and adds parsing test.
Transcript parsing, discovery, and data conversion
rust/crates/ccusage/src/adapter/antigravity/*
Implements JSONL transcript parsing with timestamp/session extraction, model selection text parsing, per-message token estimation from character counts (including reasoning tokens from thinking blocks), cost calculation with fallback pricing, filesystem discovery of transcript.jsonl files, and LoadedEntry conversion for aggregation and reporting.
Main router, loader, and progress tracking integration
rust/crates/ccusage/src/main.rs, rust/crates/ccusage/src/adapter/mod.rs, rust/crates/ccusage/src/adapter/all/loader.rs, rust/crates/ccusage/src/adapter/all/report.rs, rust/crates/ccusage/src/progress.rs, rust/crates/ccusage/src/config.rs
Wires Command::Antigravity dispatch to adapter::antigravity::run(), declares adapter module, adds antigravity to parallel AgentLoadSpec loader with pricing map, extends UsageLoadAgent enum and agent-label mappings, and registers "antigravity" in config schema validation.
User-facing documentation
docs/.vitepress/config.ts, docs/guide/antigravity/index.md, docs/guide/index.md, docs/guide/source-support-qa.md
Adds Antigravity CLI guide page (Beta) with setup, ANTIGRAVITY_DATA_DIR configuration, report views, environment variables, and troubleshooting; updates data sources table to list Antigravity as supported; removes Antigravity from unsupported-sources section.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ryoppippi/ccusage#1058: Refactor that overhauls how config-schema.json is generated from Rust schema types, which underpins the schema generation for antigravity added in this PR.
  • ryoppippi/ccusage#1030: Adds a new agent namespace by extending the same shared integration points (CLI command routing, config agent-token detection, progress tracking) that antigravity uses.
  • ryoppippi/ccusage#1008: Reworks schema generation and config loading to support agent-scoped defaults/commands namespaces, which the antigravity schema additions directly build on.

Suggested labels

enhancement

Poem

🐰 Antigravity soars up high,
With floating tokens in the sky,
Transcripts parsed from brain's deep store,
Costs computed, models explore,
Beta wings now let ccusage fly!

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented May 28, 2026

@coderabbitai review
@cubic-dev-ai review

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get PR details
gh pr view 1178 --repo ryoppippi/ccusage --json title,body,files,additions,deletions 2>/dev/null | head -100

# Get the list of changed files
gh pr view 1178 --repo ryoppippi/ccusage --json files 2>/dev/null | jq -r '.files[].path'

Length of output: 7329


🏁 Script executed:

#!/bin/bash
# Get the full diff
gh pr diff 1178 --repo ryoppippi/ccusage 2>/dev/null | head -2000

Length of output: 62581



@kexi Here is my review of this PR.


Review: feat: support Antigravity CLI agent log tracking

The implementation is well-structured and follows the established adapter pattern. The code is clean, tests are included, and the documentation is clear about the beta/estimated nature of token counts. Below are my findings.


🔴 Issues

1. Model name slugification produces invalid LiteLLM IDs

File: rust/crates/ccusage/src/adapter/antigravity/parser.rs

The test at the bottom confirms this — "Gemini 3.5 Flash (Medium)" is slugified to "google/gemini-3.5-flash-(medium)", with parentheses preserved in the model ID. LiteLLM pricing lookups are very unlikely to match google/gemini-3.5-flash-(medium), so every session that receives a model-change event to a variant like Flash (Medium), Flash (Thinking), etc. will silently fall back to google/gemini-1.5-flash pricing.

The parentheses (and their content) should either be stripped or mapped to known canonical LiteLLM model names:

fn extract_model_from_settings_change(content: &str) -> Option<String> {
    // ... existing parsing ...
    // Strip parenthesized qualifiers before slugifying:
    let raw_model = RAW_PARENS_RE.replace_all(raw_model.trim(), "");
    let slug = raw_model.trim().to_lowercase().replace(' ', "-").replace("--", "-");
    return Some(slug);

Or better, maintain an explicit mapping from Antigravity display names to LiteLLM model IDs:

match raw_model.trim().to_lowercase().as_str() {
    "gemini 3.5 flash" | "gemini 3.5 flash (medium)" => "gemini-2.5-flash",
    "gemini 3.5 pro" => "gemini-2.5-pro",
    _ => /* fallback slug */
}

🟡 Warnings

2. Coupling to opencode internals

File: rust/crates/ccusage/src/adapter/antigravity/mod.rs

run() calls opencode::summary_period, opencode::agent_summary_json, and opencode::first_column from the report module. This is a silent coupling — if opencode internals change, antigravity behavior changes too with no compilation warning. Other adapters with similar structure could be refactored to expose these as shared utilities.

// mod.rs
sort_summaries(&mut rows, &shared.order, |row| {
    opencode::summary_period(row)   // ← coupling to opencode
});

3. Character-count estimation is inaccurate for CJK / emoji content

File: rust/crates/ccusage/src/adapter/antigravity/parser.rs

chars().count() counts Unicode scalar values, which means a CJK character counts as 1 char and maps to ~1.5 tokens — but a CJK character typically encodes to 1–2 tokens in Gemini's tokenizer. Conversely, emoji (which are multi-scalar sequences) are undercounted. This is inherent to the estimation approach, but it's worth documenting clearly (e.g., "accuracy degrades significantly for non-Latin content").

4. ANTIGRAVITY_DATA_DIR set to nonexistent paths silently yields zero data

File: rust/crates/ccusage/src/adapter/antigravity/paths.rs

If ANTIGRAVITY_DATA_DIR is set but all listed directories don't exist, the function returns Ok(vec![]) without any diagnostic. Other adapters have the same pattern, but since path filtering is strict here (no home-dir fallback when the env var is set), users may be confused. A log::warn when the env var is set but resolves to zero valid paths would help.


🟢 Suggestions / Nits

5. DEFAULT_MODEL is asserted in tests but never used in production without data

DEFAULT_MODEL = "google/gemini-3.5-flash" is applied to all events before any model-change line appears. The loader test at Line 55 of loader.rs asserts entries[0].model.as_deref() == Some("google/gemini-3.5-flash") — which depends on no model-change event existing in the fixture. This is fine, but it would be valuable to add a test with an actual model-change event to exercise the extract_model_from_settings_change path end-to-end through the loader.

6. Weekly aggregation in report.rs is dead code from the CLI perspective

summarize_entries handles AgentReportKind::Weekly but the CLI (agent_report_supported in parser.rs) doesn't expose weekly for antigravity. This won't cause bugs but could cause confusion. Either expose it (consistent with opencode) or add a comment noting it's included for completeness.

7. Snapshot source field correction

File: rust/crates/ccusage-cli/src/snapshots/ccusage_cli__tests__root_help.snap

The source was corrected from crates/ccusage/src/cli.rs to crates/ccusage-cli/src/tests.rs — good catch, this was a pre-existing stale reference.


Summary

The overall design is sound and consistent with other adapters. The primary actionable issue is the model name slugification producing (medium)/(thinking) suffixes that won't resolve in LiteLLM, causing silent fallback to gemini-1.5-flash pricing for those model variants. The rest are lower-severity concerns.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 24 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/guide/index.md">

<violation number="1" location="docs/guide/index.md:92">
P2: Documentation update is incomplete: Antigravity CLI was added to the data-source table but is still missing from the introductory capability lists, the "All Sources by Default" bullet, and the command examples on the same page.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread docs/guide/index.md
@@ -72,28 +72,29 @@ Each data source page covers the details that only apply to that source, includi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Documentation update is incomplete: Antigravity CLI was added to the data-source table but is still missing from the introductory capability lists, the "All Sources by Default" bullet, and the command examples on the same page.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/guide/index.md, line 92:

<comment>Documentation update is incomplete: Antigravity CLI was added to the data-source table but is still missing from the introductory capability lists, the "All Sources by Default" bullet, and the command examples on the same page.</comment>

<file context>
@@ -72,28 +72,29 @@ Each data source page covers the details that only apply to that source, includi
+| Qwen            | `qwen`        | `${QWEN_DATA_DIR:-~/.qwen}`                          |
+| Copilot CLI     | `copilot`     | `~/.copilot/otel/*.jsonl`                            |
+| Gemini CLI      | `gemini`      | `${GEMINI_DATA_DIR:-~/.gemini/tmp}`                  |
+| Antigravity CLI | `antigravity` | `${ANTIGRAVITY_DATA_DIR:-~/.gemini/antigravity-cli}` |
 
 The tool automatically detects available data and aggregates all supported coding CLIs by default.
</file context>

@ryoppippi
Copy link
Copy Markdown
Owner

@kexi hey, did you find the token info on log? last time i saw it i couldn't find it

@ryoppippi ryoppippi reopened this May 29, 2026
@kexi
Copy link
Copy Markdown
Author

kexi commented May 30, 2026

@ryoppippi
Thanks for taking the time to look into this with me — I went and checked the actual data.
You were right. Antigravity writes plenty of logs, but none of them contain token counts. Every other source ccusage supports records real token counts in its logs — Antigravity is the only exception.
That's why this PR estimates from character counts (chars × 1.5). Since it's estimate-only for now, I'll close this PR for the time being and revisit if Antigravity starts recording real token usage.

@kexi kexi closed this May 30, 2026
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.

2 participants