Vibepanions Get Vibepanions

Home / Guides / Status line setup

Claude Code status line setup that shows usage and reset time

Updated 23 Sep 2026 by DevSparks

Quick answer: save a script that reads JSON from stdin, make it executable, and point the statusLine setting in ~/.claude/settings.json at it (or run /statusline and describe what you want). On a claude.ai Pro or Max plan, Claude Code sends rate_limits.five_hour and rate_limits.seven_day, each with used_percentage and resets_at. The tested script below turns them into [Opus] 5h: 24% | 7d: 41% | resets 17:00.

What is the Claude Code status line?

It is a row at the bottom of Claude Code that shows whatever a script of yours prints. Claude Code runs the script, passes it JSON about the session on stdin, and displays its stdout.

Because the data includes your claude.ai plan's rate limits, a status line can keep your 5-hour and weekly usage in view all the time, updated as you work, without you asking.

How do I set up a status line?

With the /statusline command

Type /statusline followed by what you want, in plain words:

/statusline show model name and 5-hour usage with the reset time

Claude Code writes a script into ~/.claude/ and updates your settings. Approve the file edits if it asks.

By hand in settings.json

Add a statusLine field to ~/.claude/settings.json (or to project settings). Set type to "command" and point command at a script or an inline shell command:

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

Two useful optional fields: padding adds horizontal spacing in characters (default 0), and refreshInterval re-runs the command every N seconds (minimum 1).

What JSON does Claude Code send to the script?

A single JSON object on stdin. The fields most status lines use:

This is the sample input used to test every script on this page. It follows the documented shape, trimmed to the fields that matter here:

{
  "session_id": "abc123",
  "model": { "id": "claude-opus-5-5", "display_name": "Opus" },
  "workspace": { "current_dir": "/Users/you/project" },
  "version": "2.1.278",
  "context_window": { "used_percentage": 8 },
  "rate_limits": {
    "five_hour": { "used_percentage": 23.5, "resets_at": 1790182800 },
    "seven_day": { "used_percentage": 41.2, "resets_at": 1790586000 }
  }
}

Which plans get rate_limits?

The docs say rate_limits is present only for claude.ai Pro and Max subscribers, or behind a Claude apps gateway that sets a spend limit for you, and only after the first API response in the session. Each window can be absent on its own, and Claude Code drops a window once its resets_at time passes. So your script must cope with the field missing. On an API key you will not see it at all.

A script that shows usage and reset time

This prints the model, 5-hour use, weekly use and the 5-hour reset in your local time, using jq. Save it as ~/.claude/statusline.sh:

#!/bin/bash
# Claude Code status line: model, 5-hour and weekly use, 5-hour reset time.
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name // "Claude"')
# "// empty" prints nothing when a field is absent
FIVE=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
RESET=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')

OUT="[$MODEL]"
[ -n "$FIVE" ] && OUT="$OUT 5h: $(printf '%.0f' "$FIVE")%"
[ -n "$WEEK" ] && OUT="$OUT | 7d: $(printf '%.0f' "$WEEK")%"
if [ -n "$RESET" ]; then
  # macOS date takes -r, Linux (GNU) date takes -d @
  WHEN=$(date -r "$RESET" +%H:%M 2>/dev/null || date -d "@$RESET" +%H:%M)
  OUT="$OUT | resets $WHEN"
fi
echo "$OUT"

Make it executable and test it with the sample before you touch settings:

chmod +x ~/.claude/statusline.sh
TZ=UTC ~/.claude/statusline.sh < sample.json

Real output (jq 1.8.2, macOS):

[Opus] 5h: 24% | 7d: 41% | resets 17:00

Without TZ=UTC the reset time is in your own time zone; in Singapore the same input prints resets 01:00. With the rate_limits field removed, it prints just [Opus].

How do I do it without jq?

The command runs in a shell, so any language works. This python3 version needs only the standard library and prints the same line. Save it as ~/.claude/statusline.py, run chmod +x on it, and use that path as the command:

#!/usr/bin/env python3
# Claude Code status line without jq: same output as the bash version.
import json
import sys
from datetime import datetime

data = json.load(sys.stdin)
model = data.get("model", {}).get("display_name", "Claude")
rate = data.get("rate_limits", {})
five = rate.get("five_hour", {})
week = rate.get("seven_day", {})

out = f"[{model}]"
if five.get("used_percentage") is not None:
    out += f" 5h: {five['used_percentage']:.0f}%"
if week.get("used_percentage") is not None:
    out += f" | 7d: {week['used_percentage']:.0f}%"
if five.get("resets_at") is not None:
    out += " | resets " + datetime.fromtimestamp(five["resets_at"]).strftime("%H:%M")
print(out)

Real output (Python 3.14, same sample, TZ=UTC):

[Opus] 5h: 24% | 7d: 41% | resets 17:00

How often does the status line refresh?

Claude Code runs the script once when a session starts or resumes, then again when:

Updates are debounced at 300ms, and if a new update fires while your script is still running, the running one is cancelled. When the main session sits idle the event triggers can go quiet, so set refreshInterval if you show anything time-based, such as a countdown.

Why is my status line blank or wrong?

How do I keep my status line when a tool wraps it?

Only one statusLine command runs, so a tool that wants the same data has two choices: replace your status line, or sit in front of it. A pass-through reads stdin once, saves a copy for itself, then pipes the exact same bytes into your original command, so your status line prints what it always did:

#!/bin/bash
# Pass-through: keep a copy of the status JSON, then run your own status line.
input="$(cat; printf x)"   # the x keeps any trailing newlines
input="${input%x}"
printf '%s' "$input" > "$HOME/.my-tool/status.json"
printf '%s' "$input" | ~/.claude/statusline.sh

With the sample, it printed the same line as before and the saved copy matched the input byte for byte. Before you let any tool change statusLine, check three things: it shows you the change, it runs your command unchanged, and uninstalling puts your old command back.

How Vibepanions wraps it

Vibepanions shows your Claude Code limits in a floating Mac widget, and it gets them this way. Its installer changes statusLine.command to "$HOME/.vibepanions/statusline.sh" followed by your old command in single quotes. The script:

Install backs up settings.json first and shows the diff. Uninstall puts your original command back (or removes statusLine if you had none) and deletes the script. On Claude Code 2.1.278, on 23 Sep 2026, the saved file read 0% five-hour and 68% weekly, and the app showed the same. Until a status arrives, the app labels its numbers "estimated".

FAQ

Does the status line use up my tokens?

No. The Claude Code docs say the status line runs locally and does not consume API tokens. It only reads the JSON Claude Code already has and prints text.

Why does my status line show the model but no limits?

The rate_limits field is only sent to claude.ai Pro and Max subscribers, or behind a Claude apps gateway that sets a spend limit, and only after the first API response in the session. On an API key it is absent, so the script prints just the model.

What time zone is resets_at in?

None. It is Unix epoch seconds, so your script turns it into local time: date -r on macOS, date -d @ on Linux, or datetime.fromtimestamp in Python.

Can I write a status line without jq?

Yes. The command runs in a shell, so any language that reads stdin works. The python3 script in this guide prints the same line as the jq version.

How do I remove the status line?

Run /statusline and ask it to remove or clear your status line, or delete the statusLine field from settings.json yourself.

Want your limits on screen outside the terminal too? Get Vibepanions.

Sources

Fetched 23 Sep 2026.

Next: How to check your Claude Code and Codex usage limits.