目录
  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(终端交互式智能体)
  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 快速向上 / 向下翻页滚动会话记录