From 6e599d51933b57a299e8e3dfa6944ca1267ff97f Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 17 Jan 2026 14:10:08 +0000 Subject: [PATCH 1/5] Add status line --- claude-plugin/statusline/statusline.sh | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 claude-plugin/statusline/statusline.sh diff --git a/claude-plugin/statusline/statusline.sh b/claude-plugin/statusline/statusline.sh new file mode 100755 index 0000000..98820c8 --- /dev/null +++ b/claude-plugin/statusline/statusline.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Read JSON input from stdin +input=$(cat) + +# Extract context stats using jq +USED_TOKENS=$(echo "$input" | jq -r '(.context_window.total_input_tokens // 0) + (.context_window.total_output_tokens // 0)') +USED_PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0') + +# Calculate total context window from percentage +if (( $(echo "$USED_PCT > 0" | bc -l) )); then + MAX_TOKENS=$(echo "scale=0; $USED_TOKENS * 100 / $USED_PCT" | bc) +else + MAX_TOKENS=0 +fi + +# Format token counts (e.g., 15234 -> 15.2k) +format_tokens() { + local tokens=$1 + if [ "$tokens" -ge 1000 ]; then + echo "$(echo "scale=1; $tokens / 1000" | bc)k" + else + echo "$tokens" + fi +} + +USED_FMT=$(format_tokens "$USED_TOKENS") +MAX_FMT=$(format_tokens "$MAX_TOKENS") + +# Color based on usage (green < 50%, yellow 50-75%, red > 75%) +if (( $(echo "$USED_PCT < 50" | bc -l) )); then + COLOR="\033[32m" # Green +elif (( $(echo "$USED_PCT < 75" | bc -l) )); then + COLOR="\033[33m" # Yellow +else + COLOR="\033[31m" # Red +fi +RESET="\033[0m" + +# Output: 68.4k/200k tokens (20%) +printf "%s/%s tokens ${COLOR}(%.0f%%)${RESET}" "$USED_FMT" "$MAX_FMT" "$USED_PCT" From c26ebee6afe8b0644d6f0acba4ee3f853bf4b45a Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 17 Jan 2026 14:32:28 +0000 Subject: [PATCH 2/5] Add visual context bar and documentation to status line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace token count with ASCII progress bar (■◧□) - Show model name prefix (e.g., "Opus 4.5 | ctx") - Color coding: grey (<60%), orange (60-80%), red (>80%) - Hide status line when context is 0% - Add README with setup instructions --- claude-plugin/README.md | 33 ++++++++++++++++ claude-plugin/statusline/statusline.sh | 52 ++++++++++++++------------ 2 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 claude-plugin/README.md diff --git a/claude-plugin/README.md b/claude-plugin/README.md new file mode 100644 index 0000000..937aaf8 --- /dev/null +++ b/claude-plugin/README.md @@ -0,0 +1,33 @@ +# Claude Code Dotfiles Plugin + +Personal development workflow automation - hooks, tools, and configurations. + +## Status Line + +A custom status bar showing model name and context usage with a visual progress bar. + +### Enable + +Add to `~/.claude/settings.json`: + +```json +{ + "statusLine": { + "type": "command", + "command": "~/Code/dotfiles/claude-plugin/statusline/statusline.sh", + "padding": 0 + } +} +``` + +### Output + +``` +Opus 4.5 | ctx ■■■■■□□□□□□□□□□□□□□□ 25% +``` + +Colors change based on usage: + +- Grey: < 60% +- Orange: 60-80% +- Red: > 80% diff --git a/claude-plugin/statusline/statusline.sh b/claude-plugin/statusline/statusline.sh index 98820c8..79df7d6 100755 --- a/claude-plugin/statusline/statusline.sh +++ b/claude-plugin/statusline/statusline.sh @@ -3,38 +3,42 @@ input=$(cat) # Extract context stats using jq -USED_TOKENS=$(echo "$input" | jq -r '(.context_window.total_input_tokens // 0) + (.context_window.total_output_tokens // 0)') USED_PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0') +MODEL=$(echo "$input" | jq -r '.model.display_name // .model // "unknown"') -# Calculate total context window from percentage -if (( $(echo "$USED_PCT > 0" | bc -l) )); then - MAX_TOKENS=$(echo "scale=0; $USED_TOKENS * 100 / $USED_PCT" | bc) -else - MAX_TOKENS=0 +# Don't show anything for 0% +if (( $(echo "$USED_PCT == 0" | bc -l) )); then + exit 0 fi -# Format token counts (e.g., 15234 -> 15.2k) -format_tokens() { - local tokens=$1 - if [ "$tokens" -ge 1000 ]; then - echo "$(echo "scale=1; $tokens / 1000" | bc)k" - else - echo "$tokens" - fi -} +# Build progress bar (20 squares total, each full = 5%, half = 2.5%) +FULL_SQUARES=$(echo "scale=0; $USED_PCT / 5" | bc) +REMAINDER=$(echo "scale=1; $USED_PCT - ($FULL_SQUARES * 5)" | bc) +HAS_HALF=$(echo "$REMAINDER >= 2.5" | bc -l) -USED_FMT=$(format_tokens "$USED_TOKENS") -MAX_FMT=$(format_tokens "$MAX_TOKENS") +BAR="" +for ((i=0; i 75%) -if (( $(echo "$USED_PCT < 50" | bc -l) )); then - COLOR="\033[32m" # Green -elif (( $(echo "$USED_PCT < 75" | bc -l) )); then - COLOR="\033[33m" # Yellow +# Color based on usage (grey < 60%, orange 60-80%, red > 80%) +if (( $(echo "$USED_PCT < 60" | bc -l) )); then + COLOR="\033[90m" # Grey +elif (( $(echo "$USED_PCT < 80" | bc -l) )); then + COLOR="\033[38;5;208m" # Orange else COLOR="\033[31m" # Red fi RESET="\033[0m" -# Output: 68.4k/200k tokens (20%) -printf "%s/%s tokens ${COLOR}(%.0f%%)${RESET}" "$USED_FMT" "$MAX_FMT" "$USED_PCT" +# Output: opus 4.5 | context: ■■■■■■◧□□□□□□□□□□□□□ 62% +printf "%s | ctx ${COLOR}%s %.0f%%${RESET}" "$MODEL" "$BAR" "$USED_PCT" From 13b98340e79dcddfd987af80d68a447ec5843d0c Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 17 Jan 2026 14:40:32 +0000 Subject: [PATCH 3/5] Fix progress bar edge cases and clarify color thresholds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Clamp percentage to 0-100 range to handle overflow - Cap full squares at 20 to prevent negative empty squares - Only add half square when room available - Update README with precise threshold ranges (60–79%, ≥80%) --- claude-plugin/README.md | 4 ++-- claude-plugin/statusline/statusline.sh | 26 ++++++++++++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/claude-plugin/README.md b/claude-plugin/README.md index 937aaf8..3d44353 100644 --- a/claude-plugin/README.md +++ b/claude-plugin/README.md @@ -29,5 +29,5 @@ Opus 4.5 | ctx ■■■■■□□□□□□□□□□□□□□□ 25% Colors change based on usage: - Grey: < 60% -- Orange: 60-80% -- Red: > 80% +- Orange: 60–79% +- Red: ≥ 80% diff --git a/claude-plugin/statusline/statusline.sh b/claude-plugin/statusline/statusline.sh index 79df7d6..ff247da 100755 --- a/claude-plugin/statusline/statusline.sh +++ b/claude-plugin/statusline/statusline.sh @@ -11,10 +11,27 @@ if (( $(echo "$USED_PCT == 0" | bc -l) )); then exit 0 fi +# Clamp percentage to 0-100 range +CLAMPED_PCT=$(echo "if ($USED_PCT < 0) 0 else if ($USED_PCT > 100) 100 else $USED_PCT" | bc -l) + # Build progress bar (20 squares total, each full = 5%, half = 2.5%) -FULL_SQUARES=$(echo "scale=0; $USED_PCT / 5" | bc) -REMAINDER=$(echo "scale=1; $USED_PCT - ($FULL_SQUARES * 5)" | bc) -HAS_HALF=$(echo "$REMAINDER >= 2.5" | bc -l) +FULL_SQUARES=$(echo "scale=0; $CLAMPED_PCT / 5" | bc) +if [ "$FULL_SQUARES" -gt 20 ]; then + FULL_SQUARES=20 +fi + +REMAINDER=$(echo "scale=1; $CLAMPED_PCT - ($FULL_SQUARES * 5)" | bc) +if [ "$FULL_SQUARES" -lt 20 ] && (( $(echo "$REMAINDER >= 2.5" | bc -l) )); then + HAS_HALF=1 +else + HAS_HALF=0 +fi + +HALF_COUNT=$((HAS_HALF)) +EMPTY_SQUARES=$((20 - FULL_SQUARES - HALF_COUNT)) +if [ "$EMPTY_SQUARES" -lt 0 ]; then + EMPTY_SQUARES=0 +fi BAR="" for ((i=0; i Date: Sat, 17 Jan 2026 15:12:43 +0000 Subject: [PATCH 4/5] Show effective context usage against 77.5% auto-compact threshold MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Display reserved context as shaded blocks (▨) in dark gray to visualize the 22.5% auto-compact buffer. Percentage now reflects usable context rather than total, giving accurate warning before auto-compact triggers. --- claude-plugin/README.md | 14 ++++++---- claude-plugin/statusline/statusline.sh | 38 ++++++++++++++++---------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/claude-plugin/README.md b/claude-plugin/README.md index 3d44353..194eee2 100644 --- a/claude-plugin/README.md +++ b/claude-plugin/README.md @@ -22,12 +22,14 @@ Add to `~/.claude/settings.json`: ### Output +```text +Opus 4.5 | ctx ■■■■■□□□□□□□□□□▨▨▨▨▨ 33% ``` -Opus 4.5 | ctx ■■■■■□□□□□□□□□□□□□□□ 25% -``` -Colors change based on usage: +The bar shows 15 usable squares plus 5 reserved squares (▨) representing the 22.5% auto-compact buffer. The percentage shown is the **effective usage** against the usable 77.5% of context (e.g., 25% total context = 32% effective). + +Colors change based on effective usage: -- Grey: < 60% -- Orange: 60–79% -- Red: ≥ 80% +- Grey: < 75% (~58% total) +- Orange: 75–93% (~58–72% total) +- Red: ≥ 94% (~73%+ total) diff --git a/claude-plugin/statusline/statusline.sh b/claude-plugin/statusline/statusline.sh index ff247da..7d91427 100755 --- a/claude-plugin/statusline/statusline.sh +++ b/claude-plugin/statusline/statusline.sh @@ -11,24 +11,32 @@ if (( $(echo "$USED_PCT == 0" | bc -l) )); then exit 0 fi -# Clamp percentage to 0-100 range -CLAMPED_PCT=$(echo "if ($USED_PCT < 0) 0 else if ($USED_PCT > 100) 100 else $USED_PCT" | bc -l) +# Auto-compact threshold is 77.5% (22.5% buffer) +# Calculate effective percentage against the 77.5% threshold +EFFECTIVE_PCT=$(echo "scale=2; $USED_PCT / 77.5 * 100" | bc -l) +if (( $(echo "$EFFECTIVE_PCT > 100" | bc -l) )); then + EFFECTIVE_PCT=100 +fi + +# Clamp raw percentage to 0-77.5 range (usable portion) +CLAMPED_PCT=$(echo "if ($USED_PCT < 0) 0 else if ($USED_PCT > 77.5) 77.5 else $USED_PCT" | bc -l) -# Build progress bar (20 squares total, each full = 5%, half = 2.5%) +# Build progress bar: 15 usable squares (75%) + 5 reserved squares (25%) +# Each square = 5% of total context FULL_SQUARES=$(echo "scale=0; $CLAMPED_PCT / 5" | bc) -if [ "$FULL_SQUARES" -gt 20 ]; then - FULL_SQUARES=20 +if [ "$FULL_SQUARES" -gt 15 ]; then + FULL_SQUARES=15 fi REMAINDER=$(echo "scale=1; $CLAMPED_PCT - ($FULL_SQUARES * 5)" | bc) -if [ "$FULL_SQUARES" -lt 20 ] && (( $(echo "$REMAINDER >= 2.5" | bc -l) )); then +if [ "$FULL_SQUARES" -lt 15 ] && (( $(echo "$REMAINDER >= 2.5" | bc -l) )); then HAS_HALF=1 else HAS_HALF=0 fi HALF_COUNT=$((HAS_HALF)) -EMPTY_SQUARES=$((20 - FULL_SQUARES - HALF_COUNT)) +EMPTY_SQUARES=$((15 - FULL_SQUARES - HALF_COUNT)) if [ "$EMPTY_SQUARES" -lt 0 ]; then EMPTY_SQUARES=0 fi @@ -44,15 +52,17 @@ for ((i=0; i 80%) -if (( $(echo "$USED_PCT < 60" | bc -l) )); then +# Color based on effective usage (grey < 75%, orange 75-94%, red >= 94%) +# These thresholds correspond to 60%/75%/80% of total context +if (( $(echo "$EFFECTIVE_PCT < 75" | bc -l) )); then COLOR="\033[90m" # Grey -elif (( $(echo "$USED_PCT < 80" | bc -l) )); then - COLOR="\033[38;5;208m" # Orange +elif (( $(echo "$EFFECTIVE_PCT < 94" | bc -l) )); then + COLOR="\033[38;5;208m" # Orange (75% effective = 60% total) else - COLOR="\033[31m" # Red + COLOR="\033[31m" # Red (94% effective ≈ 75% total, near limit) fi RESET="\033[0m" +DARK_GRAY="\033[38;5;240m" # Dark gray for reserved blocks -# Output: opus 4.5 | context: ■■■■■■◧□□□□□□□□□□□□□ 62% -printf "%s | ctx ${COLOR}%s %.0f%%${RESET}" "$MODEL" "$BAR" "$USED_PCT" +# Output: Opus 4.5 | ctx ■■■■■■■■■■■■■■□▨▨▨▨▨ 89% +printf "%s | ctx ${COLOR}%s${DARK_GRAY}▨▨▨▨▨${COLOR} %.0f%%${RESET}" "$MODEL" "$BAR" "$EFFECTIVE_PCT" From 5e24dd78934902666e8309cc2b5b8d9ae7420280 Mon Sep 17 00:00:00 2001 From: Tyom Semonov Date: Sat, 17 Jan 2026 15:17:49 +0000 Subject: [PATCH 5/5] Add jq dependency check and documentation --- claude-plugin/README.md | 2 ++ claude-plugin/statusline/statusline.sh | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/claude-plugin/README.md b/claude-plugin/README.md index 194eee2..4956f13 100644 --- a/claude-plugin/README.md +++ b/claude-plugin/README.md @@ -6,6 +6,8 @@ Personal development workflow automation - hooks, tools, and configurations. A custom status bar showing model name and context usage with a visual progress bar. +Requires: `jq` + ### Enable Add to `~/.claude/settings.json`: diff --git a/claude-plugin/statusline/statusline.sh b/claude-plugin/statusline/statusline.sh index 7d91427..c078a73 100755 --- a/claude-plugin/statusline/statusline.sh +++ b/claude-plugin/statusline/statusline.sh @@ -1,4 +1,11 @@ #!/bin/bash + +# Requires: jq +if ! command -v jq &>/dev/null; then + echo "statusline: jq required" >&2 + exit 1 +fi + # Read JSON input from stdin input=$(cat)