@buckits/claude-statusline 1.0.0 → 2.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.
Files changed (3) hide show
  1. package/README.md +49 -16
  2. package/package.json +2 -2
  3. package/statusline.sh +213 -60
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @buckits/claude-statusline
2
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.
3
+ A beautiful 2-line dashboard statusline for Claude Code with gradient progress bar, compact threshold marker, git status indicators, and cost tracking.
4
4
 
5
5
  ## Installation
6
6
 
@@ -10,30 +10,62 @@ npx @buckits/claude-statusline
10
10
 
11
11
  ## Features
12
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
13
+ - **2-Line Dashboard Layout** - Clean separation of AI info and project info
14
+ - **Gradient Progress Bar** - 50 segments (4k tokens each) that smoothly transition green → yellow → orange → red
15
+ - **⚡ Compact Threshold Marker** - Red lightning bolt shows exactly where auto-compact triggers (78%)
16
+ - **Session Cost Tracking** - See your running cost in real-time
17
+ - **Git Status Indicators**:
18
+ - `✓` Green checkmark = clean (all committed)
19
+ - `●` Yellow dot = unstaged changes
20
+ - `✚` Green plus = staged changes ready to commit
21
+ - `●✚` Both = partial commit state
22
+ - **Ahead/Behind Tracking** - `↑5 ↓2` shows commits ahead/behind remote
23
+ - **Visual Icons** - 🤖 for AI line, 📁 for project line
18
24
 
19
25
  ## Screenshot
20
26
 
21
27
  ```
22
- Opus 4.5 [████████████░░░░░░░░] 98.2k/200.0k ⚡15% until compact main my-project
28
+ 🤖 Opus 4.5 ($14.61) │ [████████████████████░░░░░░░░░░░░░░░░░░░⚡░░░░░░░░░░░] 80k/200k
29
+ 📁 trellis POC ✓ → origin/POC ↑15
23
30
  ```
24
31
 
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
+ ## What Each Element Means
33
+
34
+ ### Line 1 - AI Session Info
35
+ | Element | Description |
36
+ |---------|-------------|
37
+ | 🤖 | AI indicator |
38
+ | `Opus 4.5` | Current model (cyan) |
39
+ | `($14.61)` | Session cost (green) |
40
+ | `│` | Separator |
41
+ | `[███░░░⚡░░░]` | Context usage with compact threshold |
42
+ | `80k/200k` | Tokens used / total |
43
+
44
+ ### Line 2 - Project Info
45
+ | Element | Description |
46
+ |---------|-------------|
47
+ | 📁 | Project indicator |
48
+ | `trellis` | Project name (cyan) |
49
+ | `POC` | Current branch (magenta) |
50
+ | `✓●✚` | Git status (clean/unstaged/staged) |
51
+ | `→` | Points to tracking branch |
52
+ | `origin/POC` | Remote tracking branch (blue) |
53
+ | `↑15` | Commits ahead (green) |
54
+ | `↓3` | Commits behind (red) |
55
+
56
+ ## Progress Bar Colors
57
+
58
+ The bar gradient is calculated relative to the ⚡ threshold (not total capacity):
59
+
60
+ | Distance to ⚡ | Color |
61
+ |---------------|-------|
62
+ | Far (safe) | Bright green |
63
+ | Approaching | Yellow |
64
+ | Close | Orange |
65
+ | At threshold | Red |
32
66
 
33
67
  ## Manual Installation
34
68
 
35
- If you prefer to install manually:
36
-
37
69
  1. Copy `statusline.sh` to `~/.claude/statusline.sh`
38
70
  2. Make it executable: `chmod +x ~/.claude/statusline.sh`
39
71
  3. Add to `~/.claude/settings.json`:
@@ -51,6 +83,7 @@ If you prefer to install manually:
51
83
  - Claude Code CLI
52
84
  - `jq` (for JSON parsing)
53
85
  - Bash
86
+ - Git (for git status features)
54
87
 
55
88
  ## License
56
89
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
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",
3
+ "version": "2.0.0",
4
+ "description": "A beautiful 2-line dashboard statusline for Claude Code with gradient progress bar, compact threshold marker, git status indicators, and cost tracking",
5
5
  "bin": {
6
6
  "claude-statusline": "./bin/install.js"
7
7
  },
package/statusline.sh CHANGED
@@ -38,8 +38,8 @@ fi
38
38
  [ "$percent" -lt 0 ] && percent=0
39
39
  [ "$percent" -gt 100 ] && percent=100
40
40
 
41
- # Progress bar settings
42
- bar_width=20
41
+ # Progress bar settings - 50 squares (4k tokens each for 200k context)
42
+ bar_width=50
43
43
  filled=$((percent * bar_width / 100))
44
44
  empty=$((bar_width - filled))
45
45
 
@@ -100,10 +100,64 @@ for ((i=0; i<empty; i++)); do
100
100
  done
101
101
  bar+="]"
102
102
 
103
- # Get git branch if in a git repo
103
+ # Get git information if in a git repo
104
104
  git_branch=""
105
+ git_remote=""
105
106
  if [ -n "$cwd" ] && git -C "$cwd" rev-parse --git-dir >/dev/null 2>&1; then
106
107
  git_branch=$(git -C "$cwd" branch --show-current 2>/dev/null)
108
+
109
+ # Get the upstream tracking branch
110
+ upstream=$(git -C "$cwd" rev-parse --abbrev-ref --symbolic-full-name @{upstream} 2>/dev/null)
111
+ if [ -n "$upstream" ]; then
112
+ # upstream will be in format like "origin/POC" or "origin/main"
113
+ git_remote="$upstream"
114
+ fi
115
+
116
+ # Get ahead/behind counts
117
+ git_ahead=""
118
+ git_behind=""
119
+ if [ -n "$upstream" ]; then
120
+ # Get number of commits ahead/behind
121
+ ahead_behind=$(git -C "$cwd" rev-list --left-right --count HEAD...$upstream 2>/dev/null)
122
+ if [ -n "$ahead_behind" ]; then
123
+ ahead=$(echo "$ahead_behind" | awk '{print $1}')
124
+ behind=$(echo "$ahead_behind" | awk '{print $2}')
125
+ [ "$ahead" -gt 0 ] && git_ahead="$ahead"
126
+ [ "$behind" -gt 0 ] && git_behind="$behind"
127
+ fi
128
+ fi
129
+
130
+ # Get git status (dirty/staged indicators)
131
+ git_status_indicator=""
132
+ if git -C "$cwd" rev-parse --git-dir >/dev/null 2>&1; then
133
+ porcelain=$(git -C "$cwd" status --porcelain 2>/dev/null)
134
+
135
+ has_unstaged=false
136
+ has_staged=false
137
+
138
+ if [ -n "$porcelain" ]; then
139
+ # Check for staged changes (first column not space)
140
+ if echo "$porcelain" | grep -q '^[MADRC]'; then
141
+ has_staged=true
142
+ fi
143
+
144
+ # Check for unstaged changes (second column not space, or untracked files)
145
+ if echo "$porcelain" | grep -q '^\?\?' || echo "$porcelain" | grep -q '^.[MD]'; then
146
+ has_unstaged=true
147
+ fi
148
+ fi
149
+
150
+ # Build status indicator
151
+ if [ "$has_unstaged" = true ] && [ "$has_staged" = true ]; then
152
+ git_status_indicator=$(printf "\033[1;33m●\033[1;32m✚\033[0m") # Both
153
+ elif [ "$has_unstaged" = true ]; then
154
+ git_status_indicator=$(printf "\033[1;33m●\033[0m") # Unstaged (yellow)
155
+ elif [ "$has_staged" = true ]; then
156
+ git_status_indicator=$(printf "\033[1;32m✚\033[0m") # Staged (green)
157
+ else
158
+ git_status_indicator=$(printf "\033[1;32m✓\033[0m") # Clean (green)
159
+ fi
160
+ fi
107
161
  fi
108
162
 
109
163
  # Get project name from directory
@@ -131,8 +185,49 @@ format_tokens() {
131
185
  fi
132
186
  }
133
187
 
188
+ # Format tokens without decimals (e.g., 72k/200k)
189
+ format_tokens_int() {
190
+ local tokens=$1
191
+ if [ "$tokens" -ge 1000000 ]; then
192
+ local millions=$((tokens / 1000000))
193
+ printf "%dM" "$millions"
194
+ elif [ "$tokens" -ge 1000 ]; then
195
+ local thousands=$((tokens / 1000))
196
+ printf "%dk" "$thousands"
197
+ else
198
+ echo "$tokens"
199
+ fi
200
+ }
201
+
134
202
  used_fmt=$(format_tokens $used_tokens)
135
203
  max_fmt=$(format_tokens $max_tokens)
204
+ used_fmt_int=$(format_tokens_int $used_tokens)
205
+ max_fmt_int=$(format_tokens_int $max_tokens)
206
+
207
+ # Extract cost information
208
+ cost_usd=$(echo "$input" | jq -r '.cost.total_cost_usd // empty')
209
+ cost_display=""
210
+ if [ -n "$cost_usd" ] && [ "$cost_usd" != "null" ]; then
211
+ # Format cost to 2 decimal places
212
+ cost_display=$(printf "\$%.2f" "$cost_usd")
213
+ fi
214
+
215
+ # Extract tools/skills/agents counts
216
+ skills_count=$(echo "$input" | jq -r '.context.skills // [] | length')
217
+ agents_count=$(echo "$input" | jq -r '.context.agents // [] | length')
218
+ mcp_tools_count=$(echo "$input" | jq -r '.context.mcp_tools // [] | length')
219
+ total_tools=$((skills_count + agents_count + mcp_tools_count))
220
+ tools_display=""
221
+ if [ "$total_tools" -gt 0 ]; then
222
+ tools_display=$(printf "🔧 %d" "$total_tools")
223
+ fi
224
+
225
+ # Extract background tasks (check for various possible field names)
226
+ bg_tasks=$(echo "$input" | jq -r '.background_tasks // .running_agents // .active_tasks // empty | length')
227
+ bg_display=""
228
+ if [ -n "$bg_tasks" ] && [ "$bg_tasks" != "null" ] && [ "$bg_tasks" -gt 0 ]; then
229
+ bg_display=$(printf "⏳ %d" "$bg_tasks")
230
+ fi
136
231
 
137
232
  # Extract "until compact" percentage
138
233
  # Auto-compact triggers at a threshold (appears to be around 78% usage / 22% remaining)
@@ -175,80 +270,138 @@ if [ -n "$until_compact" ] && [ "$until_compact" != "null" ] && [ "$until_compac
175
270
  else
176
271
  compact_color="38;5;196"
177
272
  fi
178
- compact_indicator=$(printf "⚡%d%% until compact" "$until_compact")
179
- fi
180
273
 
181
- # Build the status line in requested order:
182
- # Model Name | Progress bar with % | Tokens | Git branch | Project name
183
- status=""
274
+ # Calculate tokens until compact threshold
275
+ # Auto-compact threshold is 22% remaining (78% used)
276
+ # Tokens until compact = until_compact * context_window_size / 100
277
+ remaining_pct=$(echo "$input" | jq -r '.context_window.remaining_percentage // 0')
278
+ tokens_until_compact=$((until_compact * max_tokens / 100))
279
+ tokens_until_compact_fmt=$(format_tokens $tokens_until_compact)
184
280
 
185
- # 1. Model name (cyan)
186
- if [ -n "$model" ]; then
187
- status+=$(printf "\033[1;36m%s\033[0m" "$model")
281
+ # Build indicator with tokens primary (gradient color) and percentage in parens (dim)
282
+ compact_indicator_text=$(printf "⚡%s until compact" "$tokens_until_compact_fmt")
283
+ compact_indicator_pct=$(printf "(%d%%)" "$until_compact")
188
284
  fi
189
285
 
190
- # 2. Progress bar
191
- status+=$(printf " %s" "$bar")
286
+ # ==========================================
287
+ # 2-LINE DASHBOARD LAYOUT
288
+ # ==========================================
192
289
 
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")
290
+ # LINE 1: Model + Context
291
+ # Format: Opus 4.5 ($12.01) [███████░░░░░░░░⚡░░░░░] 74k/200k
292
+ line1=""
198
293
 
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")"
294
+ # Robot icon and model name in cyan
295
+ if [ -n "$model" ]; then
296
+ line1+=$(printf "🤖 \033[1;36m%s\033[0m" "$model")
203
297
  fi
204
298
 
205
- # 4. Git branch (magenta)
206
- if [ -n "$git_branch" ]; then
207
- status+=$(printf " \033[1;35m %s\033[0m" "$git_branch")
299
+ # Add cost after model name (bright green)
300
+ if [ -n "$cost_display" ]; then
301
+ line1+=$(printf " \033[1;32m(%s)\033[0m" "$cost_display")
208
302
  fi
209
303
 
210
- # 5. Project name (blue)
211
- if [ -n "$project_name" ]; then
212
- status+=$(printf " \033[1;34m%s\033[0m" "$project_name")
213
- fi
304
+ # Add subtle separator between cost and progress bar
305
+ line1+=$(printf " \033[2;37m│\033[0m")
214
306
 
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')
307
+ # Build progress bar for line 1
308
+ # Calculate compact threshold position (78% of bar = 22% remaining)
309
+ AUTO_COMPACT_THRESHOLD=22
310
+ compact_threshold_pct=$((100 - AUTO_COMPACT_THRESHOLD)) # 78%
311
+ threshold_position=$((compact_threshold_pct * bar_width / 100))
219
312
 
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')
313
+ # Build unified progress bar with per-bar gradient toward threshold
314
+ unified_bar="["
315
+ unified_rightmost_color="38;5;46" # Default green
224
316
 
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)
317
+ for ((i=0; i<bar_width; i++)); do
318
+ if [ "$i" -eq "$threshold_position" ]; then
319
+ # Insert red lightning bolt threshold marker
320
+ unified_bar+=$(printf "\033[0;31m⚡\033[0m")
321
+ fi
229
322
 
230
- # Build second line with context information
231
- status2=""
323
+ if [ "$i" -lt "$filled" ]; then
324
+ # Calculate color for this specific bar position
325
+ # Gradient from green (position 0) to red (threshold position)
326
+ if [ "$threshold_position" -gt 0 ]; then
327
+ bar_position_pct=$((i * 100 / threshold_position))
328
+ else
329
+ bar_position_pct=0
330
+ fi
232
331
 
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
332
+ # Map position percentage to gradient colors
333
+ if [ "$bar_position_pct" -le 20 ]; then
334
+ bar_color="38;5;46" # Bright green
335
+ elif [ "$bar_position_pct" -le 40 ]; then
336
+ bar_color="38;5;118" # Green-yellow
337
+ elif [ "$bar_position_pct" -le 60 ]; then
338
+ bar_color="38;5;154" # Yellow-green
339
+ elif [ "$bar_position_pct" -le 70 ]; then
340
+ bar_color="38;5;226" # Yellow
341
+ elif [ "$bar_position_pct" -le 80 ]; then
342
+ bar_color="38;5;220" # Light orange
343
+ elif [ "$bar_position_pct" -le 90 ]; then
344
+ bar_color="38;5;214" # Orange
345
+ elif [ "$bar_position_pct" -le 95 ]; then
346
+ bar_color="38;5;208" # Orange-red
347
+ else
348
+ bar_color="38;5;196" # Red
349
+ fi
237
350
 
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
351
+ unified_rightmost_color=$bar_color
352
+ unified_bar+=$(printf "\033[${bar_color}m█\033[0m")
353
+ else
354
+ unified_bar+=""
355
+ fi
356
+ done
357
+
358
+ unified_bar+="]"
359
+
360
+ # Add progress bar and tokens to line 1
361
+ line1+=$(printf " %s \033[${unified_rightmost_color}m%s\033[0m\033[1;36m/%s\033[0m" "$unified_bar" "$used_fmt_int" "$max_fmt_int")
362
+
363
+ # LINE 2: Project/Git Info
364
+ # Format: 📁 trellis POC → origin/POC ↑11
365
+ line2=""
243
366
 
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")
367
+ # Folder icon and project name in cyan
368
+ if [ -n "$project_name" ]; then
369
+ line2+=$(printf "📁 \033[1;36m%s\033[0m" "$project_name")
248
370
  fi
249
371
 
250
- # Output the status lines
251
- echo "$status"
252
- if [ -n "$status2" ]; then
253
- echo "$status2"
372
+ # Git branch and tracking
373
+ if [ -n "$git_branch" ]; then
374
+ [ -n "$line2" ] && line2+=" "
375
+
376
+ # Branch in magenta
377
+ line2+=$(printf "\033[1;35m%s\033[0m" "$git_branch")
378
+
379
+ # Git status indicator (after branch name)
380
+ if [ -n "$git_status_indicator" ]; then
381
+ line2+=$(printf " %s" "$git_status_indicator")
382
+ fi
383
+
384
+ # Arrow and tracking
385
+ line2+=$(printf " \033[2;37m→\033[0m")
386
+
387
+ if [ -n "$git_remote" ]; then
388
+ # Tracking branch in blue
389
+ line2+=$(printf " \033[1;34m%s\033[0m" "$git_remote")
390
+
391
+ # Ahead/behind indicators
392
+ if [ -n "$git_ahead" ] || [ -n "$git_behind" ]; then
393
+ line2+=" "
394
+ [ -n "$git_ahead" ] && line2+=$(printf "\033[0;32m↑%s\033[0m" "$git_ahead")
395
+ if [ -n "$git_behind" ]; then
396
+ [ -n "$git_ahead" ] && line2+=" "
397
+ line2+=$(printf "\033[0;31m↓%s\033[0m" "$git_behind")
398
+ fi
399
+ fi
400
+ else
401
+ line2+=$(printf " \033[2;37m(no upstream)\033[0m")
402
+ fi
254
403
  fi
404
+
405
+ # Output the 2-line dashboard
406
+ echo "$line1"
407
+ echo "$line2"