Appearance
Status Line:自定义底部状态栏
Status Line 是 Claude Code 底部可以完全自定义的信息栏。它运行你配置的任何 shell 脚本,把 JSON 会话数据传入脚本,把脚本输出内容显示出来。
常见用途:
- 实时监控上下文窗口使用量(避免突然被压缩)
- 追踪会话费用
- 多会话并行时显示当前会话信息
- 始终显示 git 分支和状态
快速上手
方法一(推荐):用 /statusline 命令自动生成
直接描述你想显示什么,Claude Code 会自动生成脚本文件并更新 settings:
text
/statusline show model name and context percentage with a progress bar
/statusline 显示模型名、目录、git 分支和上下文进度条方法二:手动配置
在 ~/.claude/settings.json(或项目设置)中添加:
json
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh",
"padding": 2
}
}或者直接内联命令(用 jq 解析 JSON):
json
{
"statusLine": {
"type": "command",
"command": "jq -r '\"[\\(.model.display_name)] \\(.context_window.used_percentage // 0)% context\"'"
}
}删除 Status Line:运行 /statusline delete(或 clear/remove),或手动删除 settings.json 里的 statusLine 字段。
工作原理
Claude Code 运行你的脚本,通过 stdin 传入 JSON 会话数据,显示脚本打印到 stdout 的内容。
- 更新时机:每次 Claude 回复后、权限模式变更时、vim 模式切换时(有 300ms 防抖)
- 多行输出:每行 echo 对应一行显示
- 颜色:支持 ANSI 转义码
- 链接:支持 OSC 8 转义序列(可点击链接,需终端支持)
- Status Line 在本地运行,不消耗 API token
可用数据字段
脚本通过 stdin 接收的 JSON:
| 字段 | 说明 |
|---|---|
model.id, model.display_name | 当前模型 ID 和显示名称 |
workspace.current_dir | 当前工作目录(推荐用此字段) |
workspace.project_dir | Claude Code 启动时的目录(可能与 cwd 不同) |
cwd | 当前工作目录(同 workspace.current_dir) |
cost.total_cost_usd | 会话总费用(美元) |
cost.total_duration_ms | 会话总时长(毫秒) |
cost.total_api_duration_ms | 等待 API 响应的总时长(毫秒) |
cost.total_lines_added/removed | 代码增删行数 |
context_window.used_percentage | 上下文窗口使用百分比(预计算好的) |
context_window.remaining_percentage | 剩余百分比 |
context_window.context_window_size | 最大上下文大小(token 数,默认 200000,1M 上下文时为 1000000) |
context_window.total_input_tokens | 会话累计输入 token |
context_window.total_output_tokens | 会话累计输出 token |
context_window.current_usage | 最近一次 API 调用的 token 明细(见下方) |
exceeds_200k_tokens | 是否超过 20 万 token(固定阈值) |
rate_limits.five_hour.used_percentage | 5 小时限额使用百分比(0-100) |
rate_limits.seven_day.used_percentage | 7 天限额使用百分比(0-100) |
rate_limits.five_hour.resets_at | 5 小时窗口重置时间(Unix 秒) |
session_id | 会话唯一标识 |
transcript_path | 对话记录文件路径 |
version | Claude Code 版本 |
output_style.name | 当前输出风格名称 |
vim.mode | Vim 模式(NORMAL/INSERT,仅启用 vim 模式时存在) |
agent.name | Agent 名称(使用 --agent 时存在) |
worktree.name/path/branch | Worktree 信息(worktree 会话时存在) |
current_usage 字段说明
json
{
"input_tokens": 8500,
"output_tokens": 1200,
"cache_creation_input_tokens": 5000,
"cache_read_input_tokens": 2000
}used_percentage 只基于输入 token 计算:input_tokens + cache_creation_input_tokens + cache_read_input_tokens,不含 output_tokens。
实用示例
以下示例保存为脚本后需要 chmod +x 赋权,再在 settings.json 中配置路径。
上下文进度条(Bash)
bash
#!/bin/bash
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
BAR_WIDTH=10
FILLED=$((PCT * BAR_WIDTH / 100))
EMPTY=$((BAR_WIDTH - FILLED))
BAR=""
[ "$FILLED" -gt 0 ] && printf -v FILL "%${FILLED}s" && BAR="${FILL// /▓}"
[ "$EMPTY" -gt 0 ] && printf -v PAD "%${EMPTY}s" && BAR="${BAR}${PAD// /░}"
echo "[$MODEL] $BAR $PCT%"Git 状态 + 颜色(Python)
python
#!/usr/bin/env python3
import json, sys, subprocess, os
data = json.load(sys.stdin)
model = data['model']['display_name']
directory = os.path.basename(data['workspace']['current_dir'])
GREEN, YELLOW, RESET = '\033[32m', '\033[33m', '\033[0m'
try:
subprocess.check_output(['git', 'rev-parse', '--git-dir'], stderr=subprocess.DEVNULL)
branch = subprocess.check_output(['git', 'branch', '--show-current'], text=True).strip()
staged_output = subprocess.check_output(['git', 'diff', '--cached', '--numstat'], text=True).strip()
modified_output = subprocess.check_output(['git', 'diff', '--numstat'], text=True).strip()
staged = len(staged_output.split('\n')) if staged_output else 0
modified = len(modified_output.split('\n')) if modified_output else 0
git_status = f"{GREEN}+{staged}{RESET}" if staged else ""
git_status += f"{YELLOW}~{modified}{RESET}" if modified else ""
print(f"[{model}] 📁 {directory} | 🌿 {branch} {git_status}")
except:
print(f"[{model}] 📁 {directory}")费用 + 时长(Node.js)
javascript
#!/usr/bin/env node
let input = '';
process.stdin.on('data', chunk => input += chunk);
process.stdin.on('end', () => {
const data = JSON.parse(input);
const model = data.model.display_name;
const cost = data.cost?.total_cost_usd || 0;
const durationMs = data.cost?.total_duration_ms || 0;
const mins = Math.floor(durationMs / 60000);
const secs = Math.floor((durationMs % 60000) / 1000);
console.log(`[${model}] 💰 $${cost.toFixed(2)} | ⏱️ ${mins}m ${secs}s`);
});双行状态栏(颜色进度条 + git)
bash
#!/bin/bash
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')
CYAN='\033[36m'; GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; RESET='\033[0m'
if [ "$PCT" -ge 90 ]; then BAR_COLOR="$RED"
elif [ "$PCT" -ge 70 ]; then BAR_COLOR="$YELLOW"
else BAR_COLOR="$GREEN"; fi
FILLED=$((PCT / 10)); EMPTY=$((10 - FILLED))
printf -v FILL "%${FILLED}s"; printf -v PAD "%${EMPTY}s"
BAR="${FILL// /█}${PAD// /░}"
MINS=$((DURATION_MS / 60000)); SECS=$(((DURATION_MS % 60000) / 1000))
BRANCH=""
git rev-parse --git-dir > /dev/null 2>&1 && BRANCH=" | 🌿 $(git branch --show-current 2>/dev/null)"
echo -e "${CYAN}[$MODEL]${RESET} 📁 ${DIR##*/}$BRANCH"
COST_FMT=$(printf '$%.2f' "$COST")
echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}% | ${YELLOW}${COST_FMT}${RESET} | ⏱️ ${MINS}m ${SECS}s"Windows PowerShell 配置
json
{
"statusLine": {
"type": "command",
"command": "powershell -NoProfile -File C:/Users/username/.claude/statusline.ps1"
}
}powershell
$input_json = $input | Out-String | ConvertFrom-Json
$model = $input_json.model.display_name
$cwd = $input_json.cwd
$used = $input_json.context_window.used_percentage
$dirname = Split-Path $cwd -Leaf
if ($used) {
Write-Host "$dirname [$model] ctx: $used%"
} else {
Write-Host "$dirname [$model]"
}性能技巧:缓存慢操作
Status line 频繁触发。git status 在大型仓库里可能很慢。用缓存文件避免每次都运行:
bash
CACHE_FILE="/tmp/statusline-git-cache"
CACHE_MAX_AGE=5 # 秒
# 检查缓存是否过期
if [ ! -f "$CACHE_FILE" ] || [ $(($(date +%s) - $(stat -f %m "$CACHE_FILE" 2>/dev/null || stat -c %Y "$CACHE_FILE"))) -gt $CACHE_MAX_AGE ]; then
# 更新缓存
git rev-parse --git-dir > /dev/null 2>&1 && echo "$(git branch --show-current)" > "$CACHE_FILE" || echo "" > "$CACHE_FILE"
fi
BRANCH=$(cat "$CACHE_FILE")使用固定文件名(如
/tmp/statusline-git-cache),不要用$$或PID——每次 status line 调用是新进程,PID 每次不同,缓存永远不会被复用。
调试技巧
手动测试脚本:
bash
echo '{"model":{"display_name":"Opus"},"context_window":{"used_percentage":25},"cost":{"total_cost_usd":0.05},"workspace":{"current_dir":"/home/user/project"}}' | ~/.claude/statusline.sh常见问题:
- 不显示:确认脚本有执行权限(
chmod +x);确认脚本输出到 stdout;disableAllHooks: true时 status line 也会禁用 - 显示
--或空值:第一次 API 响应前某些字段为 null,用// 0提供回退值 - 上下文百分比异常:用
used_percentage而非累计 token 数计算;累计 token 可能超过上下文窗口大小 - OSC 8 链接不可点击:需要 iTerm2、Kitty、WezTerm 等支持 OSC 8 的终端;Terminal.app 不支持
- ANSI 转义码显示乱码:简化为纯文本输出,多行 + 转义码更容易出现渲染问题
- 工作区信任:未接受工作区信任对话框时,status line 不会运行,显示
statusline skipped · restart to fix