2026-05-24
编程工具
claudecode
3
#!/usr/bin/env bash
# Claude Code 自定义状态栏(单行 + 图标,| 分隔)
set -u
input="$(cat)"
# -----------------------------
# 颜色定义
# -----------------------------
RESET="\033[0m"
C_MUTED="\033[38;5;245m"
C_GREEN="\033[38;5;114m"
C_MINT="\033[38;5;121m"
C_BLUE="\033[38;5;117m"
C_YELLOW="\033[38;5;221m"
C_RED="\033[38;5;203m"
C_CYAN="\033[38;5;81m"
C_ORANGE="\033[38;5;215m"
if [ "${NO_COLOR:-}" != "" ]; then
RESET=""
C_MUTED=""; C_GREEN=""; C_MINT=""
C_BLUE=""; C_YELLOW=""; C_RED=""
C_CYAN=""; C_ORANGE=""
fi
_expand() { printf -v "$1" "%b" "${!1}"; }
for _v in RESET C_MUTED C_GREEN C_MINT C_BLUE C_YELLOW C_RED C_CYAN C_ORANGE; do
_expand "$_v"
done
# -----------------------------
# JSON 解析(内联 node 解析器)
# -----------------------------
eval "$(echo "$input" | node -e "
var chunks = [];
process.stdin.on('data', function(c) { chunks.push(c); });
process.stdin.on('end', function() {
try {
var d = JSON.parse(Buffer.concat(chunks).toString('utf8'));
var m = d.model || {};
var w = d.workspace || {};
var cw = d.context_window || {};
var cu = cw.current_usage || {};
var cost = d.cost || {};
function num(v) { return Math.floor(Number(v)) || 0; }
function num1(v) { var n = Number(v); return (isNaN(n) ? 0 : Math.round(n * 10) / 10).toFixed(1); }
console.log('model=' + JSON.stringify(m.display_name || 'Claude'));
console.log('cwd=' + JSON.stringify(w.current_dir || d.cwd || ''));
console.log('ctx_pct=' + num1(cw.used_percentage));
console.log('duration_ms=' + num(cost.total_duration_ms));
console.log('req_hit=' + num(cu.cache_read_input_tokens));
console.log('req_miss=' + num(cu.input_tokens));
console.log('total_output_tokens=' + num(cw.total_output_tokens));
} catch(e) {
console.log('model=\"Claude\"'); console.log('cwd=\"\"'); console.log('ctx_pct=0');
console.log('duration_ms=0'); console.log('req_hit=0'); console.log('req_miss=0');
console.log('total_output_tokens=0');
}
});
" 2>/dev/null)"
# node 失败时的兜底默认值
: "${model:=Claude}"
: "${cwd:=}"
: "${ctx_pct:=0}"
: "${duration_ms:=0}"
: "${req_hit:=0}"
: "${req_miss:=0}"
: "${total_output_tokens:=0}"
# -----------------------------
# 工具函数
# -----------------------------
fmt_tokens() {
local n="${1:-0}"
[ -z "$n" ] || [ "$n" = "null" ] && n=0
awk -v n="$n" 'BEGIN {
if (n >= 1000000) printf "%.1fm", n / 1000000
else if (n >= 1000) { if (n % 1000 == 0) printf "%.0fk", n / 1000; else printf "%.1fk", n / 1000 }
else printf "%.1f", n
}'
}
fmt_time() {
local ms="${1:-0}"
[ -z "$ms" ] || [ "$ms" = "null" ] && ms=0
awk -v ms="$ms" 'BEGIN {
s = ms / 1000
if (s < 1) printf "0s"
else if (s < 60) printf "%.0fs", s
else if (s < 3600) printf "%.0fm", s / 60
else printf "%.0fh %.0fm", int(s / 3600), (s % 3600) / 60
}'
}
short_dir() {
local dir="${1:-$PWD}"
if [ -n "${HOME:-}" ] && [ "${dir#$HOME}" != "$dir" ]; then
dir="~${dir#$HOME}"
fi
if [[ "$dir" =~ ^/[a-zA-Z]/ ]]; then
local drive="${dir:1:1}"
drive="${drive^^}"
dir="${drive}:${dir:2}"
dir="${dir//\//\\}"
fi
if [ "${#dir}" -gt 36 ]; then
basename "$dir"
else
echo "$dir"
fi
}
git_branch() {
local dir="$1"
git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1 || { echo "无"; return; }
local b
b="$(git -C "$dir" branch --show-current 2>/dev/null)"
[ -z "$b" ] && b="$(git -C "$dir" rev-parse --short HEAD 2>/dev/null)"
[ -z "$b" ] && b="detached"
if [ -n "$(git -C "$dir" status --porcelain 2>/dev/null)" ]; then
b="${b}*"
fi
echo "$b"
}
# -----------------------------
# 计算缓存命中率
# -----------------------------
if [ $((req_hit + req_miss)) -gt 0 ]; then
cache_pct="$(awk -v r="$req_hit" -v i="$req_miss" \
'BEGIN { printf "%.1f", r / (r + i) * 100 }')"
else
cache_pct="0.0"
fi
project="$(short_dir "$cwd")"
branch="$(git_branch "$cwd")"
tokens="⇣$(fmt_tokens "$req_hit") ⇡$(fmt_tokens "$req_miss") ${cache_pct}% →$(fmt_tokens "$total_output_tokens")"
time_display="$(fmt_time "$duration_ms")"
# -----------------------------
# 输出(单行 + 图标,| 分隔)
# -----------------------------
SEP=" ${C_MUTED}│${RESET} "
printf "%b" "${C_MINT}🤖 ${model}${RESET}"
printf "%b" "${SEP}"
printf "%b" "${C_YELLOW}📁 ${project}${RESET}"
printf "%b" "${SEP}"
printf "%b" "${C_BLUE}🔀 ${branch}${RESET}"
printf "%b" "${SEP}"
printf "%b" "${C_GREEN}🫧 ${ctx_pct}%${RESET}"
printf "%b" "${SEP}"
printf "%b" "${C_RED}🚀 ${tokens}${RESET}"
printf "%b" "${SEP}"
printf "%b" "${C_MUTED}⏱ ${time_display}${RESET}"
printf "\n"
标签:
claudecode