tips · · 4 min read

See Your Rate Limits Before You Hit Them: A 20-Line Statusline Upgrade

Claude Code v2.1.80 exposes rate limit data in the statusline JSON. Here's how to display it and stop getting surprised by throttling.

If you’ve ever been mid-thought in a long Claude Code session and suddenly hit a rate limit wall, you know the frustration. No warning, no countdown --- just a hard stop that kills your flow.

Since v2.1.80, Claude Code exposes rate limit data in the statusline JSON. You can surface it in your prompt and see the wall coming before you hit it.

What’s Available

The statusline JSON input now includes a rate_limits object:

{
  "rate_limits": {
    "five_hour": {
      "used_percentage": 67.3,
      "resets_at": "2026-03-22T18:00:00Z"
    },
    "seven_day": {
      "used_percentage": 42.1,
      "resets_at": "2026-03-28T00:00:00Z"
    }
  }
}

Two windows: a 5-hour rolling window and a 7-day rolling window. Each has used_percentage (0-100) and resets_at (ISO timestamp).

The Implementation

If you already have a custom statusline script (Python-based, reading JSON from stdin), adding rate limits is about 5 lines.

In the Python block where you extract model, context percentage, cost, and tokens:

# Existing extractions
model = d.get('model', {}).get('display_name', '?')
pct = d.get('context_window', {}).get('used_percentage', 0)
cost = d.get('cost', {}).get('total_cost_usd', 0)

# Add rate limits
rl = d.get('rate_limits', {})
rl_5h = rl.get('five_hour', {}).get('used_percentage', 0)
rl_7d = rl.get('seven_day', {}).get('used_percentage', 0)
rl_display = f'RL:{int(rl_5h)}%' if rl_5h > 0 else ''

Then include rl_display in your output string. The result looks like:

project:main [Opus 4.6] 42% ctx | RL:67% | 15.2K tokens | $0.55 | +120/-30 lines

When rate limits aren’t available (some configurations don’t report them), the display gracefully disappears.

Why This Matters Behaviorally

The rate limit display works as a visual forcing function. When your prompt shows RL:92%, you instinctively think “I should wrap up this session.” Without it, you keep prompting until the hard stop.

This aligns with session hygiene --- the #1 cost optimization for power users. The rate limit percentage provides an external signal that maps directly to “time to close and start fresh.”

Combined with /loop for periodic cost reporting, you get two complementary nudges:

  • Cost: “This session has spent $47” (am I getting value?)
  • Rate limit: “I’ve used 85% of my 5-hour window” (can I keep going?)

Forwarding to a Dashboard

If you run a usage dashboard (like a self-hosted session monitor), you can forward rate limit data alongside your other metrics:

heartbeat = {
    'session_id': sid,
    'cost_usd': float(cost),
    'context_pct': int(pct),
    'rate_limit_5h_pct': int(rl_5h),
    'rate_limit_7d_pct': int(rl_7d),
    'rate_limit_5h_resets': rl.get('five_hour', {}).get('resets_at', ''),
    # ... other fields
}

Over time, this lets you spot patterns: “I consistently hit 90% of my 5-hour window by 3pm” or “My 7-day usage spikes on Mondays.” These patterns inform when to schedule intensive work versus light tasks.

No Custom Statusline? Start Simple

If you don’t have a custom statusline yet, Claude Code’s built-in status bar already shows some information. But for power users who want rate limits, cost tracking, and custom displays, a statusline script is the way to go.

The key is the statusLine setting in ~/.claude/settings.json:

{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh"
  }
}

Your script receives JSON on stdin and outputs a single line to stdout. That line becomes your prompt’s status display. Start with model + context percentage + cost, then add rate limits once the basics work.


The rate_limits field was added to the statusline JSON in Claude Code v2.1.80. It reports both 5-hour and 7-day usage windows.