用 Claude Code 跑久了,最怕兩件事:context 快滿了卻不知道(突然 auto-compact,思路被打斷),和這個 session 到底花了多少錢(帳單來了才驚覺)。
Claude Code 支援自訂 status line——終端機底部那一行狀態。我用一個 235 行的 Python 腳本,讓它即時顯示:context 用量百分比(彩色進度條)、這個 session 的花費、執行時間、改了幾行。這篇拆解這個 status line 怎麼運作、怎麼設定。
status line 是什麼
Claude Code 會在每次更新時,把 session 的狀態資料以 JSON 從 stdin 傳給你指定的程式,程式印出一行字,就成為終端機底部的狀態列。
設定在 settings.json:
{
"statusLine": {
"type": "command",
"command": "python .claude/scripts/context-monitor.py"
}
}
每次狀態更新,Claude Code 就跑一次這個 Python,把結果顯示在底部。
Claude Code 傳進來的資料
status line 程式從 stdin 收到的 JSON:
data = json.load(sys.stdin)
model_name = data.get('model', {}).get('display_name', 'Claude')
workspace = data.get('workspace', {}) # current_dir, project_dir
transcript_path = data.get('transcript_path', '') # 對話紀錄檔路徑
cost_data = data.get('cost', {}) # 花費、時間、行數
關鍵欄位:
model.display_name— 當前模型workspace— 目前目錄 / 專案目錄transcript_path— 對話紀錄檔(context 用量的關鍵)cost— 花費、執行時間、增刪行數
核心:從 transcript 算 context 用量
Claude Code 沒有直接傳 context 百分比,但有傳 transcript_path——對話紀錄的 JSONL 檔。每一行是一筆訊息,裡面有 token 用量。解析它就能算出 context 用了多少:
def parse_context_from_transcript(transcript_path):
with open(transcript_path, 'r', encoding='utf-8', errors='replace') as f:
lines = f.readlines()
# 只看最後 15 行(最新狀態)
recent_lines = lines[-15:] if len(lines) > 15 else lines
for line in reversed(recent_lines):
data = json.loads(line.strip())
# 方法 1:從 assistant 訊息的 usage 算
if data.get('type') == 'assistant':
usage = data.get('message', {}).get('usage', {})
if usage:
total = (usage.get('input_tokens', 0)
+ usage.get('cache_read_input_tokens', 0)
+ usage.get('cache_creation_input_tokens', 0))
if total > 0:
percent = min(100, (total / 200000) * 100)
return {'percent': percent, 'tokens': total, 'method': 'usage'}
關鍵洞察:context 用量 = input_tokens + cache_read + cache_creation。這三個加起來就是這一輪送進模型的總 token,除以 context window(這裡假設 200k)就是百分比。
從最後一行往回找
for line in reversed(recent_lines) ——從最新的訊息往回找第一個有 usage 的。因為最新一輪的 token 數才反映當前 context 狀態,舊的訊息 usage 是歷史值。
第二種來源:系統警告
# 方法 2:解析系統的 context 警告訊息
elif data.get('type') == 'system_message':
content = data.get('content', '')
match = re.search(r'Context left until auto-compact: (\d+)%', content)
if match:
return {'percent': 100 - int(match.group(1)), 'warning': 'auto-compact'}
Claude Code 接近 auto-compact 時會發系統訊息,直接抓那個百分比更準。兩種方法都試,哪個有就用哪個。
視覺化:彩色進度條 + 警示
光有數字不夠,要一眼看出「危險程度」。用顏色 + 進度條:
def get_context_display(context_info):
percent = context_info.get('percent', 0)
# 依用量決定顏色和圖示
if percent >= 95:
icon, color, alert = "🚨", "\033[31;1m", "CRIT" # 閃紅
elif percent >= 90:
icon, color, alert = "🔴", "\033[31m", "HIGH" # 紅
elif percent >= 75:
icon, color, alert = "🟠", "\033[91m", "" # 橙
elif percent >= 50:
icon, color, alert = "🟡", "\033[33m", "" # 黃
else:
icon, color, alert = "🟢", "\033[32m", "" # 綠
# 8 格進度條
segments = 8
filled = int((percent / 100) * segments)
bar = "█" * filled + "▁" * (segments - filled)
return f"{icon}{color}{bar}\033[0m {percent:.0f}%{alert_str}"
效果(終端機底部):
[Claude] 📁 blog 🧠 🟡████▁▁▁▁ 52% | 💰 $0.34 ⏱ 12m 📝 +156
- 🟢 0-50% 綠(安全)
- 🟡 50-75% 黃(注意)
- 🟠 75-90% 橙(該考慮收尾)
- 🔴 90-95% 紅(快滿)
- 🚨 95%+ 閃紅 + CRIT(馬上要 compact)
8 格進度條 + 顏色 + emoji 三重編碼,餘光掃一眼就知道還剩多少 context,不用停下來算。
Session 統計:花費、時間、行數
cost 資料裡有這個 session 的累計統計,也做進狀態列:
def get_session_metrics(cost_data):
metrics = []
# 花費(依金額變色)
cost_usd = cost_data.get('total_cost_usd', 0)
if cost_usd > 0:
if cost_usd >= 0.10: cost_color = "\033[31m" # 紅(貴)
elif cost_usd >= 0.05: cost_color = "\033[33m" # 黃
else: cost_color = "\033[32m" # 綠(便宜)
cost_str = f"{cost_usd*100:.0f}¢" if cost_usd < 0.01 else f"${cost_usd:.3f}"
metrics.append(f"{cost_color}💰 {cost_str}\033[0m")
# 執行時間(超過 30 分鐘變黃)
duration_ms = cost_data.get('total_duration_ms', 0)
if duration_ms > 0:
minutes = duration_ms / 60000
duration_str = f"{duration_ms//1000}s" if minutes < 1 else f"{minutes:.0f}m"
metrics.append(f"⏱ {duration_str}")
# 增刪行數(淨值,正綠負紅)
net = cost_data.get('total_lines_added', 0) - cost_data.get('total_lines_removed', 0)
sign = "+" if net >= 0 else ""
metrics.append(f"📝 {sign}{net}")
return " | " + " ".join(metrics) if metrics else ""
- 💰 花費:< 5¢ 綠、5-10¢ 黃、> 10¢ 紅——一眼知道這個 session 燒了多少
- ⏱ 時間:超過 30 分鐘變黃,提醒這是長 session
- 📝 淨行數:增刪相抵的淨值,正綠負紅
組合 + 防呆
def main():
try:
data = json.load(sys.stdin)
# ... 組合各部分
status_line = f"{model_display} 📁 {directory} 🧠 {context_display}{session_metrics}"
print(status_line)
except Exception as e:
# 任何錯誤都要 fallback,不能讓狀態列整個消失
print(f"[Claude] 📁 {os.path.basename(os.getcwd())} 🧠 [Error: {str(e)[:20]}]")
關鍵:整個包在 try/except 裡。status line 每次更新都跑,如果某次 transcript 格式怪、JSON parse 失敗,不能讓狀態列整個消失或噴錯——fallback 印一個最小狀態。status line 壞掉不該影響工作。
連 model 名稱也跟著 context 變色:
# context 越滿,model 名稱越紅
if percent >= 90: model_color = "\033[31m" # 紅
elif percent >= 75: model_color = "\033[33m" # 黃
else: model_color = "\033[32m" # 綠
整行的視覺重心隨危險程度移動。
為什麼這值得做
Claude Code 內建會在快滿時提示,但那是「事件式」的——跳出來才知道。status line 是「持續可見」的:
| 沒有 status line | 有 status line |
|---|---|
| context 突然 auto-compact,思路被打斷 | 隨時看到 % ,75% 就開始準備收尾 |
| session 結束才知道花多少 | 即時看到 💰,貴了自己踩煞車 |
| 不知道改了多少行 | 📝 淨行數一直在眼前 |
最有價值的是主動收尾:看到 🟠 75%,就知道該把當前任務做個段落、必要時開新 session,而不是衝到 🚨 被動 compact。
怎麼設定你自己的
- 把腳本放在
.claude/scripts/context-monitor.py(或任何路徑) settings.json加:
{
"statusLine": {
"type": "command",
"command": "python .claude/scripts/context-monitor.py"
}
}
- 重點實作:
- 從 stdin 讀 JSON,拿
transcript_path - 讀 transcript 最後幾行,從
usage算input + cache_read + cache_creation - 除以你的 context window(200k)算百分比
- 用 ANSI 顏色碼 + emoji 視覺化
- 整個包 try/except,壞掉要有 fallback
- 從 stdin 讀 JSON,拿
注意事項
- 效能:status line 更新頻繁,腳本要快。這個版本只讀 transcript 最後 15 行,不讀整個檔——大檔案也快
- context window 數字:腳本寫死 200k,不同模型不同,要自己對應
- ANSI 顏色:在不支援的終端機會變亂碼,但大部分現代終端機都支援
結語
status line 是 Claude Code 最被低估的客製點。它不改變 AI 的行為,但改變你的行為——當 context 用量、花費一直在眼前,你會更早收尾、更注意成本,而不是等系統提示或帳單來了才反應。
235 行 Python,核心其實就一件事:從 transcript 算出 context 百分比,用顏色讓你一眼看懂。如果你常跑長 session,這個投資很值——它把「看不見的 context 消耗」變成「隨時可見的儀表板」。