cd /news/developer-tools/add-cache-health-to-statusline Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-7503] src=gist.github.com β†— pub= topic=developer-tools verified=true sentiment=Β· neutral

Add cache health to statusline

To add cache health monitoring to a custom statusline script for Claude Code, tracking the ratio between cache reads (cheap, reused tokens) and cache creation (expensive, rebuilding tokens). The implementation uses a JSON state file to detect consecutive zero-read checks, displaying a "CACHE MISS" warning in red when the cache is completely thrashed (3+ consecutive zero reads) or showing the cache hit percentage in green, yellow, or red based on performance. A broken cache means users pay full input token prices instead of receiving the ~90% cache discount, and the author notes that certain workflows like batch tool calls can consistently thrash the cache.

read3 min views17 publishedApr 5, 2026

If you're using a custom statusline script, you can add cache health monitoring to catch when your prompt cache is getting thrashed. Here's what to add and what it means.

What it tracks: The ratio between cache_read_input_tokens (cheap, reused from cache) and cache_creation_input_tokens (expensive, rebuilding cache). When cache reads drop to zero while creation stays high, you're paying full price every turn instead of getting the ~90% cache discount.

Step 1: Extract the token data #

Add this near the top where you parse the statusline JSON input:

context_window=$(echo "$input" | jq -c '.context_window // null')
current_usage=$(echo "$input" | jq -c '.context_window.current_usage // null')

context_pct=""
if [ "$context_window" != "null" ]; then
    context_window_size=$(echo "$context_window" | jq -r '.context_window_size // 0')
    if [ "$current_usage" != "null" ]; then
        input_tokens=$(echo "$current_usage" | jq -r '.input_tokens // 0')
        cache_creation=$(echo "$current_usage" | jq -r '.cache_creation_input_tokens // 0')
        cache_read=$(echo "$current_usage" | jq -r '.cache_read_input_tokens // 0')
        total_tokens=$((input_tokens + cache_creation + cache_read))
        if [ "$context_window_size" -gt 0 ]; then
            context_pct=$((total_tokens * 100 / context_window_size))
        fi
    fi
fi

Step 2: Add the cache health indicator #

Add this where you build your status line segments:

if [ "$current_usage" != "null" ] && [ -n "$context_pct" ]; then
    STATE_DIR="/tmp/claude-code-state"
    mkdir -p "$STATE_DIR"
    CACHE_HEALTH_FILE="${STATE_DIR}/${SESSION_ID}-cache-health.json"

    if [ -f "$CACHE_HEALTH_FILE" ]; then
        prev_checks=$(jq -r '.checks // 0' "$CACHE_HEALTH_FILE" 2>/dev/null)
        prev_zero_reads=$(jq -r '.zero_reads // 0' "$CACHE_HEALTH_FILE" 2>/dev/null)
    else
        prev_checks=0
        prev_zero_reads=0
    fi

    new_checks=$((prev_checks + 1))
    if [ "$cache_read" -eq 0 ] && [ "$cache_creation" -gt 0 ]; then
        new_zero_reads=$((prev_zero_reads + 1))
    else
        new_zero_reads=0
    fi

    printf '{"checks":%d,"zero_reads":%d,"last_read":%s,"last_creation":%s,"timestamp":"%s"}\n' \
        "$new_checks" "$new_zero_reads" "$cache_read" "$cache_creation" \
        "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$CACHE_HEALTH_FILE" 2>/dev/null

    if [ "$new_checks" -gt 2 ] && [ "$new_zero_reads" -ge 3 ]; then
        status_parts+=("${RED}CACHE MISS${RESET}")
    elif [ "$new_checks" -gt 2 ] && [ "$cache_read" -gt 0 ]; then
        cache_total=$((cache_read + cache_creation))
        if [ "$cache_total" -gt 0 ]; then
            cache_hit_pct=$((cache_read * 100 / cache_total))
            dollar='$'
            if [ "$cache_hit_pct" -gt 80 ]; then
                status_parts+=("${GREEN}${cache_hit_pct}%${dollar}${RESET}")
            elif [ "$cache_hit_pct" -gt 50 ]; then
                status_parts+=("${YELLOW}${cache_hit_pct}%${dollar}${RESET}")
            else
                status_parts+=("${RED}${cache_hit_pct}%${dollar}${RESET}")
            fi
        fi
    fi
fi

What you'll see in the statusline #

  • 92%$ in green -- healthy, 92% of tokens hitting cache (saving money)
  • 45%$ in red -- poor cache hit rate, you're overpaying
  • CACHE MISS in red -- cache is completely thrashed, zero reads for 3+ consecutive checks

Why this matters #

A broken cache means you're paying full input token price every turn instead of getting the ~90% discount. It also increases latency. I found that certain workflows (like batch tool calls in quick succession) consistently thrash the cache, and was able to restructure them once I could actually see it happening in real time.

SESSION_ID should match however you identify your session -- tmux pane ID, env var, or a hash of the working directory.

── more in #developer-tools 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/add-cache-health-to-…] indexed:0 read:3min 2026-04-05 Β· β€”