From bf8651020e41ac037fb59fc9ceb954e8fe3f3af4 Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Fri, 8 May 2026 20:42:48 +0200 Subject: [PATCH] feat(statusline): rate-limit burndown colors + reset times - Show 5h reset as HH:MM and 7d reset as "Day HH:MM" from rate_limits.*.resets_at - Color 5h/7d pill+arrow by burndown vs expected rate (5h: 20%/h, 7d: 14%/day) - Green if available% >= expected, yellow if >= expected/2, red otherwise - Add separator between 5h and 7d blocks --- .claude/statusline.sh | 66 ++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/.claude/statusline.sh b/.claude/statusline.sh index a4102ef..49fd700 100755 --- a/.claude/statusline.sh +++ b/.claude/statusline.sh @@ -49,6 +49,14 @@ LINES_REMOVED=$(echo "$INPUT" | jq -r '.cost.total_lines_removed // 0') # Rate Limits RATE_5H=$(echo "$INPUT" | jq -r '.rate_limits.five_hour.used_percentage // 0' | xargs printf "%.0f") RATE_7D=$(echo "$INPUT" | jq -r '.rate_limits.seven_day.used_percentage // 0' | xargs printf "%.0f") +RESET_5H_EPOCH=$(echo "$INPUT" | jq -r '.rate_limits.five_hour.resets_at // 0') +RESET_7D_EPOCH=$(echo "$INPUT" | jq -r '.rate_limits.seven_day.resets_at // 0') + +# Formatear resets (vacio si epoch=0) +RESET_5H="" +RESET_7D="" +[ "$RESET_5H_EPOCH" -gt 0 ] && RESET_5H=$(date -d "@$RESET_5H_EPOCH" +"%H:%M" 2>/dev/null) +[ "$RESET_7D_EPOCH" -gt 0 ] && RESET_7D=$(date -d "@$RESET_7D_EPOCH" +"%a %H:%M" 2>/dev/null) # Git info (si estamos en un repo) GIT_BRANCH="" @@ -190,23 +198,49 @@ LINE2="${LINE2} ${GRAY}│${RESET} ${DIM}Total:${RESET} ${CYAN}↓${TOTAL_IN_FMT # 4. Rate Limits (siempre mostrar) LINE2="${LINE2} ${GRAY}│${RESET} ${BOLD}Limits:${RESET}" -# 5h limit -if [ "$RATE_5H" -ge 80 ]; then - LINE2="${LINE2} ${RED}5h:${RATE_5H}%${RESET}" -elif [ "$RATE_5H" -ge 50 ]; then - LINE2="${LINE2} ${YELLOW}5h:${RATE_5H}%${RESET}" -else - LINE2="${LINE2} ${GREEN}5h:${RATE_5H}%${RESET}" -fi +# Color por burndown vs tasa esperada +# Tasa: % consumible permitido por unidad de tiempo (5h: 20%/h, 7d: 14%/dia) +# expected = tasa * unidades_restantes_hasta_reset +# available = 100 - used% +# verde: available >= expected (consumo bajo control) +# amarillo: available >= expected/2 (consumo agresivo) +# rojo: available < expected/2 (riesgo de agotar antes del reset) +NOW_EPOCH=$(date +%s) +burndown_color() { + local used_pct=$1 + local secs_left=$2 + local rate=$3 + local secs_per_unit=$4 + local available=$((100 - used_pct)) + if [ "$secs_left" -le 0 ]; then + printf "%s" "$GREEN"; return + fi + local expected + expected=$(echo "scale=2; $rate * $secs_left / $secs_per_unit" | bc) + if (( $(echo "$available >= $expected" | bc -l) )); then + printf "%s" "$GREEN" + elif (( $(echo "$available >= $expected / 2" | bc -l) )); then + printf "%s" "$YELLOW" + else + printf "%s" "$RED" + fi +} -# 7d limit -if [ "$RATE_7D" -ge 80 ]; then - LINE2="${LINE2} ${RED}7d:${RATE_7D}%${RESET}" -elif [ "$RATE_7D" -ge 50 ]; then - LINE2="${LINE2} ${YELLOW}7d:${RATE_7D}%${RESET}" -else - LINE2="${LINE2} ${GREEN}7d:${RATE_7D}%${RESET}" -fi +# 5h limit (tasa 20%/h) +SECS_5H=0 +[ "$RESET_5H_EPOCH" -gt "$NOW_EPOCH" ] && SECS_5H=$((RESET_5H_EPOCH - NOW_EPOCH)) +C5=$(burndown_color $RATE_5H $SECS_5H 20 3600) +RESET_5H_STR="" +[ -n "$RESET_5H" ] && RESET_5H_STR=" ${C5}→${RESET_5H}${RESET}" +LINE2="${LINE2} ${C5}5h:${RATE_5H}%${RESET}${RESET_5H_STR} ${GRAY}│${RESET}" + +# 7d limit (tasa 14%/dia) +SECS_7D=0 +[ "$RESET_7D_EPOCH" -gt "$NOW_EPOCH" ] && SECS_7D=$((RESET_7D_EPOCH - NOW_EPOCH)) +C7=$(burndown_color $RATE_7D $SECS_7D 14 86400) +RESET_7D_STR="" +[ -n "$RESET_7D" ] && RESET_7D_STR=" ${C7}→${RESET_7D}${RESET}" +LINE2="${LINE2} ${C7}7d:${RATE_7D}%${RESET}${RESET_7D_STR}" # 5. Duración sesión if [ "$SESSION_DURATION" -gt 0 ]; then