Skip to main content

Performance Targets

From README.md:246-253, cc-statusline is designed for minimal performance impact:
MetricTargetTypical
Execution Time<100ms45-80ms
Memory Usage<5MB~2MB
CPU ImpactNegligible<1%
DependenciesMinimaljq only
Benchmarked on macOS with all features enabled

Performance Categories

From src/cli/preview.ts:88-92, statuslines are categorized by execution time:

🚀 Excellent

<100msIdeal performance. No noticeable delay.

✅ Good

100-500msAcceptable. Slight delay but usable.

⚠️ Slow

500-1000msNoticeable delay. Optimization recommended.

🐌 Timeout

>1000msPoor performance. Action required.

Measuring Performance

Use the preview command to benchmark your statusline:
cc-statusline preview .claude/statusline.sh
Example output:
✔ Test completed in 67ms

📊 Performance: 🚀 excellent (67ms)
Run preview multiple times to get average performance. First run may be slower due to disk caching.

Performance Impact by Feature

Zero-Cost Features

These features have negligible performance impact (<5ms):
Impact: ~1msWhy fast: Simple environment variable lookup and string replacement
current_dir=$(pwd | sed "s|^$HOME|~|g")
Impact: ~2msWhy fast: Direct JSON field extractionWith jq:
model_name=$(echo "$input" | jq -r '.model.display_name')
Impact: <1msWhy fast: Simple string concatenationColors are ANSI escape codes - no computation needed.

Low-Cost Features

These features add minimal overhead (5-20ms):
Impact: ~10msWhy reasonably fast: Single git command with caching
git_branch=$(git symbolic-ref --short HEAD 2>/dev/null)
Git operations are cached by the OS. Subsequent calls are faster.
Impact: ~5ms with jq, ~15ms withoutWhy fast: Simple arithmetic on JSON fieldsFrom bash-generator.ts:164-198:
CONTEXT_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size')
CURRENT_TOKENS=$(echo "$USAGE" | jq '(.input_tokens // 0) + (.cache_creation_input_tokens // 0)')
context_remaining_pct=$(( 100 - (CURRENT_TOKENS * 100 / CONTEXT_SIZE) ))

Medium-Cost Features

These features can add noticeable overhead (20-100ms):
Impact: ~50-200msWhy slower: Requires spawning ccusage process
npx ccusage@latest
This is the single most expensive operation. Can add 100-500ms if ccusage cache is cold.
Optimization: ccusage includes file-based locking to prevent concurrent execution:From README.md:278-305 (locking mechanism tests):
# Only 1 process runs ccusage at a time
# Others skip gracefully
Impact: ~10-30msWhy slower: Requires parsing large usage data from ccusageDepends on ccusage call + additional jq parsing.
Impact: ~5-15msWhy slower: Additional calculations on usage dataRequires ccusage data + burn rate calculation.
Impact: ~20-40msWhy slower: Time zone calculations and formattingRequires ccusage + date/time arithmetic + progress bar rendering.

Optimization Strategies

Strategy 1: Minimal Configuration

For maximum speed, use only essential features:
cc-statusline init
# Select only:
# ✓ 📁 Working Directory
# ✓ 🌿 Git Branch
# ✓ 🤖 Model Name
# ✓ 🧠 Context Remaining
# ✗ All usage/cost features
Expected performance: 20-40ms

Strategy 2: Disable ccusage

ccusage is the slowest component. If you don’t need cost tracking:
cc-statusline init
# Deselect:
# ✗ 💵 Usage & Cost
# ✗ 📊 Token Statistics  
# ✗ ⚡ Burn Rate
# ✗ ⌛ Session Reset Time
Expected improvement: -100 to -500ms

Strategy 3: Install jq

The bash fallback parser is slower than jq:
brew install jq
Expected improvement: -10 to -30ms for JSON parsing From README.md:42:
⚠️ Basic fallback parser is used (less reliable)

Strategy 4: Disable Logging

Debug logging adds I/O overhead:
cc-statusline init
# Select "No" for debug logging
Expected improvement: -5 to -10ms From bash-generator.ts:64-84, logging includes:
  • File I/O to .claude/statusline.log
  • JSON formatting
  • Multiple echo statements

Strategy 5: Use Compact Theme

Progress bars and formatting add rendering time:
cc-statusline init
# This is not exposed in prompts yet, but you can edit the generated script
# Look for progress_bar() function calls and simplify
Expected improvement: -2 to -5ms

Technical Optimizations

Bash Script Optimization

The generated bash script is already optimized:
All JSON fields are extracted in one pass to avoid multiple jq invocations.From bash-generator.ts:127-133:
if [ "$HAS_JQ" -eq 1 ]; then
  current_dir=$(echo "$input" | jq -r '.workspace.current_dir')
  model_name=$(echo "$input" | jq -r '.model.display_name')  
  model_version=$(echo "$input" | jq -r '.model.version')
  # All extracted in one conditional block
fi
Features are only executed if enabled during generation.From bash-generator.ts:9-14:
const hasGit = config.features.includes('git')
const hasUsage = config.features.some(f => ['usage', 'session', 'tokens', 'burnrate'].includes(f))

// Only generate code for enabled features
${hasGit ? generateGitBashCode(gitConfig, config.colors) : ''}
Missing dependencies don’t cause errors or retries.
if command -v jq >/dev/null 2>&1; then
  HAS_JQ=1
else
  HAS_JQ=0
  # Use bash fallback
fi
Command substitution is minimized to reduce process spawning.

ccusage Locking Mechanism

From README.md:278-305, cc-statusline prevents performance issues from concurrent ccusage calls:
# File-based locking ensures only 1 ccusage process at a time
# Other statusline updates skip usage data gracefully
Benefits:
  • Prevents process pile-up
  • No hanging processes
  • Automatic lock cleanup
Test the locking:
# Spawn 10 concurrent statusline processes
for i in {1..10}; do 
  echo '{}' | .claude/statusline.sh & 
done

# Verify only 1 ccusage runs
ps aux | grep ccusage

Benchmarking Different Configurations

Minimal Config

# Features: directory, git, model
cc-statusline preview .claude/statusline.sh
Expected: 20-40ms

Standard Config

# Features: directory, git, model, context
cc-statusline preview .claude/statusline.sh
Expected: 40-60ms

Full Config (No ccusage)

# Features: directory, git, model, context
# Colors: enabled
# Logging: disabled
cc-statusline preview .claude/statusline.sh
Expected: 45-70ms

Maximum Config

# All features including ccusage
cc-statusline preview .claude/statusline.sh
Expected: 100-300ms (first run), 50-150ms (cached)

Real-World Performance

From README.md:247-253, typical real-world measurements:
ConfigurationCold StartWarm Cache
Minimal35ms25ms
Standard60ms45ms
Full + ccusage250ms80ms
”Cold start” means first run after system boot. “Warm cache” means subsequent runs with OS caching.

Monitoring Performance

Enable Performance Logging

Add timing to your statusline:
# Edit .claude/statusline.sh manually
# Add at the top:
START_TIME=$(date +%s%N)

# Add at the end:
END_TIME=$(date +%s%N)
ELAPSED=$(( (END_TIME - START_TIME) / 1000000 ))
echo "[Performance: ${ELAPSED}ms]" >> .claude/statusline-perf.log

Analyze Performance Logs

# View performance history
cat .claude/statusline-perf.log

# Calculate average
awk -F'[' '{print $2}' .claude/statusline-perf.log | \
  awk -F'ms' '{sum+=$1; count++} END {print "Average: " sum/count "ms"}'

Troubleshooting Slow Performance

1

Identify the Bottleneck

Enable debug logging and check which features are taking time:
# Edit .claude/statusline.sh
# Add time stamps around each feature
echo "[$(date +%s%N)] Starting git branch" >> .claude/statusline.log
git_branch=$(git symbolic-ref --short HEAD 2>/dev/null)
echo "[$(date +%s%N)] Completed git branch" >> .claude/statusline.log
2

Check ccusage Performance

Test ccusage directly:
time npx ccusage@latest
If this takes >500ms, ccusage is the bottleneck.
3

Verify jq Installation

time echo '{}' | jq .
Should be <10ms. If slower, reinstall jq.
4

Check Disk I/O

If logging is enabled:
# Disable logging and compare
cc-statusline init
# Select "No" for logging

Best Practices

Begin with basic features and add more as needed.This helps identify which features impact performance most for your setup.
If you don’t look at cost tracking, disable it.Every disabled feature improves performance.
Always install jq on your system.The bash fallback is 2-3x slower for JSON parsing.
Enable logging only for debugging.Disable it once your statusline is working correctly.
Run preview periodically to ensure performance hasn’t degraded.
# Add to your regular workflow
cc-statusline preview .claude/statusline.sh

Performance FAQ

Answer: OS disk caching, ccusage cache warming, and npm package loading.Subsequent runs are much faster due to caching.
Answer: No, statusline runs asynchronously and doesn’t block user input.Even a 500ms statusline won’t impact your ability to type or interact with Claude Code.
Answer: Statusline update frequency is controlled by Claude Code, not cc-statusline.Typically updates on each command completion.
Answer: No, ANSI escape codes have negligible performance impact (<1ms).Disabling colors won’t improve performance noticeably.

Next Steps

Configuration Guide

Learn about all available features

Troubleshooting

Fix common issues

Build docs developers (and LLMs) love