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
/statuslinein Claude Code with natural language instructions to auto-generate a script in~/.claude/. - Deterministic setup: Add a
statusLinecommand in~/.claude/settings.jsonpointing to an executable Bash script that parses JSON viajq. - 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_atepoch 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).
Statusline breakdown:
[Sonnet]: Active model name parsed frommodel.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 aboveClaude 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.shStep 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.sh3. 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:
| Meter | Payload JSON Field | What It Measures | How It Clears or Resets |
|---|---|---|---|
| Context Window | context_window.used_percentage | Memory fill of the active model's context window. | Clears or reduces when you run /compact or start a new session with /clear. |
| 5-Hour Session | rate_limits.five_hour.used_percentage | Account 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 Weekly | rate_limits.seven_day.used_percentage | Cumulative 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 Path | Type | Description |
|---|---|---|
| model.id | string | Unique model identifier (e.g., "claude-opus-5-5"). |
| model.display_name | string | Human-readable model label (e.g., "Claude Opus 5.5"). |
| workspace.current_dir | string | Absolute path to the current working directory. |
| workspace.project_dir | string | Root path of the current project or repository. |
| context_window.used_percentage | number | null | Percentage (0–100) of the active context window currently used. May be null before turn 1. |
| context_window.total_input_tokens | integer | Context token total from the latest model response, including raw input tokens plus prompt cache read and cache write tokens. |
| context_window.context_window_size | integer | Total context window size in tokens (200,000 by default, or 1,000,000 for models with extended context). |
| rate_limits.five_hour.used_percentage | number | Consumed percentage (0–100) of the rolling 5-hour session allowance. |
| rate_limits.five_hour.resets_at | integer | Unix epoch timestamp (seconds) when the current 5-hour window resets. |
| rate_limits.seven_day.used_percentage | number | Consumed percentage (0–100) of the 7-day weekly allowance across all models. |
| rate_limits.seven_day.resets_at | integer | Unix epoch timestamp (seconds) when the current 7-day window resets. |
| cost.total_cost_usd | number | Cumulative session cost in USD calculated from Claude Code's internal list-price ledger. |
| cost.total_duration_ms | integer | Wall-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.shVerify 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"
fiVisual 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_hourandseven_daylimits 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.
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.shHow 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.