目錄
  1. 一、 如何安裝 Google Antigravity
  2. 1. 終端 CLI 安裝命令
  3. 2. 啟動與初始化認證
  4. 二、 關鍵環境門檻與帳號網路排障
  5. 1. 代理與出口 IP 約束
  6. 2. 谷歌帳號國家/地區歸屬地
  7. 3. 年齡與身分認證
  8. 三、 高效使用設定與避坑技巧
  9. 1. 開啟權限自動審批(告別打斷)
  10. 2. 設定終端 StatusLine 即時狀態列
  11. 四、 常用指令與快捷鍵速查
  12. 1. CLI 終端核心命令
  13. 2. 常用斜槓命令(Slash Commands)
  14. 3. 高頻操作技巧(Quick Tips)
  15. 4. 鍵盤快捷鍵對映(Keybindings)

Antigravity 全景指南:Google 跨模型排程接入 Claude 5.5 實操教程與進階技巧

Google 新一代模型 Gemini 4 Argon 發布後,最受矚目的首創特性在於支援高達 100 萬 Token 的上下文輸出。這意味著無論是直接輸出超長業務架構程式碼、整本技術規範,還是完成高吞吐量的複雜自動化任務,模型都具備了前所未有的展開空間。

從實際 Benchmark 測試成績來看,Gemini 4 Argon 在多項推理與編碼基準上超越了 GPT-6 Astra、Claude Fable 5.1 與 Claude Opus 5.5:

Gemini 4 Argon 與 GPT-6、Claude 系列 Benchmark 效能對比實測

更為關鍵的是:Google Antigravity 的 Google AI Pro 與 Google AI Ultra 付費訂閱使用者,現已原生開放了跨模型排程能力,可以直接掛載 Claude Opus 5.5 與 Claude Sonnet 5.5 模型後端。

Antigravity 排程 Claude Opus 5.5 與 Sonnet 5.5 實測

通過 Google Antigravity 統一的環境架構,既能享受 Gemini 超大上下文的排程優勢,又能無縫呼叫 Claude 頂級的邏輯推導與程式碼生成能力。本文系統整理 Antigravity 桌面端與 CLI 的安裝部署、帳號環境門檻排查、權限全自動審批設定、終端 StatusLine 狀態列腳本及全套快捷鍵速查表。


一、 如何安裝 Google Antigravity

Antigravity 三種形態:桌面 App、CLI 與 IDE 入口對比

Google Antigravity 提供了三種產品形態供開發者選擇:

  1. Antigravity 2.0(桌面 App)
  2. Antigravity CLI(終端互動式 AI 代理)
  3. Antigravity IDE(一體化開發環境)

桌面 App 與 IDE 可直接通過 Antigravity 官方下載頁 獲取安裝包;終端 CLI 則支援單行腳本極速部署:

1. 終端 CLI 安裝命令

  • macOS / Linux(Bash / Zsh):

    curl -fsSL https://antigravity.google/cli/install.sh | bash
    
  • Windows(PowerShell):

    irm https://antigravity.google/cli/install.ps1 | iex
    
  • Windows(CMD):

    curl -fsSL https://antigravity.google/cli/install.cmd -o install.cmd && install.cmd && del install.cmd
    

2. 啟動與初始化認證

安裝完成後,在終端直接輸入 agy 即可啟動互動式 CLI:

# 查看版本确认安装成功
agy --version

# 启动 Antigravity 交互式终端
agy

首次啟動時,終端會輸出登入認證指引並自動生成 Google 授權連結。在瀏覽器中完成帳號授權繫結後,憑據將自動寫入本機快取,隨後直接進入 Agent 互動式開發工作區。


二、 關鍵環境門檻與帳號網路排障

Antigravity 對網路出口、帳號關聯地區以及帳號年齡有明確的准入規則:

1. 代理與出口 IP 約束

Antigravity 對出口 IP 的機房屬性與風控較為敏感:

  • 避免使用公共資料中心機房節點,優先選用低風控、支援原生 UDP/QUIC 協議的住宅/專線節點;
  • 配合 Clash Verge、Surge 等工具開啟 TUN 虛擬網卡模式,確保終端 CLI 流量(包含底層 gRPC 握手)完整走代理分流,避免 DNS 汙染或 TLS 握手異常。

2. 谷歌帳號國家/地區歸屬地

谷歌帳號的國家地區歸屬必須處於服務支援地區。如果帳號此前歸屬在不支援區域,可通過官方申訴通道申請修正:

  • 存取:Google 帳號關聯地區更改請求
  • 申請理由選擇:「我住在這裡」或「我經常使用代理/VPN 出行網路」;
  • 申請時確保當前網路出口所在地與申請變更的目標國家/地區保持一致。

3. 年齡與身分認證

部分進階模型能力受年齡限制,未完成認證的帳號可能無法撥出 Claude 或前沿模型:

  • 存取:Google 帳號年齡認證
  • 按官方提示上傳身分檔案或繫結支援國際支付的信用卡即可即時核驗解除。

三、 高效使用設定與避坑技巧

1. 開啟權限自動審批(告別打斷)

Antigravity 預設的安全策略較為嚴格:修改本機檔案、執行終端指令、檢視 Artifact 均會彈窗請求人工逐次確認。在長週期複雜任務中,頻繁被打斷會嚴重拖慢 Agent 的吞吐效率。

如果你希望 Agent 全自主流暢執行,可在設定中開啟自動審批:

在終端輸入 /config 喚起設定選單,將:

  • Artifact Review 設為 always proceeds
  • Tool Permission 設為 always proceeds

設定將即時寫入全域設定檔 ~/.gemini/antigravity-cli/settings.json。

💡 啟動參數覆蓋機制: 如果在啟動 CLI 時顯式傳入了 --dangerously-skip-permissions 或 --sandbox,當前會話將處於覆蓋(Override)生效狀態,優先遵循命令列參數,退出重啟後恢復預設。


2. 設定終端 StatusLine 即時狀態列

在終端底部隨時掌握當前模型版本、Git 分支、上下文已用百分比、輸入/輸出 Token 消耗以及限流配額狀態,能夠大幅提高排障與開發效率。

Antigravity 終端 StatusLine 即時狀態列效果實錄

該狀態列腳本通過單個 jq 呼叫一次性提取並格式化全部狀態欄位,避免頻繁 fork 子程序導致終端卡頓。

① 建立腳本檔案

將以下腳本儲存到本機路徑 ~/.gemini/antigravity-cli/agy-statusline.sh:

#!/bin/bash
# Hot path: agy kills this script when it runs too long, so the only external
# process is jq. Everything else uses bash builtins (no git, sed or subshells).

# ==============================================================================
# 用户可配置项 (User Configuration)
# ==============================================================================
# 布局模式 (Layout Mode):
#   "double"    : 双行模式 (推荐:第1行身份与位置状态,第2行容量、速率、单轮用量与配额指标)
#   "dashboard" : 四行看板模式 (大屏全景看板,分行展示模型、上下文、Git位置、速率与费用,别名: "quad")
#   "single"    : 单行紧凑模式 (最省终端垂直空间)
#   "triple"    : 三行模式
LAYOUT_MODE="${LAYOUT_MODE:-dashboard}" # 默认设置为 dashboard (四行看板模式,按需可切换为 double / single / triple)

# 基础信息开关
SHOW_ACCOUNT="${SHOW_ACCOUNT:-true}"   # 是否展示当前登录账号 (例如: 👤 wardlu.test@gmail.com)
SHOW_DIR="${SHOW_DIR:-true}"           # 是否展示当前所处工程目录 (例如: 📁 shadow-portal)
SHOW_BRANCH="${SHOW_BRANCH:-true}"     # 是否展示 Git 分支 (例如: 🌿 main)
SHOW_WORKTREE="${SHOW_WORKTREE:-true}" # 是否展示 Git Worktree (例如: 🌲 main 或 🌲 ci-doc-3)
ONLY_SECONDARY_WORKTREE="${ONLY_SECONDARY_WORKTREE:-false}" # true: 仅在非主分支独立 worktree 时显示; false: 始终显示 (主目录显示 🌲 main)

# 额度与限额开关
SHOW_REMAINING="${SHOW_REMAINING:-true}"     # true: 展示剩余比例 (周剩 / 5h剩); false: 展示已用比例 (周用 / 5h用)
SHOW_RESET_TIME="${SHOW_RESET_TIME:-true}"   # 是否在周限额旁展示重置倒计时 (例如: 6d 20h)
SHOW_5H_RESET_TIME="${SHOW_5H_RESET_TIME:-false}" # 是否在5h限额旁展示重置倒计时 (默认 false 保持紧凑)
SHOW_PLAN_TIER="${SHOW_PLAN_TIER:-false}"   # 是否展示计划等级 (🏆 Google AI Pro,默认隐藏,需要时设为 true)
SHOW_STATIC_LIMIT="${SHOW_STATIC_LIMIT:-false}" # 是否展示静态限额说明 (⚠️ Limit: 15 RPM / 1.5K RPD,默认隐藏,需要时设为 true)
QUOTA_STYLE="${QUOTA_STYLE:-en}"             # 额度标签风格: "en" (Weekly/Session) 或 "cn" (周剩/5h剩)
QUOTA_PRECISION="${QUOTA_PRECISION:-1}"     # 额度百分比保留小数位数 (1位小数,如 83.7%,与 Claude Code 一致)

# ⚡ Token 速率 (TPS) 与单轮用量配置 (Speed & Turn Token Configuration)
SHOW_SPEED="${SHOW_SPEED:-true}"         # 是否展示 Token 吞吐速率 TPS (对标 Claude Code speed 模块)
SPEED_MODE="${SPEED_MODE:-all}"          # 速率展示模式:
                                         #   "all"   : 展示输出速度与总吞吐 (例如: ⚡ Out: 52.3 t/s │ Total: 820.6 t/s)
                                         #   "out"   : 仅展示模型输出生成速度 (例如: ⚡ 52.3 t/s)
                                         #   "total" : 仅展示总吞吐速度 (例如: ⚡ 820.6 t/s)
SHOW_SPEED_IN="${SHOW_SPEED_IN:-false}"  # 是否在 "all" 模式中单独展示输入速度 (例如: In: 768.3 t/s)
SHOW_TURN_USAGE="${SHOW_TURN_USAGE:-true}" # 是否展示当前/上一轮单轮 Token 消耗 (例如: 🔄 Turn: In 2.4K / Out 3.0K)
SHOW_TURN_CACHE="${SHOW_TURN_CACHE:-false}" # 是否在单轮消耗中展示 Prompt Cache 命中量 (例如: Cache: 185K)

# Prepare accounts file for jq slurp fallback
ACCOUNTS_FILE="$HOME/.antigravity_tools/accounts.json"
ACC_SLURP=(--slurpfile acc /dev/null)
if [ -r "$ACCOUNTS_FILE" ]; then
  ACC_SLURP=(--slurpfile acc "$ACCOUNTS_FILE")
fi

# 极速读取 stdin 缓存至内存 (<1ms,避免子进程)
INPUT_DATA=$(cat)

# 提取 session_id 隔离不同会话速率探针
SESSION_ID=""
if [[ $INPUT_DATA =~ \"session_id\"[[:space:]]*:[[:space:]]*\"([^\"]+)\" ]]; then
  SESSION_ID="${BASH_REMATCH[1]}"
elif [[ $INPUT_DATA =~ \"conversation_id\"[[:space:]]*:[[:space:]]*\"([^\"]+)\" ]]; then
  SESSION_ID="${BASH_REMATCH[1]}"
fi
[ -z "$SESSION_ID" ] && SESSION_ID="default"

SPEED_FILE="/tmp/agy_speed_${SESSION_ID}.txt"
PREV_SPEED_STATE=""
if [ -r "$SPEED_FILE" ]; then
  read -r PREV_SPEED_STATE < "$SPEED_FILE"
fi

# 单次 jq 极速提取并计算所有基础字段、配额百分比、倒计时与 TPS
eval "$(jq -r "${ACC_SLURP[@]}" --arg prev "$PREV_SPEED_STATE" '
now as $now |
def format_tokens(val):
  if (val == null or val == 0) then "0"
  else
    (val | tonumber) as $n |
    if $n >= 1000000000 then "\(( ($n / 1000000000 * 100 | round) / 100 ))B"
    elif $n >= 1000000 then "\(( ($n / 1000000 * 100 | round) / 100 ))M"
    elif $n >= 1000 then "\(( ($n / 1000 * 100 | round) / 100 ))K"
    else "\($n)"
    end
  end;

def format_sec(s):
  if (s == null or s <= 0) then ""
  else
    (s / 86400 | floor) as $d |
    ((s % 86400) / 3600 | floor) as $h |
    ((s % 3600) / 60 | floor) as $m |
    if $d > 0 then "\($d)d \($h)h"
    elif $h > 0 then "\($h)h \($m)m"
    else "\($m)m"
    end
  end;

def format_speed(val):
  if (val == null or val <= 0) then "—"
  else
    (val | tonumber) as $n |
    if $n >= 1000000 then "\(( ($n / 1000000 * 10 | round) / 10 ))M t/s"
    elif $n >= 1000 then "\(( ($n / 1000 * 10 | round) / 10 ))k t/s"
    else "\(( ($n * 10 | round) / 10 )) t/s"
    end
  end;

($prev | split(" ")) as $p |
($p[0] // "0" | tonumber) as $prev_ts |
($p[1] // "idle") as $prev_agent |
($p[2] // "0" | tonumber) as $prev_in |
($p[3] // "0" | tonumber) as $prev_out |
($p[4] // "0" | tonumber) as $w_start_ts |
($p[5] // "0" | tonumber) as $w_start_in |
($p[6] // "0" | tonumber) as $w_start_out |
($p[7] // "0" | tonumber) as $last_tps_out |
($p[8] // "0" | tonumber) as $last_tps_in |
($p[9] // "0" | tonumber) as $last_tps_total |

.agent_state as $cur_agent |
(.context_window.total_input_tokens // 0) as $cur_in |
(.context_window.total_output_tokens // 0) as $cur_out |
(.context_window.current_usage.input_tokens // 0) as $turn_in_raw |
(.context_window.current_usage.output_tokens // 0) as $turn_out_raw |
(.context_window.current_usage.cache_read_input_tokens // 0) as $turn_cache_raw |

# 速度计算与状态机维护
(
  if ($prev_agent == "idle" and $cur_agent == "working") then
    # 从空闲转为工作:开启新轮次计时
    {
      w_ts: $now,
      w_in: $cur_in,
      w_out: $cur_out,
      tps_out: $last_tps_out,
      tps_in: $last_tps_in,
      tps_tot: $last_tps_total
    }
  elif ($cur_agent == "working" or ($prev_agent == "working" and $cur_agent == "idle") or ($cur_out > $prev_out)) then
    # 工作中、工作刚结束或检测到输出增加:计算速度
    (
      if ($w_start_ts > 0 and ($now - $w_start_ts) >= 0.1 and ($now - $w_start_ts) <= 300) then ($now - $w_start_ts)
      elif (($now - $prev_ts) >= 0.1 and ($now - $prev_ts) <= 300) then ($now - $prev_ts)
      else 1.0 end
    ) as $dt |
    (if ($cur_out - $w_start_out) > 0 then ($cur_out - $w_start_out) elif ($turn_out_raw > 0) then $turn_out_raw else 0 end) as $dout |
    (if ($cur_in - $w_start_in) > 0 then ($cur_in - $w_start_in) elif ($turn_in_raw > 0) then $turn_in_raw else 0 end) as $din |
    if ($dt >= 0.1 and ($dout > 0 or $din > 0)) then
      {
        w_ts: (if $cur_agent == "working" then $w_start_ts else 0 end),
        w_in: (if $cur_agent == "working" then $w_start_in else $cur_in end),
        w_out: (if $cur_agent == "working" then $w_start_out else $cur_out end),
        tps_out: (if $dout > 0 then ($dout / $dt) else $last_tps_out end),
        tps_in: (if $din > 0 then ($din / $dt) else $last_tps_in end),
        tps_tot: (( ($dout + $din) / $dt ))
      }
    else
      {
        w_ts: $w_start_ts,
        w_in: $w_start_in,
        w_out: $w_start_out,
        tps_out: $last_tps_out,
        tps_in: $last_tps_in,
        tps_tot: $last_tps_total
      }
    end
  else
    # 空闲等待用户,保持上一轮速度值
    {
      w_ts: $w_start_ts,
      w_in: $w_start_in,
      w_out: $w_start_out,
      tps_out: $last_tps_out,
      tps_in: $last_tps_in,
      tps_tot: $last_tps_total
    }
  end
) as $calc |

# 针对当前模型优先选择配额桶 (gemini 或 3p 或兼容 rate_limits)
.model.id as $mid |
(if ($mid // "" | test("claude|3p|openai|gpt"; "i")) then "3p" else "gemini" end) as $prefix |

(.quota[$prefix + "-5h"] // .quota["gemini-5h"] // .quota["3p-5h"] // .rate_limits.five_hour // null) as $b_5h |
(.quota[$prefix + "-weekly"] // .quota["gemini-weekly"] // .quota["3p-weekly"] // .rate_limits.seven_day // null) as $b_7d |

{
  model: (.model.display_name // .model.id // "Unknown"),
  cost: (.cost.total_cost_usd // 0),
  context_pct: (.context_window.used_percentage // 0),
  context_size: format_tokens(.context_window.context_window_size // 0),
  in_tokens: format_tokens(.context_window.total_input_tokens // 0),
  out_tokens: format_tokens(.context_window.total_output_tokens // 0),
  cwd: (.cwd // ""),
  agent: (.agent.name // ""),
  plan_tier: (.plan_tier // ""),
  account: (
    .email // .user.email // .account.email // .oauth_account.emailAddress //
    ($acc[0] | .current_agy_account_id as $id | (.accounts[]? | select(.id == $id) | .email)) //
    ""
  ),
  account_name: (
    ($acc[0] | .current_agy_account_id as $id | (.accounts[]? | select(.id == $id) | .name)) //
    ""
  ),
  five_hour_rem: (if $b_5h.remaining_fraction != null then (($b_5h.remaining_fraction * 1000 | round) / 10)
                  elif $b_5h.used_percentage != null then (((100 - $b_5h.used_percentage) * 10 | round) / 10)
                  else null end),
  five_hour_used: (if $b_5h.remaining_fraction != null then (((1 - $b_5h.remaining_fraction) * 1000 | round) / 10)
                   elif $b_5h.used_percentage != null then (($b_5h.used_percentage * 10 | round) / 10)
                   else null end),
  five_hour_reset_str: format_sec($b_5h.reset_in_seconds),
  seven_day_rem: (if $b_7d.remaining_fraction != null then (($b_7d.remaining_fraction * 1000 | round) / 10)
                  elif $b_7d.used_percentage != null then (((100 - $b_7d.used_percentage) * 10 | round) / 10)
                  else null end),
  seven_day_used: (if $b_7d.remaining_fraction != null then (((1 - $b_7d.remaining_fraction) * 1000 | round) / 10)
                   elif $b_7d.used_percentage != null then (($b_7d.used_percentage * 10 | round) / 10)
                   else null end),
  seven_day_reset_str: format_sec($b_7d.reset_in_seconds),
  turn_in_raw: $turn_in_raw,
  turn_out_raw: $turn_out_raw,
  turn_cache_raw: $turn_cache_raw,
  turn_in_fmt: format_tokens($turn_in_raw),
  turn_out_fmt: format_tokens($turn_out_raw),
  turn_cache_fmt: format_tokens($turn_cache_raw),
  tps_out_val: $calc.tps_out,
  tps_total_val: $calc.tps_tot,
  tps_in_val: $calc.tps_in,
  tps_out_fmt: format_speed($calc.tps_out),
  tps_total_fmt: format_speed($calc.tps_tot),
  tps_in_fmt: format_speed($calc.tps_in),
  new_speed_state: "\($now) \($cur_agent) \($cur_in) \($cur_out) \($calc.w_ts) \($calc.w_in) \($calc.w_out) \($calc.tps_out) \($calc.tps_in) \($calc.tps_tot)"
} | [
  @sh "MODEL=\(.model)",
  @sh "COST=\(.cost)",
  @sh "CONTEXT_PCT=\(.context_pct)",
  @sh "CONTEXT_SIZE_FMT=\(.context_size)",
  @sh "IN_TOKENS_FMT=\(.in_tokens)",
  @sh "OUT_TOKENS_FMT=\(.out_tokens)",
  @sh "CWD=\(.cwd)",
  @sh "AGENT=\(.agent)",
  @sh "PLAN_TIER=\(.plan_tier)",
  @sh "ACCOUNT=\(.account)",
  @sh "ACCOUNT_NAME=\(.account_name)",
  @sh "FIVE_HOUR_REM=\(.five_hour_rem)",
  @sh "FIVE_HOUR_USED=\(.five_hour_used)",
  @sh "FIVE_HOUR_RESET_STR=\(.five_hour_reset_str)",
  @sh "SEVEN_DAY_REM=\(.seven_day_rem)",
  @sh "SEVEN_DAY_USED=\(.seven_day_used)",
  @sh "SEVEN_DAY_RESET_STR=\(.seven_day_reset_str)",
  @sh "TURN_IN_RAW=\(.turn_in_raw)",
  @sh "TURN_OUT_RAW=\(.turn_out_raw)",
  @sh "TURN_CACHE_RAW=\(.turn_cache_raw)",
  @sh "TURN_IN_FMT=\(.turn_in_fmt)",
  @sh "TURN_OUT_FMT=\(.turn_out_fmt)",
  @sh "TURN_CACHE_FMT=\(.turn_cache_fmt)",
  @sh "TPS_OUT_VAL=\(.tps_out_val)",
  @sh "TPS_TOTAL_VAL=\(.tps_total_val)",
  @sh "TPS_IN_VAL=\(.tps_in_val)",
  @sh "TPS_OUT_FMT=\(.tps_out_fmt)",
  @sh "TPS_TOTAL_FMT=\(.tps_total_fmt)",
  @sh "TPS_IN_FMT=\(.tps_in_fmt)",
  @sh "NEW_SPEED_STATE=\(.new_speed_state)"
] | join("\n")
' <<< "$INPUT_DATA")"

# 保存最新速率探针状态 (纯 bash 重定向,<0.5ms)
[ -n "$NEW_SPEED_STATE" ] && printf '%s\n' "$NEW_SPEED_STATE" > "$SPEED_FILE" 2>/dev/null

# Format a number with printf -v (no subshell); fall back to the raw value
fmt_num() { # var precision value
  LC_NUMERIC=C printf -v "$1" "%.$2f" "$3" 2>/dev/null || printf -v "$1" '%s' "$3"
}

fmt_num CONTEXT_FMT 1 "$CONTEXT_PCT"

# ==============================================================================
# Git 目录、分支与 Worktree 探测 (纯 Bash 内置,零子进程极速探测)
# ==============================================================================
BRANCH=""
GITDIR=""
REPO_ROOT=""
WORKTREE=""
IS_WORKTREE=false
MAIN_REPO_ROOT=""

if [ -n "$CWD" ] && [ "$CWD" != "null" ] && [ -d "$CWD" ]; then
  DIR=$CWD
  while :; do
    if [ -d "$DIR/.git" ]; then
      GITDIR="$DIR/.git"
      REPO_ROOT="$DIR"
      MAIN_REPO_ROOT="$DIR"
      WORKTREE="main"
      break
    elif [ -f "$DIR/.git" ]; then
      # Worktree 或 submodule: .git 文件包含 "gitdir: <path>"
      read -r GITDIR < "$DIR/.git"
      GITDIR=${GITDIR#gitdir: }
      [[ $GITDIR != /* ]] && GITDIR="$DIR/$GITDIR"
      REPO_ROOT="$DIR"
      IS_WORKTREE=true
      case "$GITDIR" in
        */.git/worktrees/*)
          WORKTREE="${GITDIR##*/.git/worktrees/}"
          MAIN_REPO_ROOT="${GITDIR%%/.git/worktrees/*}"
          ;;
        */worktrees/*)
          WORKTREE="${GITDIR##*/worktrees/}"
          MAIN_REPO_ROOT="${GITDIR%%/worktrees/*}"
          ;;
        *)
          WORKTREE="${DIR##*/}"
          MAIN_REPO_ROOT="$DIR"
          ;;
      esac
      break
    fi
    [ -z "$DIR" ] || [ "$DIR" = "/" ] && break
    DIR=${DIR%/*}
  done

  # 读取 HEAD 分支名称
  if [ -n "$GITDIR" ] && [ -r "$GITDIR/HEAD" ]; then
    read -r HEAD_REF < "$GITDIR/HEAD"
    case $HEAD_REF in
      "ref: refs/heads/"*) BRANCH=${HEAD_REF#ref: refs/heads/} ;;
      *) BRANCH="HEAD" ;;
    esac
  fi
fi

# 解析目录展示 (若在子目录下,展示为 工程名/子目录)
DIR_DISPLAY=""
if [ -n "$REPO_ROOT" ]; then
  REL_DIR=""
  if [ "$CWD" != "$REPO_ROOT" ]; then
    REL_DIR="${CWD#$REPO_ROOT/}"
  fi
  DIR_DISPLAY="${REPO_ROOT##*/}"
  if [ -n "$REL_DIR" ] && [ "$REL_DIR" != "$CWD" ]; then
    DIR_DISPLAY="${DIR_DISPLAY}/${REL_DIR}"
  fi
elif [ -n "$CWD" ] && [ "$CWD" != "null" ]; then
  DIR_DISPLAY="${CWD##*/}"
else
  DIR_DISPLAY="workspace"
fi

# 目录部分
DIR_PART=""
if [ "$SHOW_DIR" = "true" ] && [ -n "$DIR_DISPLAY" ]; then
  DIR_PART=" │ 📁 $DIR_DISPLAY"
fi

# 分支部分
BRANCH_PART=""
if [ "$SHOW_BRANCH" = "true" ] && [ -n "$BRANCH" ]; then
  BRANCH_PART=" │ 🌿 $BRANCH"
fi

# Worktree 部分
WORKTREE_PART=""
if [ "$SHOW_WORKTREE" = "true" ] && [ -n "$WORKTREE" ]; then
  if [ "$ONLY_SECONDARY_WORKTREE" = "true" ]; then
    if [ "$IS_WORKTREE" = "true" ]; then
      WORKTREE_PART=" │ 🌲 $WORKTREE"
    fi
  else
    WORKTREE_PART=" │ 🌲 $WORKTREE"
  fi
fi

# 账号展示部分
ACCOUNT_PART=""
if [ "$SHOW_ACCOUNT" = "true" ]; then
  ACC_VAL="${ACCOUNT:-$ACCOUNT_NAME}"
  # 回退到 antigravity-tools whoami(若索引未命中)
  if [ -z "$ACC_VAL" ] || [ "$ACC_VAL" = "null" ]; then
    if command -v antigravity-tools >/dev/null 2>&1; then
      RAW_WHOAMI=$(antigravity-tools whoami 2>/dev/null)
      while IFS= read -r line; do
        case "$line" in
          agy:*)
            parsed="${line#agy:}"
            parsed="${parsed// /}"
            [ "$parsed" != "none" ] && ACC_VAL="$parsed"
            break
            ;;
        esac
      done <<< "$RAW_WHOAMI"
    fi
  fi
  if [ -n "$ACC_VAL" ] && [ "$ACC_VAL" != "null" ]; then
    ACCOUNT_PART=" │ 👤 $ACC_VAL"
  fi
fi

# Agent 标识
AGENT_PART=""
if [ -n "$AGENT" ] && [ "$AGENT" != "null" ]; then
  AGENT_PART=" (🤖 $AGENT)"
fi

# Plan 等级指示(可选,默认隐藏)
PLAN_PART=""
if [ "$SHOW_PLAN_TIER" = "true" ] && [ -n "$PLAN_TIER" ] && [ "$PLAN_TIER" != "null" ]; then
  PLAN_PART=" │ 🏆 $PLAN_TIER"
fi

# 费用统计
COST_PART=""
if [ -n "$COST" ] && [ "$COST" != "0" ] && [ "$COST" != "null" ]; then
  fmt_num COST_FMT 6 "$COST"
  if [[ $COST_FMT == *.* ]]; then
    while [[ $COST_FMT == *0 ]]; do COST_FMT=${COST_FMT%0}; done
    COST_FMT=${COST_FMT%.}
  fi
  COST_PART=" │ 💰 $COST_FMT"
fi

# 额度百分比标签与数值
QUOTA_PARTS=()
if [ "$SHOW_REMAINING" = "true" ]; then
  VAL_7D="$SEVEN_DAY_REM"
  VAL_5H="$FIVE_HOUR_REM"
  if [ "$QUOTA_STYLE" = "en" ]; then
    L_7D="Weekly"
    L_5H="Session"
  else
    L_7D="周剩"
    L_5H="5h剩"
  fi
else
  VAL_7D="$SEVEN_DAY_USED"
  VAL_5H="$FIVE_HOUR_USED"
  if [ "$QUOTA_STYLE" = "en" ]; then
    L_7D="Weekly"
    L_5H="Session"
  else
    L_7D="周用"
    L_5H="5h用"
  fi
fi

# 周限额格式化
FMT_7D=""
if [ -n "$VAL_7D" ] && [ "$VAL_7D" != "null" ]; then
  fmt_num FMT_7D "$QUOTA_PRECISION" "$VAL_7D"
  RESET_TXT=""
  if [ "$SHOW_RESET_TIME" = "true" ] && [ -n "$SEVEN_DAY_RESET_STR" ] && [ "$SEVEN_DAY_RESET_STR" != "null" ]; then
    RESET_TXT=" ($SEVEN_DAY_RESET_STR)"
  fi
  QUOTA_PARTS+=("${L_7D}: ${FMT_7D}%${RESET_TXT}")
fi

# 5h 限额格式化
FMT_5H=""
if [ -n "$VAL_5H" ] && [ "$VAL_5H" != "null" ]; then
  fmt_num FMT_5H "$QUOTA_PRECISION" "$VAL_5H"
  RESET_TXT=""
  if [ "$SHOW_5H_RESET_TIME" = "true" ] && [ -n "$FIVE_HOUR_RESET_STR" ] && [ "$FIVE_HOUR_RESET_STR" != "null" ]; then
    RESET_TXT=" ($FIVE_HOUR_RESET_STR)"
  fi
  QUOTA_PARTS+=("${L_5H}: ${FMT_5H}%${RESET_TXT}")
fi

# 组装配额字符串
QUOTA_PART=""
if [ ${#QUOTA_PARTS[@]} -gt 0 ]; then
  QUOTA_STR=""
  for p in "${QUOTA_PARTS[@]}"; do
    if [ -z "$QUOTA_STR" ]; then
      QUOTA_STR="$p"
    else
      QUOTA_STR="$QUOTA_STR │ $p"
    fi
  done
  QUOTA_PART=" │ 📊 $QUOTA_STR"
elif [ "$SHOW_STATIC_LIMIT" = "true" ]; then
  if [ "$PLAN_TIER" = "Google AI Pro" ]; then
    QUOTA_PART=" │ ⚠️ Limit: 15 RPM / 1.5K RPD"
  elif [ "$PLAN_TIER" = "Google AI Studio" ]; then
    QUOTA_PART=" │ ⚠️ Limit: 360 RPM / 4M TPM"
  fi
fi

# ==============================================================================
# 速率 (TPS) 与本轮单轮用量 (Turn) 拼装
# ==============================================================================
SPEED_PART=""
if [ "$SHOW_SPEED" = "true" ]; then
  case "$SPEED_MODE" in
    out)
      [ "$TPS_OUT_FMT" != "—" ] && SPEED_PART=" │ ⚡ ${TPS_OUT_FMT}"
      ;;
    total)
      [ "$TPS_TOTAL_FMT" != "—" ] && SPEED_PART=" │ ⚡ Total: ${TPS_TOTAL_FMT}"
      ;;
    all|*)
      SPEED_ITEMS=()
      [ "$TPS_OUT_FMT" != "—" ] && SPEED_ITEMS+=("Out: ${TPS_OUT_FMT}")
      if [ "$SHOW_SPEED_IN" = "true" ] && [ "$TPS_IN_FMT" != "—" ]; then
        SPEED_ITEMS+=("In: ${TPS_IN_FMT}")
      fi
      [ "$TPS_TOTAL_FMT" != "—" ] && SPEED_ITEMS+=("Total: ${TPS_TOTAL_FMT}")
      if [ ${#SPEED_ITEMS[@]} -gt 0 ]; then
        SP_STR=""
        for item in "${SPEED_ITEMS[@]}"; do
          [ -z "$SP_STR" ] && SP_STR="$item" || SP_STR="$SP_STR │ $item"
        done
        SPEED_PART=" │ ⚡ $SP_STR"
      fi
      ;;
  esac
fi

TURN_PART=""
if [ "$SHOW_TURN_USAGE" = "true" ]; then
  if [ "$TURN_IN_RAW" -gt 0 ] 2>/dev/null || [ "$TURN_OUT_RAW" -gt 0 ] 2>/dev/null; then
    CACHE_TXT=""
    if [ "$SHOW_TURN_CACHE" = "true" ] && [ "$TURN_CACHE_RAW" -gt 0 ] 2>/dev/null; then
      CACHE_TXT=" (Cache: ${TURN_CACHE_FMT})"
    fi
    TURN_PART=" │ 🔄 Turn: In ${TURN_IN_FMT} / Out ${TURN_OUT_FMT}${CACHE_TXT}"
  fi
fi

# ==============================================================================
# 输出排版渲染 (Render output based on LAYOUT_MODE)
# ==============================================================================
case "$LAYOUT_MODE" in
  double)
    # 双行推荐模式:上行身份与位置状态,下行容量、速率、单轮用量与配额指标
    printf "🤖 %s%s%s%s%s%s%s%s\n" \
      "$MODEL" "$ACCOUNT_PART" "$DIR_PART" "$BRANCH_PART" "$WORKTREE_PART" "$AGENT_PART" "$PLAN_PART" "$COST_PART"
    printf "🧠 Context: %s%% / %s │ In: %s │ Out: %s%s%s%s\n" \
      "$CONTEXT_FMT" "$CONTEXT_SIZE_FMT" "$IN_TOKENS_FMT" "$OUT_TOKENS_FMT" "$SPEED_PART" "$TURN_PART" "$QUOTA_PART"
    ;;
  triple)
    # 三行模式
    printf "🤖 %s%s%s%s\n" \
      "$MODEL" "$ACCOUNT_PART" "$PLAN_PART" "$COST_PART"
    printf "📁 %s%s%s%s\n" \
      "$DIR_DISPLAY" "$BRANCH_PART" "$WORKTREE_PART" "$AGENT_PART"
    printf "🧠 Context: %s%% / %s │ In: %s │ Out: %s%s%s%s\n" \
      "$CONTEXT_FMT" "$CONTEXT_SIZE_FMT" "$IN_TOKENS_FMT" "$OUT_TOKENS_FMT" "$SPEED_PART" "$TURN_PART" "$QUOTA_PART"
    ;;
  dashboard|quad|claude)
    # 四行看板模式 (大屏全景看板布局)
    Q5_TXT=""
    [ -n "$FMT_5H" ] && Q5_TXT=" │ ⚡ ${L_5H}: ${FMT_5H}%"
    Q7_TXT=""
    [ -n "$FMT_7D" ] && Q7_TXT=" │ 📅 ${L_7D}: ${FMT_7D}%"
    RESET_TXT=""
    if [ -n "$SEVEN_DAY_RESET_STR" ] && [ "$SEVEN_DAY_RESET_STR" != "null" ]; then
      if [ "$QUOTA_STYLE" = "en" ]; then
        RESET_TXT=" │ ⏱️ Reset: ${SEVEN_DAY_RESET_STR}"
      else
        RESET_TXT=" │ ⏱️ 重置: ${SEVEN_DAY_RESET_STR}"
      fi
    fi

    # Line 1: 模型与账号 (及5h限额)
    printf "🤖 Model: %s │ 👤 %s%s\n" "$MODEL" "${ACC_VAL:-Unknown}" "$Q5_TXT"
    # Line 2: 上下文容量与Token用量 (及周限额)
    printf "🧠 Context: %s%% / %s │ In: %s │ Out: %s%s\n" "$CONTEXT_FMT" "$CONTEXT_SIZE_FMT" "$IN_TOKENS_FMT" "$OUT_TOKENS_FMT" "$Q7_TXT"
    # Line 3: 目录、分支、Worktree与重置倒计时 (仅图标无冗余文字)
    printf "📁 %s │ 🌿 %s │ 🌲 %s%s\n" "$DIR_DISPLAY" "${BRANCH:-HEAD}" "${WORKTREE:-main}" "$RESET_TXT"
    # Line 4: 速率、本轮用量与费用
    L4_ITEMS=()
    [ -n "$SPEED_PART" ] && L4_ITEMS+=("${SPEED_PART# │ }")
    [ -n "$TURN_PART" ] && L4_ITEMS+=("${TURN_PART# │ }")
    [ -n "$COST_PART" ] && L4_ITEMS+=("${COST_PART# │ }")
    [ -n "$PLAN_PART" ] && L4_ITEMS+=("${PLAN_PART# │ }")
    if [ ${#L4_ITEMS[@]} -eq 0 ]; then
      if [ "$QUOTA_STYLE" = "en" ]; then
        printf "💰 Cost: 0\n"
      else
        printf "💰 费用: 0\n"
      fi
    else
      L4_STR=""
      for it in "${L4_ITEMS[@]}"; do
        [ -z "$L4_STR" ] && L4_STR="$it" || L4_STR="$L4_STR │ $it"
      done
      printf "%s\n" "$L4_STR"
    fi
    ;;
  single|*)
    # 单行模式
    printf "🤖 %s%s%s%s%s%s │ 🧠 Context: %s%% / %s │ In: %s │ Out: %s%s%s%s%s%s\n" \
      "$MODEL" "$ACCOUNT_PART" "$DIR_PART" "$BRANCH_PART" "$WORKTREE_PART" "$AGENT_PART" \
      "$CONTEXT_FMT" "$CONTEXT_SIZE_FMT" "$IN_TOKENS_FMT" "$OUT_TOKENS_FMT" \
      "$SPEED_PART" "$TURN_PART" "$PLAN_PART" "$COST_PART" "$QUOTA_PART"
    ;;
esac

② 賦予執行權限

chmod +x ~/.gemini/antigravity-cli/agy-statusline.sh

③ 在設定中掛載

開啟 ~/.gemini/antigravity-cli/settings.json,在最外層 JSON 結構中增加 statusLine 設定:

{
  "statusLine": {
    "type": "command",
    "command": "~/.gemini/antigravity-cli/agy-statusline.sh",
    "enabled": true
  }
}

重新進入 agy,終端底部即可常駐高顏值、低開銷的即時監控指示條。


四、 常用指令與快捷鍵速查

1. CLI 終端核心命令

命令或入口 用途說明
agy 啟動互動式 Agent 終端會話
agy --version / -v 檢視當前安裝的 CLI 版本號
agy help 開啟所有可用子命令與參數幫助
agy -c / --continue 恢復最近一次的歷史會話
agy --conversation <ID> 精確恢復指定 ID 的歷史會話
agy --mode plan / --mode accept-edits 啟動規劃模式或全自動程式碼修改模式
agy --effort low|medium|high|max 動態調節大模型思考強度(Chain-of-Thought)
agy -p "任务描述" / --print 非互動式單次執行並輸出結果(適合整合進流水線)
agy --model <名称> / --agent <名称> 啟動時顯式指定底座推理模型或專屬 Subagent
agy --add-dir <路径> / --sandbox 為當前會話追加工作區目錄,或強制啟用沙箱隔離模式
agy --dangerously-skip-permissions 跳過工具與終端命令確認(需自行把控安全邊界)
agy remote-control 管理遠端控制後臺守護程序(啟動、狀態檢視、終止)
agy models / agy agents 列出當前帳號下所有可用的推理模型與預置代理
agy plugin / agy plugins 管理外掛生態(安裝、解除安裝、更新、啟用與停用)
agy mcp list / add / remove 檢視與設定標準 Model Context Protocol(MCP)伺服器
agy update 檢查並原地熱升級 CLI 至最新穩定版本

2. 常用斜槓命令(Slash Commands)

斜槓命令 功能與使用場景
/config 開啟全屏互動式設定面板(快捷檢視與調整當前全部參數)
/usage 快速檢視當前訂閱週期內的 Token 用量與各視窗配額消耗
/model 喚起模型切換器,跨會話切換預設推理模型(如 Gemini 4 Argon 或 Claude 5.5)
/goal 開啟持久目標模式,Agent 將自主拆解並連續執行直至全部驗收通過,中途不打斷
/permissions 動態調整權限等級(request-review 人工確認、always-proceed 全自動、strict 嚴格模式)
/schedule 為 Agent 設定定時喚醒或一次性定時任務
/diff 開啟互動式程式碼 Diff 審查器,在提交前複核 Agent 的全部修改
/rewind / /undo 將會話歷史與程式碼修改狀態一鍵回滾到上一個安全檢查點
/fork 從當前會話的指定檢查點分叉出一個全新的獨立分支工作區
/tasks 即時檢視、審查日誌或強行終止當前後臺執行的非同步任務
/mcp 喚起 MCP 管理器,掛載外部檔案系統、資料庫或第三方 API 工具源
/exit / /clear 安全退出當前會話 / 清空當前視口對話流

3. 高頻操作技巧(Quick Tips)

快捷技巧 觸發方式 功能與收益
檔案自動補全 輸入 @ 觸發 即時聯想並補全當前程式碼庫中的檔案與目錄絕對/相對路徑
快速清屏 連按兩次 Esc (Esc Esc) 非推流狀態下一鍵清空當前輸入框
Shell 直通執行 輸入框以 ! 開頭 (如 !git status) 直接在當前終端上下文中執行原生命令,無需跳出會話
即時指令幫助 輸入 ? 回車 快速列出全部可用的斜槓命令與操作手冊
精簡工具呼叫日誌 在 /config 中將 verbosity 設為 low 隱藏大量的細微讀寫檔案日誌,讓終端介面保持極簡清爽

4. 鍵盤快捷鍵對映(Keybindings)

自定義快捷鍵位於 ~/.gemini/antigravity-cli/keybindings.json,也可在終端輸入 /keybindings 開啟互動式編輯器。常用快捷鍵如下:

快捷鍵 功能說明
Ctrl + L 清空當前終端視口輸出
Enter 提交當前 Prompt 或確認所選操作
Ctrl + C / Esc 中斷當前正在推流的回答、關閉彈窗或取消當前輸入
Ctrl + D 安全終止並退出當前 CLI 會話
Ctrl + Z 將 CLI 會話掛起至後臺執行
y / n 快速批准 / 拒絕 Agent 提議執行的終端命令
e 在首選外部編輯器中二次編輯即將執行的終端命令
Alt + Enter / Ctrl + J 在多行 Prompt 輸入框中換行(不觸發提交)
Ctrl + Home / Ctrl + End 視口游標快速跳轉至頂部 / 底部
PgUp / PgDn 快速向上 / 向下翻頁滾動會話記錄