ccstatusline 2.0.13 → 2.0.14

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 CHANGED
@@ -34,7 +34,9 @@
34
34
  - [Recent Updates](#-recent-updates)
35
35
  - [Features](#-features)
36
36
  - [Quick Start](#-quick-start)
37
+ - [Windows Support](#-windows-support)
37
38
  - [Usage](#-usage)
39
+ - [API Documentation](#-api-documentation)
38
40
  - [Development](#️-development)
39
41
  - [Contributing](#-contributing)
40
42
  - [License](#-license)
@@ -44,6 +46,10 @@
44
46
 
45
47
  ## 🆕 Recent Updates
46
48
 
49
+ ### v2.0.14 - Add remaining mode toggle to Context Percentage widgets
50
+
51
+ - **Remaining Mode** - You can now toggle the Context Percentage widgets between usage percentage and remaining percentage when configuring them in the TUI by pressing the 'l' key.
52
+
47
53
  ### v2.0.12 - Custom Text widget now supports emojis
48
54
 
49
55
  - **👾 Emoji Support** - You can now paste emoji into the custom text widget. You can also turn on the merge option to get emoji labels for your widgets like this:
@@ -145,6 +151,176 @@ The interactive configuration tool provides a terminal UI where you can:
145
151
 
146
152
  ---
147
153
 
154
+ ## 🪟 Windows Support
155
+
156
+ ccstatusline works seamlessly on Windows with full feature compatibility across PowerShell (5.1+ and 7+), Command Prompt, and Windows Subsystem for Linux (WSL).
157
+
158
+ ### Installation on Windows
159
+
160
+ #### Option 1: Using Bun (Recommended)
161
+ ```powershell
162
+ # Install Bun for Windows
163
+ irm bun.sh/install.ps1 | iex
164
+
165
+ # Run ccstatusline
166
+ bunx ccstatusline@latest
167
+ ```
168
+
169
+ #### Option 2: Using Node.js
170
+ ```powershell
171
+ # Using npm
172
+ npx ccstatusline@latest
173
+
174
+ # Or with Yarn
175
+ yarn dlx ccstatusline@latest
176
+
177
+ # Or with pnpm
178
+ pnpm dlx ccstatusline@latest
179
+ ```
180
+
181
+ ### Windows-Specific Features
182
+
183
+ #### Powerline Font Support
184
+ For optimal Powerline rendering on Windows:
185
+
186
+ **Windows Terminal** (Recommended):
187
+ - Supports Powerline fonts natively
188
+ - Download from [Microsoft Store](https://aka.ms/terminal)
189
+ - Auto-detects compatible fonts
190
+
191
+ **PowerShell/Command Prompt**:
192
+ ```powershell
193
+ # Install JetBrains Mono Nerd Font via winget
194
+ winget install DEVCOM.JetBrainsMonoNerdFont
195
+
196
+ # Alternative: Install base JetBrains Mono font
197
+ winget install "JetBrains.JetBrainsMono"
198
+
199
+ # Or download manually from: https://www.nerdfonts.com/font-downloads
200
+ ```
201
+
202
+ #### Path Handling
203
+ ccstatusline automatically handles Windows-specific paths:
204
+ - Git repositories work with both `/` and `\` path separators
205
+ - Current Working Directory widget displays Windows-style paths correctly
206
+ - Full support for mapped network drives and UNC paths
207
+ - Handles Windows drive letters (C:, D:, etc.)
208
+
209
+ ### Windows Troubleshooting
210
+
211
+ #### Common Issues & Solutions
212
+
213
+ **Issue**: Powerline symbols showing as question marks or boxes
214
+ ```powershell
215
+ # Solution: Install a compatible Nerd Font
216
+ winget install JetBrainsMono.NerdFont
217
+ # Then set the font in your terminal settings
218
+ ```
219
+
220
+ **Issue**: Git commands not recognized
221
+ ```powershell
222
+ # Check if Git is installed and in PATH
223
+ git --version
224
+
225
+ # If not found, install Git:
226
+ winget install Git.Git
227
+ # Or download from: https://git-scm.com/download/win
228
+ ```
229
+
230
+ **Issue**: Permission errors during installation
231
+ ```powershell
232
+ # Use non-global installation (recommended)
233
+ npx ccstatusline@latest
234
+
235
+ # Or run PowerShell as Administrator for global install
236
+ ```
237
+
238
+ **Issue**: "Execution Policy" errors in PowerShell
239
+ ```powershell
240
+ # Temporarily allow script execution
241
+ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
242
+ ```
243
+
244
+ **Issue**: Windows Defender blocking execution
245
+ ```powershell
246
+ # If Windows Defender flags the binary:
247
+ # 1. Open Windows Security
248
+ # 2. Go to "Virus & threat protection"
249
+ # 3. Add exclusion for the ccstatusline binary location
250
+ # Or use temporary bypass (not recommended for production):
251
+ Add-MpPreference -ExclusionPath "$env:USERPROFILE\.bun\bin"
252
+ ```
253
+
254
+ #### Windows Subsystem for Linux (WSL)
255
+ ccstatusline works perfectly in WSL environments:
256
+
257
+ ```bash
258
+ # Install in WSL Ubuntu/Debian
259
+ curl -fsSL https://bun.sh/install | bash
260
+ source ~/.bashrc
261
+ bunx ccstatusline@latest
262
+ ```
263
+
264
+ **WSL Benefits**:
265
+ - Native Unix-style path handling
266
+ - Better font rendering in WSL terminals
267
+ - Seamless integration with Linux development workflows
268
+
269
+ ### Windows Terminal Configuration
270
+
271
+ For the best experience, configure Windows Terminal with these recommended settings:
272
+
273
+ #### Terminal Settings (settings.json)
274
+ ```json
275
+ {
276
+ "profiles": {
277
+ "defaults": {
278
+ "font": {
279
+ "face": "JetBrainsMono Nerd Font",
280
+ "size": 12
281
+ },
282
+ "colorScheme": "One Half Dark"
283
+ }
284
+ }
285
+ }
286
+ ```
287
+
288
+ #### Claude Code Integration
289
+ Configure ccstatusline in your Claude Code settings:
290
+
291
+ **For Bun users** (Windows: `%USERPROFILE%\.claude\settings.json`):
292
+ ```json
293
+ {
294
+ "statusLine": "bunx ccstatusline@latest"
295
+ }
296
+ ```
297
+
298
+ **For npm users**:
299
+ ```json
300
+ {
301
+ "statusLine": "npx ccstatusline@latest"
302
+ }
303
+ ```
304
+
305
+ ### Performance on Windows
306
+
307
+ ccstatusline is optimized for Windows performance:
308
+ - **Bun runtime**: Significantly faster startup times on Windows
309
+ - **Caching**: Intelligent caching of git status and file operations
310
+ - **Async operations**: Non-blocking command execution
311
+ - **Memory efficient**: Minimal resource usage
312
+
313
+ ### Windows-Specific Widget Behavior
314
+
315
+ Some widgets have Windows-specific optimizations:
316
+
317
+ - **Current Working Directory**: Displays Windows drive letters and UNC paths
318
+ - **Git Widgets**: Handle Windows line endings (CRLF) automatically
319
+ - **Custom Commands**: Support both PowerShell and cmd.exe commands
320
+ - **Block Timer**: Accounts for Windows timezone handling
321
+
322
+ ---
323
+
148
324
  ## 📖 Usage
149
325
 
150
326
  Once configured, ccstatusline automatically formats your Claude Code status line. The status line appears at the bottom of your terminal during Claude Code sessions.
@@ -291,6 +467,38 @@ When terminal width is detected, status lines automatically truncate with ellips
291
467
 
292
468
  ---
293
469
 
470
+ ## 📖 API Documentation
471
+
472
+ Complete API documentation is generated using TypeDoc and includes detailed information about:
473
+
474
+ - **Core Types**: Configuration interfaces, widget definitions, and render contexts
475
+ - **Widget System**: All available widgets and their customization options
476
+ - **Utility Functions**: Helper functions for rendering, configuration, and terminal handling
477
+ - **Status Line Rendering**: Core rendering engine and formatting options
478
+
479
+ ### Generating Documentation
480
+
481
+ To generate the API documentation locally:
482
+
483
+ ```bash
484
+ # Generate documentation
485
+ bun run docs
486
+
487
+ # Clean generated documentation
488
+ bun run docs:clean
489
+ ```
490
+
491
+ The documentation will be generated in the `docs/` directory and can be viewed by opening `docs/index.html` in your web browser.
492
+
493
+ ### Documentation Structure
494
+
495
+ - **Types**: Core TypeScript interfaces and type definitions
496
+ - **Widgets**: Individual widget implementations and their APIs
497
+ - **Utils**: Utility functions for configuration, rendering, and terminal operations
498
+ - **Main Module**: Primary entry point and orchestration functions
499
+
500
+ ---
501
+
294
502
  ## 🛠️ Development
295
503
 
296
504
  ### Prerequisites
@@ -51374,7 +51374,7 @@ import { execSync as execSync3 } from "child_process";
51374
51374
  import * as fs5 from "fs";
51375
51375
  import * as path4 from "path";
51376
51376
  var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils";
51377
- var PACKAGE_VERSION = "2.0.13";
51377
+ var PACKAGE_VERSION = "2.0.14";
51378
51378
  function getPackageVersion() {
51379
51379
  if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
51380
51380
  return PACKAGE_VERSION;
@@ -53308,23 +53308,52 @@ class ContextPercentageWidget {
53308
53308
  return "blue";
53309
53309
  }
53310
53310
  getDescription() {
53311
- return "Shows percentage of context window used (of 200k tokens)";
53311
+ return "Shows percentage of context window used or remaining (of 200k tokens)";
53312
53312
  }
53313
53313
  getDisplayName() {
53314
53314
  return "Context %";
53315
53315
  }
53316
53316
  getEditorDisplay(item) {
53317
- return { displayText: this.getDisplayName() };
53317
+ const isInverse = item.metadata?.inverse === "true";
53318
+ const modifiers = [];
53319
+ if (isInverse) {
53320
+ modifiers.push("remaining");
53321
+ }
53322
+ return {
53323
+ displayText: this.getDisplayName(),
53324
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
53325
+ };
53326
+ }
53327
+ handleEditorAction(action, item) {
53328
+ if (action === "toggle-inverse") {
53329
+ const currentState = item.metadata?.inverse === "true";
53330
+ return {
53331
+ ...item,
53332
+ metadata: {
53333
+ ...item.metadata,
53334
+ inverse: (!currentState).toString()
53335
+ }
53336
+ };
53337
+ }
53338
+ return null;
53318
53339
  }
53319
53340
  render(item, context, settings) {
53341
+ const isInverse = item.metadata?.inverse === "true";
53320
53342
  if (context.isPreview) {
53321
- return item.rawValue ? "9.3%" : "Ctx: 9.3%";
53343
+ const previewValue = isInverse ? "90.7%" : "9.3%";
53344
+ return item.rawValue ? previewValue : `Ctx: ${previewValue}`;
53322
53345
  } else if (context.tokenMetrics) {
53323
- const percentage = Math.min(100, context.tokenMetrics.contextLength / 200000 * 100);
53324
- return item.rawValue ? `${percentage.toFixed(1)}%` : `Ctx: ${percentage.toFixed(1)}%`;
53346
+ const usedPercentage = Math.min(100, context.tokenMetrics.contextLength / 200000 * 100);
53347
+ const displayPercentage = isInverse ? 100 - usedPercentage : usedPercentage;
53348
+ return item.rawValue ? `${displayPercentage.toFixed(1)}%` : `Ctx: ${displayPercentage.toFixed(1)}%`;
53325
53349
  }
53326
53350
  return null;
53327
53351
  }
53352
+ getCustomKeybinds() {
53353
+ return [
53354
+ { key: "l", label: "(l)eft/remaining", action: "toggle-inverse" }
53355
+ ];
53356
+ }
53328
53357
  supportsRawValue() {
53329
53358
  return true;
53330
53359
  }
@@ -53338,23 +53367,52 @@ class ContextPercentageUsableWidget {
53338
53367
  return "green";
53339
53368
  }
53340
53369
  getDescription() {
53341
- return "Shows percentage of usable context window used (of 160k tokens before auto-compact)";
53370
+ return "Shows percentage of usable context window used or remaining (of 160k tokens before auto-compact)";
53342
53371
  }
53343
53372
  getDisplayName() {
53344
53373
  return "Context % (usable)";
53345
53374
  }
53346
53375
  getEditorDisplay(item) {
53347
- return { displayText: this.getDisplayName() };
53376
+ const isInverse = item.metadata?.inverse === "true";
53377
+ const modifiers = [];
53378
+ if (isInverse) {
53379
+ modifiers.push("remaining");
53380
+ }
53381
+ return {
53382
+ displayText: this.getDisplayName(),
53383
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
53384
+ };
53385
+ }
53386
+ handleEditorAction(action, item) {
53387
+ if (action === "toggle-inverse") {
53388
+ const currentState = item.metadata?.inverse === "true";
53389
+ return {
53390
+ ...item,
53391
+ metadata: {
53392
+ ...item.metadata,
53393
+ inverse: (!currentState).toString()
53394
+ }
53395
+ };
53396
+ }
53397
+ return null;
53348
53398
  }
53349
53399
  render(item, context, settings) {
53400
+ const isInverse = item.metadata?.inverse === "true";
53350
53401
  if (context.isPreview) {
53351
- return item.rawValue ? "11.6%" : "Ctx(u): 11.6%";
53402
+ const previewValue = isInverse ? "88.4%" : "11.6%";
53403
+ return item.rawValue ? previewValue : `Ctx(u): ${previewValue}`;
53352
53404
  } else if (context.tokenMetrics) {
53353
- const percentage = Math.min(100, context.tokenMetrics.contextLength / 160000 * 100);
53354
- return item.rawValue ? `${percentage.toFixed(1)}%` : `Ctx(u): ${percentage.toFixed(1)}%`;
53405
+ const usedPercentage = Math.min(100, context.tokenMetrics.contextLength / 160000 * 100);
53406
+ const displayPercentage = isInverse ? 100 - usedPercentage : usedPercentage;
53407
+ return item.rawValue ? `${displayPercentage.toFixed(1)}%` : `Ctx(u): ${displayPercentage.toFixed(1)}%`;
53355
53408
  }
53356
53409
  return null;
53357
53410
  }
53411
+ getCustomKeybinds() {
53412
+ return [
53413
+ { key: "l", label: "(l)eft/remaining", action: "toggle-inverse" }
53414
+ ];
53415
+ }
53358
53416
  supportsRawValue() {
53359
53417
  return true;
53360
53418
  }
@@ -53379,10 +53437,9 @@ class SessionClockWidget {
53379
53437
  render(item, context, settings) {
53380
53438
  if (context.isPreview) {
53381
53439
  return item.rawValue ? "2hr 15m" : "Session: 2hr 15m";
53382
- } else if (context.sessionDuration) {
53383
- return item.rawValue ? context.sessionDuration : `Session: ${context.sessionDuration}`;
53384
53440
  }
53385
- return null;
53441
+ const duration3 = context.sessionDuration ?? "0m";
53442
+ return item.rawValue ? duration3 : `Session: ${duration3}`;
53386
53443
  }
53387
53444
  supportsRawValue() {
53388
53445
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccstatusline",
3
- "version": "2.0.13",
3
+ "version": "2.0.14",
4
4
  "description": "A customizable status line formatter for Claude Code CLI",
5
5
  "module": "src/ccstatusline.ts",
6
6
  "type": "module",
@@ -17,12 +17,15 @@
17
17
  "example": "cat scripts/payload.example.json | bun start",
18
18
  "prepublishOnly": "bun run build",
19
19
  "lint": "bun tsc --noEmit; eslint . --config eslint.config.js --max-warnings=999999 --fix",
20
- "test": "bun vitest"
20
+ "test": "bun vitest",
21
+ "docs": "typedoc",
22
+ "docs:clean": "rm -rf docs"
21
23
  },
22
24
  "devDependencies": {
23
25
  "@eslint/js": "^9.33.0",
24
26
  "@stylistic/eslint-plugin": "^5.2.3",
25
27
  "@types/bun": "latest",
28
+ "@types/pluralize": "^0.0.33",
26
29
  "@types/react": "^19.1.10",
27
30
  "chalk": "^5.5.0",
28
31
  "eslint": "^9.33.0",
@@ -34,16 +37,16 @@
34
37
  "ink": "^6.2.0",
35
38
  "ink-gradient": "^3.0.0",
36
39
  "ink-select-input": "^6.2.0",
40
+ "pluralize": "^8.0.0",
37
41
  "react": "^19.1.1",
38
42
  "react-devtools-core": "^6.1.5",
39
43
  "strip-ansi": "^7.1.0",
40
44
  "tinyglobby": "^0.2.14",
45
+ "typedoc": "^0.28.12",
41
46
  "typescript": "^5.9.2",
42
47
  "typescript-eslint": "^8.39.1",
43
48
  "vitest": "^3.2.4",
44
- "zod": "^4.0.17",
45
- "pluralize": "^8.0.0",
46
- "@types/pluralize": "^0.0.33"
49
+ "zod": "^4.0.17"
47
50
  },
48
51
  "keywords": [
49
52
  "claude",