Skip to content

Instantly share code, notes, and snippets.

@4rmx
Created August 9, 2026 09:11
Show Gist options
  • Select an option

  • Save 4rmx/e8b15d791a6dc3cb1c1c70728db063a0 to your computer and use it in GitHub Desktop.

Select an option

Save 4rmx/e8b15d791a6dc3cb1c1c70728db063a0 to your computer and use it in GitHub Desktop.

Antigravity CLI Custom Status Line (with Vim mode & Quota Bars)

This is a custom Python script that generates a rich status line for the Google Antigravity CLI (agy). It natively supports extracting your current Vim mode (-- NORMAL --, -- INSERT --) and rendering it dynamically on its own line, along with your active model, effort level, token usage, and session/weekly quota progress bars!

How to setup

  1. Create the Python script: Save the following code to ~/.gemini/antigravity-cli/statusline.py and make sure it is executable (chmod +x ~/.gemini/antigravity-cli/statusline.py).
#!/usr/bin/env python3
import sys
import json

def format_tokens(number):
    try:
        val = float(number)
    except (ValueError, TypeError):
        return "0"
    
    if val >= 1_000_000:
        return f"{val / 1_000_000:.1f}M"
    elif val >= 1_000:
        return f"{val / 1_000:.1f}k"
    return str(int(val))

def get_tokens_and_limit(data):
    cw = data.get("context_window", {})
    if not isinstance(cw, dict):
        cw = {}

    input_tokens = cw.get("total_input_tokens", 0) or 0
    output_tokens = cw.get("total_output_tokens", 0) or 0
    used_tokens = input_tokens + output_tokens

    if not used_tokens:
        used_tokens = cw.get("current_usage", 0) or 0

    limit = cw.get("context_window_size", 1_000_000) or 1_000_000
    return used_tokens, limit

def colorize_tokens(text, tokens):
    if tokens > 300_000:
        return f"\033[38;5;208m{text}\033[0m"  # orange
    elif tokens > 200_000:
        return f"\033[38;5;220m{text}\033[0m"  # yellow
    return text

def make_bar(pct, width=10):
    filled = int(pct / 100 * width + 0.5)
    filled = max(0, min(width, filled))
    return "█" * filled + "░" * (width - filled)

def get_quota_pct(data, period):
    """period: '5h' or 'weekly'"""
    quota = data.get("quota", {})
    if not isinstance(quota, dict):
        return None

    model_name = ""
    if isinstance(data.get("model"), dict):
        model_name = data["model"].get("display_name", "") or data["model"].get("id", "")
    prefix = "gemini" if "gemini" in model_name.lower() else "3p"
    key = f"{prefix}-{period}"

    entry = quota.get(key)
    if not isinstance(entry, dict) or "remaining_fraction" not in entry:
        return None

    try:
        remaining = float(entry["remaining_fraction"])
    except (TypeError, ValueError):
        return None
    return (1 - remaining) * 100

def main():
    try:
        input_data = sys.stdin.read()
        if not input_data.strip():
            return
        data = json.loads(input_data)
    except Exception:
        print("agy | [Error Reading State]")
        return

    # Get formatted token string
    used, limit = get_tokens_and_limit(data)
    used_str = colorize_tokens(f"{format_tokens(used)} tokens", used)

    # Extract Vim mode
    vim_badge = ""
    vim_data = data.get("vim", {})
    if vim_data and "mode" in vim_data:
        vim_badge = f"\n -- {vim_data['mode']} --"

    # Extract Model and Effort
    model_str = ""
    if isinstance(data.get("model"), dict):
        m_name = data["model"].get("display_name", "") or data["model"].get("id", "")
        m_effort = data["model"].get("effort", "")
        clean_name = m_name
        if m_effort and f"({m_effort.capitalize()})" in m_name:
            clean_name = m_name.replace(f"({m_effort.capitalize()})", "").strip()
        
        if clean_name and m_effort:
            model_str = f" {clean_name} · {m_effort} |"
        elif clean_name:
            model_str = f" {clean_name} |"

    # Output to the status line
    status_str = f"{model_str} {used_str} "

    weekly_pct = get_quota_pct(data, "weekly")
    if weekly_pct is not None:
        bar = make_bar(weekly_pct)
        status_str = f" {bar}  {weekly_pct:.0f}% weekly limit |{status_str}"

    session_pct = get_quota_pct(data, "5h")
    if session_pct is not None:
        bar = make_bar(session_pct)
        status_str = f" {bar}  {session_pct:.0f}% session limit |{status_str}"

    print(status_str + vim_badge)

if __name__ == "__main__":
    main()
  1. Configure the CLI (settings.json): Open your Antigravity CLI settings file (located at ~/.gemini/antigravity-cli/settings.json) and configure the statusLine and theme properties.

    • Make sure "stack_with_default": false is set so the default dimmed status line doesn't conflict.
    • (Optional) Set "theme": "terminal" to ensure the UI colors perfectly match your system's normal text color.

    Your config should look like this:

    {
      "theme": "terminal",
      "editorMode": "vim",
      "statusLine": {
        "type": "command",
        "command": "~/.gemini/antigravity-cli/statusline.py",
        "enabled": true,
        "stack_with_default": false
      }
    }
  2. Restart the CLI: Close your current CLI session (press Ctrl+D) and run agy again to see the magic!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment