Practical guidance for Claude Code status lines - what to display for real workflow benefits, not just configuration syntax. Use when setting up status lines or wondering what information would actually help.
Inherits all available tools
Additional assets for this skill
This skill inherits all available tools. When active, it can use any tool Claude has access to.
This skill provides practical guidance on what makes status lines useful. The official docs explain how to configure them; this skill explains what to display and why.
Fetch official documentation with WebFetch:
Status lines are a real-time development dashboard at the bottom of Claude Code. Think vim statusline or tmux status bar - persistent, glanceable, always-current information.
How they work:
What you DON'T need a status line skill to know:
Claude knows all that. This skill focuses on what to display based on real developer workflows.
The problem: You're deep in a session and suddenly realize you've burned through $15 in API costs.
The solution: Display session cost and daily total prominently.
cost=$(echo "$input" | jq -r '.cost.total_cost_usd')
printf "💰 \$%.4f" "$cost"
Workflow benefit: Catch runaway sessions early. Know when to switch models.
The problem: Claude starts forgetting earlier context because you've filled the window.
The solution: Display context usage percentage.
Workflow benefit: Know when to compact (/compact) or start fresh before context degrades.
Note: The official JSON schema includes cost data but context percentage requires external tools like ccstatusline.
The problem: You switched to haiku for a quick task and forgot, now wondering why responses feel different.
The solution: Always show current model.
model=$(echo "$input" | jq -r '.model.display_name')
echo "[$model]"
Workflow benefit: Model awareness without checking settings. Crucial when switching between opus/sonnet/haiku for different task types.
The problem: You're making changes on the wrong branch.
The solution: Show current git branch in status line.
if git rev-parse --git-dir > /dev/null 2>&1; then
branch=$(git symbolic-ref --short HEAD 2>/dev/null || echo "detached")
echo "🌿 $branch"
fi
Workflow benefit: Never commit to main accidentally. Stay oriented in multi-branch workflows.
The problem: Claude Code 5-hour blocks expire and you lose context.
The solution: Display session duration or time remaining in block.
duration_sec=$(echo "$input" | jq -r '.cost.total_duration_ms / 1000 | floor')
printf "[%dm]" "$((duration_sec / 60))"
Workflow benefit: Plan commits and breaks around block boundaries. Don't lose work mid-session.
The problem: Working across multiple projects and forgetting which terminal is which.
The solution: Show project directory name.
dir=$(echo "$input" | jq -r '.workspace.project_dir' | xargs basename)
echo "📁 $dir"
Workflow benefit: Instant orientation. Critical in multi-terminal setups.
#!/bin/bash
input=$(cat)
model=$(echo "$input" | jq -r '.model.display_name')
dir=$(echo "$input" | jq -r '.workspace.current_dir' | xargs basename)
echo "[$model] 📁 $dir"
Best for: Simple awareness, low noise.
#!/bin/bash
input=$(cat)
model=$(echo "$input" | jq -r '.model.display_name')
cost=$(echo "$input" | jq -r '.cost.total_cost_usd')
dir=$(echo "$input" | jq -r '.workspace.project_dir')
branch=""
if git -C "$dir" rev-parse --git-dir > /dev/null 2>&1; then
branch=" 🌿 $(git -C "$dir" symbolic-ref --short HEAD 2>/dev/null)"
fi
printf "[%s]%s 💰 \$%.4f\n" "$model" "$branch" "$cost"
Best for: Most development workflows. Balance of information and brevity.
When working without an IDE (terminal-only), you need more context:
#!/bin/bash
input=$(cat)
model=$(echo "$input" | jq -r '.model.display_name')
dir=$(echo "$input" | jq -r '.workspace.project_dir')
# Full git status for terminal-only work
if git -C "$dir" rev-parse --git-dir > /dev/null 2>&1; then
branch=$(git -C "$dir" symbolic-ref --short HEAD 2>/dev/null)
staged=$(git -C "$dir" diff --cached --numstat | wc -l | tr -d ' ')
unstaged=$(git -C "$dir" diff --numstat | wc -l | tr -d ' ')
echo "[$model] $branch ✓$staged ✗$unstaged"
else
echo "[$model] ${dir##*/}"
fi
Best for: Pure terminal development without IDE git integration.
Multi-line powerline-style status with widgets. Interactive TUI configuration.
When to use: You want rich visuals without writing scripts, or need widgets for context percentage/tokens.
Install: npx ccstatusline@latest
18 atomic components, 1-9 configurable lines, TOML configuration.
When to use: Complex layouts, cost projections, MCP server monitoring, Islamic prayer times integration.
Unique features: Cache efficiency metrics, burn rate alerts, daily/weekly/monthly cost tracking.
Focused on cost tracking with visual burn rate indicators.
When to use: Cost management is your primary concern.
Ask yourself:
What problem am I solving?
How much information density?
How performance-sensitive?
Custom script vs community tool?
Scripts run frequently (every 300ms throttle). Keep them fast.
Safe (use JSON data only):
model=$(echo "$input" | jq -r '.model.display_name')
cost=$(echo "$input" | jq -r '.cost.total_cost_usd')
Usually fine (git is fast locally):
branch=$(git symbolic-ref --short HEAD 2>/dev/null)
Potentially slow (cache if needed):
# External API calls, npm commands, slow git operations
Caching pattern for slow operations:
CACHE_FILE="/tmp/statusline_cache"
CACHE_TTL=5
if [ -f "$CACHE_FILE" ] && [ $(($(date +%s) - $(stat -f%m "$CACHE_FILE"))) -lt $CACHE_TTL ]; then
cat "$CACHE_FILE"
else
expensive_result=$(expensive_command)
echo "$expensive_result" > "$CACHE_FILE"
echo "$expensive_result"
fi
Problem: Status line so long it wraps or gets truncated.
Reality: You'll stop reading it. Less is more.
Fix: Pick 3-4 most valuable pieces. Use community tools for multi-line if you need more.
Problem: Status line lags behind, script takes 500ms+.
Impact: Typing feels sluggish.
Fix: Profile with time echo '{}' | ./statusline.sh. Keep under 100ms ideally.
Problem: Script fails or shows errors in non-git directories.
Fix: Always check:
if git rev-parse --git-dir > /dev/null 2>&1; then
# git commands here
fi
Problem: Script assumes jq is installed.
Fix: Use Python or Node instead, or check for jq:
if ! command -v jq &> /dev/null; then
echo "[status line: jq required]"
exit 0
fi
Problem: Status line doesn't work.
Fix: chmod +x ~/.claude/statusline.sh
Fastest path to useful status line:
# Create script
cat > ~/.claude/statusline.sh << 'EOF'
#!/bin/bash
input=$(cat)
model=$(echo "$input" | jq -r '.model.display_name')
cost=$(echo "$input" | jq -r '.cost.total_cost_usd')
dir=$(echo "$input" | jq -r '.workspace.current_dir' | xargs basename)
printf "[%s] 📁 %s 💰 \$%.4f\n" "$model" "$dir" "$cost"
EOF
# Make executable
chmod +x ~/.claude/statusline.sh
# Configure (add to ~/.claude/settings.json)
# {
# "statusLine": {
# "type": "command",
# "command": "~/.claude/statusline.sh"
# }
# }
Or use /statusline command to have Claude Code set it up for you.
Your script receives this via stdin (partial list - see official docs for complete schema):
{
"model": {
"id": "model-identifier",
"display_name": "Claude 3.5 Sonnet"
},
"workspace": {
"current_dir": "/path/to/current",
"project_dir": "/path/to/project"
},
"cost": {
"total_cost_usd": 0.012,
"total_duration_ms": 45000
},
"session_id": "unique-id",
"version": "1.0.80"
}
Key fields for workflows:
model.display_name - Current model namecost.total_cost_usd - Session costcost.total_duration_ms - Session durationworkspace.project_dir - Project rootworkspace.current_dir - Current directory