首页 / 资讯中心 / 文章详情

Claude Code 状态栏脚本:一行显示模型、上下文占用、git 分支和当前目录

Claude Code 状态栏脚本:一行显示模型、上下文占用、git 分支和当前目录 ★ FEATURED ARTICLE
Claude Code 状态栏脚本一行显示模型、上下文占用、git 分支和当前目录Claude Code 界面底部有一行状态栏~/.local/bin/claude-statusline.sh就是渲染它的脚本。它把当前会话的模型、上下文占用、git 分支和当前目录压成一行 Sonnet 4.6 (1M context) | 92K (9%) | feature/pipeline | ~/project/module/camera1. 脚本与功能脚本是一段 bash不到 120 行除jq、git、awk外没有依赖。启用方式是在~/.claude/settings.json里声明一行命令{statusLine:{type:command,command:bash ~/.local/bin/claude-statusline.sh}}它渲染的内容按段划分每段相互独立段内容来源模型展示名缺失版本号时自动补model.display_name与model.id上下文占用 token 数与百分比context_window当前 git 分支名git rev-parseworktree 标记workspace.git_worktree当前目录家目录缩写成~workspace.current_dir所有段都是可选的。不在 git 仓库里就没有段字段缺失时对应段整体消失不会留下这样的空壳。脚本另外实现了一条 5 小时与周配额的采集链路调用外部 CLIcodexbar取数但没有接进输出详见 3.3 节。2. 原理契约与 payloadstatusline 的机制是一个进程契约CLI 把会话状态以 JSON 写进命令的 stdin命令把渲染结果写进 stdoutstdout 的内容就是状态栏。三条硬约束随之而来命令必须是一行可执行程序全部解析由脚本承担stdout 即渲染结果调试输出必须走 stderr它是渲染路径上的同步调用任何阻塞都会体现为界面卡顿。实测 payloadClaude Code 2.1.233的主要字段字段含义备注model.id/model.display_name模型标识与展示名展示名可能不含版本号context_window.total_input_tokens上下文占用 token 数与used_percentage配套workspace.current_dir实时工作目录跟随cd变化workspace.project_dir会话启动目录取自originalCwd不跟随cdworkspace.git_worktreeworktree 名称可选仅当 cwd 位于 linked worktree三个字段的语义与字面直觉不符是踩坑高发区project_dir读起来像「项目根目录」实际取自e.project.originalCwd即会话启动那一刻的目录用户cd之后它不变。如果会话从非 git 仓库的目录启动例如repo工具管理的多仓库工作区根目录用它做git -C永远取不到分支。current_dir才跟随cd是分支解析的正确输入。git_worktree是字符串形式的 worktree 名不是含branch字段的对象分支信息仍需问 git。3. 设计与实现3.1 流水线脚本是单向流水线没有分支嵌套各部件产出的都是可选段stdin JSONjq 字段解析模型名与版本上下文窗口token 与百分比用量配额codexbar 缓存分支与 worktreegit 调用目录缩写printf 拼接stdout 一行可选段由预拼字符串实现先拼好带分隔符的片段为空则整段不出现。3.2 逐段取舍模型名用正则从model.id尾部提取主次版本仅在display_name未包含时追加避免Sonnet 4.6 (1M context) 4.6这样的重复。token 数按量级折算为1.2M/92K/847除法交给awk因为 bash 的$(( ))只有整数运算精度不足以做小数展示。家目录前缀替换为~用 bash 参数展开而非sed省一次进程。百分比按绿、黄、红三级着色p 50绿50 ≤ p ≤ 80黄p 80红输出裸 ANSI 转义序列。配额来自外部 CLIcodexbar单次调用数十到数百毫秒放进渲染路径会拖慢界面。解法是读旧值加后台刷新_refresh(){(env-uCLAUDECODE codexbar usage--providerclaude--formatjson2/dev/null\|jq-r.[0].usage | \(.primary.usedPercent // 0)|\(.secondary.usedPercent // 0)\${CACHE}.tmp2/dev/nullmv${CACHE}.tmp$CACHE)}刷新跑在后台子进程里不阻塞本次渲染结果先写.tmp再mv避免读到半截文件因此本次渲染读到的永远是上一轮缓存值用延迟一次刷新换取零阻塞。缓存以文件 mtime 判龄超过 300 秒才触发刷新。env -u CLAUDECODE剥掉 Claude Code 注入的环境变量部分工具会据此判定自己运行在嵌套会话中而改变行为。分支解析按第 2 节的字段语义顺序为current_dir再到project_dir任一命中即停GIT_BRANCHfordin$CWD$PROJ_DIR;doif[[-z$GIT_BRANCH-n$d]];thenGIT_BRANCH$(git-C$drev-parse --abbrev-ref HEAD2/dev/null||echo)fidone分支段用预拼串不在输出语句里堆条件。worktree 标记由workspace.git_worktree驱动只负责输出分支名仍以 git 为准。3.3 冗余与边界项说明头部注释的格式说明注释描述「userhost/branch 模型/用量」两行格式实际只渲染一行WHO与PROJECT计算后未使用VER、C5、CW计算后未进入输出属未接线的中间变量配额链路也因此只采集不显示jq调用次数单次渲染约 8 次jq每次一个进程字段量再增长时应合并为一次调用输出多值printf %b加变量插值格式串含插值内容分支名若含%会被当作格式符实际极少出现属可接受边界可改进的有三处多次jq合并为一次调用把头部注释里的两行格式真正实现补齐 userhost 与 5h/wk 配额未接线的中间变量要么接线要么删除让代码与注释重新对齐。附录完整脚本#!/usr/bin/env bash# Claude Code statusline for tmuxset-euopipefail# Claude Code Custom StatusLine# Format:# userhostname:project_name | branch_name# Model | Context | 5h (%) | wk (%)# Note: Claude Code renders its own token counter on the right sideinput$(cat)# ── Model ──────────────────────────────────────────────MODEL$(echo$input|jq-r.model.display_name // ?)MODEL_ID$(echo$input|jq-r.model.id // )# Append version only if display_name doesnt already contain itVERif[[$MODEL_ID~([0-9])-([0-9])$]];thenVER_STR${BASH_REMATCH[1]}.${BASH_REMATCH[2]}[[$MODEL!*$VER_STR*]]VER$VER_STRfi# ── Context Window ─────────────────────────────────────CTX_PCT$(echo$input|jq-r.context_window.used_percentage // 0)TOTAL_IN$(echo$input|jq-r.context_window.total_input_tokens // 0)fmt_tok(){localn$1if((n1000000));thenawkBEGIN { printf\%.1fM\,$n/ 1000000 }elif((n1000));thenawkBEGIN { printf\%dK\,$n/ 1000 }elseprintf%d$nfi}CTX_TOK$(fmt_tok$TOTAL_IN)# ── CodexBar (300s cache TTL) ───────────────────────────CACHE/tmp/statusline-codexbar-cacheS_PCT0W_PCT0_refresh(){(env-uCLAUDECODE codexbar usage--providerclaude--formatjson2/dev/null\|jq-r.[0].usage | \(.primary.usedPercent // 0)|\(.secondary.usedPercent // 0)\${CACHE}.tmp2/dev/null\mv${CACHE}.tmp$CACHE)}if[[-f$CACHE]];thenage$(($(date%s)-$(stat-c%Y $CACHE2/dev/null||echo0)))((age300))_refreshIFS|read-rS_PCT W_PCT$CACHE2/dev/null||trueelse_refreshfiS_PCT${S_PCT:-0}W_PCT${W_PCT:-0}# ── Colored Percent (ANSI: green→yellow→red) ──────────cpct(){localp${1:-0}localc32((p50))c33((p80))c31printf\033[%dm%d%%\033[0m$c$p}C5$(cpct$S_PCT)CW$(cpct$W_PCT)# ── Identity ───────────────────────────────────────────PROJECT$(echo$input|jq-r.workspace.project_dir // .cwd // |xargsbasename)WHO${USER}$(hostname-s)${PROJECT::${PROJECT}}# ── Git Branch Worktree ────────────────────────────# current_dir follows cd; project_dir is the sessions original cwd and never# moves. Try the live directory first, then the project root, so the branch still# shows after cd-ing out of a repo.CWD$(echo$input|jq-r.workspace.current_dir // .cwd // )PROJ_DIR$(echo$input|jq-r.workspace.project_dir // )WORKTREE_NAME$(echo$input|jq-r.workspace.git_worktree // empty)GIT_BRANCHfordin$CWD$PROJ_DIR;doif[[-z$GIT_BRANCH-n$d]];thenGIT_BRANCH$(git-C$drev-parse --abbrev-ref HEAD2/dev/null||echo)fidoneBRANCH_PARTif[[-n$GIT_BRANCH]];thenBRANCH_PART | ${GIT_BRANCH}if[[-n$WORKTREE_NAME]];thenBRANCH_PART fifi# ── Current Directory (with ~ abbreviation) ───────────CWD_PARTif[[-n$CWD]];then[[$CWD$HOME*]]CWD~${CWD#$HOME}CWD_PART | ${CWD}fi# ── Output ─────────────────────────────────────────────printf%b\n${MODEL}| ${CTX_TOK}(${CTX_PCT}%)${BRANCH_PART}${CWD_PART}
阅读完成 · 觉得有帮助?
咨询建站