SpyBara
Go Premium

statusline.md 2026-09-27 23:59 UTC to 2026-09-28 22:01 UTC

This page contains 2 additions and 2 deletions.

2026
Thu 10 23:00 Fri 18 23:58 Tue 22 23:59 Fri 25 23:58 Mon 28 22:59

自定义你的状态行

配置自定义状态栏以监控 Claude Code 中的上下文窗口使用情况、成本和 git 状态

状态行是 Claude Code 底部的可自定义栏,可以运行你配置的任何 shell 脚本。它通过 stdin 接收 JSON 会话数据,并显示你的脚本打印的任何内容,为你提供一个持久的、一目了然的上下文使用情况、成本、git 状态或任何其他你想跟踪的内容的视图。

状态行在以下情况下很有用:

  • 你想在工作时监控上下文窗口使用情况
  • 你需要跟踪会话成本
  • 你在多个会话中工作,需要区分它们
  • 你希望 git 分支和状态始终可见

状态行在其自己的行中呈现,位于内置页脚徽章上方,不会替换它们。配置自定义状态行后,Claude Code 会停止显示页脚中的大多数键盘提示,包括 esc to interrupt、? for shortcuts 回退和 hold space to speak 语音听写提示。要在对话中出现 ID 时向页脚添加可点击的链接徽章,而无需编写脚本,请改为配置 footerLinksRegexes。

这是一个多行状态行的示例,它在第一行显示 git 信息,在第二行显示颜色编码的上下文栏。

一个多行状态行,显示第一行上的模型名称、目录、git 分支,第二行上的上下文使用进度条、成本和持续时间

本页面介绍了设置基本状态行,解释了数据如何从 Claude Code 流向你的脚本,列出了你可以显示的所有字段,并提供了常见模式的现成示例,如 git 状态、成本跟踪和进度条。

设置状态行

使用/statusline 命令让 Claude Code 为你生成脚本,或手动创建脚本并将其添加到你的设置中。

使用 /statusline 命令

/statusline 命令接受描述你想显示的内容的自然语言指令。Claude Code 在 ~/.claude/ 中生成脚本文件并自动更新你的设置:

/statusline show model name and context percentage with a progress bar

如果 Claude Code 在设置过程中要求权限,请批准文件编辑提示。

手动配置状态行

将 statusLine 字段添加到你的用户设置(~/.claude/settings.json,其中 ~ 是你的主目录)或项目设置。将 type 设置为 "command" 并将 command 指向脚本路径或内联 shell 命令。有关创建脚本的完整演练,请参阅逐步构建状态行。

{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh",
    "padding": 2
  }
}

command 字段在 shell 中运行,所以你也可以使用内联命令而不是脚本文件。此示例使用 jq 解析 JSON 输入并显示模型名称和上下文百分比:

{
  "statusLine": {
    "type": "command",
    "command": "jq -r '\"[\\(.model.display_name)] \\(.context_window.used_percentage // 0)% context\"'"
  }
}

可选的 padding 字段为状态行内容添加额外的水平间距(以字符为单位)。默认为 0。此填充是在界面的内置间距之外的,所以它控制相对缩进而不是距离终端边缘的绝对距离。

可选的 refreshInterval 字段除了事件驱动的更新外,每 N 秒重新运行一次你的命令。最小值为 1。当你的状态行显示基于时间的数据(如时钟)或后台子代理在主会话空闲时更改 git 状态时,设置此选项。如果不设置,则仅在事件上运行。

可选的 hideVimModeIndicator 字段会抑制提示符下方的内置 -- INSERT -- 文本。当你的脚本自己呈现 vim.mode 时,将此设置为 true,这样模式就不会显示两次。

禁用状态行

运行 /statusline 并要求它删除或清除你的状态行(例如,/statusline delete、/statusline clear、/statusline remove it)。你也可以手动从 settings.json 中删除 statusLine 字段。

逐步构建状态行

本演练展示了 /statusline 为你设置的内容,通过手动创建显示当前模型、工作目录和上下文窗口使用百分比的状态行。

这些示例使用 Bash 脚本,在 macOS 和 Linux 上工作。在 Windows 上,请参阅Windows 配置了解 PowerShell 和 Git Bash 示例。

一个状态行,显示模型名称、目录和上下文百分比
1

创建一个读取 JSON 并打印输出的脚本

Claude Code 通过 stdin 向你的脚本发送 JSON 数据。此脚本使用 jq,一个你可能需要安装的命令行 JSON 解析器,来提取模型名称、目录和上下文百分比,然后打印格式化的行。

将其保存到 ~/.claude/statusline.sh(其中 ~ 是你的主目录,例如 macOS 上的 /Users/username 或 Linux 上的 /home/username):

#!/bin/bash
# Read JSON data that Claude Code sends to stdin
input=$(cat)

# Extract fields using jq
MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
# The "// 0" provides a fallback if the field is null
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)

# Output the status line - ${DIR##*/} extracts just the folder name
echo "[$MODEL] 📁 ${DIR##*/} | ${PCT}% context"
2

使其可执行

将脚本标记为可执行,以便你的 shell 可以运行它:

chmod +x ~/.claude/statusline.sh
3

添加到设置

告诉 Claude Code 运行你的脚本作为状态行。将此配置添加到 ~/.claude/settings.json,它将 type 设置为 "command"(意思是"运行此 shell 命令")并将 command 指向你的脚本:

{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}

你的状态行出现在界面的底部。Claude Code 会自动重新加载设置,并在你保存文件后立即运行你的脚本。

状态行如何工作

Claude Code 运行你的脚本,通过 stdin 向其传输 JSON 会话数据,并显示脚本打印到 stdout 的任何内容。

何时更新

你的脚本在会话启动时运行一次,包括当你恢复一个会话时。之后,它在以下情况下再次运行:

  • 新的助手消息到达
  • /compact 完成
  • 权限模式更改
  • Vim 模式切换
  • 你在 statusLine 设置中更改 command
  • 如果你设置了 refreshInterval,计时器会经过
  • 你的脚本最后接收的数据中的 速率限制窗口 到达其 resets_at 时间
  • 你的脚本最后接收的数据中的 预热提示缓存 到达其 expires_at 时间

Claude Code 在 300ms 处对更新进行防抖,因此快速更改会批处理在一起,你的脚本在更改停止后运行一次。对 command 本身的更改会跳过防抖:Claude Code 立即运行新命令。如果在你的脚本仍在运行时触发新的更新,Claude Code 会取消正在进行的脚本。如果你编辑你的脚本,更改会在下次更新触发重新运行它时出现。

当主会话空闲时,事件驱动的触发器可能会安静,例如当协调器等待后台子代理时。为了在空闲期间保持基于时间或外部来源的段的最新状态,设置 refreshInterval 以也在固定计时器上重新运行命令。

你的脚本可以输出什么

  • 多行:每个 echo 或 print 语句显示为单独的行。请参阅多行示例。
  • 颜色:使用 ANSI 转义码,如 \033[32m 表示绿色(终端必须支持它们)。请参阅 git 状态示例。
  • 链接:使用 OSC 8 转义序列 使文本可点击(macOS 上为 Cmd+click,Windows/Linux 上为 Ctrl+click)。需要支持超链接的终端,如 iTerm2、Kitty 或 WezTerm。请参阅可点击链接示例。

调整输出大小以适应终端

Claude Code 捕获你的脚本输出而不是直接将其连接到终端,因此 tput cols 和语言级宽度检测无法从脚本内部读取终端大小。改为读取 COLUMNS 和 LINES 环境变量。Claude Code 在运行你的脚本之前将这些设置为当前终端尺寸。

可用数据

Claude Code 通过 stdin 向你的脚本发送以下 JSON 字段:

字段 描述
model.id, model.display_name 当前模型标识符和显示名称
cwd, workspace.current_dir 当前工作目录。两个字段包含相同的值;为了与 workspace.project_dir 保持一致,首选 workspace.current_dir。
workspace.project_dir 启动 Claude Code 的目录,如果在会话期间工作目录更改,可能与 cwd 不同
workspace.added_dirs 通过 /add-dir 或 --add-dir 添加的其他目录。如果未添加任何目录,则为空数组
workspace.git_worktree 当前目录在使用 git worktree add 创建的链接 worktree 内时的 Git worktree 名称。在主工作树中不存在。对于任何 git worktree 都会填充,不同于仅在 worktree 会话 期间出现的 worktree.*
workspace.repo.host, workspace.repo.owner, workspace.repo.name 从 origin 远程解析的存储库标识,例如 "github.com"、"anthropics"、"claude-code"。在 git 存储库外或未配置 origin 远程时不存在。对于嵌套在子组中的 gitlab.com 项目,owner 是带有斜杠的完整命名空间路径,例如 "group/subgroup"。在 v2.1.260 之前,这些项目的 workspace.repo 不存在
cost.total_cost_usd 以美元计的估计会话成本,在客户端按列表价格计算,除非有 modelPricing 表生效。可能与你的实际账单不同。当 /clear 启动新会话时重置为 $0。在 v2.1.211 之前,总计在 /clear 后继续累积
cost.total_duration_ms 自会话开始以来的总挂钟时间(毫秒)
cost.total_api_duration_ms 等待 API 响应的总时间(毫秒)
cost.total_lines_added, cost.total_lines_removed 更改的代码行数
context_window.total_input_tokens, context_window.total_output_tokens 当前在上下文窗口中的令牌计数,来自最近的 API 响应。输入包括缓存读取和写入
context_window.context_window_size 最大上下文窗口大小(令牌)。默认为 200000,或对于具有扩展上下文的模型为 1000000。
context_window.used_percentage 预计算的已使用上下文窗口百分比
context_window.remaining_percentage 预计算的剩余上下文窗口百分比
context_window.current_usage 来自最后一次 API 调用的令牌计数,在 上下文窗口字段 中描述
exceeds_200k_tokens 最近一次 API 响应中的总令牌计数(输入、缓存和输出令牌合并)是否超过 200k。这是一个固定阈值,与实际上下文窗口大小无关。
fast_mode 是否为会话启用了 快速模式
effort.level 当前推理工作量(low、medium、high、xhigh 或 max)。反映实时会话值,包括中途 /effort 更改。Ultracode 不是一个独立的级别,报告为 xhigh。当当前模型不支持工作量参数时不存在
thinking.enabled 是否为会话启用了扩展思考
rate_limits.five_hour.used_percentage, rate_limits.seven_day.used_percentage 消耗的 5 小时或 7 天速率限制的百分比,从 0 到 100
rate_limits.five_hour.resets_at, rate_limits.seven_day.resets_at Unix 纪元秒,当 5 小时或 7 天速率限制窗口重置时
rate_limits.spend_limit.used_percentage, rate_limits.spend_limit.resets_at 在 Claude apps gateway 后面,应用于你的支出限制的已使用百分比,以及其周期重置时的 Unix 纪元秒。百分比从 0 到 100 运行,或一旦你超过限制就超过 100。需要 Claude Code v2.1.251 或更高版本
prompt_cache 会话的主对话的 prompt cache 统计信息:命中率、未命中次数以及缓存是否预热。有关每个字段,请参阅 prompt cache 字段。在主对话的第一次 API 响应之前不存在。需要 Claude Code v2.1.251 或更高版本
session_id 唯一的会话标识符
session_name 会话名称。使用使用 --name 标志或 /rename 设置的自定义名称(如果存在),否则使用 AI 生成的会话标题。默认显示名称(例如 my-app-3f)不会填充此字段。当会话既没有自定义名称也没有 AI 生成的标题时不存在
prompt_id 标识当前正在处理的用户提示的 UUID。与 OpenTelemetry 事件上的 prompt.id 属性 匹配。在第一次用户输入之前不存在。需要 Claude Code v2.1.196 或更高版本
transcript_path 对话记录文件的路径
version Claude Code 版本
output_style.name 当前输出样式的名称
vim.mode 启用 vim 模式 时的当前 vim 模式(NORMAL、INSERT、VISUAL 或 VISUAL LINE)
agent.name 使用 --agent 标志或配置的代理设置运行时的代理名称
pr.number, pr.url 当前分支的开放拉取请求。镜像底部状态栏中的 PR 徽章。在具有 GitLab 远程的存储库中,Claude Code 从分支的开放 merge request 填充这些字段,因此 pr.number 是 merge request 编号。Merge request 数据需要 Claude Code v2.1.234 或更高版本。当不在 git 存储库中、找到拉取请求或 merge request 之前,或一旦它合并或关闭后不存在
pr.review_state 开放 PR 的审查状态:approved、pending、changes_requested 或 draft。即使 pr 存在,也可能独立不存在
pr.kind 当 pr 描述 GitLab merge request 时为 mr。对于 GitHub 拉取请求不存在,因此在此字段之前编写的脚本继续工作。对于 merge request,当 GitLab 报告它可合并时,Claude Code 将 review_state 设置为 approved,对于任何其他开放状态设置为 pending,对于草稿设置为 draft。需要 Claude Code v2.1.234 或更高版本
worktree.name 活跃 worktree 的名称。仅在 worktree 会话 期间出现
worktree.path worktree 目录的绝对路径
worktree.branch worktree 的 Git 分支名称(例如,"worktree-my-feature")。对于基于钩子的 worktree 不存在
worktree.original_cwd Claude 进入 worktree 之前所在的目录
worktree.original_branch 进入 worktree 之前检出的 Git 分支。对于基于钩子的 worktree 不存在
完整 JSON 架构

你的状态行命令通过 stdin 接收此 JSON 结构:

{
"cwd": "/current/working/directory",
"session_id": "abc123...",
"session_name": "my-session",
"prompt_id": "550e8400-e29b-41d4-a716-446655440000",
"transcript_path": "/path/to/transcript.jsonl",
"model": {
"id": "claude-opus-5-5",
"display_name": "Opus"
},
"workspace": {
"current_dir": "/current/working/directory",
"project_dir": "/original/project/directory",
"added_dirs": [],
"git_worktree": "feature-xyz",
"repo": {
"host": "github.com",
"owner": "anthropics",
"name": "claude-code"
}
},
"version": "2.1.90",
"output_style": {
"name": "default"
},
"cost": {
"total_cost_usd": 0.01234,
"total_duration_ms": 45000,
"total_api_duration_ms": 2300,
"total_lines_added": 156,
"total_lines_removed": 23
},
"context_window": {
"total_input_tokens": 15500,
"total_output_tokens": 1200,
"context_window_size": 200000,
"used_percentage": 8,
"remaining_percentage": 92,
"current_usage": {
"input_tokens": 8500,
"output_tokens": 1200,
"cache_creation_input_tokens": 5000,
"cache_read_input_tokens": 2000
}
},
"exceeds_200k_tokens": false,
"prompt_cache": {
"warm": true,
"caching_observed": true,
"ttl": "1h",
"expires_at": 1738429200,
"requests": 14,
"misses": 2,
"expected_rebuilds": 1,
"hit_ratio": 0.91,
"cache_write_tokens": 352000,
"miss_recache_tokens": 310200,
"last_miss_at": 1738425230,
"last_miss_cause": {
"causes": ["tools_changed"],
"tools_added": 2,
"tools_removed": 0
},
"miss_causes": {
"tools_changed": 2
},
"recache_tokens_if_cold": 45000
},
"fast_mode": false,
"effort": {
"level": "high"
},
"thinking": {
"enabled": true
},
"rate_limits": {
"five_hour": {
"used_percentage": 23.5,
"resets_at": 1738425600
},
"seven_day": {
"used_percentage": 41.2,
"resets_at": 1738857600
},
"spend_limit": {
"used_percentage": 62.8,
"resets_at": 1740787200
}
},
"vim": {
"mode": "NORMAL"
},
"agent": {
"name": "security-reviewer"
},
"pr": {
"number": 1234,
"url": "https://github.com/anthropics/claude-code/pull/1234",
"review_state": "pending"
},
"worktree": {
"name": "my-feature",
"path": "/path/to/.claude/worktrees/my-feature",
"branch": "worktree-my-feature",
"original_cwd": "/path/to/project",
"original_branch": "main"
}
}

可能不存在的字段(不在 JSON 中):

  • session_name:当使用 --name 或 /rename 设置了自定义名称时出现,或一旦存在 AI 生成的会话标题。默认显示名称(例如 my-app-3f)不会填充它
  • prompt_id:仅在第一次用户输入后出现
  • workspace.git_worktree:仅当当前目录在链接的 git worktree 内时出现
  • workspace.repo:仅在 git 存储库内且配置了 origin 远程时出现
  • effort:仅当当前模型支持推理工作量参数时出现
  • vim:仅在启用 vim 模式时出现
  • agent:仅在使用 --agent 标志或配置的代理设置运行时出现
  • pr:仅在为当前分支找到开放 PR 或 GitLab merge request 时出现,一旦它合并或关闭就会被移除。pr.review_state 和 pr.kind 可能独立不存在
  • worktree:仅在 worktree 会话 期间出现。当存在时,对于基于钩子的 worktree,branch 和 original_branch 也可能不存在
  • rate_limits:仅对 Claude.ai Pro 和 Max 订阅者,或在为你设置支出限制的 Claude apps gateway 后面,以及仅在会话中第一次 API 响应后出现。每个窗口(five_hour、seven_day、spend_limit)可能独立不存在,Claude Code 在其 resets_at 时间过去后删除一个窗口。使用 jq -r '.rate_limits.five_hour.used_percentage // empty' 来优雅地处理缺失。
  • prompt_cache:在主对话的第一次 API 响应后出现。请参阅 prompt cache 字段

可能为 null 的字段:

  • context_window.current_usage:在会话中第一次 API 调用之前为 null,以及在 /compact 之后直到下一次 API 调用重新填充它为止为 null
  • context_window.used_percentage, context_window.remaining_percentage:在会话早期可能为 null

在你的脚本中使用条件访问处理缺失字段,使用回退默认值处理 null 值。

上下文窗口字段

context_window 对象描述来自最近一次 API 响应的实时上下文窗口。

  • 合并总计(total_input_tokens, total_output_tokens):当前在上下文窗口中的令牌。total_input_tokens 是 input_tokens、cache_creation_input_tokens 和 cache_read_input_tokens 的总和;total_output_tokens 是最近一次响应中的输出令牌。在第一次 API 响应之前,两者都是 0。
  • 按组件使用情况(current_usage):相同的令牌计数按类别分解。当你需要将缓存命中与新输入分开时,使用此选项。

current_usage 对象包含:

  • input_tokens:当前上下文中的输入令牌
  • output_tokens:生成的输出令牌
  • cache_creation_input_tokens:写入缓存的令牌
  • cache_read_input_tokens:从缓存读取的令牌

有关缓存字段的含义以及它们如何计费的信息,请参阅 检查缓存性能。

used_percentage 字段仅从输入令牌计算:input_tokens + cache_creation_input_tokens + cache_read_input_tokens。它不包括 output_tokens。

如果你从 current_usage 手动计算上下文百分比,使用相同的仅输入公式来匹配 used_percentage。

current_usage 对象在会话中第一次 API 调用之前为 null,以及在 /compact 之后直到下一次 API 调用重新填充它为止再次为 null。

Prompt cache 字段

prompt_cache 对象总结了会话的主对话如何使用 prompt cache。Claude Code 从 API 响应中的缓存令牌计数计算它,因此它适用于每个提供商。

该对象在主对话的第一次 API 响应后出现。Claude Code 不计算这些统计信息中的子代理请求。需要 Claude Code v2.1.251 或更高版本。

该表列出了每个字段及其含义。时间戳是 Unix 纪元秒,与 rate_limits.*.resets_at 相同的单位。短状态行通常显示其中一个或两个;warm 和 hit_ratio 最直接地总结缓存状态。

字段 描述
warm 缓存的前缀是否仍在其 TTL 内。当最后一次响应未报告缓存令牌时为 false,即使 caching_observed 为 true
caching_observed 此会话的任何响应是否报告了缓存令牌。false 意味着 prompt caching 已关闭,或你的提供商或网关不报告它
ttl 当前缓存前缀的 缓存生命周期:"5m" 或 "1h"
expires_at 缓存的前缀离开其 TTL 并变冷时,以纪元秒为单位。当最后一次响应未报告缓存令牌时为 null
requests 为此会话的主对话记录的 API 请求
misses 重新处理缓存已持有的内容的请求:超过 5% 且至少 2,000 个令牌的请求可以从缓存读取,没有压缩或清除旧工具结果来解释缓存读取的不足
expected_rebuilds 在压缩或清除旧工具结果后进行的缓存重建
hit_ratio 缓存读取令牌作为此会话所有输入令牌的分数,从 0 到 1。分母计算缓存读取、缓存写入和未缓存输入。当这些计数都为零时为 null
cache_write_tokens 此会话中写入缓存的所有令牌,包括第一个请求的初始写入
miss_recache_tokens 由计为未命中的请求写入缓存的令牌
last_miss_at 最后一次未命中发生时,以纪元秒为单位。当会话没有未命中时为 null
last_miss_cause Claude Code 识别为最后一次未命中可能原因的内容,在 最后一次未命中原因 下描述。需要 Claude Code v2.1.260 或更高版本
miss_causes 此会话的诊断未命中中有多少具有每个原因,由与 last_miss_cause 相同的原因名称键入。需要 Claude Code v2.1.260 或更高版本
recache_tokens_if_cold 如果缓存到那时已变冷,下一个请求重新缓存的令牌。在压缩或清除旧工具结果后为 null,直到下一个请求记录重写对话的大小

Claude Code 在终端上显示相同的统计信息,在 /usage 命令的 Prompt cache (main) 行 上。

最后一次未命中原因

last_miss_cause 对象报告 Claude Code 识别为最近一次未命中可能原因的内容。其 causes 数组包含一个或多个原因名称,例如 tools_changed、system_prompt_changed、ttl_expired_5m 或 likely_server_side。该对象在会话的第一次未命中之前为 null,以及每当 Claude Code 无法识别最近一次未命中的原因时再次为 null。需要 Claude Code v2.1.260 或更高版本。

两个原因向对象添加计数:

  • tools_added 和 tools_removed:与 tools_changed 一起,有多少工具被添加到或从请求中移除
  • system_char_delta:与 system_prompt_changed 一起,系统提示长度的变化,以字符为单位

示例

这些示例展示了常见的状态行模式。要使用任何示例:

  1. 将脚本保存到文件,如 ~/.claude/statusline.sh(或 .py/.js)
  2. 使其可执行:chmod +x ~/.claude/statusline.sh
  3. 将路径添加到你的设置

Bash 示例使用 jq 来解析 JSON。Python 和 Node.js 具有内置的 JSON 解析。

上下文窗口使用情况

显示当前模型和上下文窗口使用情况,带有可视进度条。每个脚本从 stdin 读取 JSON,提取 used_percentage 字段,并构建一个 10 字符的栏,其中填充的块(▓)代表使用情况:

一个状态行,显示模型名称和带有百分比的进度条
#!/bin/bash
# Read all of stdin into a variable
input=$(cat)

# Extract fields with jq, "// 0" provides fallback for null
MODEL=$(echo "$input" | jq -r '.model.display_name')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)

# Build progress bar: printf -v creates a run of spaces, then
# ${var// /▓} replaces each space with a block character
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 状态与颜色

显示 git 分支,带有暂存和修改文件的颜色编码指示器。此脚本使用ANSI 转义码表示终端颜色:\033[32m 是绿色,\033[33m 是黄色,\033[0m 重置为默认值。

一个状态行,显示模型、目录、git 分支和暂存和修改文件的彩色指示器

每个脚本检查当前目录是否是 git 存储库,计算暂存和修改文件,并显示颜色编码的指示器:

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')

GREEN='\033[32m'
YELLOW='\033[33m'
RESET='\033[0m'

if git rev-parse --git-dir > /dev/null 2>&1; then
BRANCH=$(git branch --show-current 2>/dev/null)
STAGED=$(git diff --cached --numstat 2>/dev/null | wc -l | tr -d ' ')
MODIFIED=$(git diff --numstat 2>/dev/null | wc -l | tr -d ' ')

GIT_STATUS=""
[ "$STAGED" -gt 0 ] && GIT_STATUS="${GREEN}+${STAGED}${RESET}"
[ "$MODIFIED" -gt 0 ] && GIT_STATUS="${GIT_STATUS}${YELLOW}~${MODIFIED}${RESET}"

echo -e "[$MODEL] 📁 ${DIR##*/} | 🌿 $BRANCH $GIT_STATUS"
else
echo "[$MODEL] 📁 ${DIR##*/}"
fi

成本和持续时间跟踪

跟踪你的会话的 API 成本和经过的时间。cost.total_cost_usd 字段累积当前会话中所有 API 调用的估计成本。cost.total_duration_ms 字段测量自会话开始以来的总经过时间,而 cost.total_api_duration_ms 仅跟踪等待 API 响应的时间。

每个脚本将成本格式化为货币并将毫秒转换为分钟和秒:

一个状态行,显示模型名称、会话成本和持续时间
#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')

COST_FMT=$(printf '$%.2f' "$COST")
DURATION_SEC=$((DURATION_MS / 1000))
MINS=$((DURATION_SEC / 60))
SECS=$((DURATION_SEC % 60))

echo "[$MODEL] 💰 $COST_FMT | ⏱️ ${MINS}m ${SECS}s"

显示多行

你的脚本可以输出多行来创建更丰富的显示。

一个多行状态行,显示第一行上的模型名称、目录、git 分支,第二行上的上下文使用进度条、成本和持续时间

此示例结合了几种技术:基于阈值的颜色(70% 以下为绿色,70-89% 为黄色,90%+ 为红色)、进度条和 git 分支信息。每个 print 或 echo 语句创建单独的行:

#!/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'

# Pick bar color based on context usage
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"

此示例创建指向你的 GitHub 存储库的可点击链接。按住 Cmd(macOS)或 Ctrl(Windows/Linux)并单击以在浏览器中打开链接。

一个状态行,显示指向 GitHub 存储库的可点击链接

每个脚本获取 git 远程 URL,将 SSH 格式转换为 HTTPS,并将存储库名称包装在 OSC 8 转义码中。Bash 版本使用 printf '%b',它比 echo -e 更可靠地跨不同 shell 解释反斜杠转义:

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')

# Convert git SSH URL to HTTPS
REMOTE=$(git remote get-url origin 2>/dev/null | sed 's/git@github.com:/https:\/\/github.com\//' | sed 's/\.git$//')

if [ -n "$REMOTE" ]; then
REPO_NAME=$(basename "$REMOTE")
# OSC 8 format: \e]8;;URL\a then TEXT then \e]8;;\a
# printf %b interprets escape sequences reliably across shells
printf '%b' "[$MODEL] 🔗 \e]8;;${REMOTE}\a${REPO_NAME}\e]8;;\a\n"
else
echo "[$MODEL]"
fi

速率限制使用情况

在状态行中显示 claude.ai 订阅速率限制使用情况。rate_limits 对象包含一个滚动的 five_hour 窗口和一个每周的 seven_day 窗口。每个窗口提供 used_percentage(从 0 到 100)和 resets_at(Unix 纪元秒,当窗口重置时)。

在具有支出限制的 Claude 应用网关后面,rate_limits 携带 spend_limit,其中包含适用于你的支出限制的相同两个字段,除了其 used_percentage 一旦超过限制可能会超过 100。需要 Claude Code v2.1.251 或更高版本。

rate_limits 对象仅对 claude.ai Pro 和 Max 订阅者或具有支出限制的 Claude 应用网关后面的用户出现,并且仅在第一次 API 响应后出现。每个脚本优雅地处理缺失字段:

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
# "// empty" produces no output when rate_limits is absent
FIVE_H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')

LIMITS=""
[ -n "$FIVE_H" ] && LIMITS="5h: $(printf '%.0f' "$FIVE_H")%"
[ -n "$WEEK" ] && LIMITS="${LIMITS:+$LIMITS }7d: $(printf '%.0f' "$WEEK")%"

[ -n "$LIMITS" ] && echo "[$MODEL] | $LIMITS" || echo "[$MODEL]"

缓存昂贵的操作

你的状态行脚本在活跃会话期间频繁运行。像 git status 或 git diff 这样的命令可能很慢,特别是在大型存储库中。此示例将 git 信息缓存到临时文件,并仅每 5 秒刷新一次。

缓存文件名需要在会话内的状态行调用中保持稳定,但在会话之间是唯一的,以便不同存储库中的并发会话不会读取彼此的缓存 git 状态。基于进程的标识符如 $$、os.getpid() 或 process.pid 在每次调用时都会改变,会破坏缓存。改用 JSON 输入中的 session_id:它在会话的生命周期内是稳定的,并且对每个会话是唯一的。

每个脚本在运行 git 命令之前检查缓存文件是否缺失或早于 5 秒:

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
SESSION_ID=$(echo "$input" | jq -r '.session_id')

CACHE_FILE="/tmp/statusline-git-cache-$SESSION_ID"
CACHE_MAX_AGE=5  # seconds

cache_is_stale() {
[ ! -f "$CACHE_FILE" ] || \
# stat -c %Y (Linux) or stat -f %m (macOS) prints the file's last-modified
# time. The Linux form must run first: on Linux, the macOS form prints a
# filesystem report to stdout before failing, and that output would be
# captured by the command substitution and break the arithmetic.
[ $(($(date +%s) - $(stat -c %Y "$CACHE_FILE" 2>/dev/null || stat -f %m "$CACHE_FILE" 2>/dev/null || echo 0))) -gt $CACHE_MAX_AGE ]
}

if cache_is_stale; then
if git rev-parse --git-dir > /dev/null 2>&1; then
BRANCH=$(git branch --show-current 2>/dev/null)
STAGED=$(git diff --cached --numstat 2>/dev/null | wc -l | tr -d ' ')
MODIFIED=$(git diff --numstat 2>/dev/null | wc -l | tr -d ' ')
echo "$BRANCH|$STAGED|$MODIFIED" > "$CACHE_FILE"
else
echo "||" > "$CACHE_FILE"
fi
fi

IFS='|' read -r BRANCH STAGED MODIFIED < "$CACHE_FILE"

if [ -n "$BRANCH" ]; then
echo "[$MODEL] 📁 ${DIR##*/} | 🌿 $BRANCH +$STAGED ~$MODIFIED"
else
echo "[$MODEL] 📁 ${DIR##*/}"
fi

Windows 配置

在 Windows 上,Claude Code 通过 Git Bash 运行状态行命令(如果已安装 Git Bash),或在没有 Git Bash 时通过 PowerShell 运行。

Git Bash 将未引用的反斜杠视为转义字符,因此 Windows 风格的路径(如 C:\Users\username\script.mjs)到达脚本运行器时会删除其分隔符,命令会失败而没有可见的错误。在 command 字符串中使用正斜杠编写文件路径,如下面的示例所示。~ 快捷方式也有效,并扩展到你的 Windows 主目录。

要将 PowerShell 脚本作为状态行运行,请通过 powershell 调用它。无论 Claude Code 通过 Git Bash 还是 PowerShell 路由命令,这都有效:

{
"statusLine": {
"type": "command",
"command": "powershell -NoProfile -File C:/Users/username/.claude/statusline.ps1"
}
}

或者,当安装了 Git Bash 时,直接运行 Bash 脚本:

{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}

子代理状态行

subagentStatusLine 设置为代理面板中显示的每个子代理呈现自定义行体。使用它来替换默认的 name · description · token count 行为你自己的格式。

{
  "subagentStatusLine": {
    "type": "command",
    "command": "~/.claude/subagent-statusline.sh"
  }
}

该命令在每个刷新周期运行一次,所有可见的子代理行作为单个 JSON 对象传递到 stdin。输入包括基本钩子字段、columns 字段(可用行宽)和 tasks 数组。每个任务有 id、name、type、status、description、label、startTime、model、effort、contextWindowSize、tokenCount、tokenSamples 和 cwd。

每个任务的 model 字段是任务运行的已解析模型 ID。contextWindowSize 是该模型的上下文窗口(以令牌计),计算方式与主状态行的 context_window.context_window_size 相同,因此你可以从 tokenCount 呈现每行百分比。这两个字段需要 Claude Code v2.1.205 或更高版本,对于模型尚未解析的任务会被省略。

每个任务的 effort 字段是为该子代理设置的推理工作量,在其定义 frontmatter中或在单个调用时设置。该值要么是工作量级别字符串 low、medium、high、xhigh 或 max 之一,要么是数字令牌预算。该字段报告配置的值(按原样写入):如果模型不支持该级别,Claude Code 实际应用的工作量可能会有所不同。该字段需要 Claude Code v2.1.214 或更高版本,当子代理继承会话的工作量级别时不存在。

将一个 JSON 行写入 stdout,用于你想覆盖的每一行,形式为 {"id": "<task id>", "content": "<row body>"} 。content 字符串按原样呈现,包括 ANSI 颜色和 OSC 8 超链接。省略任务的 id 以保持该行的默认呈现;发出空 content 字符串以隐藏它。

适用于 statusLine 的相同信任、disableAllHooks 和 allowManagedHooksOnly 门控也适用于此处。插件可以在其settings.json中提供默认的 subagentStatusLine,但与钩子不同,即使插件在托管设置 enabledPlugins 中被强制启用,插件值也不会在 allowManagedHooksOnly 下运行。

提示

  • 使用模拟输入测试:echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/home/user/project"},"context_window":{"used_percentage":25},"session_id":"test-session-abc"}' | ./statusline.sh
  • 保持输出简短:状态栏的宽度有限,所以长输出可能会被截断或换行不当
  • 缓存慢速操作:你的脚本在活跃会话期间频繁运行,所以像 git status 这样的命令可能会导致延迟。请参阅缓存示例了解如何处理这个问题。

社区项目如 ccstatusline 和 starship-claude 提供带有主题和其他功能的预构建配置。

故障排除

状态行未出现

  • 验证你的脚本是可执行的:chmod +x ~/.claude/statusline.sh
  • 检查你的脚本输出到 stdout,而不是 stderr
  • 手动运行你的脚本以验证它产生输出
  • 在安装了 Git Bash 的 Windows 上,command 路径中的反斜杠可能在脚本运行前被当作转义字符消耗。在路径中使用正斜杠。参见 Windows 配置。
  • 如果在应用 设置优先级 后 disableAllHooks 在托管设置之外为 true,Claude Code 仅运行来自托管设置的 statusLine,如果没有托管 statusLine,状态行将被禁用。删除该设置,或在设置它的文件中将其设置为 false 以重新启用。参见 disableAllHooks。
  • 如果你的组织在托管设置中设置了 allowManagedHooksOnly,你的自定义状态行会无警告地消失:你只能从那些托管设置中的 statusLine 值获得状态行。参见 在 allowManagedHooksOnly 下运行的内容 了解完整行为,并询问你的管理员此设置是否适用于你。
  • 运行 claude --debug 以记录会话中第一次状态行调用的退出代码和 stderr
  • 要求 Claude 读取你的设置文件并直接执行 statusLine 命令以显示错误

状态行显示 -- 或空值

  • 在第一次 API 响应完成之前,字段可能为 null
  • 在你的脚本中使用回退处理 null 值,如 jq 中的 // 0
  • 如果值在多条消息后仍然为空,请重新启动 Claude Code

上下文百分比显示意外值

  • 使用 used_percentage 获得最简单的准确上下文状态
  • 上下文百分比可能与 /context 输出不同,因为每个的计算时间不同

OSC 8 链接不可点击

  • 验证你的终端支持 OSC 8 超链接(iTerm2、Kitty、WezTerm)

  • Terminal.app 不支持可点击链接

  • 如果链接文本出现但不可点击,Claude Code 可能未检测到你的终端中的超链接支持。在启动 Claude Code 之前设置 FORCE_HYPERLINK 环境变量以覆盖检测:

    FORCE_HYPERLINK=1 claude
    

    在 PowerShell 中,首先在当前会话中设置变量:

    $env:FORCE_HYPERLINK = "1"; claude
    
  • SSH 和 tmux 会话可能根据配置剥离 OSC 序列

  • 如果转义序列显示为文字文本,如 \e]8;;,使用 printf '%b' 而不是 echo -e 以获得更可靠的转义处理

转义序列显示故障

  • 复杂的转义序列(ANSI 颜色、OSC 8 链接)如果与其他 UI 更新重叠,偶尔会导致输出混乱
  • 如果你看到损坏的文本,尝试简化你的脚本为纯文本输出
  • 带有转义码的多行状态行比单行纯文本更容易出现渲染问题

工作区信任需要

  • 因为 statusLine 执行 shell 命令,Claude Code 在与 设置文件中的 hooks 相同的工作区信任规则 下运行它。接受该文件夹的对话框,或接受其信任扩展到它的父目录,就足够了。
  • 在此之前,状态行保持空白,claude --debug 记录 Status line command skipped: workspace trust not accepted。重新启动 Claude Code 并接受信任对话框以启用它。

脚本错误或挂起

  • 以非零代码退出或不产生输出的脚本会导致状态行变为空白
  • 慢速脚本会阻止状态行更新,直到它们完成。保持脚本快速以避免陈旧输出。
  • 如果在慢速脚本运行时触发新的更新,正在进行的脚本会被取消
  • 在配置之前使用模拟输入独立测试你的脚本

通知共享状态行行

在 全屏渲染 之外,Claude Code 在与你的状态行相同的行上显示通知。在全屏渲染中,Claude Code 为通知提供自己的行。

  • 系统通知,如 MCP 服务器错误和自动更新,显示在行的右侧。临时通知,如上下文低警告,也会循环通过此区域。
  • 启用详细模式会向此区域添加令牌计数器
  • 在窄终端上,这些通知可能会截断你的状态行输出