import json, sys, datetime, os, subprocess, urllib.parse
# Source: https://gist.github.com/it3xl/3d7b91d6b8fa3c790fdbcfc0e8d0321b
# Force UTF-8 on stdin/stdout for Windows compatibility
for _stream in (sys.stdin, sys.stdout):
try:
_stream.reconfigure(encoding='utf-8', errors='replace')
except Exception:
pass
def fmt_num(n):
n = int(n)
if n >= 1_000_000:
return f"{n / 1_000_000:.1f}".replace('.0', '') + "M"
if n >= 1000:
return f"{int(n / 1000)}k"
return str(n)
# Colors
R = '\033[0m'
G = '\033[32m' # green - user
C = '\033[36m' # cyan - model, branch, plan tier
DC = '\033[38;5;66m' # dim cyan - git status
Y = '\033[33m' # yellow - ctx
M = '\033[35m' # magenta - path
TM = '\033[97m' # bright white - time
LD = '\033[91m' # bright red - day limit pct
DLD = '\033[38;5;174m' # muted red - day reset time
LW = '\033[38;5;220m' # gold yellow - week limit pct
DLW = '\033[38;5;179m' # dim yellow - week reset time
try:
data = json.load(sys.stdin)
except Exception:
data = {}
# Model
model = (data.get('model') or {}).get('display_name') or data.get('model_name')
if not model:
try:
settings_path = os.path.join(os.path.expanduser('~'), '.gemini', 'antigravity-cli', 'settings.json')
with open(settings_path, 'r', encoding='utf-8') as f:
model = json.load(f).get('model')
except Exception:
pass
if not model:
model = os.environ.get('AGY_MODEL', '?model')
model_lower = model.lower()
# Directory
ws = data.get('workspace') or {}
cwd = ws.get('project_dir') or data.get('cwd') or ws.get('current_dir') or os.getcwd()
if cwd.startswith('file://'):
cwd = urllib.parse.unquote(cwd[7:])
if os.name == 'nt' and cwd.startswith('/'):
cwd = cwd[1:]
# Context window
ctx_obj = data.get('context_window') or {}
used_pct = ctx_obj.get('used_percentage')
ctx_size = ctx_obj.get('context_window_size')
remaining_pct = ctx_obj.get('remaining_percentage')
if used_pct is not None:
ctx_str = f'ctx:{round(used_pct)}%'
if remaining_pct is not None and ctx_size:
left = int(ctx_size * remaining_pct / 100)
ctx_str += f' ({fmt_num(left)} of {fmt_num(ctx_size)})'
else:
ctx_str = 'ctx:?'
# --- QUOTA DIAGNOSTIC LOGIC ---
fh_used = None
fh_reset_str = None
quota_status = 'ok'
pct_text = None
wk_used = None
wk_reset_str = None
wk_status = 'ok'
wk_pct_text = None
quota_obj = data.get('quota')
# --- SYNC ACROSS SESSIONS ---
SHARED_FILE = os.path.expanduser('~/.gemini/shared_quota_v2.json')
shared_quota = {}
try:
if os.path.exists(SHARED_FILE):
with open(SHARED_FILE, 'r', encoding='utf-8') as f:
shared_quota = json.load(f)
except Exception:
pass
if quota_obj is None:
quota_obj = shared_quota if shared_quota else None
else:
merged = {}
all_keys = set(quota_obj.keys()).union(shared_quota.keys())
for k in all_keys:
q1 = quota_obj.get(k)
q2 = shared_quota.get(k)
if not q1:
merged[k] = q2
elif not q2:
merged[k] = q1
else:
rt1 = q1.get('reset_time', '')
rt2 = q2.get('reset_time', '')
if rt1 != rt2:
merged[k] = q1 if rt1 > rt2 else q2
else:
try:
rf1 = float(q1.get('remaining_fraction', 1.0))
except Exception:
rf1 = 1.0
try:
rf2 = float(q2.get('remaining_fraction', 1.0))
except Exception:
rf2 = 1.0
merged[k] = q1 if rf1 <= rf2 else q2
if merged != shared_quota:
try:
tmp_file = SHARED_FILE + f".tmp.{os.getpid()}"
with open(tmp_file, 'w', encoding='utf-8') as f:
json.dump(merged, f)
os.replace(tmp_file, SHARED_FILE)
except Exception:
pass
quota_obj = merged
if quota_obj is None:
quota_status = 'missing_obj' # d-noquota
wk_status = 'missing_obj' # w-noquota
else:
is_gemini = 'gemini' in model_lower
key_5h = 'gemini-5h' if is_gemini else '3p-5h'
key_wk = 'gemini-weekly' if is_gemini else '3p-weekly'
q = quota_obj.get(key_5h)
qw = quota_obj.get(key_wk)
if not q:
quota_status = 'missing_model' # d-?model
else:
if 'remaining_fraction' in q:
rem_frac = q['remaining_fraction']
try:
fh_used = (1.0 - float(rem_frac)) * 100.0
pct_text = f'd-{round(fh_used)}%'
except (ValueError, TypeError):
quota_status = 'math_err' # d-err
pct_text = 'd-err'
else:
quota_status = 'missing_fraction' # d-??%
pct_text = 'd-??%'
fh_reset_str = q.get('reset_time')
if not fh_reset_str:
if quota_status == 'ok':
quota_status = 'missing_time'
if not qw:
wk_status = 'missing_model' # w-?model
else:
if 'remaining_fraction' in qw:
wk_rem_frac = qw['remaining_fraction']
try:
wk_used = (1.0 - float(wk_rem_frac)) * 100.0
wk_pct_text = f'w-{round(wk_used)}%'
except (ValueError, TypeError):
wk_status = 'math_err' # w-err
wk_pct_text = 'w-err'
else:
wk_status = 'missing_fraction' # w-??%
wk_pct_text = 'w-??%'
wk_reset_str = qw.get('reset_time')
if not wk_reset_str:
if wk_status == 'ok':
wk_status = 'missing_time'
def fmt_day_limit(status, pct_txt, reset_str):
if status == 'missing_obj':
return f'{LD}d-noquota{R}'
if status == 'missing_model':
return f'{LD}d-?model{R}'
if status == 'math_err':
return f'{LD}d-err{R}'
if status == 'missing_time':
return f'{LD}{pct_txt} ??:??{R}'
if not reset_str:
return f'{LD}{pct_txt}{R}'
try:
reset_str_fixed = reset_str.replace('Z', '+00:00')
reset_dt = datetime.datetime.fromisoformat(reset_str_fixed).astimezone()
now = datetime.datetime.now(datetime.timezone.utc)
diff = reset_dt - now
if diff.total_seconds() > 0:
h, m = divmod(int(diff.total_seconds() // 60), 60)
dur = f'{h}h {m}m' if h else f'{m}m'
return f'{LD}{pct_txt}{R} {DLD}{reset_dt.strftime("%H:%M")}{R} {LD}{dur}{R}'
else:
return f'{LD}{pct_txt}{R}' # Keep showing the last known usage
except Exception:
return f'{LD}{pct_txt} ?format{R}'
def fmt_week_limit(status, pct_txt, reset_str):
if status == 'missing_obj':
return f'{LW}w-noquota{R}'
if status == 'missing_model':
return f'{LW}w-?model{R}'
if status == 'math_err':
return f'{LW}w-err{R}'
if status == 'missing_time':
return f'{LW}{pct_txt} ??:??{R}'
if not reset_str:
return f'{LW}{pct_txt}{R}'
try:
reset_str_fixed = reset_str.replace('Z', '+00:00')
reset_dt = datetime.datetime.fromisoformat(reset_str_fixed).astimezone()
now = datetime.datetime.now(datetime.timezone.utc)
diff = reset_dt - now
if diff.total_seconds() > 0:
d = diff.days
h, m = divmod(int(diff.seconds // 60), 60)
if d > 0:
dur = f'{d}d {h}h'
else:
dur = f'{h}h {m}m' if h else f'{m}m'
return f'{LW}{pct_txt}{R} {DLW}{reset_dt.strftime("%a %H:%M")}{R} {LW}{dur}{R}'
else:
return f'{LW}{pct_txt}{R}'
except Exception:
return f'{LW}{pct_txt} ?format{R}'
day_str = f" {fmt_day_limit(quota_status, pct_text, fh_reset_str)}"
week_str = f" {fmt_week_limit(wk_status, wk_pct_text, wk_reset_str)}"
# Git info (timeout clamped to 1s to prevent hanging prompts)
try:
branch = subprocess.check_output(
['git', '-C', cwd, 'branch', '--show-current'],
stderr=subprocess.DEVNULL, timeout=1
).decode('utf-8', 'replace').strip() or '?'
status_out = subprocess.check_output(
['git', '-C', cwd, 'status', '--porcelain'],
stderr=subprocess.DEVNULL, timeout=1
).decode('utf-8', 'replace').strip()
if status_out:
lines = status_out.splitlines()
def conflict(l): return 'U' in l[:2] or l[:2] in ('AA', 'DD')
conflicted = sum(1 for l in lines if conflict(l))
staged = sum(1 for l in lines if not conflict(l) and l[0] in 'MADRCT')
modified = sum(1 for l in lines if not conflict(l) and l[1] in 'MDT')
untracked = sum(1 for l in lines if l.startswith('??'))
parts = []
if conflicted: parts.append(f'!{conflicted}')
if staged: parts.append(f'+{staged}')
if modified: parts.append(f'~{modified}')
if untracked: parts.append(f'?{untracked}')
git_status = ' '.join(parts) if parts else 'clean'
else:
git_status = 'clean'
except Exception:
branch = ''
git_status = ''
now_str = datetime.datetime.now().strftime('%H:%M')
account = data.get('email', '')
plan_tier = data.get('plan_tier', '')
home = os.path.expanduser('~')
if os.name == 'nt':
home = home.replace('\\', '/')
cwd = cwd.replace('\\', '/')
# Check directory boundary to avoid matching sibling folders (e.g. ~/ann vs ~/annette)
low_cwd, low_home = cwd.lower(), home.lower().rstrip('/')
if low_cwd == low_home:
display_cwd = '~'
elif low_cwd.startswith(low_home + '/'):
display_cwd = '~' + cwd[len(low_home):]
else:
display_cwd = cwd
conv_id = data.get('conversation_id')
conv_name = ""
if conv_id:
history_path = os.path.join(os.path.expanduser('~'), '.gemini', 'antigravity-cli', 'history.jsonl')
try:
if os.path.exists(history_path):
with open(history_path, 'r', encoding='utf-8') as f:
for line in f:
if conv_id in line and '/rename ' in line:
try:
item = json.loads(line)
if item.get('conversationId') == conv_id:
display = item.get('display', '')
if display.startswith('/rename '):
conv_name = display[8:].strip()
except Exception:
pass
except Exception:
pass
name_str = f' {M}{conv_name}{R}' if conv_name else ''
path_part = f'{M}{display_cwd}{R}'
branch_str = f' {C}{branch}{R}' if branch else ''
gs_str = (f' {DC}{git_status}{R}' if git_status and git_status != 'clean' else f' {DC}clean{R}') if branch else ''
account_str = f' {G}{account}{R}' if account else ''
plan_str = f' {C}{plan_tier}{R}' if plan_tier else ''
print(f'{TM}{now_str}{R}{name_str} {C}{model}{R} {Y}{ctx_str}{R}{day_str}{week_str} {path_part}{branch_str}{gs_str}{account_str}{plan_str}')
Last active
July 15, 2026 20:45
-
-
Save it3xl/3d7b91d6b8fa3c790fdbcfc0e8d0321b to your computer and use it in GitHub Desktop.
Antigravity CLI Custom Status Line Guide
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment