Claude Code statusline
The Claude Code statusline is a customizable bar at the bottom of the terminal that runs a shell script after each assistant message. Claude Code sends JSON session data to stdin, and whatever the script prints becomes the status bar content -- ANSI colors included.
My setup displays the current model, a context window progress bar, and rate limit information when available.
Configuration
The statusline is enabled in ~/.claude/settings.json:
The script at ~/.claude/statusline-command.sh:
#!/usr/bin/env bash input=$(cat) CYN='\033[1;36m' GRN='\033[0;32m' YLW='\033[0;33m' MAG='\033[0;35m' RST='\033[0m' eval "$(echo "$input" | jq -r ' @sh "model=\(.model.display_name // "Claude")", @sh "used=\(.context_window.used_percentage // "")", @sh "rl_pct=\(.rate_limits.five_hour.used_percentage // .rate_limits.seven_day.used_percentage // "")", @sh "rl_reset=\(.rate_limits.five_hour.resets_at // .rate_limits.seven_day.resets_at // "")", @sh "rl_label=\(if .rate_limits.five_hour.used_percentage then "5h" elif .rate_limits.seven_day.used_percentage then "7d" else "" end)" ')" printf "%b%b" "$CYN" "$model" if [ -n "$used" ]; then used_int=$(printf '%.0f' "$used") filled=$((used_int / 5)) bar=$(printf "%${filled}s" | tr ' ' '#')$(printf "%$((20 - filled))s" | tr ' ' '-') printf "%b 📊 %b[%b%s%b]%b %s%%" "$RST" "$RST" "$GRN" "$bar" "$RST" "$YLW" "$used_int" fi if [ -n "$rl_pct" ]; then rl_int=$(printf '%.0f' "$rl_pct") reset_time="" [ -n "$rl_reset" ] && reset_time=$(date -d "@${rl_reset}" +%H:%M 2>/dev/null || date -r "${rl_reset}" +%H:%M) printf " %b⏱️%s:%s%%%b" "$MAG" "$rl_label" "$rl_int" "$RST" [ -n "$reset_time" ] && printf " %s" "$reset_time" fi printf "%b" "$RST"
What it shows
The script parses the JSON that Claude Code pipes in and displays up to three pieces of information on a single line:
Model name in bold cyan (e.g. "Opus" or "Sonnet")
Context window usage as a 20-character progress bar (
#for filled,-for empty) with a percentageRate limit usage for the 5-hour or 7-day window, including the reset time -- this only appears when the data is available (Claude Pro/Max subscriptions)
Before the first API response, only the model name is shown because context and rate limit fields are still null.

How it works
Claude Code runs the configured command after each assistant message and on permission mode changes.
The full session state is sent as JSON to stdin -- the documentation lists all available fields.
The script uses jq to extract what it needs and printf with ANSI escape codes to produce colored output.
One thing to note: the // empty fallback in jq is important.
Fields like used_percentage and the rate limit data are null before the first API call, so without the fallback the script would print "null" in the status bar.
The /statusline slash command can generate a script from a natural language description, but I used Claude Code itself to iterate on the script until I was happy with the output.


