cc-context-stats 1.7.0 → 1.8.1
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/package.json +9 -1
- package/scripts/context-stats.sh +1 -1
- package/scripts/statusline.js +128 -18
- package/.editorconfig +0 -60
- package/.eslintrc.json +0 -35
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -49
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -31
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -33
- package/.github/dependabot.yml +0 -44
- package/.github/workflows/ci.yml +0 -294
- package/.github/workflows/release.yml +0 -151
- package/.pre-commit-config.yaml +0 -74
- package/.prettierrc +0 -33
- package/.shellcheckrc +0 -10
- package/CHANGELOG.md +0 -163
- package/CLAUDE.md +0 -66
- package/CODE_OF_CONDUCT.md +0 -59
- package/CONTRIBUTING.md +0 -240
- package/RELEASE_NOTES.md +0 -19
- package/SECURITY.md +0 -44
- package/TODOS.md +0 -72
- package/assets/logo/favicon.svg +0 -19
- package/assets/logo/logo-black.svg +0 -24
- package/assets/logo/logo-full.svg +0 -40
- package/assets/logo/logo-icon.svg +0 -27
- package/assets/logo/logo-mark.svg +0 -28
- package/assets/logo/logo-white.svg +0 -24
- package/assets/logo/logo-wordmark.svg +0 -6
- package/config/settings-example.json +0 -7
- package/config/settings-node.json +0 -7
- package/config/settings-python.json +0 -7
- package/docs/ARCHITECTURE.md +0 -128
- package/docs/CSV_FORMAT.md +0 -42
- package/docs/DEPLOYMENT.md +0 -71
- package/docs/DEVELOPMENT.md +0 -161
- package/docs/configuration.md +0 -118
- package/docs/context-stats.md +0 -143
- package/docs/installation.md +0 -255
- package/docs/scripts.md +0 -140
- package/docs/troubleshooting.md +0 -278
- package/images/claude-statusline-token-graph.gif +0 -0
- package/images/claude-statusline.png +0 -0
- package/images/context-status-dumbzone.png +0 -0
- package/images/context-status.png +0 -0
- package/images/statusline-detail.png +0 -0
- package/images/token-graph.jpeg +0 -0
- package/images/token-graph.png +0 -0
- package/images/v1.6.1.png +0 -0
- package/install +0 -351
- package/install.sh +0 -298
- package/jest.config.js +0 -11
- package/pyproject.toml +0 -115
- package/requirements-dev.txt +0 -12
- package/scripts/statusline-full.sh +0 -304
- package/scripts/statusline-git.sh +0 -88
- package/scripts/statusline-minimal.sh +0 -67
- package/scripts/statusline.py +0 -485
- package/src/claude_statusline/__init__.py +0 -11
- package/src/claude_statusline/__main__.py +0 -6
- package/src/claude_statusline/cli/__init__.py +0 -1
- package/src/claude_statusline/cli/context_stats.py +0 -512
- package/src/claude_statusline/cli/explain.py +0 -228
- package/src/claude_statusline/cli/statusline.py +0 -169
- package/src/claude_statusline/core/__init__.py +0 -1
- package/src/claude_statusline/core/colors.py +0 -124
- package/src/claude_statusline/core/config.py +0 -148
- package/src/claude_statusline/core/git.py +0 -78
- package/src/claude_statusline/core/state.py +0 -323
- package/src/claude_statusline/formatters/__init__.py +0 -1
- package/src/claude_statusline/formatters/layout.py +0 -67
- package/src/claude_statusline/formatters/time.py +0 -50
- package/src/claude_statusline/formatters/tokens.py +0 -70
- package/src/claude_statusline/graphs/__init__.py +0 -1
- package/src/claude_statusline/graphs/renderer.py +0 -366
- package/src/claude_statusline/graphs/statistics.py +0 -92
- package/src/claude_statusline/ui/__init__.py +0 -1
- package/src/claude_statusline/ui/icons.py +0 -93
- package/src/claude_statusline/ui/waiting.py +0 -62
- package/tests/bash/test_delta_parity.bats +0 -199
- package/tests/bash/test_install.bats +0 -29
- package/tests/bash/test_parity.bats +0 -315
- package/tests/bash/test_statusline_full.bats +0 -139
- package/tests/bash/test_statusline_git.bats +0 -42
- package/tests/bash/test_statusline_minimal.bats +0 -37
- package/tests/fixtures/json/comma_in_path.json +0 -31
- package/tests/fixtures/json/high_usage.json +0 -17
- package/tests/fixtures/json/low_usage.json +0 -17
- package/tests/fixtures/json/medium_usage.json +0 -17
- package/tests/fixtures/json/valid_full.json +0 -30
- package/tests/fixtures/json/valid_minimal.json +0 -9
- package/tests/node/rotation.test.js +0 -89
- package/tests/node/statusline.test.js +0 -240
- package/tests/python/conftest.py +0 -84
- package/tests/python/test_colors.py +0 -105
- package/tests/python/test_config_colors.py +0 -78
- package/tests/python/test_data_pipeline.py +0 -446
- package/tests/python/test_explain.py +0 -177
- package/tests/python/test_icons.py +0 -152
- package/tests/python/test_layout.py +0 -127
- package/tests/python/test_state_rotation_validation.py +0 -232
- package/tests/python/test_statusline.py +0 -215
- package/tests/python/test_waiting.py +0 -127
|
@@ -1,304 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Full-featured status line with context window usage
|
|
3
|
-
# Usage: Copy to ~/.claude/statusline.sh and make executable
|
|
4
|
-
#
|
|
5
|
-
# Configuration:
|
|
6
|
-
# Create/edit ~/.claude/statusline.conf and set:
|
|
7
|
-
#
|
|
8
|
-
# autocompact=true (when autocompact is enabled in Claude Code - default)
|
|
9
|
-
# autocompact=false (when you disable autocompact via /config in Claude Code)
|
|
10
|
-
#
|
|
11
|
-
# token_detail=true (show exact token count like 64,000 - default)
|
|
12
|
-
# token_detail=false (show abbreviated tokens like 64.0k)
|
|
13
|
-
#
|
|
14
|
-
# show_delta=true (show token delta since last refresh like [+2,500] - default)
|
|
15
|
-
# show_delta=false (disable delta display - saves file I/O on every refresh)
|
|
16
|
-
#
|
|
17
|
-
# show_session=true (show session_id in status line - default)
|
|
18
|
-
# show_session=false (hide session_id from status line)
|
|
19
|
-
#
|
|
20
|
-
# When AC is enabled, 22.5% of context window is reserved for autocompact buffer.
|
|
21
|
-
#
|
|
22
|
-
# State file format (CSV):
|
|
23
|
-
# timestamp,total_input_tokens,total_output_tokens,current_usage_input_tokens,current_usage_output_tokens,current_usage_cache_creation,current_usage_cache_read,total_cost_usd,total_lines_added,total_lines_removed,session_id,model_id,workspace_project_dir
|
|
24
|
-
|
|
25
|
-
# Colors
|
|
26
|
-
BLUE='\033[0;34m'
|
|
27
|
-
MAGENTA='\033[0;35m'
|
|
28
|
-
CYAN='\033[0;36m'
|
|
29
|
-
GREEN='\033[0;32m'
|
|
30
|
-
YELLOW='\033[0;33m'
|
|
31
|
-
RED='\033[0;31m'
|
|
32
|
-
DIM='\033[2m'
|
|
33
|
-
RESET='\033[0m'
|
|
34
|
-
|
|
35
|
-
# Read JSON input from stdin
|
|
36
|
-
input=$(cat)
|
|
37
|
-
|
|
38
|
-
# Extract information from JSON
|
|
39
|
-
cwd=$(echo "$input" | jq -r '.workspace.current_dir')
|
|
40
|
-
project_dir=$(echo "$input" | jq -r '.workspace.project_dir')
|
|
41
|
-
model=$(echo "$input" | jq -r '.model.display_name // "Claude"')
|
|
42
|
-
session_id=$(echo "$input" | jq -r '.session_id // empty')
|
|
43
|
-
dir_name=$(basename "$cwd")
|
|
44
|
-
|
|
45
|
-
# Git information (skip optional locks for performance)
|
|
46
|
-
git_info=""
|
|
47
|
-
if [[ -d "$project_dir/.git" ]]; then
|
|
48
|
-
git_branch=$(cd "$project_dir" 2>/dev/null && git --no-optional-locks rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
49
|
-
git_status_count=$(cd "$project_dir" 2>/dev/null && git --no-optional-locks status --porcelain 2>/dev/null | wc -l | tr -d ' ')
|
|
50
|
-
|
|
51
|
-
if [[ -n "$git_branch" ]]; then
|
|
52
|
-
if [[ "$git_status_count" != "0" ]]; then
|
|
53
|
-
git_info=" | ${MAGENTA}${git_branch}${RESET} ${CYAN}[${git_status_count}]${RESET}"
|
|
54
|
-
else
|
|
55
|
-
git_info=" | ${MAGENTA}${git_branch}${RESET}"
|
|
56
|
-
fi
|
|
57
|
-
fi
|
|
58
|
-
fi
|
|
59
|
-
|
|
60
|
-
# Read settings from ~/.claude/statusline.conf
|
|
61
|
-
# Sync this manually when you change settings in Claude Code via /config
|
|
62
|
-
autocompact_enabled=true
|
|
63
|
-
token_detail_enabled=true
|
|
64
|
-
show_delta_enabled=true
|
|
65
|
-
show_session_enabled=true
|
|
66
|
-
autocompact="" # Will be set by sourced config
|
|
67
|
-
token_detail="" # Will be set by sourced config
|
|
68
|
-
show_delta="" # Will be set by sourced config
|
|
69
|
-
show_session="" # Will be set by sourced config
|
|
70
|
-
ac_info=""
|
|
71
|
-
delta_info=""
|
|
72
|
-
session_info=""
|
|
73
|
-
|
|
74
|
-
# Create config file with defaults if it doesn't exist
|
|
75
|
-
if [[ ! -f ~/.claude/statusline.conf ]]; then
|
|
76
|
-
mkdir -p ~/.claude
|
|
77
|
-
cat >~/.claude/statusline.conf <<'EOF'
|
|
78
|
-
# Autocompact setting - sync with Claude Code's /config
|
|
79
|
-
autocompact=true
|
|
80
|
-
|
|
81
|
-
# Token display format
|
|
82
|
-
token_detail=true
|
|
83
|
-
|
|
84
|
-
# Show token delta since last refresh (adds file I/O on every refresh)
|
|
85
|
-
# Disable if you don't need it to reduce overhead
|
|
86
|
-
show_delta=true
|
|
87
|
-
|
|
88
|
-
# Show session_id in status line
|
|
89
|
-
show_session=true
|
|
90
|
-
EOF
|
|
91
|
-
fi
|
|
92
|
-
|
|
93
|
-
if [[ -f ~/.claude/statusline.conf ]]; then
|
|
94
|
-
# shellcheck source=/dev/null
|
|
95
|
-
source ~/.claude/statusline.conf
|
|
96
|
-
if [[ "$autocompact" == "false" ]]; then
|
|
97
|
-
autocompact_enabled=false
|
|
98
|
-
fi
|
|
99
|
-
if [[ "$token_detail" == "false" ]]; then
|
|
100
|
-
token_detail_enabled=false
|
|
101
|
-
fi
|
|
102
|
-
if [[ "$show_delta" == "false" ]]; then
|
|
103
|
-
show_delta_enabled=false
|
|
104
|
-
fi
|
|
105
|
-
if [[ "$show_session" == "false" ]]; then
|
|
106
|
-
show_session_enabled=false
|
|
107
|
-
fi
|
|
108
|
-
fi
|
|
109
|
-
|
|
110
|
-
# Width-fitting helpers
|
|
111
|
-
visible_width() {
|
|
112
|
-
# Strip ANSI escape sequences (both literal \033 and actual ESC byte) and return string length
|
|
113
|
-
local stripped
|
|
114
|
-
stripped=$(printf '%s' "$1" | sed -e $'s/\033\[[0-9;]*m//g' -e 's/\\033\[[0-9;]*m//g')
|
|
115
|
-
printf '%s' "$stripped" | wc -m | tr -d ' '
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
get_terminal_width() {
|
|
119
|
-
# Return terminal width for fit_to_width truncation.
|
|
120
|
-
# When running inside Claude Code's statusline subprocess, neither $COLUMNS
|
|
121
|
-
# nor tput can detect the real terminal width (they always return 80).
|
|
122
|
-
# If COLUMNS is explicitly set, trust it. Otherwise use 200 as default
|
|
123
|
-
# so no parts are unnecessarily dropped; Claude Code handles overflow.
|
|
124
|
-
if [[ -n "$COLUMNS" ]]; then
|
|
125
|
-
echo "$COLUMNS"
|
|
126
|
-
else
|
|
127
|
-
local cols
|
|
128
|
-
cols=$(tput cols 2>/dev/null || echo 80)
|
|
129
|
-
if [[ "$cols" -eq 80 ]]; then
|
|
130
|
-
echo 200
|
|
131
|
-
else
|
|
132
|
-
echo "$cols"
|
|
133
|
-
fi
|
|
134
|
-
fi
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
fit_to_width() {
|
|
138
|
-
# Assemble parts into a single line that fits within max_width.
|
|
139
|
-
# Usage: fit_to_width max_width part1 part2 part3 ...
|
|
140
|
-
# First part (base) is always included. Subsequent parts are
|
|
141
|
-
# included only if adding them does not exceed max_width.
|
|
142
|
-
local max_width=$1
|
|
143
|
-
shift
|
|
144
|
-
local parts=("$@")
|
|
145
|
-
|
|
146
|
-
if [[ ${#parts[@]} -eq 0 ]]; then
|
|
147
|
-
echo ""
|
|
148
|
-
return
|
|
149
|
-
fi
|
|
150
|
-
|
|
151
|
-
local result="${parts[0]}"
|
|
152
|
-
local current_width
|
|
153
|
-
current_width=$(visible_width "$result")
|
|
154
|
-
|
|
155
|
-
for ((i = 1; i < ${#parts[@]}; i++)); do
|
|
156
|
-
local part="${parts[$i]}"
|
|
157
|
-
if [[ -z "$part" ]]; then
|
|
158
|
-
continue
|
|
159
|
-
fi
|
|
160
|
-
local part_width
|
|
161
|
-
part_width=$(visible_width "$part")
|
|
162
|
-
if (( current_width + part_width <= max_width )); then
|
|
163
|
-
result+="$part"
|
|
164
|
-
(( current_width += part_width ))
|
|
165
|
-
fi
|
|
166
|
-
done
|
|
167
|
-
|
|
168
|
-
echo -e "$result"
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
# Calculate context window - show remaining free space
|
|
172
|
-
context_info=""
|
|
173
|
-
total_size=$(echo "$input" | jq -r '.context_window.context_window_size // 0')
|
|
174
|
-
current_usage=$(echo "$input" | jq '.context_window.current_usage')
|
|
175
|
-
total_input_tokens=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')
|
|
176
|
-
total_output_tokens=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0')
|
|
177
|
-
cost_usd=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
|
|
178
|
-
lines_added=$(echo "$input" | jq -r '.cost.total_lines_added // 0')
|
|
179
|
-
lines_removed=$(echo "$input" | jq -r '.cost.total_lines_removed // 0')
|
|
180
|
-
model_id=$(echo "$input" | jq -r '.model.id // ""')
|
|
181
|
-
workspace_project_dir=$(echo "$input" | jq -r '.workspace.project_dir // ""' | tr ',' '_')
|
|
182
|
-
|
|
183
|
-
if [[ "$total_size" -gt 0 && "$current_usage" != "null" ]]; then
|
|
184
|
-
# Get tokens from current_usage (includes cache)
|
|
185
|
-
input_tokens=$(echo "$current_usage" | jq -r '.input_tokens // 0')
|
|
186
|
-
cache_creation=$(echo "$current_usage" | jq -r '.cache_creation_input_tokens // 0')
|
|
187
|
-
cache_read=$(echo "$current_usage" | jq -r '.cache_read_input_tokens // 0')
|
|
188
|
-
|
|
189
|
-
# Total used from current request
|
|
190
|
-
used_tokens=$((input_tokens + cache_creation + cache_read))
|
|
191
|
-
|
|
192
|
-
# Calculate autocompact buffer (22.5% of context window = 45k for 200k)
|
|
193
|
-
autocompact_buffer=$((total_size * 225 / 1000))
|
|
194
|
-
|
|
195
|
-
# Free tokens calculation depends on autocompact setting
|
|
196
|
-
if [[ "$autocompact_enabled" == "true" ]]; then
|
|
197
|
-
# When AC enabled: subtract buffer to show actual usable space
|
|
198
|
-
free_tokens=$((total_size - used_tokens - autocompact_buffer))
|
|
199
|
-
buffer_k=$(awk "BEGIN {printf \"%.0f\", $autocompact_buffer / 1000}")
|
|
200
|
-
ac_info=" ${DIM}[AC:${buffer_k}k]${RESET}"
|
|
201
|
-
else
|
|
202
|
-
# When AC disabled: show full free space
|
|
203
|
-
free_tokens=$((total_size - used_tokens))
|
|
204
|
-
ac_info=" ${DIM}[AC:off]${RESET}"
|
|
205
|
-
fi
|
|
206
|
-
|
|
207
|
-
if [[ "$free_tokens" -lt 0 ]]; then
|
|
208
|
-
free_tokens=0
|
|
209
|
-
fi
|
|
210
|
-
|
|
211
|
-
# Calculate percentage with one decimal (relative to total size)
|
|
212
|
-
free_pct=$(awk "BEGIN {printf \"%.1f\", ($free_tokens * 100.0 / $total_size)}")
|
|
213
|
-
free_pct_int=${free_pct%.*}
|
|
214
|
-
|
|
215
|
-
# Format tokens based on token_detail setting
|
|
216
|
-
if [[ "$token_detail_enabled" == "true" ]]; then
|
|
217
|
-
# Use awk for portable comma formatting (works regardless of locale)
|
|
218
|
-
free_display=$(awk -v n="$free_tokens" 'BEGIN { printf "%\047d", n }')
|
|
219
|
-
else
|
|
220
|
-
free_display=$(awk "BEGIN {printf \"%.1fk\", $free_tokens / 1000}")
|
|
221
|
-
fi
|
|
222
|
-
|
|
223
|
-
# Color based on free percentage
|
|
224
|
-
if [[ "$free_pct_int" -gt 50 ]]; then
|
|
225
|
-
ctx_color="$GREEN"
|
|
226
|
-
elif [[ "$free_pct_int" -gt 25 ]]; then
|
|
227
|
-
ctx_color="$YELLOW"
|
|
228
|
-
else
|
|
229
|
-
ctx_color="$RED"
|
|
230
|
-
fi
|
|
231
|
-
|
|
232
|
-
context_info=" | ${ctx_color}${free_display} free (${free_pct}%)${RESET}"
|
|
233
|
-
|
|
234
|
-
# Calculate and display token delta if enabled
|
|
235
|
-
if [[ "$show_delta_enabled" == "true" ]]; then
|
|
236
|
-
# Use session_id for per-session state (avoids conflicts with parallel sessions)
|
|
237
|
-
state_dir=~/.claude/statusline
|
|
238
|
-
mkdir -p "$state_dir"
|
|
239
|
-
|
|
240
|
-
# Migrate old state files from ~/.claude/ to ~/.claude/statusline/ (one-time migration)
|
|
241
|
-
old_state_dir=~/.claude
|
|
242
|
-
for old_file in "$old_state_dir"/statusline*.state; do
|
|
243
|
-
if [[ -f "$old_file" ]]; then
|
|
244
|
-
new_file="${state_dir}/$(basename "$old_file")"
|
|
245
|
-
if [[ ! -f "$new_file" ]]; then
|
|
246
|
-
mv "$old_file" "$new_file" 2>/dev/null || true
|
|
247
|
-
else
|
|
248
|
-
# New file exists, just remove old one
|
|
249
|
-
rm -f "$old_file" 2>/dev/null || true
|
|
250
|
-
fi
|
|
251
|
-
fi
|
|
252
|
-
done
|
|
253
|
-
|
|
254
|
-
if [[ -n "$session_id" ]]; then
|
|
255
|
-
state_file=${state_dir}/statusline.${session_id}.state
|
|
256
|
-
else
|
|
257
|
-
state_file=${state_dir}/statusline.state
|
|
258
|
-
fi
|
|
259
|
-
has_prev=false
|
|
260
|
-
prev_tokens=0
|
|
261
|
-
if [[ -f "$state_file" ]]; then
|
|
262
|
-
has_prev=true
|
|
263
|
-
# Read last line and calculate previous context usage
|
|
264
|
-
# CSV: ts[0],in[1],out[2],cur_in[3],cur_out[4],cache_create[5],cache_read[6]
|
|
265
|
-
last_line=$(tail -1 "$state_file" 2>/dev/null)
|
|
266
|
-
if [[ -n "$last_line" ]]; then
|
|
267
|
-
prev_cur_in=$(echo "$last_line" | cut -d',' -f4)
|
|
268
|
-
prev_cache_create=$(echo "$last_line" | cut -d',' -f6)
|
|
269
|
-
prev_cache_read=$(echo "$last_line" | cut -d',' -f7)
|
|
270
|
-
prev_tokens=$(( ${prev_cur_in:-0} + ${prev_cache_create:-0} + ${prev_cache_read:-0} ))
|
|
271
|
-
fi
|
|
272
|
-
fi
|
|
273
|
-
# Calculate delta
|
|
274
|
-
delta=$((used_tokens - prev_tokens))
|
|
275
|
-
# delta calculated for display
|
|
276
|
-
# Only show positive delta (and skip first run when no previous state)
|
|
277
|
-
if [[ "$has_prev" == "true" && "$delta" -gt 0 ]]; then
|
|
278
|
-
if [[ "$token_detail_enabled" == "true" ]]; then
|
|
279
|
-
delta_display=$(awk -v n="$delta" 'BEGIN { printf "%\047d", n }')
|
|
280
|
-
else
|
|
281
|
-
delta_display=$(awk "BEGIN {printf \"%.1fk\", $delta / 1000}")
|
|
282
|
-
fi
|
|
283
|
-
delta_info=" ${DIM}[+${delta_display}]${RESET}"
|
|
284
|
-
fi
|
|
285
|
-
# Only append if context usage changed (avoid duplicates from multiple refreshes)
|
|
286
|
-
cur_input_tokens=$(echo "$current_usage" | jq -r '.input_tokens // 0')
|
|
287
|
-
cur_output_tokens=$(echo "$current_usage" | jq -r '.output_tokens // 0')
|
|
288
|
-
if [[ "$has_prev" != "true" || "$used_tokens" != "$prev_tokens" ]]; then
|
|
289
|
-
# Append current usage with comprehensive format
|
|
290
|
-
# Format: ts,in,out,cur_in,cur_out,cache_create,cache_read,cost,+lines,-lines,session,model,dir,size
|
|
291
|
-
echo "$(date +%s),$total_input_tokens,$total_output_tokens,$cur_input_tokens,$cur_output_tokens,$cache_creation,$cache_read,$cost_usd,$lines_added,$lines_removed,$session_id,$model_id,$workspace_project_dir,$total_size" >>"$state_file"
|
|
292
|
-
fi
|
|
293
|
-
fi
|
|
294
|
-
fi
|
|
295
|
-
|
|
296
|
-
# Display session_id if enabled
|
|
297
|
-
if [[ "$show_session_enabled" == "true" && -n "$session_id" ]]; then
|
|
298
|
-
session_info=" ${DIM}${session_id}${RESET}"
|
|
299
|
-
fi
|
|
300
|
-
|
|
301
|
-
# Output: [Model] directory | branch [changes] | XXk free (XX%) [+delta] [AC] [S:session_id]
|
|
302
|
-
base="${DIM}[${model}]${RESET} ${BLUE}${dir_name}${RESET}"
|
|
303
|
-
max_width=$(get_terminal_width)
|
|
304
|
-
fit_to_width "$max_width" "$base" "$git_info" "$context_info" "$delta_info" "$ac_info" "$session_info"
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Git-aware status line - shows model, directory, and git branch
|
|
3
|
-
# Usage: Copy to ~/.claude/statusline.sh and make executable
|
|
4
|
-
|
|
5
|
-
# Colors
|
|
6
|
-
BLUE='\033[0;34m'
|
|
7
|
-
MAGENTA='\033[0;35m'
|
|
8
|
-
CYAN='\033[0;36m'
|
|
9
|
-
RESET='\033[0m'
|
|
10
|
-
|
|
11
|
-
input=$(cat)
|
|
12
|
-
|
|
13
|
-
MODEL_DISPLAY=$(echo "$input" | jq -r '.model.display_name // "Claude"')
|
|
14
|
-
CURRENT_DIR=$(echo "$input" | jq -r '.workspace.current_dir // "~"')
|
|
15
|
-
DIR_NAME="${CURRENT_DIR##*/}"
|
|
16
|
-
|
|
17
|
-
# Width-fitting helpers
|
|
18
|
-
visible_width() {
|
|
19
|
-
local stripped
|
|
20
|
-
stripped=$(printf '%s' "$1" | sed -e $'s/\033\[[0-9;]*m//g' -e 's/\\033\[[0-9;]*m//g')
|
|
21
|
-
printf '%s' "$stripped" | wc -m | tr -d ' '
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get_terminal_width() {
|
|
25
|
-
# When running inside Claude Code's statusline subprocess, $COLUMNS is not set
|
|
26
|
-
# and tput falls back to 80. If COLUMNS is set, trust it. Otherwise use 200
|
|
27
|
-
# so no parts are dropped; Claude Code handles overflow.
|
|
28
|
-
if [[ -n "$COLUMNS" ]]; then
|
|
29
|
-
echo "$COLUMNS"
|
|
30
|
-
else
|
|
31
|
-
local cols
|
|
32
|
-
cols=$(tput cols 2>/dev/null || echo 80)
|
|
33
|
-
if [[ "$cols" -eq 80 ]]; then
|
|
34
|
-
echo 200
|
|
35
|
-
else
|
|
36
|
-
echo "$cols"
|
|
37
|
-
fi
|
|
38
|
-
fi
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
fit_to_width() {
|
|
42
|
-
local max_width=$1
|
|
43
|
-
shift
|
|
44
|
-
local parts=("$@")
|
|
45
|
-
|
|
46
|
-
if [[ ${#parts[@]} -eq 0 ]]; then
|
|
47
|
-
echo ""
|
|
48
|
-
return
|
|
49
|
-
fi
|
|
50
|
-
|
|
51
|
-
local result="${parts[0]}"
|
|
52
|
-
local current_width
|
|
53
|
-
current_width=$(visible_width "$result")
|
|
54
|
-
|
|
55
|
-
for ((i = 1; i < ${#parts[@]}; i++)); do
|
|
56
|
-
local part="${parts[$i]}"
|
|
57
|
-
if [[ -z "$part" ]]; then
|
|
58
|
-
continue
|
|
59
|
-
fi
|
|
60
|
-
local part_width
|
|
61
|
-
part_width=$(visible_width "$part")
|
|
62
|
-
if (( current_width + part_width <= max_width )); then
|
|
63
|
-
result+="$part"
|
|
64
|
-
(( current_width += part_width ))
|
|
65
|
-
fi
|
|
66
|
-
done
|
|
67
|
-
|
|
68
|
-
echo -e "$result"
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
# Git branch detection
|
|
72
|
-
GIT_INFO=""
|
|
73
|
-
if git -C "$CURRENT_DIR" rev-parse --git-dir > /dev/null 2>&1; then
|
|
74
|
-
BRANCH=$(git -C "$CURRENT_DIR" branch --show-current 2>/dev/null)
|
|
75
|
-
if [ -n "$BRANCH" ]; then
|
|
76
|
-
# Count uncommitted changes
|
|
77
|
-
CHANGES=$(git -C "$CURRENT_DIR" status --porcelain 2>/dev/null | wc -l | tr -d ' ')
|
|
78
|
-
if [ "$CHANGES" -gt 0 ]; then
|
|
79
|
-
GIT_INFO=" | ${MAGENTA}${BRANCH}${RESET} ${CYAN}[${CHANGES}]${RESET}"
|
|
80
|
-
else
|
|
81
|
-
GIT_INFO=" | ${MAGENTA}${BRANCH}${RESET}"
|
|
82
|
-
fi
|
|
83
|
-
fi
|
|
84
|
-
fi
|
|
85
|
-
|
|
86
|
-
base="[${MODEL_DISPLAY}] ${BLUE}${DIR_NAME}${RESET}"
|
|
87
|
-
max_width=$(get_terminal_width)
|
|
88
|
-
fit_to_width "$max_width" "$base" "$GIT_INFO"
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Minimal status line - shows model and current directory
|
|
3
|
-
# Usage: Copy to ~/.claude/statusline.sh and make executable
|
|
4
|
-
|
|
5
|
-
input=$(cat)
|
|
6
|
-
|
|
7
|
-
MODEL_DISPLAY=$(echo "$input" | jq -r '.model.display_name // "Claude"')
|
|
8
|
-
CURRENT_DIR=$(echo "$input" | jq -r '.workspace.current_dir // "~"')
|
|
9
|
-
DIR_NAME="${CURRENT_DIR##*/}"
|
|
10
|
-
|
|
11
|
-
# Width-fitting helpers
|
|
12
|
-
visible_width() {
|
|
13
|
-
local stripped
|
|
14
|
-
stripped=$(printf '%s' "$1" | sed -e $'s/\033\[[0-9;]*m//g' -e 's/\\033\[[0-9;]*m//g')
|
|
15
|
-
printf '%s' "$stripped" | wc -m | tr -d ' '
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
get_terminal_width() {
|
|
19
|
-
# When running inside Claude Code's statusline subprocess, $COLUMNS is not set
|
|
20
|
-
# and tput falls back to 80. If COLUMNS is set, trust it. Otherwise use 200
|
|
21
|
-
# so no parts are dropped; Claude Code handles overflow.
|
|
22
|
-
if [[ -n "$COLUMNS" ]]; then
|
|
23
|
-
echo "$COLUMNS"
|
|
24
|
-
else
|
|
25
|
-
local cols
|
|
26
|
-
cols=$(tput cols 2>/dev/null || echo 80)
|
|
27
|
-
if [[ "$cols" -eq 80 ]]; then
|
|
28
|
-
echo 200
|
|
29
|
-
else
|
|
30
|
-
echo "$cols"
|
|
31
|
-
fi
|
|
32
|
-
fi
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
fit_to_width() {
|
|
36
|
-
local max_width=$1
|
|
37
|
-
shift
|
|
38
|
-
local parts=("$@")
|
|
39
|
-
|
|
40
|
-
if [[ ${#parts[@]} -eq 0 ]]; then
|
|
41
|
-
echo ""
|
|
42
|
-
return
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
local result="${parts[0]}"
|
|
46
|
-
local current_width
|
|
47
|
-
current_width=$(visible_width "$result")
|
|
48
|
-
|
|
49
|
-
for ((i = 1; i < ${#parts[@]}; i++)); do
|
|
50
|
-
local part="${parts[$i]}"
|
|
51
|
-
if [[ -z "$part" ]]; then
|
|
52
|
-
continue
|
|
53
|
-
fi
|
|
54
|
-
local part_width
|
|
55
|
-
part_width=$(visible_width "$part")
|
|
56
|
-
if (( current_width + part_width <= max_width )); then
|
|
57
|
-
result+="$part"
|
|
58
|
-
(( current_width += part_width ))
|
|
59
|
-
fi
|
|
60
|
-
done
|
|
61
|
-
|
|
62
|
-
echo -e "$result"
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
base="[$MODEL_DISPLAY] $DIR_NAME"
|
|
66
|
-
max_width=$(get_terminal_width)
|
|
67
|
-
fit_to_width "$max_width" "$base"
|