Skip to content

Capture Antigravity CLI usage via statusLine#382

Merged
iamtoruk merged 2 commits into
getagentseal:mainfrom
ozymandiashh:feat/agy-statusline-hook
May 24, 2026
Merged

Capture Antigravity CLI usage via statusLine#382
iamtoruk merged 2 commits into
getagentseal:mainfrom
ozymandiashh:feat/agy-statusline-hook

Conversation

@ozymandiashh
Copy link
Copy Markdown
Contributor

Summary

Closes #381 by adding an opt-in Antigravity CLI statusLine hook for short agy sessions.

Root cause

agy exposes useful usage data only while its short-lived local process is running. If CodeBurn's menubar refresh misses that window, CodeBurn can still discover CLI conversation files but cannot safely price them from local .pb history alone.

What changed

  • Add codeburn antigravity-hook install|uninstall.
  • Add the internal agy-statusline-hook.
  • Record sanitized context_window.current_usage token counters to CodeBurn's cache.
  • Drop prompt content, raw payload fields, and local working-directory paths.
  • Attempt a best-effort live RPC snapshot while agy is still alive.
  • Skip statusLine fallback when RPC metadata already covered the same conversation.
  • Debounce repeated/intermediate statusLine snapshots and delta monotonic counters to avoid cumulative overcounting.
  • Keep cacheReadInputTokens and cachedInputTokens distinct so codeburn models does not double-count cache reads.
  • Force append-only statusLine sources to reparse on each run.
  • Write Antigravity settings atomically.
  • Back up and restore an existing custom statusLine when install uses --force.
  • Document the hook behavior and privacy constraints.

Validation

I validated this with a deterministic fixture using isolated temp state:

HOME=/tmp/codeburn-agy-validation/home
CODEBURN_CACHE_DIR=/tmp/codeburn-agy-validation/cache
TZ=Europe/Bucharest

The fixture sends 4 real agy-statusline-hook payloads for one Antigravity CLI conversation:

snapshot A repeated twice: input=1000, output=100, cacheRead=0
snapshot B repeated twice: input=1500, output=150, cacheRead=200
raw payload also included cwd=/tmp/private-workspace-that-must-not-be-stored

Hook sanitization proof:

events 4
containsPrivatePath false

The persisted JSONL keeps only sanitized aggregate usage:

{"conversationId":"agy-validation-conversation","sessionId":"agy-validation-session","model":"Gemini 3.5 Flash (High)","usage":{"inputTokens":1000,"outputTokens":100,"cacheCreationInputTokens":0,"cacheReadInputTokens":0}}

Before: origin/main

Running the same isolated fixture against origin/main:

codeburn models --provider antigravity --period today --format markdown --min-cost 0 --top 5

produced:

No model usage found for the selected period.

The JSON report was also empty:

{
  "overview": {
    "cost": 0,
    "calls": 0,
    "sessions": 0,
    "tokens": {
      "input": 0,
      "output": 0,
      "cacheRead": 0,
      "cacheWrite": 0
    }
  },
  "models": [],
  "projects": []
}

After: this branch

Running the same fixture against this branch:

codeburn models --provider antigravity --period today --format markdown --min-cost 0 --top 5

produced:

| Provider | Model | Top Task | Input | Output | Cache Write | Cache Read | Total | Cost |
| --- | --- | --- | ---: | ---: | ---: | ---: | ---: | ---: |
| Antigravity | `Gemini 3.5 Flash` | Conversation (100%) | 1.5K | 150 | 0 | 200 | 1.9K | $0.0036 |
|  | **Total** |  | **1.5K** | **150** | **0** | **200** | **1.9K** | **$0.0036** |

The JSON model row confirms the raw model label, display mapping, call count, and cache accounting:

{
  "provider": "antigravity",
  "model": "Gemini 3.5 Flash (High)",
  "modelDisplayName": "Gemini 3.5 Flash",
  "inputTokens": 1500,
  "outputTokens": 150,
  "cacheWriteTokens": 0,
  "cacheReadTokens": 200,
  "totalTokens": 1850,
  "calls": 2,
  "costUSD": 0.0036300000000000004
}

This proves:

  • origin/main misses the Antigravity CLI statusLine usage completely.
  • this branch surfaces Gemini 3.5 Flash High as Gemini 3.5 Flash.
  • 4 repeated statusLine events become 2 billable calls, not 4.
  • monotonic cumulative counters are deltaed correctly.
  • cache read is not double-counted in codeburn models.
  • cwd from the raw hook payload is not persisted.

Additional checks:

npm test -- --run tests/providers/antigravity.test.ts tests/antigravity-statusline.test.ts tests/models-report.test.ts
# 3 files / 44 tests passed

npm test -- --run
# 66 files / 932 tests passed

npm run build
# passed

git diff --check
# passed

Gemini 3.5 Flash High review via agy CLI
# PASS

Claude Opus 4.7 effort max review
# PASS

Privacy notes

  • The statusLine hook stores aggregate usage counters only.
  • It does not store prompts, local working-directory paths, raw statusLine payloads, CSRF tokens, or local transcript contents.
  • The statusLine event log and settings backup are written with private file permissions.

@ozymandiashh
Copy link
Copy Markdown
Contributor Author

Inregistrare.ecran.din.2026-05-23.la.04.03.24.mov

@ozymandiashh
Copy link
Copy Markdown
Contributor Author

The attached video shows the menubar path using the same status --format menubar-json payload: after the hook captures agy usage, Antigravity appears in the Today provider tab instead of showing zero usage.

- readStdin() now rejects input exceeding 1MB to prevent OOM from
  a buggy or runaway caller.
- Switch from appendFile (mode only on creation) to open(path, 'a', 0o600)
  so the JSONL file is always created with private permissions.
- Set cache directory mode to 0o700.
@iamtoruk iamtoruk merged commit 584b564 into getagentseal:main May 24, 2026
3 checks passed
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.

Antigravity CLI agy sessions can miss usage after the CLI exits

2 participants