Skip to content

Status Line:自定义底部状态栏

Status Line 是 Claude Code 底部可以完全自定义的信息栏,运行你配置的 shell 脚本并显示其输出。脚本通过 stdin 接收 JSON 会话数据,可展示模型名、上下文进度条、会话费用、git 状态、速率限制等任意信息。支持多行输出、ANSI 颜色和 OSC 8 可点击链接。用 /statusline 命令让 Claude 自动生成脚本是最快的入门方式。

Status Line 是 Claude Code 底部可以完全自定义的信息栏。它运行你配置的任何 shell 脚本,把 JSON 会话数据传入脚本,把脚本输出内容显示出来。

常见用途:

  • 实时监控上下文窗口使用量(避免突然被压缩)
  • 追踪会话费用
  • 多会话并行时显示当前会话信息
  • 始终显示 git 分支和状态

如果你是从 settings.json 配置指南 过来的,先记住三件事:statusLine 写在 settings 里;脚本路径必须能被当前系统执行;脚本输出到 stdout 的内容就是底部状态栏看到的内容。

快速上手

方法一(推荐):用 /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
  }
}

padding 字段(可选)在状态栏内容两侧添加额外空格(字符数),默认 0。这是相对缩进,不是到终端边缘的绝对距离。

refreshInterval 字段(可选)每隔 N 秒重新运行一次脚本(最小值 1),不依赖事件触发。适合显示时钟或后台 subagent 修改了 git 状态时主会话处于空闲的场景。不设置则只在事件触发时运行。

最常见的三个配置目标是:显示当前模型、显示上下文百分比、显示 git 分支。先用 /statusline 生成脚本,再按下面的数据字段微调,比从零手写更稳。

或者直接内联命令(用 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_dirClaude Code 启动时的目录(可能与 cwd 不同)
workspace.added_dirs通过 /add-dir--add-dir 额外添加的目录(空数组若无)
workspace.git_worktree当前目录在 linked git worktree 内时的 worktree 名称(主工作树中不存在此字段)
cwd当前工作目录(同 workspace.current_dir
session_name--name/rename 设置的会话名称(未设置时不存在此字段)
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 明细(第一次 API 调用前为 null)
exceeds_200k_tokens是否超过 20 万 token(固定阈值,与实际上下文窗口大小无关)
rate_limits.five_hour.used_percentage5 小时限额使用百分比(0-100,仅 Pro/Max 订阅,首次 API 响应后出现)
rate_limits.seven_day.used_percentage7 天限额使用百分比(0-100)
rate_limits.five_hour.resets_at5 小时窗口重置时间(Unix 秒)
rate_limits.seven_day.resets_at7 天窗口重置时间(Unix 秒)
session_id会话唯一标识
transcript_path对话记录文件路径
versionClaude Code 版本
output_style.name当前输出风格名称
vim.modeVim 模式(NORMAL/INSERT,仅启用 vim 模式时存在)
agent.nameAgent 名称(使用 --agent 时存在)
worktree.name/path/branchWorktree 信息(--worktree 会话时存在)

字段缺失说明:以下字段在特定条件下不存在于 JSON 中(不是 null,而是完全缺失):

  • session_name:仅当通过 --name/rename 设置后才出现
  • workspace.git_worktree:仅在 linked git worktree 中存在
  • vim:仅启用 vim 模式后存在
  • agent:仅使用 --agent 时存在
  • worktree:仅 --worktree 会话时存在
  • rate_limits:仅 Pro/Max 订阅且首次 API 响应后存在

脚本中建议用 jq -r '.rate_limits.five_hour.used_percentage // empty' 这类方式安全处理可能缺失的字段。

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

相关文档

常见问题

Q: 状态栏不显示,怎么开启?

A: 运行 /statusline 命令生成配置,或在 settings.json 中设置 "statusLine": {"type": "command", "command": "~/.claude/statusline.sh"}。如果在 VS Code 集成终端中使用,还需要确保终端支持并已接受工作区信任对话框,否则会显示 statusline skipped · restart to fix

Q: 状态栏显示的信息可以自定义吗?

A: 可以。状态栏支持自定义脚本输出——在 settings.json 中配置 statusline.command 指向你的脚本,脚本输出会显示在状态栏中。也可以通过内置模板配置显示模型名称、git 分支、工作目录等预设信息。

Q: 状态栏显示 ANSI 乱码怎么处理?

A: 将状态栏脚本的输出改为纯文本,移除 ANSI 颜色转义码。状态栏在某些终端下对转义码的处理方式与常规输出不同,纯文本最兼容。

Q: 怎么在状态栏显示 token 用量?

A: 优先读取 context_window.used_percentage 显示上下文百分比;如果要显示最近一次请求的明细,再读取 context_window.current_usage.input_tokenscache_creation_input_tokenscache_read_input_tokens。不要只看累计 token 数,因为累计值可能超过当前上下文窗口。