cc-context-stats 1.6.1 → 1.7.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/CHANGELOG.md +30 -0
- package/CLAUDE.md +12 -0
- package/README.md +35 -25
- package/docs/ARCHITECTURE.md +52 -25
- package/docs/CSV_FORMAT.md +2 -0
- package/docs/DEPLOYMENT.md +19 -8
- package/docs/DEVELOPMENT.md +48 -12
- package/docs/configuration.md +35 -0
- package/docs/context-stats.md +12 -1
- package/docs/installation.md +82 -22
- package/docs/scripts.md +47 -23
- package/docs/troubleshooting.md +93 -4
- package/images/v1.6.1.png +0 -0
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/scripts/statusline.js +87 -15
- package/scripts/statusline.py +169 -51
- package/src/claude_statusline/__init__.py +1 -1
- package/src/claude_statusline/cli/context_stats.py +52 -10
- package/src/claude_statusline/cli/explain.py +228 -0
- package/src/claude_statusline/cli/statusline.py +16 -20
- package/src/claude_statusline/core/colors.py +78 -9
- package/src/claude_statusline/core/config.py +51 -9
- package/src/claude_statusline/core/git.py +16 -5
- package/tests/bash/test_delta_parity.bats +199 -0
- package/tests/python/test_colors.py +105 -0
- package/tests/python/test_config_colors.py +78 -0
- package/tests/python/test_explain.py +177 -0
package/docs/installation.md
CHANGED
|
@@ -5,32 +5,62 @@
|
|
|
5
5
|
### One-Line Install (Recommended)
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
curl -fsSL https://raw.githubusercontent.com/luongnv89/
|
|
8
|
+
curl -fsSL https://raw.githubusercontent.com/luongnv89/cc-context-stats/main/install.sh | bash
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
This downloads and runs the installer directly from GitHub.
|
|
11
|
+
This downloads and runs the installer directly from GitHub. It installs the **full** statusline script and the `context-stats` CLI tool.
|
|
12
12
|
|
|
13
|
-
###
|
|
13
|
+
### NPM (Recommended for Node.js users)
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g cc-context-stats
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or with yarn:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn global add cc-context-stats
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
After installation, add to `~/.claude/settings.json`:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"statusLine": {
|
|
30
|
+
"type": "command",
|
|
31
|
+
"command": "claude-statusline"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Python (Recommended for Python users)
|
|
16
37
|
|
|
17
38
|
```bash
|
|
18
|
-
|
|
39
|
+
pip install cc-context-stats
|
|
19
40
|
```
|
|
20
41
|
|
|
21
|
-
|
|
42
|
+
Or with uv:
|
|
22
43
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
44
|
+
```bash
|
|
45
|
+
uv pip install cc-context-stats
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
After installation, add to `~/.claude/settings.json`:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"statusLine": {
|
|
53
|
+
"type": "command",
|
|
54
|
+
"command": "claude-statusline"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
28
58
|
|
|
29
59
|
### Install from Source
|
|
30
60
|
|
|
31
61
|
```bash
|
|
32
62
|
git clone https://github.com/luongnv89/cc-context-stats.git
|
|
33
|
-
cd
|
|
63
|
+
cd cc-context-stats
|
|
34
64
|
./install.sh
|
|
35
65
|
```
|
|
36
66
|
|
|
@@ -46,14 +76,22 @@ The installer will:
|
|
|
46
76
|
Use the Python or Node.js version (no `jq` required):
|
|
47
77
|
|
|
48
78
|
```powershell
|
|
79
|
+
# Python (via pip)
|
|
80
|
+
pip install cc-context-stats
|
|
81
|
+
|
|
82
|
+
# Or manually copy the script
|
|
49
83
|
git clone https://github.com/luongnv89/cc-context-stats.git
|
|
50
|
-
copy
|
|
84
|
+
copy cc-context-stats\scripts\statusline.py %USERPROFILE%\.claude\statusline.py
|
|
51
85
|
```
|
|
52
86
|
|
|
53
87
|
Or with Node.js:
|
|
54
88
|
|
|
55
89
|
```powershell
|
|
56
|
-
|
|
90
|
+
# Node.js (via npm)
|
|
91
|
+
npm install -g cc-context-stats
|
|
92
|
+
|
|
93
|
+
# Or manually copy the script
|
|
94
|
+
copy cc-context-stats\scripts\statusline.js %USERPROFILE%\.claude\statusline.js
|
|
57
95
|
```
|
|
58
96
|
|
|
59
97
|
## Manual Installation
|
|
@@ -93,6 +131,19 @@ Add to your Claude Code settings:
|
|
|
93
131
|
- macOS/Linux: `~/.claude/settings.json`
|
|
94
132
|
- Windows: `%USERPROFILE%\.claude\settings.json`
|
|
95
133
|
|
|
134
|
+
### pip / npm Install
|
|
135
|
+
|
|
136
|
+
If you installed via `pip install cc-context-stats` or `npm install -g cc-context-stats`:
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"statusLine": {
|
|
141
|
+
"type": "command",
|
|
142
|
+
"command": "claude-statusline"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
96
147
|
### Bash (macOS/Linux)
|
|
97
148
|
|
|
98
149
|
```json
|
|
@@ -104,7 +155,7 @@ Add to your Claude Code settings:
|
|
|
104
155
|
}
|
|
105
156
|
```
|
|
106
157
|
|
|
107
|
-
### Python (
|
|
158
|
+
### Python (Manual Copy)
|
|
108
159
|
|
|
109
160
|
```json
|
|
110
161
|
{
|
|
@@ -126,7 +177,7 @@ Windows:
|
|
|
126
177
|
}
|
|
127
178
|
```
|
|
128
179
|
|
|
129
|
-
### Node.js (
|
|
180
|
+
### Node.js (Manual Copy)
|
|
130
181
|
|
|
131
182
|
```json
|
|
132
183
|
{
|
|
@@ -153,24 +204,24 @@ Windows:
|
|
|
153
204
|
### macOS
|
|
154
205
|
|
|
155
206
|
```bash
|
|
156
|
-
brew install jq
|
|
207
|
+
brew install jq # Only needed for bash scripts
|
|
157
208
|
```
|
|
158
209
|
|
|
159
210
|
### Linux (Debian/Ubuntu)
|
|
160
211
|
|
|
161
212
|
```bash
|
|
162
|
-
sudo apt install jq
|
|
213
|
+
sudo apt install jq # Only needed for bash scripts
|
|
163
214
|
```
|
|
164
215
|
|
|
165
216
|
### Linux (Fedora/RHEL)
|
|
166
217
|
|
|
167
218
|
```bash
|
|
168
|
-
sudo dnf install jq
|
|
219
|
+
sudo dnf install jq # Only needed for bash scripts
|
|
169
220
|
```
|
|
170
221
|
|
|
171
222
|
### Windows
|
|
172
223
|
|
|
173
|
-
No additional requirements for Python/Node.js scripts.
|
|
224
|
+
No additional requirements for Python/Node.js scripts (via pip or npm).
|
|
174
225
|
|
|
175
226
|
For bash scripts via WSL:
|
|
176
227
|
|
|
@@ -180,12 +231,21 @@ sudo apt install jq
|
|
|
180
231
|
|
|
181
232
|
## Verify Installation
|
|
182
233
|
|
|
183
|
-
Test your statusline
|
|
234
|
+
Test your statusline:
|
|
184
235
|
|
|
185
236
|
```bash
|
|
186
|
-
#
|
|
237
|
+
# If installed via pip or npm
|
|
238
|
+
echo '{"model":{"display_name":"Test"}}' | claude-statusline
|
|
239
|
+
|
|
240
|
+
# Bash script (macOS/Linux)
|
|
187
241
|
echo '{"model":{"display_name":"Test"}}' | ~/.claude/statusline.sh
|
|
188
242
|
|
|
243
|
+
# Python script (manual copy)
|
|
244
|
+
echo '{"model":{"display_name":"Test"}}' | python3 ~/.claude/statusline.py
|
|
245
|
+
|
|
246
|
+
# Node.js script (manual copy)
|
|
247
|
+
echo '{"model":{"display_name":"Test"}}' | node ~/.claude/statusline.js
|
|
248
|
+
|
|
189
249
|
# Windows (Python)
|
|
190
250
|
echo {"model":{"display_name":"Test"}} | python %USERPROFILE%\.claude\statusline.py
|
|
191
251
|
```
|
package/docs/scripts.md
CHANGED
|
@@ -2,18 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
| Script | Platform | Requirements | Features |
|
|
6
|
-
| ----------------------- | ------------ | ------------ | --------------------------------- |
|
|
7
|
-
| `statusline-full.sh` | macOS, Linux | `jq` | Full-featured with all indicators |
|
|
8
|
-
| `statusline-git.sh` | macOS, Linux | `jq` | Git branch and changes |
|
|
9
|
-
| `statusline-minimal.sh` | macOS, Linux | `jq` | Model + directory only |
|
|
10
|
-
| `statusline.py` | All | Python 3 | Cross-platform, full-featured |
|
|
11
|
-
| `statusline.js` | All | Node.js
|
|
12
|
-
| `context-stats.sh` | macOS, Linux |
|
|
5
|
+
| Script | Platform | Requirements | State Writes | Features |
|
|
6
|
+
| ----------------------- | ------------ | ------------ | ------------ | --------------------------------- |
|
|
7
|
+
| `statusline-full.sh` | macOS, Linux | `jq` | No | Full-featured with all indicators |
|
|
8
|
+
| `statusline-git.sh` | macOS, Linux | `jq` | No | Git branch and changes |
|
|
9
|
+
| `statusline-minimal.sh` | macOS, Linux | `jq` | No | Model + directory only |
|
|
10
|
+
| `statusline.py` | All | Python 3 | Yes | Cross-platform, full-featured |
|
|
11
|
+
| `statusline.js` | All | Node.js 18+ | Yes | Cross-platform, full-featured |
|
|
12
|
+
| `context-stats.sh` | macOS, Linux | Bash | No | Token usage visualization (CLI) |
|
|
13
|
+
|
|
14
|
+
## Installation Methods
|
|
15
|
+
|
|
16
|
+
| Method | Statusline Command | Context Stats Command |
|
|
17
|
+
| ------ | ------------------ | --------------------- |
|
|
18
|
+
| `pip install cc-context-stats` | `claude-statusline` | `context-stats` |
|
|
19
|
+
| `npm install -g cc-context-stats` | `claude-statusline` | `context-stats` |
|
|
20
|
+
| Shell installer (`install.sh`) | `~/.claude/statusline.sh` | `~/.local/bin/context-stats` |
|
|
13
21
|
|
|
14
22
|
## Bash Scripts
|
|
15
23
|
|
|
16
|
-
### statusline-full.sh (Recommended)
|
|
24
|
+
### statusline-full.sh (Recommended for bash users)
|
|
17
25
|
|
|
18
26
|
Complete status line with all features:
|
|
19
27
|
|
|
@@ -25,6 +33,8 @@ Complete status line with all features:
|
|
|
25
33
|
- Autocompact indicator
|
|
26
34
|
- Session ID
|
|
27
35
|
|
|
36
|
+
> **Note:** Does not write state files. For context-stats CLI support, use the Python or Node.js script instead.
|
|
37
|
+
|
|
28
38
|
### statusline-git.sh
|
|
29
39
|
|
|
30
40
|
Lighter version with git info:
|
|
@@ -46,15 +56,27 @@ Minimal footprint:
|
|
|
46
56
|
|
|
47
57
|
Python implementation matching `statusline-full.sh` functionality. Works on Windows, macOS, and Linux without additional dependencies beyond Python 3.
|
|
48
58
|
|
|
59
|
+
Features beyond bash scripts:
|
|
60
|
+
- Writes state files for context-stats CLI
|
|
61
|
+
- Duplicate-entry deduplication
|
|
62
|
+
- State file rotation (10k/5k threshold)
|
|
63
|
+
- 5-second git command timeout
|
|
64
|
+
|
|
49
65
|
### statusline.js
|
|
50
66
|
|
|
51
|
-
Node.js implementation matching `statusline-full.sh` functionality. Works on all platforms with Node.js installed.
|
|
67
|
+
Node.js implementation matching `statusline-full.sh` functionality. Works on all platforms with Node.js 18+ installed.
|
|
68
|
+
|
|
69
|
+
Features beyond bash scripts:
|
|
70
|
+
- Writes state files for context-stats CLI
|
|
71
|
+
- Duplicate-entry deduplication
|
|
72
|
+
- State file rotation (10k/5k threshold)
|
|
73
|
+
- 5-second git command timeout
|
|
52
74
|
|
|
53
75
|
## Utility Scripts
|
|
54
76
|
|
|
55
77
|
### context-stats.sh
|
|
56
78
|
|
|
57
|
-
Standalone CLI tool for visualizing token consumption. See [Context Stats](context-stats.md) for details.
|
|
79
|
+
Standalone bash CLI tool for visualizing token consumption. Reads state files written by the Python or Node.js statusline scripts. See [Context Stats](context-stats.md) for details.
|
|
58
80
|
|
|
59
81
|
## Output Format
|
|
60
82
|
|
|
@@ -102,15 +124,17 @@ Scripts receive JSON via stdin from Claude Code:
|
|
|
102
124
|
|
|
103
125
|
## Color Codes
|
|
104
126
|
|
|
105
|
-
All scripts use consistent ANSI colors:
|
|
106
|
-
|
|
107
|
-
| Color | Code | Usage |
|
|
108
|
-
| ------- | ------------ | -------------------------- |
|
|
109
|
-
| Blue | `\033[0;34m` | Directory |
|
|
110
|
-
| Magenta | `\033[0;35m` | Git branch |
|
|
111
|
-
| Cyan | `\033[0;36m` | Changes count |
|
|
112
|
-
| Green | `\033[0;32m` | High availability (>50%) |
|
|
113
|
-
| Yellow | `\033[0;33m` | Medium availability (>25%) |
|
|
114
|
-
| Red | `\033[0;31m` | Low availability (<=25%) |
|
|
115
|
-
| Dim | `\033[2m` | Model, AC indicator |
|
|
116
|
-
| Reset | `\033[0m` | Reset formatting |
|
|
127
|
+
All scripts use consistent ANSI colors (defaults, overridable via `~/.claude/statusline.conf`):
|
|
128
|
+
|
|
129
|
+
| Color | Code | Usage | Config Key |
|
|
130
|
+
| ------- | ------------ | -------------------------- | --------------- |
|
|
131
|
+
| Blue | `\033[0;34m` | Directory | `color_blue` |
|
|
132
|
+
| Magenta | `\033[0;35m` | Git branch | `color_magenta` |
|
|
133
|
+
| Cyan | `\033[0;36m` | Changes count | `color_cyan` |
|
|
134
|
+
| Green | `\033[0;32m` | High availability (>50%) | `color_green` |
|
|
135
|
+
| Yellow | `\033[0;33m` | Medium availability (>25%) | `color_yellow` |
|
|
136
|
+
| Red | `\033[0;31m` | Low availability (<=25%) | `color_red` |
|
|
137
|
+
| Dim | `\033[2m` | Model, AC indicator | — |
|
|
138
|
+
| Reset | `\033[0m` | Reset formatting | — |
|
|
139
|
+
|
|
140
|
+
See [Configuration](configuration.md#custom-colors) for details on overriding colors with named colors or hex codes.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -24,6 +24,22 @@
|
|
|
24
24
|
cat ~/.claude/settings.json
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
**pip/npm install:**
|
|
28
|
+
|
|
29
|
+
1. Verify the command is available:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
which claude-statusline
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
2. Test it:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
echo '{"model":{"display_name":"Test"}}' | claude-statusline
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
3. Ensure your settings.json uses `"command": "claude-statusline"` (not a file path).
|
|
42
|
+
|
|
27
43
|
**Windows (Python):**
|
|
28
44
|
|
|
29
45
|
```powershell
|
|
@@ -32,7 +48,7 @@ echo {"model":{"display_name":"Test"}} | python %USERPROFILE%\.claude\statusline
|
|
|
32
48
|
|
|
33
49
|
### jq not found
|
|
34
50
|
|
|
35
|
-
The bash scripts require `jq` for JSON parsing.
|
|
51
|
+
The bash scripts require `jq` for JSON parsing. Python and Node.js scripts do **not** need `jq`.
|
|
36
52
|
|
|
37
53
|
**macOS:**
|
|
38
54
|
|
|
@@ -56,6 +72,22 @@ Alternatively, use the Python or Node.js version which don't require `jq`.
|
|
|
56
72
|
|
|
57
73
|
### context-stats command not found
|
|
58
74
|
|
|
75
|
+
**If installed via pip or npm:**
|
|
76
|
+
|
|
77
|
+
1. Verify installation:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
which context-stats
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
2. Reinstall if missing:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pip install cc-context-stats # or: npm install -g cc-context-stats
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**If installed via shell installer:**
|
|
90
|
+
|
|
59
91
|
1. Verify installation:
|
|
60
92
|
|
|
61
93
|
```bash
|
|
@@ -80,13 +112,58 @@ Alternatively, use the Python or Node.js version which don't require `jq`.
|
|
|
80
112
|
source ~/.bashrc
|
|
81
113
|
```
|
|
82
114
|
|
|
115
|
+
### pip install fails
|
|
116
|
+
|
|
117
|
+
1. Ensure Python 3.9+:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python3 --version
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
2. Try with `--user` flag:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
pip install --user cc-context-stats
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
3. Or use `uv`:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
uv pip install cc-context-stats
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### npm install fails
|
|
136
|
+
|
|
137
|
+
1. Ensure Node.js 18+:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
node --version
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
2. Try with sudo (Linux/macOS):
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
sudo npm install -g cc-context-stats
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
3. Or fix npm permissions:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
mkdir -p ~/.npm-global
|
|
153
|
+
npm config set prefix '~/.npm-global'
|
|
154
|
+
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc
|
|
155
|
+
source ~/.zshrc
|
|
156
|
+
npm install -g cc-context-stats
|
|
157
|
+
```
|
|
158
|
+
|
|
83
159
|
### No token graph data
|
|
84
160
|
|
|
85
161
|
Token history requires:
|
|
86
162
|
|
|
87
|
-
1.
|
|
88
|
-
2.
|
|
89
|
-
3.
|
|
163
|
+
1. Python or Node.js statusline script (bash scripts do **not** write state files)
|
|
164
|
+
2. `show_delta=true` in `~/.claude/statusline.conf` (default)
|
|
165
|
+
3. Active Claude Code session generating state files
|
|
166
|
+
4. State files at `~/.claude/statusline/statusline.<session_id>.state`
|
|
90
167
|
|
|
91
168
|
Check for state files:
|
|
92
169
|
|
|
@@ -108,6 +185,8 @@ ls -la ~/.claude/statusline/statusline.*.state
|
|
|
108
185
|
which git
|
|
109
186
|
```
|
|
110
187
|
|
|
188
|
+
3. Git commands have a 5-second timeout. If your repo is very large, git operations may time out silently.
|
|
189
|
+
|
|
111
190
|
### Wrong token colors
|
|
112
191
|
|
|
113
192
|
Token colors depend on availability percentage:
|
|
@@ -124,6 +203,12 @@ If colors look wrong, check terminal color support.
|
|
|
124
203
|
|
|
125
204
|
Token delta requires multiple statusline refreshes. The first refresh establishes a baseline; subsequent refreshes show the delta.
|
|
126
205
|
|
|
206
|
+
If delta is always zero after multiple refreshes, check that the state file is being written:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
wc -l ~/.claude/statusline/statusline.*.state
|
|
210
|
+
```
|
|
211
|
+
|
|
127
212
|
### Configuration not taking effect
|
|
128
213
|
|
|
129
214
|
1. Check config file location:
|
|
@@ -167,6 +252,9 @@ EOF
|
|
|
167
252
|
cat /tmp/test-input.json | ~/.claude/statusline.sh
|
|
168
253
|
cat /tmp/test-input.json | python3 ~/.claude/statusline.py
|
|
169
254
|
cat /tmp/test-input.json | node ~/.claude/statusline.js
|
|
255
|
+
|
|
256
|
+
# Test pip/npm installed version
|
|
257
|
+
cat /tmp/test-input.json | claude-statusline
|
|
170
258
|
```
|
|
171
259
|
|
|
172
260
|
### Check state files
|
|
@@ -185,5 +273,6 @@ watch -n 1 'tail -5 ~/.claude/statusline/statusline.*.state'
|
|
|
185
273
|
- Open a new issue with:
|
|
186
274
|
- Operating system
|
|
187
275
|
- Shell type (bash/zsh)
|
|
276
|
+
- Installation method (pip, npm, shell installer, manual)
|
|
188
277
|
- Script version being used
|
|
189
278
|
- Error messages or unexpected behavior
|
|
Binary file
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cc-context-stats"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.7.0"
|
|
8
8
|
description = "Monitor your Claude Code session context in real-time - track token usage and never run out of context"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
package/scripts/statusline.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* timestamp,total_input_tokens,total_output_tokens,current_usage_input_tokens,
|
|
25
25
|
* current_usage_output_tokens,current_usage_cache_creation,current_usage_cache_read,
|
|
26
26
|
* total_cost_usd,total_lines_added,total_lines_removed,session_id,model_id,
|
|
27
|
-
* workspace_project_dir
|
|
27
|
+
* workspace_project_dir,context_window_size
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
30
|
const { execSync } = require('child_process');
|
|
@@ -72,7 +72,7 @@ function maybeRotateStateFile(stateFile) {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
// ANSI Colors
|
|
75
|
+
// ANSI Colors (defaults, overridable via config)
|
|
76
76
|
const BLUE = '\x1b[0;34m';
|
|
77
77
|
const MAGENTA = '\x1b[0;35m';
|
|
78
78
|
const CYAN = '\x1b[0;36m';
|
|
@@ -82,6 +82,54 @@ const RED = '\x1b[0;31m';
|
|
|
82
82
|
const DIM = '\x1b[2m';
|
|
83
83
|
const RESET = '\x1b[0m';
|
|
84
84
|
|
|
85
|
+
// Named colors for config parsing
|
|
86
|
+
const COLOR_NAMES = {
|
|
87
|
+
black: '\x1b[0;30m',
|
|
88
|
+
red: '\x1b[0;31m',
|
|
89
|
+
green: '\x1b[0;32m',
|
|
90
|
+
yellow: '\x1b[0;33m',
|
|
91
|
+
blue: '\x1b[0;34m',
|
|
92
|
+
magenta: '\x1b[0;35m',
|
|
93
|
+
cyan: '\x1b[0;36m',
|
|
94
|
+
white: '\x1b[0;37m',
|
|
95
|
+
bright_black: '\x1b[0;90m',
|
|
96
|
+
bright_red: '\x1b[0;91m',
|
|
97
|
+
bright_green: '\x1b[0;92m',
|
|
98
|
+
bright_yellow: '\x1b[0;93m',
|
|
99
|
+
bright_blue: '\x1b[0;94m',
|
|
100
|
+
bright_magenta: '\x1b[0;95m',
|
|
101
|
+
bright_cyan: '\x1b[0;96m',
|
|
102
|
+
bright_white: '\x1b[0;97m',
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Parse a color name or #rrggbb hex into an ANSI escape code.
|
|
107
|
+
* Returns null if unrecognized.
|
|
108
|
+
*/
|
|
109
|
+
function parseColor(value) {
|
|
110
|
+
value = value.trim().toLowerCase();
|
|
111
|
+
if (COLOR_NAMES[value]) {
|
|
112
|
+
return COLOR_NAMES[value];
|
|
113
|
+
}
|
|
114
|
+
const m = value.match(/^#([0-9a-f]{6})$/);
|
|
115
|
+
if (m) {
|
|
116
|
+
const r = parseInt(m[1].slice(0, 2), 16);
|
|
117
|
+
const g = parseInt(m[1].slice(2, 4), 16);
|
|
118
|
+
const b = parseInt(m[1].slice(4, 6), 16);
|
|
119
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const COLOR_CONFIG_KEYS = {
|
|
125
|
+
color_green: 'green',
|
|
126
|
+
color_yellow: 'yellow',
|
|
127
|
+
color_red: 'red',
|
|
128
|
+
color_blue: 'blue',
|
|
129
|
+
color_magenta: 'magenta',
|
|
130
|
+
color_cyan: 'cyan',
|
|
131
|
+
};
|
|
132
|
+
|
|
85
133
|
/**
|
|
86
134
|
* Return the visible width of a string after stripping ANSI escape sequences.
|
|
87
135
|
*/
|
|
@@ -125,7 +173,9 @@ function fitToWidth(parts, maxWidth) {
|
|
|
125
173
|
return result;
|
|
126
174
|
}
|
|
127
175
|
|
|
128
|
-
function getGitInfo(projectDir) {
|
|
176
|
+
function getGitInfo(projectDir, magentaColor, cyanColor) {
|
|
177
|
+
const mg = magentaColor || MAGENTA;
|
|
178
|
+
const cy = cyanColor || CYAN;
|
|
129
179
|
const gitDir = path.join(projectDir, '.git');
|
|
130
180
|
if (!fs.existsSync(gitDir) || !fs.statSync(gitDir).isDirectory()) {
|
|
131
181
|
return '';
|
|
@@ -154,9 +204,9 @@ function getGitInfo(projectDir) {
|
|
|
154
204
|
const changes = status.split('\n').filter(l => l.trim()).length;
|
|
155
205
|
|
|
156
206
|
if (changes > 0) {
|
|
157
|
-
return ` | ${
|
|
207
|
+
return ` | ${mg}${branch}${RESET} ${cy}[${changes}]${RESET}`;
|
|
158
208
|
}
|
|
159
|
-
return ` | ${
|
|
209
|
+
return ` | ${mg}${branch}${RESET}`;
|
|
160
210
|
} catch {
|
|
161
211
|
return '';
|
|
162
212
|
}
|
|
@@ -170,6 +220,7 @@ function readConfig() {
|
|
|
170
220
|
showSession: true,
|
|
171
221
|
showIoTokens: true,
|
|
172
222
|
reducedMotion: false,
|
|
223
|
+
colors: {},
|
|
173
224
|
};
|
|
174
225
|
const configPath = path.join(os.homedir(), '.claude', 'statusline.conf');
|
|
175
226
|
|
|
@@ -192,6 +243,12 @@ show_delta=true
|
|
|
192
243
|
|
|
193
244
|
# Show session_id in status line
|
|
194
245
|
show_session=true
|
|
246
|
+
|
|
247
|
+
# Custom colors - use named colors or hex (#rrggbb)
|
|
248
|
+
# Available: color_green, color_yellow, color_red, color_blue, color_magenta, color_cyan
|
|
249
|
+
# Examples:
|
|
250
|
+
# color_green=#7dcfff
|
|
251
|
+
# color_red=#f7768e
|
|
195
252
|
`;
|
|
196
253
|
fs.writeFileSync(configPath, defaultConfig);
|
|
197
254
|
} catch (e) {
|
|
@@ -207,9 +264,10 @@ show_session=true
|
|
|
207
264
|
if (trimmed.startsWith('#') || !trimmed.includes('=')) {
|
|
208
265
|
continue;
|
|
209
266
|
}
|
|
210
|
-
const
|
|
211
|
-
const keyTrimmed =
|
|
212
|
-
const
|
|
267
|
+
const eqIdx = trimmed.indexOf('=');
|
|
268
|
+
const keyTrimmed = trimmed.slice(0, eqIdx).trim();
|
|
269
|
+
const rawValue = trimmed.slice(eqIdx + 1).trim();
|
|
270
|
+
const valueTrimmed = rawValue.toLowerCase();
|
|
213
271
|
if (keyTrimmed === 'autocompact') {
|
|
214
272
|
config.autocompact = valueTrimmed !== 'false';
|
|
215
273
|
} else if (keyTrimmed === 'token_detail') {
|
|
@@ -222,6 +280,11 @@ show_session=true
|
|
|
222
280
|
config.showIoTokens = valueTrimmed !== 'false';
|
|
223
281
|
} else if (keyTrimmed === 'reduced_motion') {
|
|
224
282
|
config.reducedMotion = valueTrimmed !== 'false';
|
|
283
|
+
} else if (COLOR_CONFIG_KEYS[keyTrimmed]) {
|
|
284
|
+
const ansi = parseColor(rawValue);
|
|
285
|
+
if (ansi) {
|
|
286
|
+
config.colors[COLOR_CONFIG_KEYS[keyTrimmed]] = ansi;
|
|
287
|
+
}
|
|
225
288
|
}
|
|
226
289
|
}
|
|
227
290
|
} catch (e) {
|
|
@@ -250,9 +313,6 @@ process.stdin.on('end', () => {
|
|
|
250
313
|
const model = data.model?.display_name || 'Claude';
|
|
251
314
|
const dirName = path.basename(cwd) || '~';
|
|
252
315
|
|
|
253
|
-
// Git info
|
|
254
|
-
const gitInfo = getGitInfo(projectDir);
|
|
255
|
-
|
|
256
316
|
// Read settings from config file
|
|
257
317
|
const config = readConfig();
|
|
258
318
|
const autocompactEnabled = config.autocompact;
|
|
@@ -261,6 +321,18 @@ process.stdin.on('end', () => {
|
|
|
261
321
|
const showSession = config.showSession;
|
|
262
322
|
// Note: showIoTokens setting is read but not yet implemented
|
|
263
323
|
|
|
324
|
+
// Apply color overrides from config
|
|
325
|
+
const c = config.colors || {};
|
|
326
|
+
const cGreen = c.green || GREEN;
|
|
327
|
+
const cYellow = c.yellow || YELLOW;
|
|
328
|
+
const cRed = c.red || RED;
|
|
329
|
+
const cBlue = c.blue || BLUE;
|
|
330
|
+
const cMagenta = c.magenta || MAGENTA;
|
|
331
|
+
const cCyan = c.cyan || CYAN;
|
|
332
|
+
|
|
333
|
+
// Git info (pass configurable colors)
|
|
334
|
+
const gitInfo = getGitInfo(projectDir, cMagenta, cCyan);
|
|
335
|
+
|
|
264
336
|
// Extract session_id once for reuse
|
|
265
337
|
const sessionId = data.session_id;
|
|
266
338
|
|
|
@@ -320,11 +392,11 @@ process.stdin.on('end', () => {
|
|
|
320
392
|
// Color based on free percentage
|
|
321
393
|
let ctxColor;
|
|
322
394
|
if (freePctInt > 50) {
|
|
323
|
-
ctxColor =
|
|
395
|
+
ctxColor = cGreen;
|
|
324
396
|
} else if (freePctInt > 25) {
|
|
325
|
-
ctxColor =
|
|
397
|
+
ctxColor = cYellow;
|
|
326
398
|
} else {
|
|
327
|
-
ctxColor =
|
|
399
|
+
ctxColor = cRed;
|
|
328
400
|
}
|
|
329
401
|
|
|
330
402
|
contextInfo = ` | ${ctxColor}${freeDisplay} free (${freePct.toFixed(1)}%)${RESET}`;
|
|
@@ -438,7 +510,7 @@ process.stdin.on('end', () => {
|
|
|
438
510
|
}
|
|
439
511
|
|
|
440
512
|
// Output: [Model] dir | branch [n] | free (%) [+delta] [AC] session
|
|
441
|
-
const base = `${DIM}[${model}]${RESET} ${
|
|
513
|
+
const base = `${DIM}[${model}]${RESET} ${cBlue}${dirName}${RESET}`;
|
|
442
514
|
const maxWidth = getTerminalWidth();
|
|
443
515
|
const parts = [base, gitInfo, contextInfo, deltaInfo, acInfo, sessionInfo];
|
|
444
516
|
console.log(fitToWidth(parts, maxWidth));
|