@buckits/claude-statusline 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # @buckits/claude-statusline
2
+
3
+ A gradient color statusline for Claude Code featuring a visual progress bar that transitions from green to red as your context fills up.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npx @buckits/claude-statusline
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - **Gradient Progress Bar** - Visual bar that smoothly transitions green → yellow → orange → red as context fills
14
+ - **Color-coded Token Count** - Used tokens match the progress gradient color
15
+ - **Auto-compact Indicator** - Shows `⚡X% until compact` with color warnings (green when safe, red when critical)
16
+ - **Git Integration** - Displays current branch name
17
+ - **Project Name** - Shows current working directory name
18
+
19
+ ## Screenshot
20
+
21
+ ```
22
+ Opus 4.5 [████████████░░░░░░░░] 98.2k/200.0k ⚡15% until compact main my-project
23
+ ```
24
+
25
+ ## What it looks like
26
+
27
+ | Context Usage | Progress Bar Color | Compact Indicator |
28
+ |---------------|-------------------|-------------------|
29
+ | 0-33% | Green | Green (25%+) |
30
+ | 34-66% | Yellow/Orange | Yellow (15-24%) |
31
+ | 67-100% | Orange/Red | Red (< 4%) |
32
+
33
+ ## Manual Installation
34
+
35
+ If you prefer to install manually:
36
+
37
+ 1. Copy `statusline.sh` to `~/.claude/statusline.sh`
38
+ 2. Make it executable: `chmod +x ~/.claude/statusline.sh`
39
+ 3. Add to `~/.claude/settings.json`:
40
+
41
+ ```json
42
+ {
43
+ "status_line": {
44
+ "script": "/home/YOUR_USERNAME/.claude/statusline.sh"
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Requirements
50
+
51
+ - Claude Code CLI
52
+ - `jq` (for JSON parsing)
53
+ - Bash
54
+
55
+ ## License
56
+
57
+ MIT
package/bin/install.js ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+
7
+ const CLAUDE_DIR = path.join(os.homedir(), '.claude');
8
+ const SETTINGS_FILE = path.join(CLAUDE_DIR, 'settings.json');
9
+ const STATUSLINE_DEST = path.join(CLAUDE_DIR, 'statusline.sh');
10
+ const STATUSLINE_SRC = path.join(__dirname, '..', 'statusline.sh');
11
+
12
+ console.log('\n🎨 Installing @buckits/claude-statusline...\n');
13
+
14
+ // Ensure ~/.claude directory exists
15
+ if (!fs.existsSync(CLAUDE_DIR)) {
16
+ console.log('📁 Creating ~/.claude directory...');
17
+ fs.mkdirSync(CLAUDE_DIR, { recursive: true });
18
+ }
19
+
20
+ // Copy statusline.sh
21
+ console.log('📄 Copying statusline.sh...');
22
+ fs.copyFileSync(STATUSLINE_SRC, STATUSLINE_DEST);
23
+ fs.chmodSync(STATUSLINE_DEST, '755');
24
+
25
+ // Update settings.json
26
+ console.log('⚙️ Updating settings.json...');
27
+ let settings = {};
28
+
29
+ if (fs.existsSync(SETTINGS_FILE)) {
30
+ try {
31
+ const content = fs.readFileSync(SETTINGS_FILE, 'utf8');
32
+ settings = JSON.parse(content);
33
+ } catch (e) {
34
+ console.warn('⚠️ Could not parse existing settings.json, creating new one');
35
+ }
36
+ }
37
+
38
+ // Set the status_line configuration
39
+ settings.status_line = settings.status_line || {};
40
+ settings.status_line.script = STATUSLINE_DEST;
41
+
42
+ fs.writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2));
43
+
44
+ console.log('\n✅ Installation complete!\n');
45
+ console.log('Your Claude Code statusline now features:');
46
+ console.log(' • Gradient progress bar (green → yellow → orange → red)');
47
+ console.log(' • Color-coded token count matching progress');
48
+ console.log(' • Auto-compact countdown with color warnings');
49
+ console.log(' • Git branch and project name display');
50
+ console.log('\nRestart Claude Code to see the new statusline.\n');
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@buckits/claude-statusline",
3
+ "version": "1.0.0",
4
+ "description": "A gradient color statusline for Claude Code with progress bar, token counts, and auto-compact indicator",
5
+ "bin": {
6
+ "claude-statusline": "./bin/install.js"
7
+ },
8
+ "files": [
9
+ "bin/",
10
+ "statusline.sh"
11
+ ],
12
+ "keywords": [
13
+ "claude",
14
+ "claude-code",
15
+ "statusline",
16
+ "cli",
17
+ "terminal"
18
+ ],
19
+ "author": "Buckits",
20
+ "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/Buckits/claude-statusline"
24
+ },
25
+ "engines": {
26
+ "node": ">=14"
27
+ }
28
+ }
package/statusline.sh ADDED
@@ -0,0 +1,254 @@
1
+ #!/bin/bash
2
+
3
+ # Claude Code Status Line Script
4
+ # Read JSON input from stdin
5
+
6
+ input=$(cat)
7
+
8
+ # Extract values from JSON
9
+ cwd=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // empty')
10
+ model=$(echo "$input" | jq -r '.model.display_name // empty')
11
+
12
+ # Extract token information from context_window
13
+ # The actual context usage includes cache tokens from prompt caching
14
+ total_input=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')
15
+ total_output=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0')
16
+ cache_read=$(echo "$input" | jq -r '.context_window.current_usage.cache_read_input_tokens // 0')
17
+
18
+ # Total used = input + output + cached tokens being used
19
+ used_tokens=$((total_input + total_output + cache_read))
20
+ max_tokens=$(echo "$input" | jq -r '.context_window.context_window_size // 200000')
21
+
22
+ # Use the pre-calculated percentage if available (more accurate)
23
+ percent_precalc=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
24
+ if [ -n "$percent_precalc" ]; then
25
+ percent=$percent_precalc
26
+ # Recalculate used_tokens from percentage for display accuracy
27
+ used_tokens=$((max_tokens * percent / 100))
28
+ else
29
+ # Fallback: calculate percentage from tokens
30
+ if [ "$max_tokens" -gt 0 ] 2>/dev/null; then
31
+ percent=$((used_tokens * 100 / max_tokens))
32
+ else
33
+ percent=0
34
+ fi
35
+ fi
36
+
37
+ # Clamp percent to 0-100
38
+ [ "$percent" -lt 0 ] && percent=0
39
+ [ "$percent" -gt 100 ] && percent=100
40
+
41
+ # Progress bar settings
42
+ bar_width=20
43
+ filled=$((percent * bar_width / 100))
44
+ empty=$((bar_width - filled))
45
+
46
+ # Get color for a specific bar position (0 to bar_width-1)
47
+ # Each bar position gets its own color based on progression
48
+ get_bar_color_for_position() {
49
+ local pos=$1
50
+ local total=$2
51
+ # Calculate percentage for this specific bar position
52
+ local bar_pct=$((pos * 100 / total))
53
+
54
+ if [ "$bar_pct" -le 33 ]; then
55
+ # Green range: 0-33%
56
+ # Bright green (46) → yellow-green (154) → green (34)
57
+ if [ "$bar_pct" -le 16 ]; then
58
+ echo "38;5;46" # Bright green
59
+ elif [ "$bar_pct" -le 25 ]; then
60
+ echo "38;5;118" # Green-yellow
61
+ else
62
+ echo "38;5;154" # Yellow-green
63
+ fi
64
+ elif [ "$bar_pct" -le 66 ]; then
65
+ # Orange range: 34-66%
66
+ # Yellow (226) → orange (214) → dark orange (208)
67
+ local adj_pct=$((bar_pct - 33))
68
+ if [ "$adj_pct" -le 11 ]; then
69
+ echo "38;5;226" # Yellow
70
+ elif [ "$adj_pct" -le 22 ]; then
71
+ echo "38;5;220" # Light orange
72
+ else
73
+ echo "38;5;214" # Orange
74
+ fi
75
+ else
76
+ # Red range: 67-100%
77
+ # Orange-red (208) → red (196) → dark red (160)
78
+ local adj_pct=$((bar_pct - 66))
79
+ if [ "$adj_pct" -le 11 ]; then
80
+ echo "38;5;208" # Orange-red
81
+ elif [ "$adj_pct" -le 22 ]; then
82
+ echo "38;5;202" # Red-orange
83
+ else
84
+ echo "38;5;196" # Bright red
85
+ fi
86
+ fi
87
+ }
88
+
89
+ # Build progress bar with gradient colors
90
+ # Track the color of the rightmost filled bar for the percentage text
91
+ bar="["
92
+ rightmost_color="38;5;46" # Default to bright green
93
+ for ((i=0; i<filled; i++)); do
94
+ bar_color=$(get_bar_color_for_position $i $bar_width)
95
+ rightmost_color=$bar_color # Keep updating to track the last one
96
+ bar+=$(printf "\033[${bar_color}m█\033[0m")
97
+ done
98
+ for ((i=0; i<empty; i++)); do
99
+ bar+="░"
100
+ done
101
+ bar+="]"
102
+
103
+ # Get git branch if in a git repo
104
+ git_branch=""
105
+ if [ -n "$cwd" ] && git -C "$cwd" rev-parse --git-dir >/dev/null 2>&1; then
106
+ git_branch=$(git -C "$cwd" branch --show-current 2>/dev/null)
107
+ fi
108
+
109
+ # Get project name from directory
110
+ project_name=""
111
+ if [ -n "$cwd" ]; then
112
+ project_name=$(basename "$cwd")
113
+ fi
114
+
115
+ # Format tokens for display (e.g., 45.2k/200k)
116
+ format_tokens() {
117
+ local tokens=$1
118
+ # Use pure bash arithmetic to avoid bc dependency
119
+ if [ "$tokens" -ge 1000000 ]; then
120
+ local millions=$((tokens / 1000000))
121
+ local remainder=$((tokens % 1000000))
122
+ local decimal=$((remainder / 100000))
123
+ printf "%d.%dM" "$millions" "$decimal"
124
+ elif [ "$tokens" -ge 1000 ]; then
125
+ local thousands=$((tokens / 1000))
126
+ local remainder=$((tokens % 1000))
127
+ local decimal=$((remainder / 100))
128
+ printf "%d.%dk" "$thousands" "$decimal"
129
+ else
130
+ echo "$tokens"
131
+ fi
132
+ }
133
+
134
+ used_fmt=$(format_tokens $used_tokens)
135
+ max_fmt=$(format_tokens $max_tokens)
136
+
137
+ # Extract "until compact" percentage
138
+ # Auto-compact triggers at a threshold (appears to be around 78% usage / 22% remaining)
139
+ # The "until compact" value = remaining_percentage - threshold_remaining
140
+ # If threshold is 22%, and you have 24% remaining, then until_compact = 24% - 22% = 2%
141
+
142
+ # First check if there's an explicit field (unlikely but worth checking)
143
+ until_compact=$(echo "$input" | jq -r '.context_window.until_compact // .context_window.until_auto_compact // empty')
144
+
145
+ if [ -z "$until_compact" ]; then
146
+ # Calculate based on auto-compact threshold
147
+ # Auto-compact threshold appears to be 22% remaining (78% used)
148
+ AUTO_COMPACT_THRESHOLD=22
149
+
150
+ remaining_pct=$(echo "$input" | jq -r '.context_window.remaining_percentage // 0')
151
+
152
+ if [ "$remaining_pct" -gt "$AUTO_COMPACT_THRESHOLD" ]; then
153
+ until_compact=$((remaining_pct - AUTO_COMPACT_THRESHOLD))
154
+ else
155
+ # Already past threshold or at it
156
+ until_compact=0
157
+ fi
158
+ fi
159
+
160
+ compact_indicator=""
161
+ compact_color="38;5;46"
162
+ if [ -n "$until_compact" ] && [ "$until_compact" != "null" ] && [ "$until_compact" != "0" ]; then
163
+ if [ "$until_compact" -ge 25 ]; then
164
+ compact_color="38;5;46"
165
+ elif [ "$until_compact" -ge 20 ]; then
166
+ compact_color="38;5;154"
167
+ elif [ "$until_compact" -ge 15 ]; then
168
+ compact_color="38;5;226"
169
+ elif [ "$until_compact" -ge 10 ]; then
170
+ compact_color="38;5;220"
171
+ elif [ "$until_compact" -ge 7 ]; then
172
+ compact_color="38;5;214"
173
+ elif [ "$until_compact" -ge 4 ]; then
174
+ compact_color="38;5;208"
175
+ else
176
+ compact_color="38;5;196"
177
+ fi
178
+ compact_indicator=$(printf "⚡%d%% until compact" "$until_compact")
179
+ fi
180
+
181
+ # Build the status line in requested order:
182
+ # Model Name | Progress bar with % | Tokens | Git branch | Project name
183
+ status=""
184
+
185
+ # 1. Model name (cyan)
186
+ if [ -n "$model" ]; then
187
+ status+=$(printf "\033[1;36m%s\033[0m" "$model")
188
+ fi
189
+
190
+ # 2. Progress bar
191
+ status+=$(printf " %s" "$bar")
192
+
193
+ # 3. Tokens with gradient color on used, cyan on total
194
+ # Used tokens get gradient color matching progress bar (low=green, high=red)
195
+ # The rightmost_color already has the gradient based on current usage
196
+ # Slash and max tokens use cyan to match model name
197
+ status+=$(printf " \033[${rightmost_color}m%s\033[1;36m/%s\033[0m" "$used_fmt" "$max_fmt")
198
+
199
+ # 3.5. Remaining context percentage (gradient color)
200
+ if [ -n "$compact_indicator" ]; then
201
+ # Don't use printf %s with the indicator as it contains % characters
202
+ status+=" $(printf "\033[${compact_color}m")${compact_indicator}$(printf "\033[0m")"
203
+ fi
204
+
205
+ # 4. Git branch (magenta)
206
+ if [ -n "$git_branch" ]; then
207
+ status+=$(printf " \033[1;35m %s\033[0m" "$git_branch")
208
+ fi
209
+
210
+ # 5. Project name (blue)
211
+ if [ -n "$project_name" ]; then
212
+ status+=$(printf " \033[1;34m%s\033[0m" "$project_name")
213
+ fi
214
+
215
+ # Extract context information for second line
216
+ skills_count=$(echo "$input" | jq -r '[.context.skills // [] | length] | .[0] // 0')
217
+ agents_count=$(echo "$input" | jq -r '[.context.agents // [] | length] | .[0] // 0')
218
+ mcp_tools_count=$(echo "$input" | jq -r '[.context.mcp_tools // [] | length] | .[0] // 0')
219
+
220
+ # Extract token counts for context items
221
+ skills_tokens=$(echo "$input" | jq -r '.context.skills_tokens // 0')
222
+ agents_tokens=$(echo "$input" | jq -r '.context.agents_tokens // 0')
223
+ mcp_tokens=$(echo "$input" | jq -r '.context.mcp_tokens // 0')
224
+
225
+ # Format tokens for context items
226
+ skills_tokens_fmt=$(format_tokens $skills_tokens)
227
+ agents_tokens_fmt=$(format_tokens $agents_tokens)
228
+ mcp_tokens_fmt=$(format_tokens $mcp_tokens)
229
+
230
+ # Build second line with context information
231
+ status2=""
232
+
233
+ # Skills (yellow)
234
+ if [ "$skills_count" -gt 0 ]; then
235
+ status2+=$(printf "\033[1;33mSkills: %d (%s)\033[0m" "$skills_count" "$skills_tokens_fmt")
236
+ fi
237
+
238
+ # Agents (green)
239
+ if [ "$agents_count" -gt 0 ]; then
240
+ [ -n "$status2" ] && status2+=" "
241
+ status2+=$(printf "\033[1;32mAgents: %d (%s)\033[0m" "$agents_count" "$agents_tokens_fmt")
242
+ fi
243
+
244
+ # MCP Tools (blue)
245
+ if [ "$mcp_tools_count" -gt 0 ]; then
246
+ [ -n "$status2" ] && status2+=" "
247
+ status2+=$(printf "\033[1;34mMCP: %d (%s)\033[0m" "$mcp_tools_count" "$mcp_tokens_fmt")
248
+ fi
249
+
250
+ # Output the status lines
251
+ echo "$status"
252
+ if [ -n "$status2" ]; then
253
+ echo "$status2"
254
+ fi