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.
@@ -5,32 +5,62 @@
5
5
  ### One-Line Install (Recommended)
6
6
 
7
7
  ```bash
8
- curl -fsSL https://raw.githubusercontent.com/luongnv89/claude-statusline/main/install.sh | bash
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. In non-interactive mode, it installs the **full** statusline script by default.
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
- ### Interactive Install
13
+ ### NPM (Recommended for Node.js users)
14
14
 
15
- To choose a different script variant:
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
- bash <(curl -fsSL https://raw.githubusercontent.com/luongnv89/claude-statusline/main/install.sh)
39
+ pip install cc-context-stats
19
40
  ```
20
41
 
21
- This runs the installer interactively, allowing you to select from:
42
+ Or with uv:
22
43
 
23
- 1. minimal - Simple: model + directory
24
- 2. git - With git branch info
25
- 3. full - Full featured with context usage (recommended)
26
- 4. python - Python version (full featured)
27
- 5. node - Node.js version (full featured)
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 claude-statusline
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 claude-statusline\scripts\statusline.py %USERPROFILE%\.claude\statusline.py
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
- copy claude-statusline\scripts\statusline.js %USERPROFILE%\.claude\statusline.js
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 (All Platforms)
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 (All Platforms)
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 script:
234
+ Test your statusline:
184
235
 
185
236
  ```bash
186
- # macOS/Linux
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 | Cross-platform, full-featured |
12
- | `context-stats.sh` | macOS, Linux | None | Token usage visualization |
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.
@@ -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. `show_delta=true` in `~/.claude/statusline.conf` (default)
88
- 2. Active Claude Code session generating state files
89
- 3. State files at `~/.claude/statusline/statusline.<session_id>.state`
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-context-stats",
3
- "version": "1.6.1",
3
+ "version": "1.7.0",
4
4
  "description": "Monitor your Claude Code session context in real-time - track token usage and never run out of context",
5
5
  "main": "scripts/statusline.js",
6
6
  "scripts": {
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.6.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" }
@@ -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 ` | ${MAGENTA}${branch}${RESET} ${CYAN}[${changes}]${RESET}`;
207
+ return ` | ${mg}${branch}${RESET} ${cy}[${changes}]${RESET}`;
158
208
  }
159
- return ` | ${MAGENTA}${branch}${RESET}`;
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 [key, value] = trimmed.split('=', 2);
211
- const keyTrimmed = key.trim();
212
- const valueTrimmed = value.trim().toLowerCase();
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 = GREEN;
395
+ ctxColor = cGreen;
324
396
  } else if (freePctInt > 25) {
325
- ctxColor = YELLOW;
397
+ ctxColor = cYellow;
326
398
  } else {
327
- ctxColor = RED;
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} ${BLUE}${dirName}${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));