Skip to content

Instantly share code, notes, and snippets.

@andkirby
Last active February 12, 2026 15:21
Show Gist options
  • Select an option

  • Save andkirby/f826e5d264368308cd9d5c4c086aa96e to your computer and use it in GitHub Desktop.

Select an option

Save andkirby/f826e5d264368308cd9d5c4c086aa96e to your computer and use it in GitHub Desktop.
Claude Code Statusline with context usage % - Includes workaround for https://github.com/anthropics/claude-code/issues/13385 (current_usage stays at 0)

Claude Code Statusline with context usage

A custom statusline for Claude Code CLI that displays time, user@host, current directory, context window percentage, and token counts.

Example Output

UPD: statusline-command.sh has advanced version now.

Advanced version

image

Simple version

19:56:01 myname@mylaptop:my-project-dir (51% / 200k · 102k ↑ · 15k ↓)

NOTE: all info below related to the first simple version.

TODO: make "money" optional, add context window size and session tokens (200k · 102k ↑ · 15k ↓).

Format

  • Time - Current time (red)
  • user@host:dir - User, hostname, and current directory basename
  • Context info:
    • 51% - Current context window usage percentage
    • 200k - Total context window size
    • 102k ↑ - Total input tokens sent (session cumulative)
    • 15k ↓ - Total output tokens received (session cumulative)

Color Coding

Based on context percentage:

  • ≤30%: Default color
  • 31-45%: 🟢 Green
  • 46-55%: 🟠 Orange
  • 56%+: 🔴 Red

Installation

One-Line Install (Recommended)

curl -fsSL https://gist.githubusercontent.com/andkirby/f826e5d264368308cd9d5c4c086aa96e/raw/install-statusline.sh | bash

Prerequisites

# macOS
brew install jq

# Linux
sudo apt install jq  # Debian/Ubuntu
sudo yum install jq  # RHEL/CentOS

Manual Install

  1. Download the script:
curl -fsSL https://gist.githubusercontent.com/andkirby/f826e5d264368308cd9d5c4c086aa96e/raw/statusline-command.sh -o ~/.claude/statusline-command.sh
  1. Make it executable:
chmod +x ~/.claude/statusline-command.sh
  1. Add to ~/.claude/settings.json:
{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline-command.sh"
  }
}

Testing

Test the script manually:

echo '{"workspace":{"current_dir":"/Users/user/project"},"context_window":{"context_window_size":200000,"current_usage":{"input_tokens":70000,"cache_creation_input_tokens":1000,"cache_read_input_tokens":2000},"total_input_tokens":102000,"total_output_tokens":15000}}' | ~/.claude/statusline-command.sh

Known Issues

  • Context percentage shows 0% - Due to bug #13385, current_usage may return zeros. The script uses the correct property per the API docs, so it will work when the bug is fixed.

Customization

Modify color thresholds in statusline-command.sh:

if [ $context_percent -le 30 ]; then
    context_color='\033[0m'   # Default
elif [ $context_percent -le 45 ]; then
    context_color='\033[32m'  # Green
elif [ $context_percent -le 55 ]; then
    context_color='\033[33m'  # Orange
else
    context_color='\033[31m'  # Red
fi

Color Codes

Color Code
Red \033[31m
Green \033[32m
Orange/Yellow \033[33m
Blue \033[34m
Reset \033[0m
#!/bin/bash
set -e
GIST_URL="https://gist.githubusercontent.com/andkirby/f826e5d264368308cd9d5c4c086aa96e/raw/statusline-command.sh"
SCRIPT_PATH="$HOME/.claude/statusline-command.sh"
SETTINGS_FILE="$HOME/.claude/settings.json"
echo "Installing Claude Code Statusline..."
# Create .claude directory if it doesn't exist
mkdir -p "$HOME/.claude"
# Download the script
echo "Downloading statusline script..."
curl -fsSL "$GIST_URL" -o "$SCRIPT_PATH"
# Make it executable
chmod +x "$SCRIPT_PATH"
# Update settings.json
TMP=$(mktemp)
if [ -f "$SETTINGS_FILE" ]; then
echo "Updating settings.json..."
jq '.statusLine = {"type": "command", "command": "~/.claude/statusline-command.sh"}' "$SETTINGS_FILE" > "$TMP" && mv "$TMP" "$SETTINGS_FILE"
else
echo "Creating settings.json..."
echo '{"statusLine": {"type": "command", "command": "~/.claude/statusline-command.sh"}}' > "$SETTINGS_FILE"
fi
echo ""
echo "Statusline installed successfully!"
echo "Restart Claude Code to see it."
#!/bin/bash
# Read JSON input from stdin
input=$(cat)
# Extract basic information
time=$(date +%H:%M:%S)
user=$(whoami)
host=$(hostname -s)
current_dir=$(echo "$input" | jq -r '.workspace.current_dir' | xargs basename)
# Get context window info
size=$(echo "$input" | jq '.context_window.context_window_size')
usage=$(echo "$input" | jq '.context_window.current_usage')
total_input=$(echo "$input" | jq '.context_window.total_input_tokens // 0')
total_output=$(echo "$input" | jq '.context_window.total_output_tokens // 0')
# Debug: dump context_window to stdout
#echo "$input" | jq '.context_window' >&1
# Calculate current context usage (input + cache_creation + cache_read) for percentage
current_input=$(echo "$usage" | jq '.input_tokens + .cache_creation_input_tokens + .cache_read_input_tokens')
size_k=$((size / 1000))
# Use total tokens for arrow display
input_k=$((total_input / 1000))
output_k=$((total_output / 1000))
# Calculate percentage from current_usage
context_percent=$(printf "%.0f" "$(echo "scale=2; ($current_input * 100 / $size)" | bc 2>/dev/null || echo 0)")
# Determine context color based on percentage
# After 30% - green, After 45% - orange, After 55% - red
if [ $context_percent -le 30 ]; then
context_color='\033[0m' # default/no color
elif [ $context_percent -le 45 ]; then
context_color='\033[32m' # green
elif [ $context_percent -le 55 ]; then
context_color='\033[33m' # orange/yellow
else
context_color='\033[31m' # red
fi
# Build the status line with color formatting
# Time in red, followed by user@host:dir, then context info: (% / total · input ↑ · output ↓)
printf '\033[31m%s\033[0m %s@%s:%s %b(%d%% / %dk · %dk ↑ · %dk ↓)\033[0m' \
"$time" \
"$user" \
"$host" \
"$current_dir" \
"$context_color" \
"$context_percent" \
"$size_k" \
"$input_k" \
"$output_k"
#!/usr/bin/env bash
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')
CYAN='\033[36m'; GREEN='\033[32m'; DARKGREEN='\033[38;5;22m'; YELLOW='\033[33m'; ORANGE='\033[38;5;208m'; RED='\033[31m'; WHITE='\033[97m'; RESET='\033[0m'
# Pick bar color based on context usage
if [ "$PCT" -gt 70 ]; then
BAR_COLOR='\033[38;5;196m'; BAR_DARK='\033[38;5;124m'; BAR_BG_LIGHT='\033[48;5;196m'; BAR_BG_DARK='\033[48;5;124m'
elif [ "$PCT" -gt 60 ]; then
BAR_COLOR='\033[38;5;160m'; BAR_DARK='\033[38;5;88m'; BAR_BG_LIGHT='\033[48;5;160m'; BAR_BG_DARK='\033[48;5;88m'
elif [ "$PCT" -gt 50 ]; then
BAR_COLOR='\033[38;5;208m'; BAR_DARK='\033[38;5;94m'; BAR_BG_LIGHT='\033[48;5;208m'; BAR_BG_DARK='\033[48;5;94m'
elif [ "$PCT" -gt 40 ]; then
BAR_COLOR='\033[38;5;112m'; BAR_DARK='\033[38;5;28m'; BAR_BG_LIGHT='\033[48;5;112m'; BAR_BG_DARK='\033[48;5;28m'
elif [ "$PCT" -gt 30 ]; then
BAR_COLOR='\033[38;5;40m'; BAR_DARK='\033[38;5;22m'; BAR_BG_LIGHT='\033[48;5;40m'; BAR_BG_DARK='\033[48;5;22m'
else
BAR_COLOR='\033[38;5;28m'; BAR_DARK='\033[38;5;22m'; BAR_BG_LIGHT='\033[48;5;28m'; BAR_BG_DARK='\033[48;5;22m'
fi
# 10 slots total: percentage is right-aligned, visual bar shrinks accordingly
PCT_LEN=${#PCT}
PCT_TEXT_LEN=$((PCT_LEN + 1)) # digits + "%"
VISUAL_BAR_SLOTS=$((10 - PCT_TEXT_LEN))
FILLED_SLOTS=$((PCT / 10))
# Visual bar - dots with matching fg+bg colors
BAR=""
EMPTY_SYMBOL="\u2800" # "–"
# symbolds can be used instead: · -
for i in $(seq 0 $((VISUAL_BAR_SLOTS - 1))); do
if [ "$i" -lt "$FILLED_SLOTS" ]; then
BAR="${BAR}${BAR_COLOR}${BAR_BG_LIGHT}${EMPTY_SYMBOL}${RESET}"
else
BAR="${BAR}${BAR_DARK}${BAR_BG_DARK}${EMPTY_SYMBOL}${RESET}"
fi
done
# Percentage text - right-aligned, white fg, colored bg
PCT_TEXT=""
PCT_FULL="${PCT}%"
for i in $(seq $VISUAL_BAR_SLOTS 9); do
pos=$((i - VISUAL_BAR_SLOTS))
char_idx=$((PCT_TEXT_LEN - 1 - (9 - i)))
if [ "$char_idx" -ge 0 ] && [ "$char_idx" -lt "${#PCT_FULL}" ]; then
char="${PCT_FULL:$char_idx:1}"
else
char=" "
fi
if [ "$i" -lt "$FILLED_SLOTS" ]; then
PCT_TEXT="${PCT_TEXT}${WHITE}${BAR_BG_LIGHT}${char}${RESET}"
else
PCT_TEXT="${PCT_TEXT}${WHITE}${BAR_BG_DARK}${char}${RESET}"
fi
done
HOURS=$((DURATION_MS / 3600000))
MINS=$(((DURATION_MS % 3600000) / 60000))
SECS=$(((DURATION_MS % 60000) / 1000))
BRANCH=""
git rev-parse --git-dir > /dev/null 2>&1 && BRANCH=" | 🌿 $(git branch --show-current 2>/dev/null)"
echo -ne "\033[1;38;5;30m${MODEL}${RESET} 📁 ${DIR##*/}$BRANCH | "
COST_FMT=$(printf '$%.2f' "$COST")
if [ "$HOURS" -gt 0 ]; then
echo -e "${BAR}${PCT_TEXT} | 💰 ${YELLOW}${COST_FMT}${RESET} | ⏱️ ${HOURS}h ${MINS}m"
elif [ "$MINS" -gt 10 ]; then
echo -e "${BAR}${PCT_TEXT} | 💰 ${YELLOW}${COST_FMT}${RESET} | ⏱️ ${MINS}m"
else
echo -e "${BAR}${PCT_TEXT} | 💰 ${YELLOW}${COST_FMT}${RESET} | ⏱️ ${MINS}m ${SECS}s"
fi
#!/usr/bin/env bash
# Test different color segments of statusline
STATUSLINE_SCRIPT="$HOME/.claude/statusline-command.sh"
test_color() {
local pct="$1"
local desc="$2"
local duration_ms="${3:-15000}"
local json=$(cat <<EOF
{
"model": {"display_name": "Opus 4.6"},
"workspace": {"current_dir": "/Users/user/project"},
"cost": {"total_cost_usd": 0.22, "total_duration_ms": $duration_ms},
"context_window": {"used_percentage": $pct}
}
EOF
)
echo "[$pct% - $desc]"
echo "→ $(echo "$json" | "$STATUSLINE_SCRIPT")"
}
echo "=== Statusline Color Segments ==="
# 0-30: green (28)
test_color "7" "0-30%: Green" "45000"
test_color "28" "0-30%: Green" "150000"
# >30: color 40
test_color "35" ">30%: Color 40" "510000"
# >40: color 112
test_color "45" ">40%: Color 112" "900000"
# >50: color 130
test_color "55" ">50%: Color 130" "3599000"
# >60: color 160
test_color "65" ">60%: Color 160" "3900000"
# >70: color 196 (red)
test_color "80" ">70%: Color 196 (Red)" "9296000"
test_color "100" ">70%: Color 196 (Red)" "18900000"
echo "=== End ==="
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment