Refresh the usage bars every 5 minutes, not every hour

The 5h/7d bars were served from a cache with a one-hour TTL, so a bar
could sit unchanged for most of a 5-hour window. The TTL is now a named
config setting next to GIT_CACHE_SECS at 300s: worst case 12 requests an
hour, shared across every session through /tmp/claude.

The section header claimed "cached 60s" — inherited from upstream and
never true here — which is what set the expectation the code did not
meet. It now names the setting instead of a number that can drift.

The refresh is gated on the same width-tier check as the bars, so a
render that shows them is a render that refreshes them: the new tests
pin that from full width down to WRAP_FLOOR, and pin that one column
below it, where the bars are dropped, no request is paid for either.
Those widths are given in usable columns, as in the sibling width test,
so the suite does not depend on the padding in the live settings.json.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonny Barnes 2026-09-02 13:01:12 +01:00
commit f2dbe61276
No known key found for this signature in database
3 changed files with 142 additions and 5 deletions

View file

@ -16,12 +16,13 @@ WRAP_MIN_WIDTH=100 # below this, keep wide-tier line-one content (it can wr
BRANCH_MAX_LEN=28 # truncate branch names longer than this
CWD_MAX_LEN=20 # truncate the cwd basename longer than this
GIT_CACHE_SECS=10 # seconds to cache git status (git diff is slow on large repos)
USAGE_CACHE_SECS=300 # seconds to cache the usage API response (the 5h/7d bars)
TOKEN_BAR_WIDTH=8 # width of token progress bar
# Where the git and usage-API caches live. Overridable via the environment so a
# test run can render into its own directory: ~/.claude/statusline.sh is a
# symlink to this script, so a fixture written to the live cache is picked up by
# the next redraw and shown as real usage for up to an hour.
# the next redraw and shown as real usage until USAGE_CACHE_SECS is up.
CACHE_DIR="${STATUSLINE_CACHE_DIR:-/tmp/claude}"
# Terminal width detection.
@ -477,12 +478,11 @@ if [ -n "$cost_fmt" ] && [ "$width_tier" = "wide" -o "$width_tier" = "full" ]; t
out+="${sep}${dim}\$${cost_fmt}${reset}"
fi
# ===== Rate limits (API, cached 60s) =====
# ===== Rate limits (API, cached USAGE_CACHE_SECS) =====
# Built at every tier except narrow. Which variant is actually emitted,
# and on how many lines, is decided by the measured ladder at the end.
if $SHOW_RATE_LIMITS && [ "$width_tier" != "narrow" ]; then
api_cache="$CACHE_DIR/statusline-usage-cache.json"
api_cache_max=3600 # 1 hour — rate limit data changes slowly
needs_refresh=true
usage_data=""
@ -490,7 +490,7 @@ if $SHOW_RATE_LIMITS && [ "$width_tier" != "narrow" ]; then
cache_mtime=$(stat -c %Y "$api_cache" 2>/dev/null || stat -f %m "$api_cache" 2>/dev/null)
now=$(date +%s)
cache_age=$(( now - cache_mtime ))
if [ "$cache_age" -lt "$api_cache_max" ]; then
if [ "$cache_age" -lt "$USAGE_CACHE_SECS" ]; then
cached_content=$(cat "$api_cache" 2>/dev/null)
# Only use cache if it's valid data (not an error response)
if [ -n "$cached_content" ] && ! echo "$cached_content" | jq -e '.error' >/dev/null 2>&1; then