summaryrefslogtreecommitdiff
path: root/default/.claude/statuslines
diff options
context:
space:
mode:
authorTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-01-17 02:51:28 +0900
committerTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-01-17 02:51:28 +0900
commit86fefda1bc009777ca91f5a3075f49741e419e3e (patch)
treef1e8024bd90b2b0b5ada4e6ee71d3495eee58318 /default/.claude/statuslines
parent3fbb9a18372f2b6a675dd6c039ba52be76f3eeb4 (diff)
modified refactor/refactor-code.md, modified statuslines/statusline.sh, deleted hooks/hooks.json, modified .claude/settings.json
Diffstat (limited to 'default/.claude/statuslines')
-rwxr-xr-xdefault/.claude/statuslines/statusline.sh306
1 files changed, 259 insertions, 47 deletions
diff --git a/default/.claude/statuslines/statusline.sh b/default/.claude/statuslines/statusline.sh
index 7326283..54579fa 100755
--- a/default/.claude/statuslines/statusline.sh
+++ b/default/.claude/statuslines/statusline.sh
@@ -1,62 +1,274 @@
#!/bin/bash
-# Read JSON input from stdin
+
+STATUSLINE_VERSION="1.4.0"
+
input=$(cat)
-# Extract model and workspace values
-MODEL_DISPLAY=$(echo "$input" | jq -r '.model.display_name')
-CURRENT_DIR=$(echo "$input" | jq -r '.workspace.current_dir')
-
-# Extract context window metrics
-INPUT_TOKENS=$(echo "$input" | jq -r '.context_window.total_input_tokens')
-OUTPUT_TOKENS=$(echo "$input" | jq -r '.context_window.total_output_tokens')
-CONTEXT_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size')
-
-# Extract cost metrics
-COST_USD=$(echo "$input" | jq -r '.cost.total_cost_usd')
-LINES_ADDED=$(echo "$input" | jq -r '.cost.total_lines_added')
-LINES_REMOVED=$(echo "$input" | jq -r '.cost.total_lines_removed')
-
-# Extract percentage metrics
-USED_PERCENTAGE=$(echo "$input" | jq -r '.context_window.used_percentage')
-REMAINING_PERCENTAGE=$(echo "$input" | jq -r '.context_window.remaining_percentage')
-
-# Format tokens as Xk
-format_tokens() {
- local num="$1"
- if [ "$num" -ge 1000 ]; then
- echo "$((num / 1000))k"
+# ---- check jq availability ----
+HAS_JQ=0
+if command -v jq >/dev/null 2>&1; then
+ HAS_JQ=1
+fi
+
+# Get the directory where this statusline script is located
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+LOG_FILE="${SCRIPT_DIR}/statusline.log"
+TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
+
+# ---- logging ----
+{
+ echo "[$TIMESTAMP] Status line triggered (cc-statusline v${STATUSLINE_VERSION})"
+ echo "[$TIMESTAMP] Input:"
+ if [ "$HAS_JQ" -eq 1 ]; then
+ echo "$input" | jq . 2>/dev/null || echo "$input"
+ echo "[$TIMESTAMP] Using jq for JSON parsing"
else
- echo "$num"
+ echo "$input"
+ echo "[$TIMESTAMP] WARNING: jq not found, using bash fallback for JSON parsing"
fi
+ echo "---"
+} >>"$LOG_FILE" 2>/dev/null
+
+# ---- color helpers (force colors for Claude Code) ----
+use_color=1
+[ -n "$NO_COLOR" ] && use_color=0
+
+C() { if [ "$use_color" -eq 1 ]; then printf '\033[%sm' "$1"; fi; }
+RST() { if [ "$use_color" -eq 1 ]; then printf '\033[0m'; fi; }
+
+# ---- modern sleek colors ----
+dir_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;117m'; fi; } # sky blue
+model_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;147m'; fi; } # light purple
+version_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;180m'; fi; } # soft yellow
+cc_version_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;249m'; fi; } # light gray
+style_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;245m'; fi; } # gray
+rst() { if [ "$use_color" -eq 1 ]; then printf '\033[0m'; fi; }
+
+# ---- time helpers ----
+progress_bar() {
+ pct="${1:-0}"
+ width="${2:-10}"
+ [[ "$pct" =~ ^[0-9]+$ ]] || pct=0
+ ((pct < 0)) && pct=0
+ ((pct > 100)) && pct=100
+ filled=$((pct * width / 100))
+ empty=$((width - filled))
+ printf '%*s' "$filled" '' | tr ' ' '='
+ printf '%*s' "$empty" '' | tr ' ' '-'
+}
+
+# git utilities
+num_or_zero() {
+ v="$1"
+ [[ "$v" =~ ^[0-9]+$ ]] && echo "$v" || echo 0
}
-# Generate progress bar for context usage
-generate_progress_bar() {
- local percentage=$1
- local bar_width=20
- local filled=$(awk "BEGIN {printf \"%.0f\", ($percentage / 100) * $bar_width}")
- local empty=$((bar_width - filled))
- local bar=""
- for ((i = 0; i < filled; i++)); do bar+="█"; done
- for ((i = 0; i < empty; i++)); do bar+="░"; done
- echo "$bar"
+# ---- JSON extraction utilities ----
+extract_json_string() {
+ local json="$1"
+ local key="$2"
+ local default="${3:-}"
+ local field="${key##*.}"
+ field="${field%% *}"
+ local value=$(echo "$json" | grep -o "\"${field}\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | head -1 | sed 's/.*:[[:space:]]*"\([^"]*\)".*/\1/')
+ if [ -n "$value" ]; then
+ value=$(echo "$value" | sed 's/\\\\/\//g')
+ fi
+ if [ -z "$value" ] || [ "$value" = "null" ]; then
+ value=$(echo "$json" | grep -o "\"${field}\"[[:space:]]*:[[:space:]]*[0-9.]\+" | head -1 | sed 's/.*:[[:space:]]*\([0-9.]\+\).*/\1/')
+ fi
+ if [ -n "$value" ] && [ "$value" != "null" ]; then
+ echo "$value"
+ else
+ echo "$default"
+ fi
}
-# Calculate total
-TOTAL_TOKENS=$((INPUT_TOKENS + OUTPUT_TOKENS))
+# ---- basics ----
+if [ "$HAS_JQ" -eq 1 ]; then
+ current_dir=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // "unknown"' 2>/dev/null | sed "s|^$HOME|~|g")
+ model_name=$(echo "$input" | jq -r '.model.display_name // "Claude"' 2>/dev/null)
+ model_version=$(echo "$input" | jq -r '.model.version // ""' 2>/dev/null)
+ session_id=$(echo "$input" | jq -r '.session_id // ""' 2>/dev/null)
+ cc_version=$(echo "$input" | jq -r '.version // ""' 2>/dev/null)
+ output_style=$(echo "$input" | jq -r '.output_style.name // ""' 2>/dev/null)
+else
+ current_dir=$(echo "$input" | grep -o '"workspace"[[:space:]]*:[[:space:]]*{[^}]*"current_dir"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"current_dir"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' | sed 's/\\\\/\//g')
+ if [ -z "$current_dir" ] || [ "$current_dir" = "null" ]; then
+ current_dir=$(echo "$input" | grep -o '"cwd"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"cwd"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' | sed 's/\\\\/\//g')
+ fi
+ [ -z "$current_dir" ] && current_dir="unknown"
+ current_dir=$(echo "$current_dir" | sed "s|^$HOME|~|g")
+ model_name=$(echo "$input" | grep -o '"model"[[:space:]]*:[[:space:]]*{[^}]*"display_name"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"display_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
+ [ -z "$model_name" ] && model_name="Claude"
+ model_version=""
+ session_id=$(extract_json_string "$input" "session_id" "")
+ cc_version=$(echo "$input" | grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
+ output_style=$(echo "$input" | grep -o '"output_style"[[:space:]]*:[[:space:]]*{[^}]*"name"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
+fi
-# Generate progress bar
-PROGRESS_BAR=$(generate_progress_bar "$USED_PERCENTAGE")
+# ---- git colors ----
+git_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;150m'; fi; } # soft green
-# Show git branch if in a git repo
-GIT_BRANCH=""
+# ---- git ----
+git_branch=""
if git rev-parse --git-dir >/dev/null 2>&1; then
- BRANCH=$(git branch --show-current 2>/dev/null)
- if [ -n "$BRANCH" ]; then
- GIT_BRANCH=" | 🌿 $BRANCH"
+ git_branch=$(git branch --show-current 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)
+fi
+
+# ---- context window calculation (native) ----
+context_pct=""
+context_remaining_pct=""
+context_color() { if [ "$use_color" -eq 1 ]; then printf '\033[1;37m'; fi; } # default white
+
+if [ "$HAS_JQ" -eq 1 ]; then
+ CONTEXT_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size // 200000' 2>/dev/null)
+ USAGE=$(echo "$input" | jq '.context_window.current_usage' 2>/dev/null)
+
+ if [ "$USAGE" != "null" ] && [ -n "$USAGE" ]; then
+ CURRENT_TOKENS=$(echo "$USAGE" | jq '(.input_tokens // 0) + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0)' 2>/dev/null)
+
+ if [ -n "$CURRENT_TOKENS" ] && [ "$CURRENT_TOKENS" -gt 0 ] 2>/dev/null; then
+ context_used_pct=$((CURRENT_TOKENS * 100 / CONTEXT_SIZE))
+ context_remaining_pct=$((100 - context_used_pct))
+ ((context_remaining_pct < 0)) && context_remaining_pct=0
+ ((context_remaining_pct > 100)) && context_remaining_pct=100
+
+ if [ "$context_remaining_pct" -le 20 ]; then
+ context_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;203m'; fi; } # coral red
+ elif [ "$context_remaining_pct" -le 40 ]; then
+ context_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;215m'; fi; } # peach
+ else
+ context_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;158m'; fi; } # mint green
+ fi
+
+ context_pct="${context_remaining_pct}%"
+ fi
+ fi
+fi
+
+# ---- usage colors ----
+usage_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;189m'; fi; } # lavender
+cost_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;222m'; fi; } # light gold
+burn_color() { if [ "$use_color" -eq 1 ]; then printf '\033[38;5;220m'; fi; } # bright gold
+
+# ---- cost and usage extraction ----
+cost_usd=""
+cost_per_hour=""
+tpm=""
+tot_tokens=""
+
+# Extract cost and token data from Claude Code's native input
+if [ "$HAS_JQ" -eq 1 ]; then
+ # Cost data
+ cost_usd=$(echo "$input" | jq -r '.cost.total_cost_usd // empty' 2>/dev/null)
+ total_duration_ms=$(echo "$input" | jq -r '.cost.total_duration_ms // empty' 2>/dev/null)
+
+ # Calculate burn rate ($/hour) from cost and duration
+ if [ -n "$cost_usd" ] && [ -n "$total_duration_ms" ] && [ "$total_duration_ms" -gt 0 ]; then
+ cost_per_hour=$(echo "$cost_usd $total_duration_ms" | awk '{printf "%.2f", $1 * 3600000 / $2}')
fi
+
+ # Token data from native context_window (no ccusage needed)
+ input_tokens=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0' 2>/dev/null)
+ output_tokens=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0' 2>/dev/null)
+
+ if [ "$input_tokens" != "null" ] && [ "$output_tokens" != "null" ]; then
+ tot_tokens=$((input_tokens + output_tokens))
+ [ "$tot_tokens" -eq 0 ] && tot_tokens=""
+ fi
+
+ # Calculate tokens per minute from native data
+ if [ -n "$tot_tokens" ] && [ -n "$total_duration_ms" ] && [ "$total_duration_ms" -gt 0 ]; then
+ tpm=$(echo "$tot_tokens $total_duration_ms" | awk '{if ($2 > 0) printf "%.0f", $1 * 60000 / $2; else print ""}')
+ fi
+else
+ # Bash fallback for cost extraction
+ cost_usd=$(echo "$input" | grep -o '"total_cost_usd"[[:space:]]*:[[:space:]]*[0-9.]*' | sed 's/.*:[[:space:]]*\([0-9.]*\).*/\1/')
+ total_duration_ms=$(echo "$input" | grep -o '"total_duration_ms"[[:space:]]*:[[:space:]]*[0-9]*' | sed 's/.*:[[:space:]]*\([0-9]*\).*/\1/')
+
+ if [ -n "$cost_usd" ] && [ -n "$total_duration_ms" ] && [ "$total_duration_ms" -gt 0 ]; then
+ cost_per_hour=$(echo "$cost_usd $total_duration_ms" | awk '{printf "%.2f", $1 * 3600000 / $2}')
+ fi
+
+ # Token data from native context_window (bash fallback)
+ input_tokens=$(echo "$input" | grep -o '"total_input_tokens"[[:space:]]*:[[:space:]]*[0-9]*' | sed 's/.*:[[:space:]]*\([0-9]*\).*/\1/')
+ output_tokens=$(echo "$input" | grep -o '"total_output_tokens"[[:space:]]*:[[:space:]]*[0-9]*' | sed 's/.*:[[:space:]]*\([0-9]*\).*/\1/')
+
+ if [ -n "$input_tokens" ] && [ -n "$output_tokens" ]; then
+ tot_tokens=$((input_tokens + output_tokens))
+ [ "$tot_tokens" -eq 0 ] && tot_tokens=""
+ fi
+
+ if [ -n "$tot_tokens" ] && [ -n "$total_duration_ms" ] && [ "$total_duration_ms" -gt 0 ]; then
+ tpm=$(echo "$tot_tokens $total_duration_ms" | awk '{if ($2 > 0) printf "%.0f", $1 * 60000 / $2; else print ""}')
+ fi
+fi
+
+# ---- log extracted data ----
+{
+ echo "[$TIMESTAMP] Extracted: dir=${current_dir:-}, model=${model_name:-}, version=${model_version:-}, git=${git_branch:-}, context=${context_pct:-}, cost=${cost_usd:-}, cost_ph=${cost_per_hour:-}, tokens=${tot_tokens:-}, tpm=${tpm:-}"
+} >>"$LOG_FILE" 2>/dev/null
+
+# ---- render statusline ----
+# Line 1: Core info (directory, git, model, claude code version, output style)
+printf '📁 %s%s%s' "$(dir_color)" "$current_dir" "$(rst)"
+if [ -n "$git_branch" ]; then
+ printf ' 🌿 %s%s%s' "$(git_color)" "$git_branch" "$(rst)"
+fi
+printf ' 🤖 %s%s%s' "$(model_color)" "$model_name" "$(rst)"
+if [ -n "$model_version" ] && [ "$model_version" != "null" ]; then
+ printf ' 🏷️ %s%s%s' "$(version_color)" "$model_version" "$(rst)"
+fi
+if [ -n "$cc_version" ] && [ "$cc_version" != "null" ]; then
+ printf ' 📟 %sv%s%s' "$(cc_version_color)" "$cc_version" "$(rst)"
+fi
+if [ -n "$output_style" ] && [ "$output_style" != "null" ]; then
+ printf ' 🎨 %s%s%s' "$(style_color)" "$output_style" "$(rst)"
+fi
+
+# Line 2: Context and session time
+line2=""
+if [ -n "$context_pct" ]; then
+ context_bar=$(progress_bar "$context_remaining_pct" 10)
+ line2="🧠 $(context_color)Context Remaining: ${context_pct} [${context_bar}]$(rst)"
+fi
+if [ -z "$line2" ] && [ -z "$context_pct" ]; then
+ line2="🧠 $(context_color)Context Remaining: TBD$(rst)"
fi
-echo "[$MODEL_DISPLAY] 📁 ${CURRENT_DIR##*/}${GIT_BRANCH}
-Context: [$PROGRESS_BAR] ${USED_PERCENTAGE}%
-Cost: \$${COST_USD} | +${LINES_ADDED} -${LINES_REMOVED} lines"
+# Line 3: Cost and usage analytics
+line3=""
+if [ -n "$cost_usd" ] && [[ "$cost_usd" =~ ^[0-9.]+$ ]]; then
+ if [ -n "$cost_per_hour" ] && [[ "$cost_per_hour" =~ ^[0-9.]+$ ]]; then
+ cost_per_hour_formatted=$(printf '%.2f' "$cost_per_hour")
+ line3="💰 $(cost_color)\$$(printf '%.2f' "$cost_usd")$(rst) ($(burn_color)\$${cost_per_hour_formatted}/h$(rst))"
+ else
+ line3="💰 $(cost_color)\$$(printf '%.2f' "$cost_usd")$(rst)"
+ fi
+fi
+if [ -n "$tot_tokens" ] && [[ "$tot_tokens" =~ ^[0-9]+$ ]]; then
+ if [ -n "$tpm" ] && [[ "$tpm" =~ ^[0-9.]+$ ]]; then
+ tpm_formatted=$(printf '%.0f' "$tpm")
+ if [ -n "$line3" ]; then
+ line3="$line3 📊 $(usage_color)${tot_tokens} tok (${tpm_formatted} tpm)$(rst)"
+ else
+ line3="📊 $(usage_color)${tot_tokens} tok (${tpm_formatted} tpm)$(rst)"
+ fi
+ else
+ if [ -n "$line3" ]; then
+ line3="$line3 📊 $(usage_color)${tot_tokens} tok$(rst)"
+ else
+ line3="📊 $(usage_color)${tot_tokens} tok$(rst)"
+ fi
+ fi
+fi
+
+# Print lines
+if [ -n "$line2" ]; then
+ printf '\n%s' "$line2"
+fi
+if [ -n "$line3" ]; then
+ printf '\n%s' "$line3"
+fi
+printf '\n'