DEV Community

Cover image for What Antigravity CLI actually sends to your statusline script (field by field)
Wassim AZI
Wassim AZI

Posted on

What Antigravity CLI actually sends to your statusline script (field by field)

If you write your own statusline for Google's Antigravity CLI (agy), you start from the official docs: agy runs your command when its state changes, pipes a JSON payload to its stdin, and shows what the command prints.

The docs list the payload's fields. But when I captured real payloads for agy-powerline, they didn't quite match: some documented fields never showed up, a few useful ones arrived without being documented, and the quota buckets, the part most people want, aren't listed at all.

This is the payload as it actually arrived, captured from agy 1.3.0 to 1.4.0 on a Google AI Pro account, in October 2026. Your plan, version and OS may differ: treat every field as optional.

agy starts your statusline script on every refresh and sends it JSON on stdin (model, context_window, quota with 5 buckets, subagents, vcs with only its type, terminal_width); the text the script prints on stdout becomes the bar under the input box

A real payload

Trimmed, with personal values replaced:

{
  "cwd": "/home/user/project",
  "session_id": "00000000-0000-0000-0000-000000000000",
  "conversation_id": "00000000-0000-0000-0000-000000000000",
  "conversation_title": "hello",
  "transcript_path": "/home/user/.gemini/antigravity-cli/conversations/…",
  "model": {
    "id": "Gemini 3.8 Flash (High)",
    "display_name": "Gemini 3.8 Flash (High)",
    "effort": "high"
  },
  "workspace": { "current_dir": "/home/user/project", "project_dir": "/home/user/project" },
  "version": "1.3.3",
  "context_window": {
    "total_input_tokens": 33129,
    "total_output_tokens": 10161,
    "context_window_size": 1048576,
    "used_percentage": 3.159,
    "remaining_percentage": 96.841,
    "current_usage": {
      "input_tokens": 3353,
      "output_tokens": 187,
      "cache_creation_input_tokens": 0,
      "cache_read_input_tokens": 24680
    }
  },
  "exceeds_200k_tokens": false,
  "product": "antigravity",
  "quota": {
    "gemini-5h": { "remaining_fraction": 0.987, "reset_time": "2026-10-13T00:36:57Z", "reset_in_seconds": 15752 }
  },
  "agent_state": "idle",
  "vcs": { "type": "git" },
  "cycle_mode": "accept-edits",
  "sandbox": { "enabled": false },
  "subagents": [{ "name": "research", "role": "List the files in the project folder.", "status": "completed" }],
  "plan_tier": "Google AI Pro",
  "email": "user@example.com",
  "terminal_width": 198,
  "vim": { "mode": "NORMAL" }
}
Enter fullscreen mode Exit fullscreen mode

The quota buckets

quota is an object keyed by bucket. The docs' example shows only gemini-weekly. Here's every bucket I've seen:

Bucket What it is Window
gemini-5h Gemini models 5 hours
gemini-weekly Gemini models 7 days
3p-5h Third-party models (Claude, GPT) 5 hours
3p-weekly Third-party models 7 days
gemini-argon-wtu-weekly Gemini 4 Argon's own quota, on Google AI Pro (since mid-October 2026) 7 days

Each bucket has:

  • remaining_fraction: from 0 to 1. Multiply by 100 for "percent left".
  • reset_time: an ISO timestamp. Both …T00:36:57Z and …T00:36:57.000Z show up, depending on the version, so parse it with Date.parse() rather than a regex.
  • reset_in_seconds: optional according to the docs. If it's missing, compute it from reset_time.
  • Sometimes "disabled": true. I skip those buckets.

A few things worth knowing:

  • The Argon bucket arrives whatever model you're using, not only when Argon is selected. To show "the quota that matters right now", pick the bucket group from model.id: Argon models → the Argon bucket, other Gemini models → gemini-*, everything else → 3p-*.
  • How far into the window you are needs no extra field: 1 - reset_in_seconds / window_length, with 18,000 s for 5-hour buckets and 604,800 s for 7-day ones. Compare it with the share you've used, and you know if you're ahead of or behind pace.
  • The values come from agy, as of its last refresh. A statusline can't be more up to date than the payload.

Fields that arrive but aren't documented

Field Seen as Notes
cycle_mode "accept-edits" The approval mode. Missing from some captures, so treat "absent" as the default mode. The docs list execution_mode instead, which I've never seen.
subagents [{ name, role, status }] status was "running" or "completed". role is a whole sentence (the task you gave it), so cut it before printing.
conversation_title "hello" Appears once the conversation has a title.
model.effort "high" The reasoning effort.

Fields that are documented but never showed up

On my machine, with a Google AI Pro account, these never appeared:

  • execution_mode (see cycle_mode above).
  • pending_input_count, even with a prompt queued.
  • tool_confirmation_pending.
  • vcs.branch, vcs.client and vcs.dirty: vcs only ever held type (see antigravity-cli#739). Starting git on every refresh is slow on Windows (an ahead/behind count alone took about 60 ms), so read the branch from .git/HEAD yourself and cache anything that needs git.
  • sandbox.allow_network: only enabled arrived.

If your script depends on one of these, give it a fallback.

Gotchas

  • model.id isn't an API id. It held the same text as display_name, effort included: "Gemini 3.8 Flash (High)". Match on substrings (includes("argon")), not on exact ids.
  • used_percentage counts input, not output. In every real capture it equals total_input_tokens / context_window_size (33,129 / 1,048,576 = 3.159% above). total_output_tokens isn't in it. If you add output tokens to your token count, the count stops matching agy's own percentage, so show the input count, or work the count out from the percentage.
  • exceeds_200k_tokens can be null before the first request, according to the docs.
  • agent_state takes idle, thinking, working, tool_use or initializing, per the docs. I've seen idle, working and tool_use.
  • terminal_width is the live width. Use it to fit your output: a line wider than the terminal wraps and pushes the bar out of place.
  • vim appears only with Vim mode on, with mode set to NORMAL, INSERT and so on.

The cache numbers

context_window holds totals for the whole session, and current_usage the numbers for the latest request:

"current_usage": {
  "input_tokens": 3353,
  "output_tokens": 187,
  "cache_creation_input_tokens": 0,
  "cache_read_input_tokens": 24680
}
Enter fullscreen mode Exit fullscreen mode

From those you can work out how much of the latest prompt was read from the prompt cache:

cache_hit_pct = cache_read_input_tokens / (input_tokens + cache_read_input_tokens) * 100
Enter fullscreen mode Exit fullscreen mode

In the payload above, 24,680 / (3,353 + 24,680) * 100 = 88%: most of the prompt came from the cache. When cache_read_input_tokens is 0 and cache_creation_input_tokens isn't, nothing was read from the cache and the prompt was written to it: a cold start.

Subagents

subagents lists the child tasks of the conversation, with status set to "running" or "completed":

"subagents": [
  { "name": "research", "role": "List the files in the project folder.", "status": "completed" }
]
Enter fullscreen mode Exit fullscreen mode

role is the whole instruction the subagent got, so cut it short before you print it, or it wraps the line.

Personal data in the payload

The payload holds your email, session_id and conversation_id, and the full transcript_path. Your script receives them on every refresh, so be careful with them:

  • Don't print them, and don't write them to a log.
  • If you save payloads to debug, strip those fields first, and replace paths before you share a file in an issue.
  • Treat every string (cwd, conversation_title, subagent roles) as untrusted text: strip terminal escape sequences before printing, or a crafted value can change your terminal's state.

Reading stdin safely

One more thing the docs don't mention: agy can start the command and keep stdin open without writing anything (antigravity-cli#698). A blocking read then waits until agy kills the script, and after a few kills agy turns the statusline off. Read stdin with a deadline (one second works), and exit 0 with no output if nothing arrived. Also strip a leading byte order mark (\uFEFF) before JSON.parse.

Capture your own

To see exactly what your agy sends, point the statusline at a script that saves stdin to a file before rendering. With agy-powerline installed, set AGY_POWERLINE_DEBUG=1 before starting agy: each refresh saves the payload to ~/.agy-powerline/last-payload.json, with the email and IDs removed and paths replaced, so it's safe to share.

If you see a field or a bucket that isn't listed here (a cost object, another quota bucket, execution_mode in plan mode), I'd like to hear about it: comment below or open an issue with your dump. I'll update this list.

To install agy-powerline and start rendering these wire payloads right away:

npx agy-powerline init
Enter fullscreen mode Exit fullscreen mode

🤖 One-shot install with Antigravity:

Hey agy, please install agy-powerline by running `npx agy-powerline init --yes`, then tell me to restart agy.

Top comments (0)