|
# MIT License |
|
# |
|
# Copyright (c) 2026 Lucas Modrich |
|
# |
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
|
# of this software and associated documentation files (the "Software"), to deal |
|
# in the Software without restriction, including without limitation the rights |
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
# copies of the Software, and to permit persons to whom the Software is |
|
# furnished to do so, subject to the following conditions: |
|
# |
|
# The above copyright notice and this permission notice shall be included in all |
|
# copies or substantial portions of the Software. |
|
# |
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
# SOFTWARE. |
|
|
|
#!/usr/bin/env bash |
|
# Claude Code status line |
|
|
|
input=$(cat) |
|
|
|
# Extract all fields from stdin JSON — single jq call, one value per line via mapfile |
|
# (avoids the @tsv tab-collapsing bug when fields are empty) |
|
mapfile -t _f < <(jq -r ' |
|
.workspace.current_dir // .cwd, |
|
(.model.display_name // ""), |
|
(.context_window.used_percentage // ""), |
|
(.cost.total_cost_usd // "") |
|
' <<< "$input") |
|
cwd="${_f[0]}" model="${_f[1]}" used_pct="${_f[2]}" cost_usd="${_f[3]}" |
|
|
|
# Plan usage — cached at ~/.cache/claude_usage_cache.json for 60s |
|
# Token is only read from disk on a cache miss |
|
five_h_pct="" seven_d_pct="" |
|
usage_cache="$HOME/.cache/claude_usage_cache.json" |
|
if [ -f "$usage_cache" ] && [ $(( $(date +%s) - $(stat -c %Y "$usage_cache") )) -lt 60 ]; then |
|
usage_json=$(cat "$usage_cache") |
|
else |
|
token=$(jq -r '.claudeAiOauth.accessToken // empty' "$HOME/.claude/.credentials.json" 2>/dev/null) |
|
if [ -n "$token" ]; then |
|
usage_json=$(curl -sf --max-time 3 \ |
|
-H "Authorization: Bearer $token" \ |
|
-H "anthropic-beta: oauth-2025-04-20" \ |
|
-H "Content-Type: application/json" \ |
|
'https://api.anthropic.com/api/oauth/usage' 2>/dev/null) |
|
[ -n "$usage_json" ] && { mkdir -p "$HOME/.cache"; echo "$usage_json" > "$usage_cache"; } |
|
fi |
|
fi |
|
if [ -n "$usage_json" ]; then |
|
mapfile -t _u < <(jq -r ' |
|
(.five_hour.utilization // ""), |
|
(.seven_day.utilization // "") |
|
' <<< "$usage_json") |
|
five_h_pct="${_u[0]}" seven_d_pct="${_u[1]}" |
|
fi |
|
|
|
# Directory display: collapse $HOME to ~ then show last 2 path components |
|
cwd_display="${cwd/#$HOME/\~}" |
|
dir_display=$(awk -F'/' '{ |
|
n = NF |
|
if (n <= 2) print $0 |
|
else print "…/" $(n-1) "/" $n |
|
}' <<< "$cwd_display") |
|
|
|
# Git branch and uncommitted count — single git call, single awk pass on in-memory output |
|
git_branch="" git_uncommitted=0 |
|
if git_out=$(git -C "$cwd" -c gc.auto=0 status --branch --porcelain=v2 2>/dev/null); then |
|
read -r git_branch git_uncommitted < <(awk ' |
|
/^# branch\.head / { branch = $3 } |
|
/^[^#?!]/ { count++ } |
|
END { print (branch ? branch : ""), count+0 } |
|
' <<< "$git_out") |
|
fi |
|
|
|
# Usage bar renderer — binding=1 renders the label in amber (higher utilization wins) |
|
render_usage_bar() { |
|
local pct=$1 label=$2 binding=${3:-0} lo=${4:-65} hi=${5:-85} |
|
local filled empty bar="" color label_fmt i |
|
pct=$(printf '%.0f' "$pct") |
|
filled=$(( pct * 10 / 100 )); empty=$(( 10 - filled )) |
|
for ((i=0; i<filled; i++)); do bar="${bar}█"; done |
|
for ((i=0; i<empty; i++)); do bar="${bar}░"; done |
|
if [ "$pct" -lt "$lo" ]; then color="\033[32m" |
|
elif [ "$pct" -lt "$hi" ]; then color="\033[33m" |
|
else color="\033[31m" |
|
fi |
|
if [ "$binding" -eq 1 ]; then |
|
label_fmt="\033[33m%s\033[0m" |
|
else |
|
label_fmt="\033[2;37m%s\033[0m" |
|
fi |
|
printf " ${label_fmt} ${color}[%s] %d%%\033[0m" "$label" "$bar" "$pct" |
|
} |
|
|
|
# ── Line 1 ────────────────────────────────────────────────────────────────── |
|
printf "\033[1;36m📂 %s\033[0m" "$dir_display" |
|
printf " \033[2;37m|\033[0m" |
|
|
|
if [ -n "$git_branch" ]; then |
|
if [ "$git_uncommitted" -gt 0 ]; then |
|
printf " \033[1;36m🌿 %s (%d)\033[0m" "$git_branch" "$git_uncommitted" |
|
else |
|
printf " \033[1;36m🌿 %s\033[0m" "$git_branch" |
|
fi |
|
printf " \033[2;37m|\033[0m" |
|
fi |
|
|
|
[ -n "$model" ] && printf " \033[2;37m★ %s\033[0m" "$model" |
|
|
|
# ── Line 2 ────────────────────────────────────────────────────────────────── |
|
printf "\n" |
|
render_usage_bar "${used_pct:-0}" "Context" 0 50 70 |
|
|
|
if [ -n "$five_h_pct" ] && [ -n "$seven_d_pct" ]; then |
|
if awk -v a="$five_h_pct" -v b="$seven_d_pct" 'BEGIN { exit (a >= b) ? 0 : 1 }'; then |
|
render_usage_bar "$five_h_pct" "5h" 1 |
|
render_usage_bar "$seven_d_pct" "7d" 0 |
|
else |
|
render_usage_bar "$five_h_pct" "5h" 0 |
|
render_usage_bar "$seven_d_pct" "7d" 1 |
|
fi |
|
elif [ -n "$five_h_pct" ]; then render_usage_bar "$five_h_pct" "5h" 0 |
|
elif [ -n "$seven_d_pct" ]; then render_usage_bar "$seven_d_pct" "7d" 0 |
|
fi |
|
|
|
# Cost: single awk call handles both the >0 guard and formatting |
|
if [ -n "$cost_usd" ]; then |
|
cost_fmt=$(awk -v v="$cost_usd" 'BEGIN { if (v+0 > 0) { printf "%.2f", v+0; exit 0 } exit 1 }') |
|
[ -n "$cost_fmt" ] && printf " \033[2;37m💰 \033[0m\033[37m\$%s\033[0m" "$cost_fmt" |
|
fi |
|
|
|
printf "\n" |