claudeusage.dev

Verified against Anthropic documentation & Claude Code 2.1.289 · Updated

Claude Code Statusline: Setup, Config, and Usage Limits

Claude Code supports a customizable terminal statusline configured by running /statusline or setting statusLine in ~/.claude/settings.json. It executes a local command that receives session JSON over standard input, updating as assistant messages arrive to display your active model, git branch, context-window percentage, and live 5-hour and 7-day rate-limit meters.

Answer in short:

  • Fastest setup: Run /statusline in Claude Code with natural language instructions to auto-generate a script in ~/.claude/.
  • Deterministic setup: Add a statusLine command in ~/.claude/settings.json pointing to an executable Bash script that parses JSON via jq.
  • Supported meters: Displays active model name, working directory, git branch, context window fill (0–100%), and live 5-hour and 7-day subscription usage.
  • Reset timestamps: The payload includes resets_at epoch timestamps for active 5-hour and 7-day windows, formatted into local clock times.
  • Zero token overhead: Runs locally on your machine with zero network calls and zero prompt token consumption.
  • Missing values: Rate-limit fields remain absent until the first API response completes, and do not appear for sessions authenticated via API key (ANTHROPIC_API_KEY).
Terminal Statusline Preview
tmux / zsh
[Sonnet] my-project (main) | Ctx: 24% | 5h: 34% (resets 3:15 PM) | 7d: 18%

Statusline breakdown:

  • [Sonnet]: Active model name parsed from model.display_name.
  • my-project (main): Working directory basename and current git branch.
  • Ctx: 24%: Percentage of the active conversation context window consumed (green < 70%, yellow 70–89%, red ≥ 90%).
  • 5h: 34% (resets 3:15 PM): Rolling 5-hour session quota consumed and local clock time when it resets.
  • 7d: 18%: Cumulative weekly account usage across all models.

1. Fastest setup: native /statusline command

To configure a statusline automatically without manually writing scripts or editing JSON files, run /statusline directly inside any active Claude Code session followed by your formatting instructions:

/statusline show model, current directory, git branch, context window percentage, 5-hour usage with local reset time, and 7-day usage when available; show n/a when a usage field is missing; color percentages green below 70%, yellow from 70% to 89%, and red at 90% or above

Claude Code interprets your instructions, writes an executable script into ~/.claude/, and registers it under the statusLine property in your global configuration file (~/.claude/settings.json). The statusline renders immediately at the bottom of your terminal interface.

2. Deterministic manual setup (Bash + jq)

If you manage your development environment via dotfiles, require reproducible configurations across machines, or prefer exact control over shell execution, configure the statusline manually.

This configuration is designed for macOS and Linux systems and requires bash and jq installed on your PATH.

Step 1: Create the statusline script

Save the following script to ~/.claude/statusline.sh. It safely handles missing fields, checks for git repositories without errors, formats epoch timestamps to local time, and applies ANSI color formatting:

#!/usr/bin/env bash
# ~/.claude/statusline.sh
# Requires: bash, jq. Compatible with macOS and Linux.

# Read complete JSON payload passed via stdin from Claude Code
input=$(cat)

# 1. Model display name (shortened)
model=$(echo "$input" | jq -r '.model.display_name // .model.id // "Claude"')
model_short=$(echo "$model" | sed -E 's/Claude ([0-9.]+) ([A-Za-z]+)/\2 \1/; s/Claude //')

# 2. Workspace directory basename and optional git branch
dir=$(echo "$input" | jq -r '.workspace.current_dir // empty')
dir_base=""
if [ -n "$dir" ]; then
  dir_base=$(basename "$dir" 2>/dev/null)
fi
[ -z "$dir_base" ] && dir_base="workspace"

git_branch=""
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  branch=$(git branch --show-current 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)
  [ -n "$branch" ] && git_branch=" (${branch})"
fi

# ANSI color codes
RESET="\033[0m"
BOLD="\033[1m"
GRAY="\033[90m"
GREEN="\033[32m"
YELLOW="\033[33m"
RED="\033[31m"

# Format percentage values with presentation color thresholds:
# green < 70%, yellow 70-89%, red >= 90%. Missing or null values render as "n/a".
format_pct() {
  local raw="$1"
  if [ -z "$raw" ] || [ "$raw" = "null" ]; then
    printf "${GRAY}n/a${RESET}"
    return
  fi

  local val
  val=$(printf "%.0f" "$raw" 2>/dev/null)
  if [ -z "$val" ]; then
    printf "${GRAY}n/a${RESET}"
    return
  fi

  local color="$GREEN"
  if [ "$val" -ge 90 ] 2>/dev/null; then
    color="$RED"
  elif [ "$val" -ge 70 ] 2>/dev/null; then
    color="$YELLOW"
  fi

  printf "${color}%d%%${RESET}" "$val"
}

# 3. Context window used percentage
ctx_raw=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
ctx_disp=$(format_pct "$ctx_raw")

# 4. Five-hour and seven-day rate-limit percentages
limit_5h_raw=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
limit_7d_raw=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')

disp_5h=$(format_pct "$limit_5h_raw")
disp_7d=$(format_pct "$limit_7d_raw")

# 5. Optional: Format 5-hour local reset time if available
reset_5h_epoch=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')
reset_5h_str=""
if [ -n "$reset_5h_epoch" ] && [ "$reset_5h_epoch" != "null" ]; then
  # Format epoch timestamp to local 12-hour clock (e.g., 03:15 PM) via jq built-in strflocaltime
  local_time=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at | strflocaltime("%I:%M %p")' 2>/dev/null)
  if [ -n "$local_time" ]; then
    reset_5h_str=" ${GRAY}(resets ${local_time})${RESET}"
  fi
fi

# 6. Output single compact terminal line
printf "${BOLD}[%s]${RESET} %s%s ${GRAY}|${RESET} Ctx: %b ${GRAY}|${RESET} 5h: %b%b ${GRAY}|${RESET} 7d: %b\n" \
  "$model_short" "$dir_base" "$git_branch" "$ctx_disp" "$disp_5h" "$reset_5h_str" "$disp_7d"

Step 2: Make the script executable

Ensure your user account has execution permissions for the script:

chmod +x ~/.claude/statusline.sh

Step 3: Register in settings.json

Add or merge the statusLine configuration object into ~/.claude/settings.json:

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

type: Must be set to "command".

command: The executable path or inline shell command to run.

padding: Horizontal character padding around the statusline output (defaults to 0).

refreshInterval: Optional timer-based refresh interval in seconds (minimum 1). Claude Code automatically refreshes the statusline on key session events (such as new assistant messages, context compaction, and permission toggles) and re-runs the statusline when a known rate-limit window reaches its resets_at time. Because the script displays a fixed local reset clock time rather than a live countdown, refreshInterval is not required in the default configuration. It remains available if your statusline includes genuinely time-dependent or externally changing data.

Step 4: Verify your script in the terminal

You can test your script's output and verify jq parsing immediately without launching Claude Code by piping mock JSON into it:

echo '{"model":{"display_name":"Claude 3.7 Sonnet"},"workspace":{"current_dir":"/Users/developer/my-project"},"context_window":{"used_percentage":24.2},"rate_limits":{"five_hour":{"used_percentage":34.0,"resets_at":1742651200},"seven_day":{"used_percentage":18.0,"resets_at":1743120000}}}' | ~/.claude/statusline.sh

3. Understanding the three usage meters

Developers frequently confuse conversation context consumption with account rate limits. A low context percentage does not mean your account quota is untouched. Claude Code exposes three distinct meters:

MeterPayload JSON FieldWhat It MeasuresHow It Clears or Resets
Context Windowcontext_window.used_percentageMemory fill of the active model's context window.Clears or reduces when you run /compact or start a new session with /clear.
5-Hour Sessionrate_limits.five_hour.used_percentageAccount session capacity consumed across web, desktop, and Claude Code.Resets every 5 hours according to Anthropic's rolling session schedule. Reported with a resets_at timestamp.
7-Day Weeklyrate_limits.seven_day.used_percentageCumulative weekly account quota consumed across all models.Resets once every 7 days on an account-assigned schedule. Reported with a resets_at timestamp.

To understand how rapid tool calls and multi-file refactors deplete your session allowance, consult our 5-hour session limit guide. For account-wide reset schedules and cross-model pooling, see our weekly limit rules. For a detailed breakdown of how Anthropic calculates session and weekly reset timestamps, see our reset timing guide.

4. Curated statusline JSON reference

Claude Code passes session telemetry directly through stdin as a JSON object on every update trigger. Below are the primary fields available for statusline scripts:

Field PathTypeDescription
model.idstringUnique model identifier (e.g., "claude-opus-5-5").
model.display_namestringHuman-readable model label (e.g., "Claude Opus 5.5").
workspace.current_dirstringAbsolute path to the current working directory.
workspace.project_dirstringRoot path of the current project or repository.
context_window.used_percentagenumber | nullPercentage (0–100) of the active context window currently used. May be null before turn 1.
context_window.total_input_tokensintegerContext token total from the latest model response, including raw input tokens plus prompt cache read and cache write tokens.
context_window.context_window_sizeintegerTotal context window size in tokens (200,000 by default, or 1,000,000 for models with extended context).
rate_limits.five_hour.used_percentagenumberConsumed percentage (0–100) of the rolling 5-hour session allowance.
rate_limits.five_hour.resets_atintegerUnix epoch timestamp (seconds) when the current 5-hour window resets.
rate_limits.seven_day.used_percentagenumberConsumed percentage (0–100) of the 7-day weekly allowance across all models.
rate_limits.seven_day.resets_atintegerUnix epoch timestamp (seconds) when the current 7-day window resets.
cost.total_cost_usdnumberCumulative session cost in USD calculated from Claude Code's internal list-price ledger.
cost.total_duration_msintegerWall-clock elapsed session time in milliseconds, including idle time between turns.

Rate-limit coverage: Current payloads can expose aggregate five_hour and seven_day rate-limit windows, with additional conditional rate-limit fields such as spend_limit in some environments. Model-specific weekly allocations (such as dedicated Opus weekly buckets) and prepaid credit balances are not exposed.

Conditional fields: Shipped Claude Code payloads may also include conditional fields outside the curated reference (such as scratchpad_dir, agent_type, or remote.session_id). Custom scripts should safely tolerate unexpected or absent keys.

5. What these statusline numbers are actually computed from

We checked Claude Code 2.1.289's shipped code and compared it with runtime telemetry across four measured turns in an Anthropic-hosted cloud session on October 3, 2026, running Claude Opus 5.5 (high effort, no subagents, no web tools). Comparing telemetry with session logs clarifies what each metric actually represents:

Cost ledger (cost.total_cost_usd)

Claude Code reads its own cumulative list-price cost ledger—the same ledger that prints turn-end costs. In this measured session, Claude Code's own cumulative cost ledger was about 3.9% higher ($6.80 vs. $6.53) than a cost reconstructed only from model requests present in the main local transcript. Claude Code counted additional Opus model requests outside that transcript toward total session spend.

Context fill (context_window.used_percentage & total_input_tokens)

Context percentage is computed from the latest response's context usage against the resolved context-window capacity. In our measured Opus 5.5 session, Claude Code resolved a 1,000,000-token context window. Measured turn-final context totals were approximately 158k (~16%), 194k (~19%), 238k (~24%), and 289k (~29%), covering uncached prompt tokens along with cache reads and cache writes.

Duration (cost.total_duration_ms)

Wall-clock elapsed session time in milliseconds, including idle time between turns. It does not measure active model generation or tool execution time.

Refresh cadence and debounce

Claude Code re-runs the statusline as new assistant messages arrive (with a 300 ms debounce), rather than only on completed turns. It also re-runs on session state transitions (such as context compaction) and timer events when rate-limit resets_at boundaries pass.

Cloud session observation

In our claude.ai/code cloud session, a configured statusLine did not execute. The configuration remained in place across 29 model requests and a complete turn boundary. This observation is consistent with Claude Code 2.1.289's shipped code placing statusline execution in the terminal UI path, while this cloud session ran headlessly.

Study notes and limitations:

  • Tested on Claude Code 2.1.289 on October 3, 2026.
  • Based on one measured Opus 5.5 cloud session; not every Opus 5.5 session receives a 1,000,000-token window.
  • The 3.9% difference reflects additional Opus requests counted in this measured session, not a universal undercount rate.
  • Because the statusLine hook did not execute in the cloud test session, payload structures and refresh timing were verified by checking Claude Code 2.1.289's shipped code and comparing it with runtime telemetry and current Anthropic documentation.
  • No conclusions were drawn about five-hour or weekly quota consumption because the account was operating under the promotional cloud-credit bucket.

For full field mechanics, four-turn ledger reconciliations, and citation guidance, see our first-party research hub study →

6. Troubleshooting missing values and display issues

Rate limits show “n/a” on a new session

Anthropic populates the rate_limits object only after the first API response in a session completes. When you open a fresh Claude Code session before submitting your first prompt, rate_limits is absent. Submit your first instruction, and the percentages and reset times will populate automatically.

Account authenticates using an API key (ANTHROPIC_API_KEY)

Statusline rate-limit telemetry is available exclusively for Claude Pro and Max subscription accounts authenticated via OAuth. If Claude Code authenticates using an ANTHROPIC_API_KEY environment variable, usage is billed per token through the Anthropic Console. Subscription rate-limit windows do not apply, and rate_limits will remain absent from the payload.

Context percentage displays “n/a” or null

Claude Code reports context_window.used_percentage as null early in a session before the context manager computes memory usage. Our Bash script safely displays n/a instead of throwing a shell syntax error or showing an inaccurate 0%.

Configured statusLine in claude.ai/code cloud sessions

In our claude.ai/code cloud session tested on October 3, 2026, a configured statusLine did not execute across 29 model requests and a complete turn boundary. This observation is consistent with Claude Code 2.1.289's shipped code placing statusline execution in the terminal UI path, while this cloud session ran headlessly. To check session consumption in that environment, run /usage directly.

Terminal width calculation fails (tput cols)

Because Claude Code executes statusline scripts in a subshell and captures standard output, the terminal control utility tput cols cannot inspect the active terminal dimensions and returns an error. If your script requires dynamic width calculations, read the $COLUMNS and $LINES environment variables directly:

term_width="${COLUMNS:-80}"

Script permissions error

If Claude Code fails to render the footer or logs permission errors, ensure the script has executable permissions:

chmod +x ~/.claude/statusline.sh

Verify that jq is installed and accessible in your system PATH (brew install jq on macOS or sudo apt-get install jq on Linux).

7. Optional customizations

Add estimated session cost

Claude Code tracks estimated token costs in cost.total_cost_usd. To display session cost alongside context usage, add this snippet to your script:

cost_raw=$(echo "$input" | jq -r '.cost.total_cost_usd // empty')
if [ -n "$cost_raw" ] && [ "$cost_raw" != "null" ]; then
  cost_disp=$(printf "$%.2f" "$cost_raw" 2>/dev/null)
  [ -n "$cost_disp" ] && printf " ${GRAY}|${RESET} Cost: %s" "$cost_disp"
fi

Visual progress bar for context fill

To render a compact 10-character progress bar ([████░░░░░░]) for context usage:

draw_bar() {
  local pct="${1:-0}"
  local filled=$(( pct / 10 ))
  [ "$filled" -gt 10 ] && filled=10
  local empty=$(( 10 - filled ))
  
  local bar=""
  for ((i=0; i<filled; i++)); do bar="${bar}█"; done
  for ((i=0; i<empty; i++)); do bar="${bar}░"; done
  printf "[%s]" "$bar"
}

Community tools: when to write a script vs. install a package

  • Custom Bash script (this guide): Best for lightweight, zero-dependency setups, instant startup, minimal vertical terminal consumption, and direct integration into dotfiles.
  • ccstatusline: An open-source interactive Terminal User Interface (TUI) tool (npx ccstatusline@latest) that allows you to visually configure, order, and theme modular statusline widgets without writing shell scripts.
  • claude-hud: A multi-line dashboard plugin that expands the statusline into an interactive HUD tracking active tool calls, subagent executions, and detailed token breakdowns.

Native statusline vs. continuous usage tracking

A Claude Code statusline provides excellent in-session visibility while your terminal is active and focused. However, native statuslines have architectural boundaries:

  • They are only visible while Claude Code is open and running in your active terminal pane.
  • They reflect the aggregate five_hour and seven_day limits exposed to the statusline payload, but do not display model-specific weekly allocations (such as Opus weekly buckets).
  • They cannot calculate burn-rate forecasts, recommend pacing to prevent lockouts, or send system notifications when you are away from the terminal.

If you need continuous, ambient visibility across your entire development workflow, consider using the free, local Claude Usage tracker. It runs natively on your machine, reuses your existing Claude Code OAuth login, and keeps your usage visible in your macOS menu bar, on a private localhost web dashboard, or via terminal CLI:

  • macOS Menu Bar App: Live percentage indicators and reset countdowns in your system menu bar with desktop notifications at 10%, 5%, and 0% remaining.
  • Localhost Dashboard: An auto-refreshing browser dashboard at 127.0.0.1 displaying progress bars, relative countdowns, and model-specific windows.
  • Pacing & Burn Rate: Real-time calculations of sustainable usage per day and per hour to keep you working through the weekly reset.
Install Claude Usage (Mac & Linux) →

Free · Local only · No claudeusage.dev account · No hosted telemetry or analytics · Launch at Login

To compare all available official usage surfaces including browser settings and the /usage command, consult our guide on how to check Claude usage.

Frequently asked questions

Why does my statusline show “n/a” for 5-hour and 7-day rate limits?

Anthropic populates the rate_limits JSON payload only after the first API response in a session completes. Fresh sessions show n/a until you submit your first prompt. Additionally, rate limits appear only for accounts authenticated with an active Claude Pro and Max subscription; sessions using an API key (ANTHROPIC_API_KEY) do not receive rate-limit objects.

Does the statusline script consume Claude prompt tokens or cost money?

No. The statusline runs locally on your machine. Claude Code passes session telemetry already stored in local memory directly to your script's standard input. It executes without sending API requests, does not touch external network endpoints, and consumes zero prompt tokens.

Can the statusline span multiple lines?

Yes. Claude Code renders every newline printed to standard output as an additional line in your terminal footer. However, multi-line statuslines reduce the vertical terminal space available for conversation turns, code diffs, and tool output. A single compact line of 65–75 characters preserves terminal space while surfacing essential metrics.

How do I test my statusline script without running Claude Code?

You can test your script by piping a mock JSON object into it from standard input in your terminal:

echo '{"model":{"display_name":"Claude Sonnet"},"context_window":{"used_percentage":24},"rate_limits":{"five_hour":{"used_percentage":35,"resets_at":1742651200}}}' | ~/.claude/statusline.sh

How do I completely remove or disable the statusline?

To remove the statusline, open ~/.claude/settings.json in a text editor and delete the "statusLine" configuration block. Alternatively, run /statusline inside Claude Code and instruct it to clear or remove the statusline configuration.

Does the statusline show model-specific weekly limits for Opus or Sonnet?

No. Current payloads can expose aggregate five_hour and seven_day rate-limit windows, with additional conditional rate-limit fields such as spend_limit in some environments. Model-specific weekly windows (such as Opus-only quotas) are visible in the official Claude web Settings › Usage tab or through dedicated monitoring utilities like the Claude Usage tracker.