Claude Code CLI มี status line ที่ custom ได้ด้วย shell script ปกติมันแสดงแค่ model กับ token count แต่เราจะทำให้มันแสดง git branch, context %, auto-compact status, เวลา, และ working directory แบบ Starship prompt
ผลลัพธ์:
🕐 12:35 📂 ~/my-project on main* • 🤖 Opus 4.6 • 📊 28% (56k/160k) • 🔄 auto-compact
ถ้า terminal แคบ จะ split เป็น 2 บรรทัดอัตโนมัติ:
🕐 12:35 📂 ~/my-project on main* • 🤖 Opus 4.6
📊 28% (56k/160k) • 🔄 auto-compact
brew install jq # JSON parser (ถ้ายังไม่มี)
git --version # ต้องมี gitสร้างไฟล์ ~/.claude/statusline-command.sh:
#!/bin/bash
# Claude Code status line — Starship-inspired with icons
# Receives JSON on stdin from Claude Code
input=$(cat)
# Extract JSON data
cwd=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // "~"')
model=$(echo "$input" | jq -r '.model.display_name // .model.id // "Claude"')
pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
used_k=$(echo "$input" | jq -r '((.context_window.current_usage | .input_tokens + .cache_creation_input_tokens + .cache_read_input_tokens + .output_tokens) // 0) / 1000 | floor')
max_k=$(echo "$input" | jq -r '(.context_window.context_window_size // 0) / 1000 | floor')
# Format directory (~ for home)
if [[ "$cwd" == "$HOME"* ]]; then
display_dir="${cwd/#$HOME/~}"
else
display_dir="$cwd"
fi
# Git branch + worktree
git_info=""
if git -C "$cwd" rev-parse --git-dir >/dev/null 2>&1; then
branch=$(git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null || git -C "$cwd" rev-parse --short HEAD 2>/dev/null)
if [ -n "$branch" ]; then
dirty=""
if ! git -C "$cwd" diff-index --quiet HEAD -- 2>/dev/null; then
dirty="*"
fi
# Check if in a worktree (git dir is a file pointing to main repo)
wt=""
git_dir=$(git -C "$cwd" rev-parse --git-dir 2>/dev/null)
if [ -f "$git_dir" ] || echo "$input" | jq -e '.worktree' >/dev/null 2>&1; then
wt_name=$(echo "$input" | jq -r '.worktree.name // empty' 2>/dev/null)
[ -z "$wt_name" ] && wt_name=$(basename "$cwd")
wt=" 🌳 ${wt_name}"
fi
git_info=" on ${branch}${dirty}${wt}"
fi
fi
# Auto-compact status
compact_val=$(jq -r 'if .autoCompactEnabled == false then "false" else "true" end' ~/.claude.json 2>/dev/null)
compact_pct=${CLAUDE_AUTOCOMPACT_PCT_OVERRIDE:-80}
if [ "$compact_val" = "false" ]; then
compact_icon="❌ auto-compact"
else
compact_icon="🔄 auto-compact"
max_k=$((max_k * compact_pct / 100))
if [ "$max_k" -gt 0 ]; then
pct=$((used_k * 100 / max_k))
fi
fi
# Time
now=$(date '+%H:%M')
# Build one-line version, split to two if too long
line1=$(printf '🕐 %s 📂 %s%s • 🤖 %s' "$now" "$display_dir" "$git_info" "$model")
line2=$(printf '📊 %s%% (%sk/%sk) • %s' "$pct" "$used_k" "$max_k" "$compact_icon")
oneline="$line1 • $line2"
# Get terminal width (fallback 80)
cols=${COLUMNS:-$(tput cols 2>/dev/null || echo 80)}
# If one line fits, use it; otherwise split
if [ ${#oneline} -le "$cols" ]; then
printf '%s' "$oneline"
else
printf '%s\n%s' "$line1" "$line2"
fichmod +x ~/.claude/statusline-command.shก่อน enable ใน Claude Code ทดสอบด้วยตัวเองก่อน:
echo '{"workspace":{"current_dir":"'$PWD'"},"model":{"display_name":"Opus 4.6","id":"claude-opus-4-6"},"context_window":{"used_percentage":28,"context_window_size":200000,"current_usage":{"input_tokens":3,"output_tokens":94,"cache_creation_input_tokens":372,"cache_read_input_tokens":55664}}}' | ~/.claude/statusline-command.shควรเห็น output ประมาณ:
🕐 12:35 📂 ~/Code/github.com/laris-co/homelab on main • 🤖 Opus 4.6 • 📊 35% (56k/160k) • 🔄 auto-compact
ถ้าเห็น error ตรวจสอบว่า jq ติดตั้งแล้ว และ ~/.claude.json มีอยู่
เพิ่ม statusLine ใน ~/.claude/settings.json:
# ถ้ายังไม่มีไฟล์
cat ~/.claude/settings.json 2>/dev/null || echo '{}'แก้ไข (หรือสร้างใหม่):
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline-command.sh"
}
}สำคัญ: ถ้ามี settings อยู่แล้ว ให้เพิ่ม statusLine field เข้าไป อย่า overwrite ทั้งไฟล์:
# ใช้ jq เพิ่ม field (ปลอดภัยกว่า)
jq '. + {"statusLine": {"type": "command", "command": "~/.claude/statusline-command.sh"}}' ~/.claude/settings.json > /tmp/settings.json && mv /tmp/settings.json ~/.claude/settings.jsonปิดแล้วเปิด Claude Code ใหม่ — status line จะแสดงทันทีหลังจาก interaction แรก
Claude Code pipe JSON ให้ script ทุกครั้งที่มี interaction ผ่าน stdin:
{
"model": { "id": "claude-opus-4-6", "display_name": "Opus 4.6" },
"workspace": { "current_dir": "/Users/nat/Code/github.com/laris-co/homelab" },
"context_window": {
"used_percentage": 28,
"context_window_size": 200000,
"current_usage": {
"input_tokens": 3,
"output_tokens": 94,
"cache_creation_input_tokens": 372,
"cache_read_input_tokens": 55664
}
},
"cost": { "total_cost_usd": 1.55 },
"version": "2.1.71"
}Script อ่าน JSON → extract ข้อมูล → format → print ออกมา Claude Code แสดง output ของ script เป็น status line
| Icon | Info | Source |
|---|---|---|
| 🕐 | เวลาปัจจุบัน | date +%H:%M |
| 📂 | Working directory (ย่อ ~) |
.workspace.current_dir |
Git branch + dirty * |
git symbolic-ref |
|
| 🌳 | Git worktree name (ถ้าอยู่ใน worktree) | .worktree.name |
| 🤖 | Model name | .model.display_name |
| 📊 | Context usage % + token count | .context_window |
| 🔄/❌ | Auto-compact on/off | ~/.claude.json |
เรื่องนี้สำคัญ เวลา auto-compact เปิด (default) Claude Code จะ compact context ที่ ~80% ของ window หมายความว่าจริงๆ ใช้ได้แค่ 160k จาก 200k ไม่เคยเต็ม 200k
Script ปรับ max ให้สะท้อนความจริง:
- Auto-compact on:
📊 35% (56k/160k)— แสดง effective limit - Auto-compact off:
📊 28% (56k/200k)— แสดง full window
ปรับ threshold ได้ด้วย env var:
export CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=75 # trigger ที่ 75% แทน 80%ตรงนี้หา tricky สุด auto-compact status ไม่ได้อยู่ใน JSON input ของ statusLine ต้อง dig เอง
ค้นพบจากการ strings Claude Code binary:
autoCompactEnabledอ่านจาก~/.claude.json(home root ไม่ใช่~/.claude/.claude.json)- Key มีเฉพาะเมื่อ set เป็น
false— เมื่อ enabled (default) key ไม่มี jqtrap:.autoCompactEnabled // trueไม่ทำงาน! เพราะfalseถือเป็น falsy ใน jq ต้องใช้:
# ผิด — false ถูก treat เป็น falsy เลย fallback เป็น true เสมอ
jq -r '.autoCompactEnabled // true'
# ถูก — check explicitly
jq -r 'if .autoCompactEnabled == false then "false" else "true" end'เพิ่มเข้าไปได้ตามชอบ:
# Session cost
cost=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
cost_str="💰 \$${cost}"
# Session duration
dur_ms=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')
dur_min=$((dur_ms / 60000))
dur_str="⏱️ ${dur_min}m"
# Claude Code version
version=$(echo "$input" | jq -r '.version // "?"')
ver_str="v${version}"Status line ไม่แสดง?
- ตรวจสอบ script มี
chmod +x - ตรวจสอบ
~/.claude/settings.jsonsyntax ถูกต้อง:jq . ~/.claude/settings.json - ต้อง restart Claude Code (ไม่ใช่แค่ส่ง message ใหม่)
แสดง error หรือ blank?
- ทดสอบ script ด้วย test JSON ก่อน (Step 3)
- ตรวจสอบ
jqinstalled:which jq - ตรวจสอบ
~/.claude.jsonexists:cat ~/.claude.json
Git branch ไม่แสดง?
- ต้องอยู่ใน git repo
gitต้องอยู่ใน PATH
Script: statusline-command.sh Config: .wezterm.lua
-- Homekeeper Oracle