Building a Custom Status Line for Claude Code
How to create a rich, informative status line showing model info, context usage, and git status in Claude Code CLI.
Claude Code supports custom status lines via bash scripts. Here's how to build one that shows model, context usage, and git status at a glance.
Quick Start
The fastest way — just run in Claude Code:
/statusline show model name and context percentage with a progress barClaude Code generates the script and updates settings automatically. For full control, read on.
Result
Manual Setup
1. Add to ~/.claude/settings.json:
{
"statusLine": {
"type": "command",
"command": "bash ~/.claude/statusline.sh"
}
}2. Create ~/.claude/statusline.sh and make it executable (chmod +x):
#!/bin/bash
input=$(cat)
# Extract data
model_name=$(echo "$input" | jq -r '.model.display_name // .model.id')
cwd=$(echo "$input" | jq -r '.workspace.current_dir')
project_dir=$(echo "$input" | jq -r '.workspace.project_dir')
total_input=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')
context_size=$(echo "$input" | jq -r '.context_window.context_window_size // 0')
used_pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
# Shorten model name
short_model="$model_name"
[[ "$model_name" =~ Opus ]] && short_model="Opus 4.5"
[[ "$model_name" =~ Sonnet ]] && short_model="Sonnet 4"
[[ "$model_name" =~ Haiku ]] && short_model="Haiku 3.5"
# Format tokens (42000 -> 42k)
format_tokens() {
local n=$1
[ "$n" -ge 1000 ] && echo "$((n / 1000))k" || echo "$n"
}
tokens_display=$(format_tokens "$total_input")
context_display=$(format_tokens "$context_size")
# Progress bar
bar_width=10
filled=$((used_pct * bar_width / 100))
empty=$((bar_width - filled))
progress_bar="["
for ((i=0; i<filled; i++)); do progress_bar+="="; done
for ((i=0; i<empty; i++)); do progress_bar+=" "; done
progress_bar+="]"
# Git info
project_name=$(basename "$project_dir")
git_branch=""
if git -C "$cwd" rev-parse --git-dir > /dev/null 2>&1; then
git_branch=$(git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null || \
git -C "$cwd" rev-parse --short HEAD 2>/dev/null)
fi
# Colors
CYAN=$'\033[36m' YELLOW=$'\033[33m' RED=$'\033[31m' BLUE=$'\033[34m' RESET=$'\033[0m'
# Build output
if [ -n "$git_branch" ]; then
dirty=""
git -C "$cwd" diff-index --quiet HEAD -- 2>/dev/null || dirty=" ${YELLOW}✗${RESET}"
git_status="${CYAN}${project_name}${RESET}${BLUE}(${RED}${git_branch}${BLUE})${RESET}${dirty}"
else
git_status="${CYAN}${project_name}${RESET}"
fi
echo "${CYAN}${short_model}${RESET} ${progress_bar} ${YELLOW}${used_pct}%${RESET} | ${tokens_display}/${context_display} | ${git_status}"Available Data
Claude Code pipes JSON to your script via stdin. Key fields:
| Field | Description |
|---|---|
model.id, model.display_name | Current model identifier and name |
context_window.used_percentage | Pre-calculated % of context used |
context_window.total_input_tokens | Cumulative input token count |
context_window.total_output_tokens | Cumulative output token count |
context_window.context_window_size | Maximum context window size |
cost.total_cost_usd | Total session cost in USD |
cost.total_duration_ms | Wall-clock time since session start |
cost.total_lines_added / removed | Lines of code changed |
workspace.current_dir | Current working directory |
workspace.project_dir | Directory where Claude Code launched |
vim.mode | Current vim mode (NORMAL / INSERT) |
session_id | Unique session identifier |
The script runs after each assistant message, debounced at 300ms. Keep it fast — avoid network calls.
Rate limits not available. Hourly usage limits aren't exposed to statusline scripts. Feature request.
Customization
Alternative progress bars:
# Blocks: [▓▓▓░░░░░░░]
for ((i=0; i<filled; i++)); do progress_bar+="▓"; done
for ((i=0; i<empty; i++)); do progress_bar+="░"; done
# Dots: [●●●○○○○○○○]
for ((i=0; i<filled; i++)); do progress_bar+="●"; done
for ((i=0; i<empty; i++)); do progress_bar+="○"; doneColor-coded percentage:
[ "$used_pct" -lt 50 ] && pct_color=$'\033[32m' || \
[ "$used_pct" -lt 80 ] && pct_color=$'\033[33m' || pct_color=$'\033[31m'Show session cost:
cost=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
# Add to output: | \$${cost}To remove: run /statusline delete or remove the statusLine field from settings.json.
Related Posts
5 Claude Code Features That Will Boost Your Workflow
opusplan, 1M context windows, agent teams, fast mode, and effort levels — many arriving with Opus 4.6, these features make Claude Code a much sharper tool.
Using MCP to Compare Figma Designs Against Your Frontend
Set up Figma, Playwright, and Chrome extension MCP servers in Claude Code to automatically compare your live frontend against Figma designs.