How to Set Up a Custom Status Line in Claude Code: Display Context Usage, Model, and Session Cost
Configure a custom status line in Claude Code by adding a statusLine object to .claude/settings.json that executes a script receiving JSON payload data on STDIN, enabling real-time display of context consumption, model name, estimated cost, and session metadata.
The Claude Code Best-Practice repository demonstrates how to extend Claude Code's interface through custom UI components. A custom status line provides critical visibility into expensive API calls and context window limits, helping you monitor token consumption and model selection without leaving the composer pane.
Understanding the Status Line Architecture
Claude Code injects a UI layer beneath the composer that can execute external commands on every refresh. According to the repository's architecture, the Settings layer in .claude/settings.json drives UI customization, including the status line configuration documented in best-practice/claude-settings.md (lines 84-98).
The system operates through three mechanisms:
- Configuration – Define a
statusLineobject with"type": "command"pointing to an executable script - Invocation – Claude Code runs the command on each UI refresh, passing a JSON blob via STDIN
- Rendering – The script's STDOUT appears as formatted text in the status bar, with optional
paddingfor spacing
Configuring the Status Line in settings.json
Create or modify .claude/settings.json (or settings.local.json for user-specific overrides) to register your status command. The repository includes a minimal example at lines 65-69:
{
"statusLine": {
"type": "command",
"command": "echo \"shayan's best practice status line\"",
"padding": 0
}
}
For a functional implementation, point the command to an executable script that parses the incoming JSON payload. The payload contains fields such as context_window.used_percentage, context_window.remaining_percentage, current_usage, exceeds_200k_tokens, model, and modelCost.
Building a Real-Time Status Script
Create an executable script at ~/.claude/statusline.sh that reads STDIN and formats the output. The script below uses jq to extract context usage, model name, and cost data, then combines it with git and directory information:
#!/usr/bin/env bash
# ~/.claude/statusline.sh
# Reads JSON from Claude Code and outputs formatted status line
read -r payload
model=$(echo "$payload" | jq -r '.model // "unknown"')
used=$(echo "$payload" | jq -r '.context_window.used_percentage // "0"')
remain=$(echo "$payload" | jq -r '.context_window.remaining_percentage // "0"')
cost=$(echo "$payload" | jq -r '.modelCost // "0"')
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "no-branch")
dir=$(pwd | sed "s|$HOME|~|")
printf "[%s] %s%% used (%s%% left) • $%s • %s • %s\n" \
"$model" "$used" "$remain" "$cost" "$branch" "$dir"
Make the script executable and update your configuration:
chmod +x ~/.claude/statusline.sh
Then reference it in .claude/settings.json:
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh",
"padding": 1
}
}
Implementing Auto-Compaction Thresholds
Extend your status line logic to trigger session maintenance when context usage exceeds safe limits. By monitoring context_window.used_percentage, you can automate /compact calls when usage crosses 90%.
Create ~/.claude/auto-compact.sh to run as a background task:
#!/usr/bin/env bash
# ~/.claude/auto-compact.sh
# Background watcher for automatic context compaction
while true; do
payload=$(claude statusline)
used=$(echo "$payload" | jq -r '.context_window.used_percentage')
if (( used > 90 )); then
claude /compact
fi
sleep 5
done
Execute this via /task to maintain optimal context levels without manual intervention, preventing token limit errors during long sessions.
Summary
- The
statusLineconfiguration in.claude/settings.jsonaccepts acommandtype that executes on every UI refresh, receiving JSON data on STDIN. - Payload fields include
context_window.used_percentage,model,modelCost, and session directories, enabling precise monitoring of resource consumption. - Implementation requires an executable script (typically bash with
jq) that reads STDIN and prints a single-line summary to STDOUT. - Advanced workflows can leverage the same JSON payload to trigger auto-compaction when context usage exceeds defined thresholds.
Frequently Asked Questions
What data does the Claude Code status line JSON payload contain?
The JSON payload sent to your script includes context_window.used_percentage, context_window.remaining_percentage, current_usage, exceeds_200k_tokens, model, modelCost, and directory information from /add-dir commands. The full schema is documented in best-practice/claude-settings.md.
Can I use Python instead of Bash for the status line script?
Yes, any executable that reads STDIN and prints to STDOUT works. Configure the command path in settings.json to point to a Python script (e.g., "command": "~/.claude/statusline.py"), then parse sys.stdin using the json module and print your formatted status string.
Why doesn't my status line update immediately after editing settings.json?
Changes require a settings reload. Run /config in Claude Code and select "Reload settings," or restart the application. Verify the script path is absolute and the file has execute permissions (chmod +x).
How do I show Git branch information in the Claude Code status line?
Include the git rev-parse --abbrev-ref HEAD command in your status script, as shown in the bash example. Claude Code executes the status command within the current working directory, so standard git commands resolve to the active project repository.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →