跳转到主要内容
状态行是 Claude Code 底部的可自定义栏,可以运行你配置的任何 shell 脚本。它通过 stdin 接收 JSON 会话数据,并显示你的脚本打印的任何内容,为你提供一个持久的、一目了然的上下文使用情况、成本、git 状态或任何其他你想跟踪的内容的视图。 状态行在以下情况下很有用:
  • 你想在工作时监控上下文窗口使用情况
  • 你需要跟踪会话成本
  • 你在多个会话中工作,需要区分它们
  • 你希望 git 分支和状态始终可见
这是一个多行状态行的示例,它在第一行显示 git 信息,在第二行显示颜色编码的上下文栏。
一个多行状态行,显示第一行上的模型名称、目录、git 分支,第二行上的上下文使用进度条、成本和持续时间
本页面介绍了设置基本状态行,解释了数据如何从 Claude Code 流向你的脚本,列出了你可以显示的所有字段,并提供了常见模式的现成示例,如 git 状态、成本跟踪和进度条。

设置状态行

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

使用 /statusline 命令

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

手动配置状态行

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。此填充是在界面的内置间距之外的,所以它控制相对缩进而不是距离终端边缘的绝对距离。

禁用状态行

运行 /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 会话数据。你的脚本读取 JSON,提取它需要的内容,并将文本打印到 stdout。Claude Code 显示你的脚本打印的任何内容。 何时更新 你的脚本在每条新的助手消息之后、权限模式更改时或 vim 模式切换时运行。更新在 300ms 处进行防抖,这意味着快速更改会批处理在一起,你的脚本在事情稳定后运行一次。如果在你的脚本仍在运行时触发新的更新,则会取消正在进行的执行。如果你编辑你的脚本,更改在 Claude Code 的下一次交互触发更新之前不会出现。 你的脚本可以输出什么
  • 多行:每个 echoprint 语句显示为单独的行。请参阅多行示例
  • 颜色:使用ANSI 转义码,如 \033[32m 表示绿色(终端必须支持它们)。请参阅git 状态示例
  • 链接:使用OSC 8 转义序列使文本可点击(macOS 上为 Cmd+click,Windows/Linux 上为 Ctrl+click)。需要支持超链接的终端,如 iTerm2、Kitty 或 WezTerm。请参阅可点击链接示例
状态行在本地运行,不消耗 API 令牌。在某些 UI 交互期间,它会临时隐藏,包括自动完成建议、帮助菜单和权限提示。

可用数据

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 不同
cost.total_cost_usd总会话成本(美元)
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整个会话中的累积令牌计数
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。这是一个固定阈值,与实际上下文窗口大小无关。
session_id唯一的会话标识符
transcript_path对话记录文件的路径
versionClaude Code 版本
output_style.name当前输出样式的名称
vim.mode启用vim 模式时的当前 vim 模式(NORMALINSERT
agent.name使用 --agent 标志或配置的代理设置运行时的代理名称
worktree.name活跃 worktree 的名称。仅在 --worktree 会话期间出现
worktree.pathworktree 目录的绝对路径
worktree.branchworktree 的 Git 分支名称(例如,"worktree-my-feature")。对于基于钩子的 worktree 不存在
worktree.original_cwdClaude 进入 worktree 之前所在的目录
worktree.original_branch进入 worktree 之前检出的 Git 分支。对于基于钩子的 worktree 不存在
你的状态行命令通过 stdin 接收此 JSON 结构:
{
  "cwd": "/current/working/directory",
  "session_id": "abc123...",
  "transcript_path": "/path/to/transcript.jsonl",
  "model": {
    "id": "claude-opus-4-6",
    "display_name": "Opus"
  },
  "workspace": {
    "current_dir": "/current/working/directory",
    "project_dir": "/original/project/directory"
  },
  "version": "1.0.80",
  "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": 15234,
    "total_output_tokens": 4521,
    "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,
  "vim": {
    "mode": "NORMAL"
  },
  "agent": {
    "name": "security-reviewer"
  },
  "worktree": {
    "name": "my-feature",
    "path": "/path/to/.claude/worktrees/my-feature",
    "branch": "worktree-my-feature",
    "original_cwd": "/path/to/project",
    "original_branch": "main"
  }
}
可能不存在的字段(不在 JSON 中):
  • vim:仅在启用 vim 模式时出现
  • agent:仅在使用 --agent 标志或配置的代理设置运行时出现
  • worktree:仅在 --worktree 会话期间出现。当存在时,branchoriginal_branch 对于基于钩子的 worktree 也可能不存在
可能为 null 的字段
  • context_window.current_usage:在会话中第一次 API 调用之前为 null
  • context_window.used_percentage, context_window.remaining_percentage:在会话早期可能为 null
在你的脚本中使用条件访问处理缺失字段,使用回退默认值处理 null 值。

上下文窗口字段

context_window 对象提供了两种跟踪上下文使用情况的方式:
  • 累积总计total_input_tokens, total_output_tokens):整个会话中所有令牌的总和,用于跟踪总消耗
  • 当前使用情况current_usage):来自最近一次 API 调用的令牌计数,使用此来获得准确的上下文百分比,因为它反映了实际的上下文状态
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

示例

这些示例展示了常见的状态行模式。要使用任何示例:
  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"

显示多行

你的脚本可以输出多行来创建更丰富的显示。每个 echo 语句在状态区域中产生单独的行。
一个多行状态行,显示第一行上的模型名称、目录、git 分支,第二行上的上下文使用进度条、成本和持续时间
此示例结合了几种技术:基于阈值的颜色(70% 以下为绿色,70-89% 为黄色,90%+ 为红色)、进度条和 git 分支信息。每个 printecho 语句创建单独的行:
#!/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 存储库的可点击链接。它读取 git 远程 URL,使用 sed 将 SSH 格式转换为 HTTPS,并将存储库名称包装在 OSC 8 转义码中。按住 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/[email protected]:/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

缓存昂贵的操作

你的状态行脚本在活跃会话期间频繁运行。像 git statusgit diff 这样的命令可能很慢,特别是在大型存储库中。此示例将 git 信息缓存到临时文件,并仅每 5 秒刷新一次。 为缓存文件使用稳定的固定文件名,如 /tmp/statusline-git-cache。每个状态行调用作为新进程运行,所以基于进程的标识符如 $$os.getpid()process.pid 每次都产生不同的值,缓存永远不会被重用。 每个脚本在运行 git 命令之前检查缓存文件是否缺失或早于 5 秒:
#!/bin/bash
input=$(cat)

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

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

cache_is_stale() {
    [ ! -f "$CACHE_FILE" ] || \
    # stat -f %m is macOS, stat -c %Y is Linux
    [ $(($(date +%s) - $(stat -f %m "$CACHE_FILE" 2>/dev/null || stat -c %Y "$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 运行状态行命令。你可以从该 shell 调用 PowerShell:
{
  "statusLine": {
    "type": "command",
    "command": "powershell -NoProfile -File C:/Users/username/.claude/statusline.ps1"
  }
}
或直接运行 Bash 脚本:
{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh"
  }
}

提示

  • 使用模拟输入测试echo '{"model":{"display_name":"Opus"},"context_window":{"used_percentage":25}}' | ./statusline.sh
  • 保持输出简短:状态栏的宽度有限,所以长输出可能会被截断或换行不当
  • 缓存慢速操作:你的脚本在活跃会话期间频繁运行,所以像 git status 这样的命令可能会导致延迟。请参阅缓存示例了解如何处理这个问题。
社区项目如 ccstatuslinestarship-claude 提供带有主题和其他功能的预构建配置。

故障排除

状态行未出现
  • 验证你的脚本是可执行的:chmod +x ~/.claude/statusline.sh
  • 检查你的脚本输出到 stdout,而不是 stderr
  • 手动运行你的脚本以验证它产生输出
  • 如果 disableAllHooks 在你的设置中设置为 true,状态行也会被禁用。删除此设置或将其设置为 false 以重新启用。
  • 运行 claude --debug 以记录会话中第一次状态行调用的退出代码和 stderr
  • 要求 Claude 读取你的设置文件并直接执行 statusLine 命令以显示错误
状态行显示 -- 或空值
  • 在第一次 API 响应完成之前,字段可能为 null
  • 在你的脚本中使用回退处理 null 值,如 jq 中的 // 0
  • 如果值在多条消息后仍然为空,请重新启动 Claude Code
上下文百分比显示意外值
  • 使用 used_percentage 获得准确的上下文状态,而不是累积总计
  • total_input_tokenstotal_output_tokens 在整个会话中是累积的,可能超过上下文窗口大小
  • 上下文百分比可能与 /context 输出不同,因为每个的计算时间不同
OSC 8 链接不可点击
  • 验证你的终端支持 OSC 8 超链接(iTerm2、Kitty、WezTerm)
  • Terminal.app 不支持可点击链接
  • SSH 和 tmux 会话可能根据配置剥离 OSC 序列
  • 如果转义序列显示为文字文本,如 \e]8;;,使用 printf '%b' 而不是 echo -e 以获得更可靠的转义处理
转义序列显示故障
  • 复杂的转义序列(ANSI 颜色、OSC 8 链接)如果与其他 UI 更新重叠,偶尔会导致输出混乱
  • 如果你看到损坏的文本,尝试简化你的脚本为纯文本输出
  • 带有转义码的多行状态行比单行纯文本更容易出现渲染问题
脚本错误或挂起
  • 以非零代码退出或不产生输出的脚本会导致状态行变为空白
  • 慢速脚本会阻止状态行更新,直到它们完成。保持脚本快速以避免陈旧输出。
  • 如果在慢速脚本运行时触发新的更新,正在进行的脚本会被取消
  • 在配置之前使用模拟输入独立测试你的脚本
通知共享状态行行
  • 系统通知,如 MCP 服务器错误、自动更新和令牌警告,显示在与你的状态行相同行的右侧
  • 启用详细模式会向此区域添加令牌计数器
  • 在窄终端上,这些通知可能会截断你的状态行输出