# Prompt pentru alta sesiune: recreeaza statusline-ul Claude Code Copiaza tot ce urmeaza si trimite-l ca prompt intr-o sesiune Claude Code noua (pe alta masina/user), ca sa recreeze exact statusline-ul curent (Windows / Git Bash). --- Vreau sa configurezi un statusline custom pentru Claude Code, pe Windows cu Git Bash. 1. Verifica ca exista `jq.exe` in `~/.claude/bin/jq.exe`. Daca nu exista, descarca binarul oficial jq pentru Windows (jq-win64.exe de pe github.com/jqlang/jq/releases) si salveaza-l acolo ca `jq.exe`. 2. Creeaza fisierul `~/.claude/statusline.sh` (bash, LF, executabil) cu continutul de mai jos. 3. In `~/.claude/settings.json`, adauga/actualizeaza cheia de nivel radacina: ```json "statusLine": { "type": "command", "command": "C:/Users//.claude/statusline.sh" } ``` (inlocuieste `` cu userul curent; foloseste slash-uri, nu backslash). Ce face scriptul: - Linia 1: model | ctx folosit/total si % din fereastra | proiect (branch git, cu `*` daca e dirty) - Linia 2: trei bare de puncte (10 puncte fiecare) pentru consum curent (5h), saptamanal (7 zile) si sonnet (7 zile) — procent + timp pana la reset, in format `●●●○○○○○○○ 30% ↺ 2hr 15min` - Cele trei procente vin din `/api/oauth/usage` (acelasi endpoint ca ecranul `/usage`), cu cache de 10 minute in `~/.claude/.statusline-usage.json` si backoff la 429/eroare (20 min, respectiv 5 min), ca sa nu loveasca rate-limit-ul la fiecare prompt. - Pana la primul fetch reusit, current/weekly cad back pe `rate_limits` din JSON-ul primit pe stdin. - Token-ul OAuth se ia din `~/.claude/.credentials.json` (`claudeAiOauth.accessToken`). - La inceput reface PATH-ul (`$HOME/.claude/bin:/usr/bin:/bin:$PATH`), pentru ca Claude Code lanseaza scriptul ca shell non-login/non-interactiv, deci profilul Git Bash nu se incarca si PATH-ul nu are coreutils. Continutul complet al `~/.claude/statusline.sh`: ```bash #!/bin/bash # Claude Code Statusline (Windows / Git Bash) # Line 1: Model | ctx 33K/1M 3% | project (branch*) # Line 2: current 24% ↺ 3hr │ weekly 4% ↺ Thu 7pm │ sonnet 2% ↺ Thu 7pm # # All three usage figures come from /api/oauth/usage -- the same source as the # `/usage` screen -- so the numbers match it exactly. That endpoint is rate- # limited, so the result is cached for 10 min; on failure the last good values # are kept. Until the first successful fetch, current/weekly fall back to the # `rate_limits` object on stdin (slightly different snapshot, but never blank). set -o pipefail # Claude Code spawns this as a non-login, non-interactive shell, so Git Bash's # profile is never sourced and PATH has no coreutils. Restore them explicitly, # plus the bundled jq.exe in ~/.claude/bin. export PATH="$HOME/.claude/bin:/usr/bin:/bin:$PATH" input=$(cat) # Validate JSON if ! echo "$input" | jq -e . >/dev/null 2>&1; then printf '\033[90mLoading...\033[0m' exit 0 fi # --- Context / project (line 1) --- model=$(echo "$input" | jq -r '.model.display_name // "?"') workdir=$(echo "$input" | jq -r '.workspace.current_dir // ""') project=$(basename "$workdir" 2>/dev/null) || project="?" ctx_pct=$(echo "$input" | jq -r '(.context_window.used_percentage // 0) | floor') [[ "$ctx_pct" =~ ^[0-9]+$ ]] || ctx_pct=0 ctx_size=$(echo "$input" | jq -r '.context_window.context_window_size // 0') ctx_input=$(echo "$input" | jq -r '.context_window.current_usage.input_tokens // 0') ctx_output=$(echo "$input" | jq -r '.context_window.current_usage.output_tokens // 0') ctx_cache_create=$(echo "$input" | jq -r '.context_window.current_usage.cache_creation_input_tokens // 0') ctx_cache_read=$(echo "$input" | jq -r '.context_window.current_usage.cache_read_input_tokens // 0') ctx_used=$(( ctx_input + ctx_output + ctx_cache_create + ctx_cache_read )) fmt_tokens() { local n=$1 if [ "$n" -ge 1000000 ]; then printf "%dM" $(( n / 1000000 )) elif [ "$n" -ge 1000 ]; then printf "%dK" $(( n / 1000 )) else printf "%d" "$n"; fi } ctx_used_fmt=$(fmt_tokens "$ctx_used") ctx_size_fmt=$(fmt_tokens "$ctx_size") # Git branch with dirty marker git_branch="" if [ -n "$workdir" ] && [ -d "$workdir" ]; then git_branch=$(cd "$workdir" 2>/dev/null && git -c gc.auto=0 rev-parse --abbrev-ref HEAD 2>/dev/null) || git_branch="" if [ -n "$git_branch" ]; then git_dirty=$(cd "$workdir" 2>/dev/null && git -c gc.auto=0 status --porcelain 2>/dev/null | head -1) [ -n "$git_dirty" ] && git_branch="${git_branch}*" fi fi # --- Usage: all three figures from /api/oauth/usage, cached --- USAGE_CACHE="$HOME/.claude/.statusline-usage.json" USAGE_REFRESH=600 # refresh at most every 10 min USAGE_BACKOFF_429=1200 # after a rate-limit, wait 20 min before retrying USAGE_BACKOFF_ERR=300 # after any other error, wait 5 min now=$(date +%s) c5p=""; c5r=""; c7p=""; c7r=""; csp=""; csr=""; fetched=0; retry=0 read_usage_cache() { [ -f "$USAGE_CACHE" ] || return c5p=$(jq -r '.five_hour_pct // ""' "$USAGE_CACHE" 2>/dev/null) c5r=$(jq -r '.five_hour_reset // ""' "$USAGE_CACHE" 2>/dev/null) c7p=$(jq -r '.seven_day_pct // ""' "$USAGE_CACHE" 2>/dev/null) c7r=$(jq -r '.seven_day_reset // ""' "$USAGE_CACHE" 2>/dev/null) csp=$(jq -r '.sonnet_pct // ""' "$USAGE_CACHE" 2>/dev/null) csr=$(jq -r '.sonnet_reset // ""' "$USAGE_CACHE" 2>/dev/null) fetched=$(jq -r '(.fetched_at // 0) | floor' "$USAGE_CACHE" 2>/dev/null || echo 0) retry=$(jq -r '(.retry_until // 0) | floor' "$USAGE_CACHE" 2>/dev/null || echo 0) } read_usage_cache [[ "$fetched" =~ ^[0-9]+$ ]] || fetched=0 [[ "$retry" =~ ^[0-9]+$ ]] || retry=0 write_usage_cache() { # 5p 5r 7p 7r sp sr fetched_at retry_until printf '{"five_hour_pct":"%s","five_hour_reset":"%s","seven_day_pct":"%s","seven_day_reset":"%s","sonnet_pct":"%s","sonnet_reset":"%s","fetched_at":%s,"retry_until":%s}\n' \ "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" > "$USAGE_CACHE" } refresh_usage() { local creds="$HOME/.claude/.credentials.json" token tmp http [ -f "$creds" ] || return token=$(jq -r '.claudeAiOauth.accessToken // empty' "$creds" 2>/dev/null) [ -n "$token" ] || return tmp="$HOME/.claude/.statusline-usage.tmp.$$" http=$(curl -s -o "$tmp" -w '%{http_code}' --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) if [ "$http" = "200" ]; then local p5 r5 p7 r7 ps rs p5=$(jq -r 'if .five_hour.utilization!=null then (.five_hour.utilization|floor) else "" end' "$tmp" 2>/dev/null) r5=$(jq -r '.five_hour.resets_at // ""' "$tmp" 2>/dev/null) p7=$(jq -r 'if .seven_day.utilization!=null then (.seven_day.utilization|floor) else "" end' "$tmp" 2>/dev/null) r7=$(jq -r '.seven_day.resets_at // ""' "$tmp" 2>/dev/null) ps=$(jq -r 'if .seven_day_sonnet.utilization!=null then (.seven_day_sonnet.utilization|floor) else "" end' "$tmp" 2>/dev/null) rs=$(jq -r '.seven_day_sonnet.resets_at // ""' "$tmp" 2>/dev/null) write_usage_cache "$p5" "$r5" "$p7" "$r7" "$ps" "$rs" "$now" 0 elif [ "$http" = "429" ]; then write_usage_cache "$c5p" "$c5r" "$c7p" "$c7r" "$csp" "$csr" "$fetched" "$(( now + USAGE_BACKOFF_429 ))" else write_usage_cache "$c5p" "$c5r" "$c7p" "$c7r" "$csp" "$csr" "$fetched" "$(( now + USAGE_BACKOFF_ERR ))" fi rm -f "$tmp" } if [ "$(( now - fetched ))" -gt "$USAGE_REFRESH" ] && [ "$now" -gt "$retry" ]; then refresh_usage read_usage_cache fi # current / weekly: use API cache; fall back to stdin rate_limits if not yet fetched if [ -n "$c5p" ]; then five_hr_pct=$c5p; five_hr_reset=$c5r else five_hr_pct=$(echo "$input" | jq -r '(.rate_limits.five_hour.used_percentage // 0) | floor') five_hr_reset=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // ""') fi if [ -n "$c7p" ]; then weekly_pct=$c7p; weekly_reset=$c7r else weekly_pct=$(echo "$input" | jq -r '(.rate_limits.seven_day.used_percentage // 0) | floor') weekly_reset=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // ""') fi # sonnet: only available from the API sonnet_pct=${csp:-0}; sonnet_reset=$csr [[ "$five_hr_pct" =~ ^[0-9]+$ ]] || five_hr_pct=0 [[ "$weekly_pct" =~ ^[0-9]+$ ]] || weekly_pct=0 [[ "$sonnet_pct" =~ ^[0-9]+$ ]] || sonnet_pct=0 # --- reset-time formatting (accepts epoch seconds or ISO string) --- to_epoch() { local v="${1%%.*}" if [ -z "$v" ] || [ "$v" = "null" ]; then return 1; fi if [[ "$v" =~ ^[0-9]+$ ]]; then printf '%s' "$v" else date -d "$1" +%s 2>/dev/null || return 1; fi } fmt_reset() { # No TZ= : Git Bash's date has no zoneinfo DB, but with TZ unset it uses the # Windows system timezone correctly. Setting TZ=Europe/... falls back to UTC. local e e=$(to_epoch "$1") || { printf '%s' "--"; return; } date -d "@$e" "+%a %-I:%M%P" 2>/dev/null || printf '%s' "--" } fmt_remaining() { local e now_ts rem rh rm rd e=$(to_epoch "$1") || { printf '%s' "--"; return; } now_ts=$(date +%s) if [ "$e" -gt "$now_ts" ]; then rem=$(( e - now_ts )); rh=$(( rem / 3600 )); rm=$(( (rem % 3600) / 60 )) if [ "$rh" -gt 24 ]; then rd=$(( rh / 24 )); rh=$(( rh % 24 )); printf "%dd %dh" "$rd" "$rh" elif [ "$rh" -gt 0 ]; then printf "%dhr %dmin" "$rh" "$rm" else printf "%dmin" "$rm"; fi else printf "resetting"; fi } five_hr_remain=$(fmt_remaining "$five_hr_reset") weekly_reset_str=$(fmt_reset "$weekly_reset") sonnet_reset_str=$(fmt_reset "$sonnet_reset") # --- dot bar --- DOT_TOTAL=10 make_dots() { local pct=$1 filled i dots="" filled=$(( pct * DOT_TOTAL / 100 )) [ "$filled" -gt "$DOT_TOTAL" ] && filled=$DOT_TOTAL [ "$filled" -lt 0 ] && filled=0 for (( i=0; i