feat(antigravity): native token counts via title-slot tee#1356
feat(antigravity): native token counts via title-slot tee#1356peyton-alt wants to merge 7 commits into
Conversation
Adds two components that let entire capture agy token usage — the only surface where agy exposes token data is the JSON payload it pipes to the user-configured title/statusline command on every agent state change. Task 1 — Snapshot store (statusline.go / statusline_test.go): - AppendStatusSnapshot() parses the agy state JSON, deduplicates against the last persisted line (by compact-remarshaling the context_window), and appends a timestamped JSONL line to <ENTIRE_ANTIGRAVITY_STATUS_DIR|XDG_CACHE>/entire/antigravity/status/<conv_id>.jsonl. - Silently ignores malformed/incomplete payloads; only genuine I/O errors propagate. - Dedup reads only the last line of the file (seek-free linear scan) for O(file-size) worst-case but O(1) typical-case performance. - Prunes stale files (>14d) only when a new conversation file is first created, keeping the hot path to a single open+write. Task 2 — title-tee shim (hooks_antigravity_title.go / _test.go): - `entire hooks antigravity title-tee [--wrap '<cmd>']` reads stdin, calls AppendStatusSnapshot (best-effort), then optionally chains the user's original title command via sh -c so their window title is preserved. - Never exits non-zero; never writes noise to stdout (agy renders stdout verbatim as the terminal window title). - Registered on the antigravity hooks subtree, not through executeAgentHook, so it works outside git repos and without entire being enabled. Perf numbers (Apple M4 Pro, arm64, macOS 25.3): - End-to-end shim: 20-run warm avg = 41ms (budget ≤50ms); total = 830ms (budget ≤1000ms). - BenchmarkAppendStatusSnapshot_GrownFile (500-line file, dedup path, 100x): ~79µs/op (budget ≤2ms/op). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds native, per-checkpoint token usage support for the Antigravity (agy) agent by capturing token totals from agy’s title/statusline JSON payload out-of-band, computing per-turn deltas (cumulative − baseline), and ensuring those values flow through SaveStep → session state → condensation → committed checkpoint metadata so the entire.io UI can display token counts without web changes.
Changes:
- Introduces an Antigravity
title-teeshim command and global settings installer/uninstaller to persist token snapshot JSONL per conversation. - Adds a built-in-only
OutOfBandTokenSourcecapability plus lifecycle baseline/delta handling to produce checkpoint-scoped token usage when transcripts lack token data. - Extends condensation + doctor + tests (unit + integration) to propagate and validate token usage in committed metadata.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| cmd/entire/cli/strategy/manual_commit_condensation.go | Condensation fallback to persist session-state token usage when transcript recompute yields none (non-token-calculator agents). |
| cmd/entire/cli/strategy/manual_commit_condensation_test.go | Unit test ensuring out-of-band session token usage reaches committed checkpoint metadata. |
| cmd/entire/cli/state.go | Stores an opaque token baseline in PrePromptState for out-of-band token agents. |
| cmd/entire/cli/setup.go | Uninstalls Antigravity global title-tee only on agent removal (not per-repo disable). |
| cmd/entire/cli/lifecycle.go | Adds out-of-band token computation fallback at TurnEnd when transcript-based calc returns nil. |
| cmd/entire/cli/integration_test/antigravity_test.go | Integration test asserting token usage appears in both per-session metadata and checkpoint summary. |
| cmd/entire/cli/hooks_cmd.go | Adds the hidden entire hooks antigravity title-tee subcommand under Antigravity hooks. |
| cmd/entire/cli/hooks_antigravity_title.go | Implements the title-tee shim that appends snapshots and optionally pipes through a wrapped title command. |
| cmd/entire/cli/hooks_antigravity_title_test.go | Tests that title-tee is silent, writes snapshots, and wrap passthrough works. |
| cmd/entire/cli/doctor.go | Adds a doctor check warning when repo hooks exist but the global title-tee isn’t configured. |
| cmd/entire/cli/doctor_test.go | Tests the doctor check behavior for configured / missing / not-installed cases. |
| cmd/entire/cli/agent/capabilities.go | Adds AsOutOfBandTokenSource capability helper (built-in only). |
| cmd/entire/cli/agent/capabilities_test.go | Tests new capability gating behavior for out-of-band token sources. |
| cmd/entire/cli/agent/antigravity/title_install.go | Installs/uninstalls the global settings.json title command with optional --wrap preservation. |
| cmd/entire/cli/agent/antigravity/title_install_test.go | Unit tests for install/uninstall idempotency and wrap round-trips (incl. quotes). |
| cmd/entire/cli/agent/antigravity/statusline.go | Snapshot store + baseline + delta implementation for Antigravity out-of-band token usage. |
| cmd/entire/cli/agent/antigravity/statusline_test.go | Unit tests + benchmark for snapshot writing, dedup, pruning, and delta math. |
| cmd/entire/cli/agent/antigravity/hooks.go | Hook install now best-effort configures the global title-tee during repo hook setup. |
| cmd/entire/cli/agent/antigravity/hooks_test.go | Updates tests to isolate global config mutation via env override. |
| cmd/entire/cli/agent/antigravity/antigravity.go | Declares Antigravity implements OutOfBandTokenSource. |
| cmd/entire/cli/agent/antigravity/antigravity_test.go | Ensures tests don’t touch real global config by setting config-dir env override. |
| cmd/entire/cli/agent/agent.go | Adds the OutOfBandTokenSource interface definition and lifecycle contract documentation. |
…lDev + comments Addresses PR #1356 review (Cursor Bugbot + Copilot): - InstallHooks now runs InstallTitleTee BEFORE the repo-hooks idempotency early-return, so re-running setup repairs a missing/stale global title slot (upgrade, failed first install, or 'agent add' without --force). Regression test added. - localDev title command bakes the absolute main.go path at install time instead of a runtime $(git rev-parse) that would resolve against the wrong repo (the title slot is global). Falls back to the PATH form if unresolved. - Fix shellSingleQuote doc comment (stray curly quote) and the dedup comment to accurately describe the whole-file streaming read. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… comments) - condensation: gate out-of-band token fallback on AsOutOfBandTokenSource (purpose-built capability) instead of the !AsTokenCalculator inverse, so only OOB agents inherit accumulated SessionState.TokenUsage; add a negative-branch test proving a non-OOB agent (Cursor) does not. - title-tee: log a debug breadcrumb on AppendStatusSnapshot failure instead of discarding the error; contract unchanged (no stdout, returns nil). - comments: correct readLastContextWindow doc (streams the file), reframe AsOutOfBandTokenSource exclusion rationale, note sh -c wrap is the user's own settings.json command (not an injection surface). - lifecycle: use slog.String for the OOB warn log to match the file's local convention. - tests: current_usage change is not deduped; --wrap path still captures the snapshot; delta is zero (nil) when baseline is the latest snapshot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test-auditor pass: - Remove TestTitleTee_WrapPipesPayloadThrough — a strict subset of TestTitleTee_WrapStillCapturesSnapshot (which makes the same passthrough assertion plus the snapshot-capture check). Zero coverage lost. - Rewrite TestCalculateTokenUsageSince_ClampsWhenTotalsGoBackwards to assert usage == nil directly (the actual all-zero path) instead of guarded conditionals that never executed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@BugBot review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit acad86f. Configure here.

https://entire.io/gh/entireio/cli/trails/507
Summary
Follow-up to #1287 (which intentionally deferred token counts). Adds native per-checkpoint token usage for the Antigravity (agy) agent, surfaced in committed checkpoint metadata exactly like every other agent — so the entire.io UI displays agy tokens with zero web-side changes.
Why this approach: agy exposes token usage only via the JSON payload piped to its title/statusline script on every agent state change (
context_window.{total_input_tokens, total_output_tokens, current_usage{...}}, cumulative per conversation). It is absent from transcripts, hook payloads, logs, and the protobuf session state. The statusline schema is the single source — verified against real agy transcripts and the published docs.How it works (end-to-end):
title-teeshim —entire hooks antigravity title-tee [--wrap '<original>']is installed into agy's global~/.gemini/antigravity-cli/settings.jsontitleslot. On every state change it tees the JSON to a per-conversation append-only JSONL store (<cache>/entire/antigravity/status/<conversation_id>.jsonl) and pipes through to any pre-existing user title command. We use thetitleslot (notstatusLine) — same payload, lower blast radius.OutOfBandTokenSourcecapability — new interface for agents whose token data lives outside the transcript. Built-in only (external agents excluded).PrePromptState), delta = latest cumulative totals − baseline at TurnEnd (the Codex cumulative-minus-baseline pattern, sourced from the tee file). Input/output exact; cache/api-call counts best-effort sampled.SessionState.TokenUsagecopied into committed metadata for non-TokenCalculatoragents.Install/uninstall semantics: install wraps + preserves any existing user title command (self-describing via
--wrap); uninstall (agent-removal only, never per-repodisablesince the slot is global) restores the original or clears a bare tee, and leaves foreign/user-wrapped commands untouched.Notable properties
Known v1 limitations (documented in code)
agy --continue) whose title-tee hasn't fired before the first TurnStart over-count that one turn by the prior cumulative total.Test Plan
TestAntigravity_TokenUsageInCheckpointMetadata— seeds snapshots, drives the real hook lifecycle, commits, assertstoken_usage3500/300 in both per-sessionmetadata.jsonand theCheckpointSummaryaggregate onentire/checkpoints/v1.mise run checkgreen (unit-race+ integration + Vogon canary 58/58). Vogon unaffected (degrades to nil).🤖 Generated with Claude Code
Note
Medium Risk
Modifies global Antigravity user config and checkpoint token metadata paths; failures degrade to missing counts rather than blocking hooks, but misconfigured title-tee affects all agy workspaces on the machine.
Overview
Adds native per-checkpoint token usage for Antigravity, which only exposes
context_windowtotals via the global title command JSON—not transcripts or lifecycle hooks.A
title-teeshim (entire hooks antigravity title-tee) is installed into~/.gemini/antigravity-cli/settings.json, tees state JSON into a per-conversation JSONL snapshot cache, and optionally chains the user’s original title command via--wrap. Hook install always attempts title-tee setup (even when repo hooks are already idempotent) so upgrades can repair a missing global slot.New
OutOfBandTokenSourcecaptures a baseline at turn start (PrePromptState.token_baseline) and computes turn deltas at turn end when transcript token calc is nil; condensation copies accumulated session token usage into committed metadata for OOB agents only.entire doctorwarns when repo Antigravity hooks exist but title-tee is not configured; title-tee is removed on agent removal, not per-repo disable.Reviewed by Cursor Bugbot for commit acad86f. Configure here.