#!/bin/bash # # Claude Code status line. # # Opus 5+xhigh | 43% | $1.23 | ⚡99% | 5h 4% (1h 30m) | 7d 90% (2d 15h) | !err # ^effort ^ctx ^cost ^cache ^------ only on Claude.ai Pro/Max ------^ ^on failure # feat: br # ^--- git branch/worktree, on its own line, omitted entirely outside a repo # # `effort` is omitted when the current model doesn't support the effort # parameter. Every segment after the cost is optional and is omitted entirely # -- separator included -- when its data is absent. In particular # `rate_limits` is sent only to Claude.ai subscribers (Pro/Max) and each # window can be absent independently, so on a Console/corporate account billed # against a credit pool the line collapses to "Model | ctx% | $cost". The # status line payload carries no credit-balance field, so $cost is the only # usage signal there. # printf(1) is locale-aware: under LC_NUMERIC=es_ES it renders the cost as # "1,23" and rejects "31.2" outright with "invalid number". LC_ALL, when set, # overrides LC_NUMERIC per POSIX precedence, so it must be cleared first or # the export below is silently ineffective -- on a credit-pool/API-billed # account $cost is the only usage signal, so this segment failing is worse # than usual. unset LC_ALL export LC_NUMERIC=C input=$(cat) RESET="\033[0m" GREEN="\033[32m" YELLOW="\033[33m" RED="\033[31m" # --- error surfacing ------------------------------------------------------- # A status line's stderr is discarded, so a broken jq filter or a missing # dependency would silently render a blank segment. Failures are collected and # shown as a trailing marker instead. ERRORS="" note_error() { case ",$ERRORS," in *",$1,"*) return 0 ;; esac ERRORS="${ERRORS:+$ERRORS,}$1" } if ! command -v jq >/dev/null 2>&1; then echo -e "${RED}status line: jq not installed${RESET}" exit 0 fi # jqr [fallback] -- read a value into $JQ_OUT, defaulting when the key # is absent, null, or the filter fails. # # The result is returned via a global rather than stdout on purpose: called as # $(jqr ...) the function would run in a subshell, and note_error's assignment # to ERRORS would be discarded with it -- so the failure marker could never # appear. Same reason rate_window writes to $RATE_OUT. JQ_OUT="" jqr() { if ! JQ_OUT=$(printf '%s' "$input" | jq -r "$1" 2>/dev/null); then note_error "jq" JQ_OUT="${2-}" return 0 fi if [ -z "$JQ_OUT" ] || [ "$JQ_OUT" = "null" ]; then JQ_OUT="${2-}" fi } # threshold_color -- green under 50, yellow under 70, red above. threshold_color() { if [ "$1" -lt 50 ]; then printf '%s' "$GREEN" elif [ "$1" -lt 70 ]; then printf '%s' "$YELLOW" else printf '%s' "$RED" fi } # cache_color -- inverted thresholds: for a cache hit rate, high is good. cache_color() { if [ "$1" -ge 80 ]; then printf '%s' "$GREEN" elif [ "$1" -ge 50 ]; then printf '%s' "$YELLOW" else printf '%s' "$RED" fi } # human_duration -- "2d 15h", "1h 30m", "10m", or "now". human_duration() { local secs=$1 d h m [ "$secs" -le 0 ] && { echo "now"; return 0; } d=$((secs / 86400)) h=$(((secs % 86400) / 3600)) m=$(((secs % 3600) / 60)) if [ "$d" -gt 0 ]; then echo "${d}d ${h}h" elif [ "$h" -gt 0 ]; then echo "${h}h ${m}m" else echo "${m}m" fi } # rate_window