ccstatusline-usage 2.1.8 → 2.1.12
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 +157 -34
- package/dist/ccstatusline.js +110 -149
- package/package.json +1 -3
package/README.md
CHANGED
|
@@ -9,21 +9,38 @@
|
|
|
9
9
|
|
|
10
10
|
</pre>
|
|
11
11
|
|
|
12
|
-
# ccstatusline
|
|
12
|
+
# ccstatusline-usage
|
|
13
13
|
|
|
14
14
|
**🎨 A highly customizable status line formatter for Claude Code CLI**
|
|
15
|
-
*Display model info, git branch, token usage, and other metrics in your terminal*
|
|
15
|
+
*Display model info, git branch, token usage, API usage, and other metrics in your terminal*
|
|
16
16
|
|
|
17
|
-
[
|
|
18
|
-
|
|
17
|
+
> Fork of [sirmalloc/ccstatusline](https://github.com/sirmalloc/ccstatusline) with added **API usage widgets** (session/weekly utilization bars, reset timer, context bar).
|
|
18
|
+
|
|
19
|
+
[](https://www.npmjs.com/package/ccstatusline-usage)
|
|
20
|
+
[](https://www.npmjs.com/package/ccstatusline-usage)
|
|
19
21
|
[](https://github.com/sirmalloc/ccstatusline/blob/main/LICENSE)
|
|
20
|
-
[](https://nodejs.org)
|
|
21
|
-
[](https://packagephobia.com/result?p=ccstatusline)
|
|
22
|
-
[](https://github.com/
|
|
22
|
+
[](https://nodejs.org)
|
|
23
|
+
[](https://packagephobia.com/result?p=ccstatusline-usage)
|
|
24
|
+
[](https://github.com/pcvelz/ccstatusline-usage/graphs/commit-activity)
|
|
23
25
|
|
|
24
26
|
[](https://github.com/hesreallyhim/awesome-claude-code)
|
|
25
27
|
[](https://claudelog.com/)
|
|
26
28
|
|
|
29
|
+
## Fork Enhancements
|
|
30
|
+
|
|
31
|
+
This fork adds API-based usage widgets beyond the upstream:
|
|
32
|
+
|
|
33
|
+
- **Session/Weekly Usage** - Real utilization from Anthropic API with progress bars
|
|
34
|
+
- **Reset Timer** - Time until 5-hour session window resets
|
|
35
|
+
- **Context Window Display** - Visual bar showing context usage
|
|
36
|
+
- **Two-line Layout** - Session info on line 1, context on line 2
|
|
37
|
+
|
|
38
|
+
### Enhanced Status Line Preview
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Session: [████░░░░░░░░░░░] 27.0% | Weekly: [███████████████] 100.0% | Extra: €2.50/€50.00 | Model: Opus 4.6 | Session ID: 0109b99d...
|
|
42
|
+
Context: [███████░░░░░░░░] 103k/200k (51%)
|
|
43
|
+
```
|
|
27
44
|
|
|
28
45
|

|
|
29
46
|
|
|
@@ -39,6 +56,7 @@
|
|
|
39
56
|
- [API Documentation](#-api-documentation)
|
|
40
57
|
- [Development](#️-development)
|
|
41
58
|
- [Contributing](#-contributing)
|
|
59
|
+
- [Uninstall](#️-uninstall)
|
|
42
60
|
- [License](#-license)
|
|
43
61
|
- [Related Projects](#-related-projects)
|
|
44
62
|
|
|
@@ -46,6 +64,14 @@
|
|
|
46
64
|
|
|
47
65
|
## 🆕 Recent Updates
|
|
48
66
|
|
|
67
|
+
### [v2.1.12](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.12) - Remove thinking effort bars from model widget
|
|
68
|
+
|
|
69
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Remove thinking effort bars** — Claude Code now shows thinking intensity natively in its own UI, so the `▌▌▌` bars after the model name have been removed from the Model widget
|
|
70
|
+
|
|
71
|
+
### [v2.1.11](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.11) - Configurable extra usage balance
|
|
72
|
+
|
|
73
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Configurable extra usage balance** — Add `extraUsageBalance` setting (in cents) to `~/.config/ccstatusline/settings.json` to override the API's monthly limit with your actual prepaid balance (e.g., `"extraUsageBalance": 5000` shows `Extra: €0.00/€50.00`)
|
|
74
|
+
|
|
49
75
|
### [v2.1.8](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.8) - Windows support for API usage widgets
|
|
50
76
|
|
|
51
77
|
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Windows compatibility** — API usage widgets now work on Windows by using `os.homedir()` instead of `process.env.HOME` for credential and cache file paths
|
|
@@ -147,10 +173,13 @@
|
|
|
147
173
|
## ✨ Features
|
|
148
174
|
|
|
149
175
|
- **📊 Real-time Metrics** - Display model name, git branch, token usage, session duration, block timer, and more
|
|
176
|
+
- **📈 API Usage Tracking** - Real-time 5-hour session and weekly utilization from Anthropic API with progress bars
|
|
177
|
+
- **⏱️ Reset Timer** - Countdown to when your 5-hour session window resets
|
|
150
178
|
- **🎨 Fully Customizable** - Choose what to display and customize colors for each element
|
|
151
179
|
- **⚡ Powerline Support** - Beautiful Powerline-style rendering with arrow separators, caps, and custom fonts
|
|
152
180
|
- **📐 Multi-line Support** - Configure multiple independent status lines
|
|
153
181
|
- **🖥️ Interactive TUI** - Built-in configuration interface using React/Ink
|
|
182
|
+
- **🔎 Fast Widget Picker** - Add/change widgets by category with search and ranked matching
|
|
154
183
|
- **⚙️ Global Options** - Apply consistent formatting across all widgets (padding, separators, bold, background)
|
|
155
184
|
- **🚀 Cross-platform** - Works seamlessly with both Bun and Node.js
|
|
156
185
|
- **🔧 Flexible Configuration** - Supports custom Claude Code config directory via `CLAUDE_CONFIG_DIR` environment variable
|
|
@@ -165,10 +194,10 @@
|
|
|
165
194
|
|
|
166
195
|
```bash
|
|
167
196
|
# Run the configuration TUI with npm
|
|
168
|
-
npx ccstatusline@latest
|
|
197
|
+
npx -y ccstatusline-usage@latest
|
|
169
198
|
|
|
170
199
|
# Or with Bun (faster)
|
|
171
|
-
bunx ccstatusline@latest
|
|
200
|
+
bunx -y ccstatusline-usage@latest
|
|
172
201
|
```
|
|
173
202
|
|
|
174
203
|
### Configure ccstatusline
|
|
@@ -193,6 +222,24 @@ The interactive configuration tool provides a terminal UI where you can:
|
|
|
193
222
|
> $env:CLAUDE_CONFIG_DIR="C:\custom\path\.claude"
|
|
194
223
|
> ```
|
|
195
224
|
|
|
225
|
+
### Claude Code settings.json format
|
|
226
|
+
|
|
227
|
+
When you install from the TUI, ccstatusline writes a `statusLine` command object to your Claude Code settings:
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"statusLine": {
|
|
232
|
+
"type": "command",
|
|
233
|
+
"command": "npx -y ccstatusline-usage@latest",
|
|
234
|
+
"padding": 0
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Other supported command values are:
|
|
240
|
+
- `bunx -y ccstatusline-usage@latest`
|
|
241
|
+
- `ccstatusline` (for self-managed/global installs)
|
|
242
|
+
|
|
196
243
|
---
|
|
197
244
|
|
|
198
245
|
## 🪟 Windows Support
|
|
@@ -207,13 +254,13 @@ ccstatusline works seamlessly on Windows with full feature compatibility across
|
|
|
207
254
|
irm bun.sh/install.ps1 | iex
|
|
208
255
|
|
|
209
256
|
# Run ccstatusline
|
|
210
|
-
bunx ccstatusline@latest
|
|
257
|
+
bunx -y ccstatusline@latest
|
|
211
258
|
```
|
|
212
259
|
|
|
213
260
|
#### Option 2: Using Node.js
|
|
214
261
|
```powershell
|
|
215
262
|
# Using npm
|
|
216
|
-
npx ccstatusline@latest
|
|
263
|
+
npx -y ccstatusline@latest
|
|
217
264
|
|
|
218
265
|
# Or with Yarn
|
|
219
266
|
yarn dlx ccstatusline@latest
|
|
@@ -274,7 +321,7 @@ winget install Git.Git
|
|
|
274
321
|
**Issue**: Permission errors during installation
|
|
275
322
|
```powershell
|
|
276
323
|
# Use non-global installation (recommended)
|
|
277
|
-
npx ccstatusline@latest
|
|
324
|
+
npx -y ccstatusline@latest
|
|
278
325
|
|
|
279
326
|
# Or run PowerShell as Administrator for global install
|
|
280
327
|
```
|
|
@@ -302,7 +349,7 @@ ccstatusline works perfectly in WSL environments:
|
|
|
302
349
|
# Install in WSL Ubuntu/Debian
|
|
303
350
|
curl -fsSL https://bun.sh/install | bash
|
|
304
351
|
source ~/.bashrc
|
|
305
|
-
bunx ccstatusline@latest
|
|
352
|
+
bunx -y ccstatusline@latest
|
|
306
353
|
```
|
|
307
354
|
|
|
308
355
|
**WSL Benefits**:
|
|
@@ -339,14 +386,22 @@ Configure ccstatusline in your Claude Code settings:
|
|
|
339
386
|
**For Bun users**:
|
|
340
387
|
```json
|
|
341
388
|
{
|
|
342
|
-
"statusLine":
|
|
389
|
+
"statusLine": {
|
|
390
|
+
"type": "command",
|
|
391
|
+
"command": "bunx -y ccstatusline@latest",
|
|
392
|
+
"padding": 0
|
|
393
|
+
}
|
|
343
394
|
}
|
|
344
395
|
```
|
|
345
396
|
|
|
346
397
|
**For npm users**:
|
|
347
398
|
```json
|
|
348
399
|
{
|
|
349
|
-
"statusLine":
|
|
400
|
+
"statusLine": {
|
|
401
|
+
"type": "command",
|
|
402
|
+
"command": "npx -y ccstatusline@latest",
|
|
403
|
+
"padding": 0
|
|
404
|
+
}
|
|
350
405
|
}
|
|
351
406
|
```
|
|
352
407
|
|
|
@@ -354,11 +409,10 @@ Configure ccstatusline in your Claude Code settings:
|
|
|
354
409
|
|
|
355
410
|
### Performance on Windows
|
|
356
411
|
|
|
357
|
-
ccstatusline
|
|
358
|
-
- **
|
|
359
|
-
- **
|
|
360
|
-
- **
|
|
361
|
-
- **Memory efficient**: Minimal resource usage
|
|
412
|
+
ccstatusline includes Windows-specific runtime behavior:
|
|
413
|
+
- **UTF-8 piped output fix**: In piped mode, it attempts to set code page `65001` for reliable symbol rendering
|
|
414
|
+
- **Path compatibility**: Git and CWD widgets handle both `/` and `\` separators
|
|
415
|
+
- **Block timer cache**: Cached block metrics reduce repeated JSONL scanning
|
|
362
416
|
|
|
363
417
|
### Windows-Specific Widget Behavior
|
|
364
418
|
|
|
@@ -375,17 +429,31 @@ Some widgets have Windows-specific optimizations:
|
|
|
375
429
|
|
|
376
430
|
Once configured, ccstatusline automatically formats your Claude Code status line. The status line appears at the bottom of your terminal during Claude Code sessions.
|
|
377
431
|
|
|
432
|
+
### Runtime Modes
|
|
433
|
+
|
|
434
|
+
- **Interactive mode (TUI)**: Launches when there is no stdin input
|
|
435
|
+
- **Piped mode (renderer)**: Parses Claude Code status JSON from stdin and prints one or more formatted lines
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
# Interactive TUI
|
|
439
|
+
bun run start
|
|
440
|
+
|
|
441
|
+
# Piped mode with example payload
|
|
442
|
+
bun run example
|
|
443
|
+
```
|
|
444
|
+
|
|
378
445
|
### 📊 Available Widgets
|
|
379
446
|
|
|
380
447
|
- **Model Name** - Shows the current Claude model (e.g., "Claude 3.5 Sonnet")
|
|
381
448
|
- **Git Branch** - Displays current git branch name
|
|
382
449
|
- **Git Changes** - Shows uncommitted insertions/deletions (e.g., "+42,-10")
|
|
450
|
+
- **Git Root Dir** - Shows the git repository root directory name
|
|
383
451
|
- **Git Worktree** - Shows the name of the current git worktree
|
|
384
452
|
- **Session Clock** - Shows elapsed time since session start (e.g., "2hr 15m")
|
|
385
453
|
- **Session Cost** - Shows total session cost in USD (e.g., "$1.23")
|
|
386
454
|
- **Session Name** - Shows the session name set via `/rename` command in Claude Code
|
|
387
455
|
- **Block Timer** - Shows time elapsed in current 5-hour block or progress bar
|
|
388
|
-
- **Current Working Directory** - Shows current working directory with
|
|
456
|
+
- **Current Working Directory** - Shows current working directory with segment limit, fish-style abbreviation, and optional `~` home abbreviation
|
|
389
457
|
- **Version** - Shows Claude Code version
|
|
390
458
|
- **Output Style** - Shows the currently set output style in Claude Code
|
|
391
459
|
- **Tokens Input** - Shows input tokens used
|
|
@@ -393,15 +461,20 @@ Once configured, ccstatusline automatically formats your Claude Code status line
|
|
|
393
461
|
- **Tokens Cached** - Shows cached tokens used
|
|
394
462
|
- **Tokens Total** - Shows total tokens used
|
|
395
463
|
- **Context Length** - Shows current context length in tokens
|
|
396
|
-
- **Context Percentage** - Shows percentage of context limit used (dynamic: 1M for
|
|
397
|
-
- **Context Percentage (usable)** - Shows percentage of usable context (dynamic: 800k for
|
|
464
|
+
- **Context Percentage** - Shows percentage of context limit used (dynamic: 1M for model IDs with `[1m]` suffix, 200k otherwise)
|
|
465
|
+
- **Context Percentage (usable)** - Shows percentage of usable context (dynamic: 800k for model IDs with `[1m]` suffix, 160k otherwise, accounting for auto-compact at 80%)
|
|
398
466
|
- **Terminal Width** - Shows detected terminal width (for debugging)
|
|
399
467
|
- **Memory Usage** - Shows system memory usage (used/total, e.g., "Mem: 12.4G/16.0G")
|
|
400
468
|
- **Battery** - Shows battery percentage on macOS and Linux (only visible when on battery power, hidden when charging)
|
|
469
|
+
- **Claude Session ID** - Shows the current Claude Code session ID (compact: 8-char truncation)
|
|
470
|
+
- **Session Usage** *(ccstatusline-usage)* - Shows 5-hour session API utilization as a progress bar (e.g., "Session: [███░░░░░░░░░░░░] 20%")
|
|
471
|
+
- **Weekly Usage** *(ccstatusline-usage)* - Shows 7-day API utilization as a progress bar (e.g., "Weekly: [██░░░░░░░░░░░░░] 12%")
|
|
472
|
+
- **Reset Timer** *(ccstatusline-usage)* - Shows time until session limit resets (e.g., "4:30 hr"), or extra usage spending when weekly budget is exhausted
|
|
473
|
+
- **Context Bar** *(ccstatusline-usage)* - Shows context window usage as a progress bar (e.g., "Context: [████░░░░░░░░░░░] 50k/200k (25%)")
|
|
401
474
|
- **Custom Text** - Add your own custom text to the status line
|
|
402
475
|
- **Custom Command** - Execute shell commands and display their output (refreshes whenever the statusline is updated by Claude Code)
|
|
403
|
-
- **Separator** - Visual divider between widgets (customizable: |, -, comma, space)
|
|
404
|
-
- **Flex Separator** - Expands to fill available space
|
|
476
|
+
- **Separator** - Visual divider between widgets (customizable: |, -, comma, space; available when Powerline mode is off and no default separator is configured)
|
|
477
|
+
- **Flex Separator** - Expands to fill available space (available when Powerline mode is off)
|
|
405
478
|
|
|
406
479
|
---
|
|
407
480
|
|
|
@@ -471,6 +544,23 @@ Some widgets support "raw value" mode which displays just the value without a la
|
|
|
471
544
|
- Normal: `Block: 3hr 45m` → Raw: `3hr 45m`
|
|
472
545
|
- Normal: `Ctx: 18.6k` → Raw: `18.6k`
|
|
473
546
|
|
|
547
|
+
### ⌨️ Widget Editor Keybinds
|
|
548
|
+
|
|
549
|
+
Common controls in the line editor:
|
|
550
|
+
- `a` add widget
|
|
551
|
+
- `i` insert widget
|
|
552
|
+
- `Enter` enter/exit move mode
|
|
553
|
+
- `d` delete selected widget
|
|
554
|
+
- `r` toggle raw value (supported widgets)
|
|
555
|
+
- `m` cycle merge mode (`off` → `merge` → `merge no padding`)
|
|
556
|
+
|
|
557
|
+
Widget-specific shortcuts:
|
|
558
|
+
- **Git widgets**: `h` toggle hide `no git` output
|
|
559
|
+
- **Context % widgets**: `l` toggle used vs remaining display
|
|
560
|
+
- **Block Timer**: `p` cycle display mode (time/full bar/short bar)
|
|
561
|
+
- **Current Working Dir**: `h` home abbreviation, `s` segment editor, `f` fish-style path
|
|
562
|
+
- **Custom Command**: `e` command, `w` max width, `t` timeout, `p` preserve ANSI colors
|
|
563
|
+
|
|
474
564
|
---
|
|
475
565
|
|
|
476
566
|
### 🔧 Custom Widgets
|
|
@@ -487,6 +577,8 @@ Execute shell commands and display their output dynamically:
|
|
|
487
577
|
- Receives the full Claude Code JSON data via stdin (model info, session ID, transcript path, etc.)
|
|
488
578
|
- Displays command output inline in your status line
|
|
489
579
|
- Configurable timeout (default: 1000ms)
|
|
580
|
+
- Optional max-width truncation
|
|
581
|
+
- Optional ANSI color preservation (`preserve colors`)
|
|
490
582
|
- Examples:
|
|
491
583
|
- `pwd | xargs basename` - Show current directory name
|
|
492
584
|
- `node -v` - Display Node.js version
|
|
@@ -558,7 +650,7 @@ The documentation will be generated in the `docs/` directory and can be viewed b
|
|
|
558
650
|
|
|
559
651
|
- [Bun](https://bun.sh) (v1.0+)
|
|
560
652
|
- Git
|
|
561
|
-
- Node.js
|
|
653
|
+
- Node.js 14+ (optional, for running the built `dist/ccstatusline.js` binary or npm publishing)
|
|
562
654
|
|
|
563
655
|
### Setup
|
|
564
656
|
|
|
@@ -574,13 +666,38 @@ bun install
|
|
|
574
666
|
### Development Commands
|
|
575
667
|
|
|
576
668
|
```bash
|
|
577
|
-
# Run in TUI mode
|
|
578
|
-
bun run
|
|
669
|
+
# Run in TUI mode
|
|
670
|
+
bun run start
|
|
671
|
+
|
|
672
|
+
# Test piped mode with example payload
|
|
673
|
+
bun run example
|
|
674
|
+
|
|
675
|
+
# Run tests
|
|
676
|
+
bun test
|
|
677
|
+
|
|
678
|
+
# Run typecheck + eslint autofix
|
|
679
|
+
bun run lint
|
|
579
680
|
|
|
580
681
|
# Build for distribution
|
|
581
682
|
bun run build
|
|
683
|
+
|
|
684
|
+
# Generate TypeDoc documentation
|
|
685
|
+
bun run docs
|
|
582
686
|
```
|
|
583
687
|
|
|
688
|
+
### Configuration Files
|
|
689
|
+
|
|
690
|
+
- `~/.config/ccstatusline/settings.json` - ccstatusline UI/render settings
|
|
691
|
+
- `~/.claude/settings.json` - Claude Code settings (`statusLine` command object)
|
|
692
|
+
- `~/.cache/ccstatusline/block-cache-*.json` - block timer cache (keyed by Claude config directory hash)
|
|
693
|
+
|
|
694
|
+
If you use a custom Claude config location, set `CLAUDE_CONFIG_DIR` and ccstatusline will read/write that path instead of `~/.claude`.
|
|
695
|
+
|
|
696
|
+
### Build Notes
|
|
697
|
+
|
|
698
|
+
- Build target is Node.js 14+ (`dist/ccstatusline.js`)
|
|
699
|
+
- During install, `ink@6.2.0` is patched to fix backspace handling on macOS terminals
|
|
700
|
+
|
|
584
701
|
### 📁 Project Structure
|
|
585
702
|
|
|
586
703
|
```
|
|
@@ -631,11 +748,13 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
631
748
|
|
|
632
749
|
---
|
|
633
750
|
|
|
634
|
-
##
|
|
751
|
+
## 🗑️ Uninstall
|
|
635
752
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
753
|
+
```bash
|
|
754
|
+
npm uninstall -g ccstatusline-usage
|
|
755
|
+
rm -rf ~/.npm/_npx ~/.config/ccstatusline ~/.cache/ccstatusline*
|
|
756
|
+
jq 'del(.statusLine)' ~/.claude/settings.json > /tmp/cs.json && cat /tmp/cs.json > ~/.claude/settings.json
|
|
757
|
+
```
|
|
639
758
|
|
|
640
759
|
---
|
|
641
760
|
|
|
@@ -651,6 +770,10 @@ If ccstatusline is useful to you, consider buying me a coffee:
|
|
|
651
770
|
|
|
652
771
|
- GitHub: [@sirmalloc](https://github.com/sirmalloc)
|
|
653
772
|
|
|
773
|
+
**PC van Velzen** ([pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage) fork)
|
|
774
|
+
|
|
775
|
+
- GitHub: [@pcvelz](https://github.com/pcvelz)
|
|
776
|
+
|
|
654
777
|
---
|
|
655
778
|
|
|
656
779
|
## 🔗 Related Projects
|
|
@@ -688,8 +811,8 @@ Give a ⭐ if this project helped you!
|
|
|
688
811
|
[](https://github.com/sirmalloc/ccstatusline/network/members)
|
|
689
812
|
[](https://github.com/sirmalloc/ccstatusline/watchers)
|
|
690
813
|
|
|
691
|
-
[](https://www.npmjs.com/package/ccstatusline)
|
|
692
|
-
[](https://www.npmjs.com/package/ccstatusline)
|
|
814
|
+
[](https://www.npmjs.com/package/ccstatusline-usage)
|
|
815
|
+
[](https://www.npmjs.com/package/ccstatusline-usage)
|
|
693
816
|
[](https://github.com/sirmalloc/ccstatusline/blob/main/LICENSE)
|
|
694
817
|
[](https://bun.sh)
|
|
695
818
|
|
package/dist/ccstatusline.js
CHANGED
|
@@ -32401,8 +32401,8 @@ var require_utils = __commonJS((exports) => {
|
|
|
32401
32401
|
}
|
|
32402
32402
|
return output;
|
|
32403
32403
|
};
|
|
32404
|
-
exports.basename = (
|
|
32405
|
-
const segs =
|
|
32404
|
+
exports.basename = (path6, { windows } = {}) => {
|
|
32405
|
+
const segs = path6.split(windows ? /[\\/]/ : "/");
|
|
32406
32406
|
const last2 = segs[segs.length - 1];
|
|
32407
32407
|
if (last2 === "") {
|
|
32408
32408
|
return segs[segs.length - 2];
|
|
@@ -33924,6 +33924,9 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
33924
33924
|
if (env.TERM === "xterm-ghostty") {
|
|
33925
33925
|
return 3;
|
|
33926
33926
|
}
|
|
33927
|
+
if (env.TERM === "wezterm") {
|
|
33928
|
+
return 3;
|
|
33929
|
+
}
|
|
33927
33930
|
if ("TERM_PROGRAM" in env) {
|
|
33928
33931
|
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
33929
33932
|
switch (env.TERM_PROGRAM) {
|
|
@@ -51034,6 +51037,7 @@ var SettingsSchema = exports_external.object({
|
|
|
51034
51037
|
theme: undefined,
|
|
51035
51038
|
autoAlign: false
|
|
51036
51039
|
}),
|
|
51040
|
+
extraUsageBalance: exports_external.number().optional(),
|
|
51037
51041
|
updatemessage: exports_external.object({
|
|
51038
51042
|
message: exports_external.string().nullable().optional(),
|
|
51039
51043
|
remaining: exports_external.number().nullable().optional()
|
|
@@ -51469,7 +51473,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51469
51473
|
import * as fs5 from "fs";
|
|
51470
51474
|
import * as path4 from "path";
|
|
51471
51475
|
var __dirname = "/Users/peter/Documents/Code/ccstatusline-usage/src/utils";
|
|
51472
|
-
var PACKAGE_VERSION = "2.1.
|
|
51476
|
+
var PACKAGE_VERSION = "2.1.12";
|
|
51473
51477
|
function getPackageVersion() {
|
|
51474
51478
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51475
51479
|
return PACKAGE_VERSION;
|
|
@@ -52319,9 +52323,6 @@ var shouldInsertInput = (input, key) => {
|
|
|
52319
52323
|
};
|
|
52320
52324
|
|
|
52321
52325
|
// src/widgets/Model.ts
|
|
52322
|
-
import * as fs6 from "fs";
|
|
52323
|
-
import { homedir as homedir4 } from "os";
|
|
52324
|
-
import * as path5 from "path";
|
|
52325
52326
|
var MOBILE_THRESHOLD = 80;
|
|
52326
52327
|
function compactModelName(name) {
|
|
52327
52328
|
const stripped = name.replace(/^claude-/, "");
|
|
@@ -52332,44 +52333,6 @@ function compactModelName(name) {
|
|
|
52332
52333
|
}
|
|
52333
52334
|
return stripped;
|
|
52334
52335
|
}
|
|
52335
|
-
function getEffortLevel() {
|
|
52336
|
-
const envLevel = process.env.CLAUDE_CODE_EFFORT_LEVEL;
|
|
52337
|
-
if (envLevel)
|
|
52338
|
-
return envLevel.toLowerCase();
|
|
52339
|
-
try {
|
|
52340
|
-
const configDir = process.env.CLAUDE_CONFIG_DIR ?? path5.join(homedir4(), ".claude");
|
|
52341
|
-
const settingsPath = path5.join(configDir, "settings.json");
|
|
52342
|
-
const content = fs6.readFileSync(settingsPath, "utf-8");
|
|
52343
|
-
const settings = JSON.parse(content);
|
|
52344
|
-
if (settings.effortLevel)
|
|
52345
|
-
return settings.effortLevel.toLowerCase();
|
|
52346
|
-
} catch {}
|
|
52347
|
-
return "high";
|
|
52348
|
-
}
|
|
52349
|
-
function effortToLevel(effort) {
|
|
52350
|
-
switch (effort) {
|
|
52351
|
-
case "low":
|
|
52352
|
-
return 1;
|
|
52353
|
-
case "medium":
|
|
52354
|
-
return 2;
|
|
52355
|
-
default:
|
|
52356
|
-
return 3;
|
|
52357
|
-
}
|
|
52358
|
-
}
|
|
52359
|
-
function renderThinkingBars(level, settings) {
|
|
52360
|
-
if (level <= 0)
|
|
52361
|
-
return "";
|
|
52362
|
-
const colorLevel = getColorLevelString(settings.colorLevel);
|
|
52363
|
-
const activeChalk = getChalkColor("red", colorLevel);
|
|
52364
|
-
const dimChalk = getChalkColor("brightBlack", colorLevel);
|
|
52365
|
-
const bars = ["▌", "▌", "▌"];
|
|
52366
|
-
return " " + bars.map((bar, i) => {
|
|
52367
|
-
if (i < level) {
|
|
52368
|
-
return activeChalk ? activeChalk(bar) : bar;
|
|
52369
|
-
}
|
|
52370
|
-
return dimChalk ? dimChalk(bar) : bar;
|
|
52371
|
-
}).join("");
|
|
52372
|
-
}
|
|
52373
52336
|
|
|
52374
52337
|
class ModelWidget {
|
|
52375
52338
|
getDefaultColor() {
|
|
@@ -52389,21 +52352,18 @@ class ModelWidget {
|
|
|
52389
52352
|
}
|
|
52390
52353
|
render(item, context, settings) {
|
|
52391
52354
|
if (context.isPreview) {
|
|
52392
|
-
|
|
52393
|
-
return item.rawValue ? `Claude${bars2}` : `Model: Claude${bars2}`;
|
|
52355
|
+
return item.rawValue ? "Claude" : "Model: Claude";
|
|
52394
52356
|
}
|
|
52395
52357
|
const model = context.data?.model;
|
|
52396
52358
|
const modelId = typeof model === "string" ? model : model?.id;
|
|
52397
52359
|
const modelDisplayName = typeof model === "string" ? model : model?.display_name ?? model?.id;
|
|
52398
52360
|
if (!modelDisplayName)
|
|
52399
52361
|
return null;
|
|
52400
|
-
const level = effortToLevel(getEffortLevel());
|
|
52401
|
-
const bars = renderThinkingBars(level, settings);
|
|
52402
52362
|
const mobile = (context.terminalWidth ?? 0) > 0 && (context.terminalWidth ?? 0) < MOBILE_THRESHOLD;
|
|
52403
52363
|
if (mobile && modelId) {
|
|
52404
|
-
return `M: ${compactModelName(modelId)}
|
|
52364
|
+
return `M: ${compactModelName(modelId)}`;
|
|
52405
52365
|
}
|
|
52406
|
-
return item.rawValue ?
|
|
52366
|
+
return item.rawValue ? modelDisplayName : `Model: ${modelDisplayName}`;
|
|
52407
52367
|
}
|
|
52408
52368
|
supportsRawValue() {
|
|
52409
52369
|
return true;
|
|
@@ -54563,27 +54523,27 @@ class CurrentWorkingDirWidget {
|
|
|
54563
54523
|
supportsColors(item) {
|
|
54564
54524
|
return true;
|
|
54565
54525
|
}
|
|
54566
|
-
abbreviateHomeDir(
|
|
54526
|
+
abbreviateHomeDir(path5) {
|
|
54567
54527
|
const homeDir = os5.homedir();
|
|
54568
|
-
if (
|
|
54528
|
+
if (path5 === homeDir) {
|
|
54569
54529
|
return "~";
|
|
54570
54530
|
}
|
|
54571
|
-
if (
|
|
54572
|
-
const boundaryChar =
|
|
54531
|
+
if (path5.startsWith(homeDir)) {
|
|
54532
|
+
const boundaryChar = path5[homeDir.length];
|
|
54573
54533
|
if (boundaryChar !== "/" && boundaryChar !== "\\") {
|
|
54574
|
-
return
|
|
54534
|
+
return path5;
|
|
54575
54535
|
}
|
|
54576
|
-
return "~" +
|
|
54536
|
+
return "~" + path5.slice(homeDir.length);
|
|
54577
54537
|
}
|
|
54578
|
-
return
|
|
54538
|
+
return path5;
|
|
54579
54539
|
}
|
|
54580
|
-
abbreviatePath(
|
|
54540
|
+
abbreviatePath(path5) {
|
|
54581
54541
|
const homeDir = os5.homedir();
|
|
54582
|
-
const useBackslash =
|
|
54542
|
+
const useBackslash = path5.includes("\\") && !path5.includes("/");
|
|
54583
54543
|
const sep = useBackslash ? "\\" : "/";
|
|
54584
|
-
let normalizedPath =
|
|
54585
|
-
if (
|
|
54586
|
-
normalizedPath = "~" +
|
|
54544
|
+
let normalizedPath = path5;
|
|
54545
|
+
if (path5.startsWith(homeDir)) {
|
|
54546
|
+
normalizedPath = "~" + path5.slice(homeDir.length);
|
|
54587
54547
|
}
|
|
54588
54548
|
const parts = normalizedPath.split(/[\\/]+/).filter((part) => part !== "");
|
|
54589
54549
|
const abbreviated = parts.map((part, index) => {
|
|
@@ -54707,11 +54667,11 @@ import {
|
|
|
54707
54667
|
execSync as execSync6,
|
|
54708
54668
|
spawnSync
|
|
54709
54669
|
} from "child_process";
|
|
54710
|
-
import * as
|
|
54670
|
+
import * as fs6 from "fs";
|
|
54711
54671
|
import * as os6 from "os";
|
|
54712
|
-
import * as
|
|
54713
|
-
var CACHE_FILE =
|
|
54714
|
-
var LOCK_FILE =
|
|
54672
|
+
import * as path5 from "path";
|
|
54673
|
+
var CACHE_FILE = path5.join(os6.homedir(), ".cache", "ccstatusline-api.json");
|
|
54674
|
+
var LOCK_FILE = path5.join(os6.homedir(), ".cache", "ccstatusline-api.lock");
|
|
54715
54675
|
var CACHE_MAX_AGE = 180;
|
|
54716
54676
|
var LOCK_MAX_AGE = 30;
|
|
54717
54677
|
var TOKEN_CACHE_MAX_AGE = 3600;
|
|
@@ -54719,10 +54679,10 @@ var cachedData = null;
|
|
|
54719
54679
|
var cacheTime = 0;
|
|
54720
54680
|
var cachedToken = null;
|
|
54721
54681
|
var tokenCacheTime = 0;
|
|
54722
|
-
var CRED_FILE =
|
|
54682
|
+
var CRED_FILE = path5.join(os6.homedir(), ".claude", ".credentials.json");
|
|
54723
54683
|
function readTokenFromFile() {
|
|
54724
54684
|
try {
|
|
54725
|
-
const creds = JSON.parse(
|
|
54685
|
+
const creds = JSON.parse(fs6.readFileSync(CRED_FILE, "utf8"));
|
|
54726
54686
|
return creds?.claudeAiOauth?.accessToken ?? null;
|
|
54727
54687
|
} catch {
|
|
54728
54688
|
return null;
|
|
@@ -54759,7 +54719,7 @@ function getToken() {
|
|
|
54759
54719
|
}
|
|
54760
54720
|
function readStaleCache() {
|
|
54761
54721
|
try {
|
|
54762
|
-
return JSON.parse(
|
|
54722
|
+
return JSON.parse(fs6.readFileSync(CACHE_FILE, "utf8"));
|
|
54763
54723
|
} catch {
|
|
54764
54724
|
return null;
|
|
54765
54725
|
}
|
|
@@ -54817,10 +54777,10 @@ function fetchApiData() {
|
|
|
54817
54777
|
return cachedData;
|
|
54818
54778
|
}
|
|
54819
54779
|
try {
|
|
54820
|
-
const stat =
|
|
54780
|
+
const stat = fs6.statSync(CACHE_FILE);
|
|
54821
54781
|
const fileAge = now2 - Math.floor(stat.mtimeMs / 1000);
|
|
54822
54782
|
if (fileAge < CACHE_MAX_AGE) {
|
|
54823
|
-
const fileData = JSON.parse(
|
|
54783
|
+
const fileData = JSON.parse(fs6.readFileSync(CACHE_FILE, "utf8"));
|
|
54824
54784
|
if (!fileData.error) {
|
|
54825
54785
|
cachedData = fileData;
|
|
54826
54786
|
cacheTime = now2;
|
|
@@ -54829,7 +54789,7 @@ function fetchApiData() {
|
|
|
54829
54789
|
}
|
|
54830
54790
|
} catch {}
|
|
54831
54791
|
try {
|
|
54832
|
-
const lockStat =
|
|
54792
|
+
const lockStat = fs6.statSync(LOCK_FILE);
|
|
54833
54793
|
const lockAge = now2 - Math.floor(lockStat.mtimeMs / 1000);
|
|
54834
54794
|
if (lockAge < LOCK_MAX_AGE) {
|
|
54835
54795
|
const stale = readStaleCache();
|
|
@@ -54839,11 +54799,11 @@ function fetchApiData() {
|
|
|
54839
54799
|
}
|
|
54840
54800
|
} catch {}
|
|
54841
54801
|
try {
|
|
54842
|
-
const lockDir =
|
|
54843
|
-
if (!
|
|
54844
|
-
|
|
54802
|
+
const lockDir = path5.dirname(LOCK_FILE);
|
|
54803
|
+
if (!fs6.existsSync(lockDir)) {
|
|
54804
|
+
fs6.mkdirSync(lockDir, { recursive: true });
|
|
54845
54805
|
}
|
|
54846
|
-
|
|
54806
|
+
fs6.writeFileSync(LOCK_FILE, "");
|
|
54847
54807
|
} catch {}
|
|
54848
54808
|
const token = getToken();
|
|
54849
54809
|
if (!token) {
|
|
@@ -54889,11 +54849,11 @@ function fetchApiData() {
|
|
|
54889
54849
|
return { error: "parse-error" };
|
|
54890
54850
|
}
|
|
54891
54851
|
try {
|
|
54892
|
-
const cacheDir =
|
|
54893
|
-
if (!
|
|
54894
|
-
|
|
54852
|
+
const cacheDir = path5.dirname(CACHE_FILE);
|
|
54853
|
+
if (!fs6.existsSync(cacheDir)) {
|
|
54854
|
+
fs6.mkdirSync(cacheDir, { recursive: true });
|
|
54895
54855
|
}
|
|
54896
|
-
|
|
54856
|
+
fs6.writeFileSync(CACHE_FILE, JSON.stringify(apiData));
|
|
54897
54857
|
} catch {}
|
|
54898
54858
|
cachedData = apiData;
|
|
54899
54859
|
cacheTime = now2;
|
|
@@ -55025,7 +54985,8 @@ class ResetTimerWidget {
|
|
|
55025
54985
|
return getErrorMessage(data.error);
|
|
55026
54986
|
if (data.extraUsageEnabled && data.weeklyUsage !== undefined && data.weeklyUsage >= 100 && data.extraUsageUsed !== undefined && data.extraUsageLimit !== undefined) {
|
|
55027
54987
|
const used = formatCents(data.extraUsageUsed);
|
|
55028
|
-
const
|
|
54988
|
+
const displayLimit = settings.extraUsageBalance ?? data.extraUsageLimit;
|
|
54989
|
+
const limit = formatCents(displayLimit);
|
|
55029
54990
|
return `Extra: ${used}/${limit}`;
|
|
55030
54991
|
}
|
|
55031
54992
|
if (!data.sessionResetAt)
|
|
@@ -55112,7 +55073,7 @@ class ContextBarWidget {
|
|
|
55112
55073
|
}
|
|
55113
55074
|
}
|
|
55114
55075
|
// src/widgets/SessionName.ts
|
|
55115
|
-
import * as
|
|
55076
|
+
import * as fs7 from "fs";
|
|
55116
55077
|
|
|
55117
55078
|
class SessionNameWidget {
|
|
55118
55079
|
getDefaultColor() {
|
|
@@ -55139,7 +55100,7 @@ class SessionNameWidget {
|
|
|
55139
55100
|
return null;
|
|
55140
55101
|
}
|
|
55141
55102
|
try {
|
|
55142
|
-
const content =
|
|
55103
|
+
const content = fs7.readFileSync(transcriptPath, "utf-8");
|
|
55143
55104
|
const lines = content.split(`
|
|
55144
55105
|
`);
|
|
55145
55106
|
for (let i = lines.length - 1;i >= 0; i--) {
|
|
@@ -55248,7 +55209,7 @@ class FreeMemoryWidget {
|
|
|
55248
55209
|
}
|
|
55249
55210
|
// src/widgets/Battery.ts
|
|
55250
55211
|
import { execSync as execSync8 } from "child_process";
|
|
55251
|
-
import { readFileSync as
|
|
55212
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
55252
55213
|
function getMacBatteryInfo() {
|
|
55253
55214
|
try {
|
|
55254
55215
|
const output = execSync8("pmset -g batt", { encoding: "utf-8", timeout: 2000 });
|
|
@@ -55268,8 +55229,8 @@ function getMacBatteryInfo() {
|
|
|
55268
55229
|
}
|
|
55269
55230
|
function getLinuxBatteryInfo() {
|
|
55270
55231
|
try {
|
|
55271
|
-
const capacity =
|
|
55272
|
-
const status =
|
|
55232
|
+
const capacity = readFileSync5("/sys/class/power_supply/BAT0/capacity", "utf-8").trim();
|
|
55233
|
+
const status = readFileSync5("/sys/class/power_supply/BAT0/status", "utf-8").trim().toLowerCase();
|
|
55273
55234
|
const percent = parseInt(capacity, 10);
|
|
55274
55235
|
if (isNaN(percent)) {
|
|
55275
55236
|
return null;
|
|
@@ -59718,44 +59679,44 @@ function renderCompactOutput(preRenderedLines, settings, maxWidth) {
|
|
|
59718
59679
|
}
|
|
59719
59680
|
|
|
59720
59681
|
// src/utils/jsonl.ts
|
|
59721
|
-
import * as
|
|
59682
|
+
import * as fs8 from "fs";
|
|
59722
59683
|
import { createHash } from "node:crypto";
|
|
59723
59684
|
import os9 from "node:os";
|
|
59724
|
-
import
|
|
59685
|
+
import path7 from "node:path";
|
|
59725
59686
|
|
|
59726
59687
|
// node_modules/tinyglobby/dist/index.mjs
|
|
59727
|
-
import
|
|
59688
|
+
import path6, { posix } from "path";
|
|
59728
59689
|
|
|
59729
59690
|
// node_modules/fdir/dist/index.mjs
|
|
59730
59691
|
import { createRequire as createRequire2 } from "module";
|
|
59731
59692
|
import { basename as basename2, dirname as dirname3, normalize, relative, resolve as resolve2, sep } from "path";
|
|
59732
59693
|
import * as nativeFs from "fs";
|
|
59733
59694
|
var __require2 = /* @__PURE__ */ createRequire2(import.meta.url);
|
|
59734
|
-
function cleanPath(
|
|
59735
|
-
let normalized = normalize(
|
|
59695
|
+
function cleanPath(path6) {
|
|
59696
|
+
let normalized = normalize(path6);
|
|
59736
59697
|
if (normalized.length > 1 && normalized[normalized.length - 1] === sep)
|
|
59737
59698
|
normalized = normalized.substring(0, normalized.length - 1);
|
|
59738
59699
|
return normalized;
|
|
59739
59700
|
}
|
|
59740
59701
|
var SLASHES_REGEX = /[\\/]/g;
|
|
59741
|
-
function convertSlashes(
|
|
59742
|
-
return
|
|
59702
|
+
function convertSlashes(path6, separator) {
|
|
59703
|
+
return path6.replace(SLASHES_REGEX, separator);
|
|
59743
59704
|
}
|
|
59744
59705
|
var WINDOWS_ROOT_DIR_REGEX = /^[a-z]:[\\/]$/i;
|
|
59745
|
-
function isRootDirectory(
|
|
59746
|
-
return
|
|
59706
|
+
function isRootDirectory(path6) {
|
|
59707
|
+
return path6 === "/" || WINDOWS_ROOT_DIR_REGEX.test(path6);
|
|
59747
59708
|
}
|
|
59748
|
-
function normalizePath(
|
|
59709
|
+
function normalizePath(path6, options) {
|
|
59749
59710
|
const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options;
|
|
59750
|
-
const pathNeedsCleaning = process.platform === "win32" &&
|
|
59711
|
+
const pathNeedsCleaning = process.platform === "win32" && path6.includes("/") || path6.startsWith(".");
|
|
59751
59712
|
if (resolvePaths)
|
|
59752
|
-
|
|
59713
|
+
path6 = resolve2(path6);
|
|
59753
59714
|
if (normalizePath$1 || pathNeedsCleaning)
|
|
59754
|
-
|
|
59755
|
-
if (
|
|
59715
|
+
path6 = cleanPath(path6);
|
|
59716
|
+
if (path6 === ".")
|
|
59756
59717
|
return "";
|
|
59757
|
-
const needsSeperator =
|
|
59758
|
-
return convertSlashes(needsSeperator ?
|
|
59718
|
+
const needsSeperator = path6[path6.length - 1] !== pathSeparator;
|
|
59719
|
+
return convertSlashes(needsSeperator ? path6 + pathSeparator : path6, pathSeparator);
|
|
59759
59720
|
}
|
|
59760
59721
|
function joinPathWithBasePath(filename, directoryPath) {
|
|
59761
59722
|
return directoryPath + filename;
|
|
@@ -59795,9 +59756,9 @@ var pushDirectory = (directoryPath, paths) => {
|
|
|
59795
59756
|
paths.push(directoryPath || ".");
|
|
59796
59757
|
};
|
|
59797
59758
|
var pushDirectoryFilter = (directoryPath, paths, filters) => {
|
|
59798
|
-
const
|
|
59799
|
-
if (filters.every((filter2) => filter2(
|
|
59800
|
-
paths.push(
|
|
59759
|
+
const path6 = directoryPath || ".";
|
|
59760
|
+
if (filters.every((filter2) => filter2(path6, true)))
|
|
59761
|
+
paths.push(path6);
|
|
59801
59762
|
};
|
|
59802
59763
|
var empty$2 = () => {};
|
|
59803
59764
|
function build$6(root, options) {
|
|
@@ -59854,29 +59815,29 @@ var empty = () => {};
|
|
|
59854
59815
|
function build$3(options) {
|
|
59855
59816
|
return options.group ? groupFiles : empty;
|
|
59856
59817
|
}
|
|
59857
|
-
var resolveSymlinksAsync = function(
|
|
59858
|
-
const { queue, fs:
|
|
59818
|
+
var resolveSymlinksAsync = function(path6, state, callback$1) {
|
|
59819
|
+
const { queue, fs: fs8, options: { suppressErrors } } = state;
|
|
59859
59820
|
queue.enqueue();
|
|
59860
|
-
|
|
59821
|
+
fs8.realpath(path6, (error43, resolvedPath) => {
|
|
59861
59822
|
if (error43)
|
|
59862
59823
|
return queue.dequeue(suppressErrors ? null : error43, state);
|
|
59863
|
-
|
|
59824
|
+
fs8.stat(resolvedPath, (error$1, stat) => {
|
|
59864
59825
|
if (error$1)
|
|
59865
59826
|
return queue.dequeue(suppressErrors ? null : error$1, state);
|
|
59866
|
-
if (stat.isDirectory() && isRecursive(
|
|
59827
|
+
if (stat.isDirectory() && isRecursive(path6, resolvedPath, state))
|
|
59867
59828
|
return queue.dequeue(null, state);
|
|
59868
59829
|
callback$1(stat, resolvedPath);
|
|
59869
59830
|
queue.dequeue(null, state);
|
|
59870
59831
|
});
|
|
59871
59832
|
});
|
|
59872
59833
|
};
|
|
59873
|
-
var resolveSymlinks = function(
|
|
59874
|
-
const { queue, fs:
|
|
59834
|
+
var resolveSymlinks = function(path6, state, callback$1) {
|
|
59835
|
+
const { queue, fs: fs8, options: { suppressErrors } } = state;
|
|
59875
59836
|
queue.enqueue();
|
|
59876
59837
|
try {
|
|
59877
|
-
const resolvedPath =
|
|
59878
|
-
const stat =
|
|
59879
|
-
if (stat.isDirectory() && isRecursive(
|
|
59838
|
+
const resolvedPath = fs8.realpathSync(path6);
|
|
59839
|
+
const stat = fs8.statSync(resolvedPath);
|
|
59840
|
+
if (stat.isDirectory() && isRecursive(path6, resolvedPath, state))
|
|
59880
59841
|
return;
|
|
59881
59842
|
callback$1(stat, resolvedPath);
|
|
59882
59843
|
} catch (e) {
|
|
@@ -59889,10 +59850,10 @@ function build$2(options, isSynchronous) {
|
|
|
59889
59850
|
return null;
|
|
59890
59851
|
return isSynchronous ? resolveSymlinks : resolveSymlinksAsync;
|
|
59891
59852
|
}
|
|
59892
|
-
function isRecursive(
|
|
59853
|
+
function isRecursive(path6, resolved, state) {
|
|
59893
59854
|
if (state.options.useRealPaths)
|
|
59894
59855
|
return isRecursiveUsingRealPaths(resolved, state);
|
|
59895
|
-
let parent = dirname3(
|
|
59856
|
+
let parent = dirname3(path6);
|
|
59896
59857
|
let depth = 1;
|
|
59897
59858
|
while (parent !== state.root && depth < 2) {
|
|
59898
59859
|
const resolvedPath = state.symlinks.get(parent);
|
|
@@ -59902,7 +59863,7 @@ function isRecursive(path7, resolved, state) {
|
|
|
59902
59863
|
else
|
|
59903
59864
|
parent = dirname3(parent);
|
|
59904
59865
|
}
|
|
59905
|
-
state.symlinks.set(
|
|
59866
|
+
state.symlinks.set(path6, resolved);
|
|
59906
59867
|
return depth > 1;
|
|
59907
59868
|
}
|
|
59908
59869
|
function isRecursiveUsingRealPaths(resolved, state) {
|
|
@@ -59958,23 +59919,23 @@ var walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
|
59958
59919
|
state.queue.enqueue();
|
|
59959
59920
|
if (currentDepth < 0)
|
|
59960
59921
|
return state.queue.dequeue(null, state);
|
|
59961
|
-
const { fs:
|
|
59922
|
+
const { fs: fs8 } = state;
|
|
59962
59923
|
state.visited.push(crawlPath);
|
|
59963
59924
|
state.counts.directories++;
|
|
59964
|
-
|
|
59925
|
+
fs8.readdir(crawlPath || ".", readdirOpts, (error43, entries = []) => {
|
|
59965
59926
|
callback$1(entries, directoryPath, currentDepth);
|
|
59966
59927
|
state.queue.dequeue(state.options.suppressErrors ? null : error43, state);
|
|
59967
59928
|
});
|
|
59968
59929
|
};
|
|
59969
59930
|
var walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
59970
|
-
const { fs:
|
|
59931
|
+
const { fs: fs8 } = state;
|
|
59971
59932
|
if (currentDepth < 0)
|
|
59972
59933
|
return;
|
|
59973
59934
|
state.visited.push(crawlPath);
|
|
59974
59935
|
state.counts.directories++;
|
|
59975
59936
|
let entries = [];
|
|
59976
59937
|
try {
|
|
59977
|
-
entries =
|
|
59938
|
+
entries = fs8.readdirSync(crawlPath || ".", readdirOpts);
|
|
59978
59939
|
} catch (e) {
|
|
59979
59940
|
if (!state.options.suppressErrors)
|
|
59980
59941
|
throw e;
|
|
@@ -60080,21 +60041,21 @@ var Walker = class {
|
|
|
60080
60041
|
const filename = this.joinPath(entry.name, directoryPath);
|
|
60081
60042
|
this.pushFile(filename, files, this.state.counts, filters);
|
|
60082
60043
|
} else if (entry.isDirectory()) {
|
|
60083
|
-
let
|
|
60084
|
-
if (exclude && exclude(entry.name,
|
|
60044
|
+
let path6 = joinDirectoryPath(entry.name, directoryPath, this.state.options.pathSeparator);
|
|
60045
|
+
if (exclude && exclude(entry.name, path6))
|
|
60085
60046
|
continue;
|
|
60086
|
-
this.pushDirectory(
|
|
60087
|
-
this.walkDirectory(this.state,
|
|
60047
|
+
this.pushDirectory(path6, paths, filters);
|
|
60048
|
+
this.walkDirectory(this.state, path6, path6, depth - 1, this.walk);
|
|
60088
60049
|
} else if (this.resolveSymlink && entry.isSymbolicLink()) {
|
|
60089
|
-
let
|
|
60090
|
-
this.resolveSymlink(
|
|
60050
|
+
let path6 = joinPathWithBasePath(entry.name, directoryPath);
|
|
60051
|
+
this.resolveSymlink(path6, this.state, (stat, resolvedPath) => {
|
|
60091
60052
|
if (stat.isDirectory()) {
|
|
60092
60053
|
resolvedPath = normalizePath(resolvedPath, this.state.options);
|
|
60093
|
-
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath :
|
|
60054
|
+
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath : path6 + pathSeparator))
|
|
60094
60055
|
return;
|
|
60095
|
-
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath :
|
|
60056
|
+
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath : path6 + pathSeparator, depth - 1, this.walk);
|
|
60096
60057
|
} else {
|
|
60097
|
-
resolvedPath = useRealPaths ? resolvedPath :
|
|
60058
|
+
resolvedPath = useRealPaths ? resolvedPath : path6;
|
|
60098
60059
|
const filename = basename2(resolvedPath);
|
|
60099
60060
|
const directoryPath$1 = normalizePath(dirname3(resolvedPath), this.state.options);
|
|
60100
60061
|
resolvedPath = this.joinPath(filename, directoryPath$1);
|
|
@@ -60254,7 +60215,7 @@ var Builder = class {
|
|
|
60254
60215
|
isMatch2 = globFn(patterns, ...options);
|
|
60255
60216
|
this.globCache[patterns.join("\x00")] = isMatch2;
|
|
60256
60217
|
}
|
|
60257
|
-
this.options.filters.push((
|
|
60218
|
+
this.options.filters.push((path6) => isMatch2(path6));
|
|
60258
60219
|
return this;
|
|
60259
60220
|
}
|
|
60260
60221
|
};
|
|
@@ -60333,7 +60294,7 @@ function normalizePattern(pattern, expandDirectories, cwd2, props, isIgnore) {
|
|
|
60333
60294
|
if (!result2.endsWith("*") && expandDirectories)
|
|
60334
60295
|
result2 += "/**";
|
|
60335
60296
|
const escapedCwd = escapePath(cwd2);
|
|
60336
|
-
if (
|
|
60297
|
+
if (path6.isAbsolute(result2.replace(ESCAPING_BACKSLASHES, "")))
|
|
60337
60298
|
result2 = posix.relative(escapedCwd, result2);
|
|
60338
60299
|
else
|
|
60339
60300
|
result2 = posix.normalize(result2);
|
|
@@ -60370,7 +60331,7 @@ function normalizePattern(pattern, expandDirectories, cwd2, props, isIgnore) {
|
|
|
60370
60331
|
}
|
|
60371
60332
|
props.depthOffset = newCommonPath.length;
|
|
60372
60333
|
props.commonPath = newCommonPath;
|
|
60373
|
-
props.root = newCommonPath.length > 0 ?
|
|
60334
|
+
props.root = newCommonPath.length > 0 ? path6.posix.join(cwd2, ...newCommonPath) : cwd2;
|
|
60374
60335
|
}
|
|
60375
60336
|
return result2;
|
|
60376
60337
|
}
|
|
@@ -60503,25 +60464,25 @@ function globSync(patternsOrOptions, options) {
|
|
|
60503
60464
|
...options,
|
|
60504
60465
|
patterns: patternsOrOptions
|
|
60505
60466
|
} : patternsOrOptions;
|
|
60506
|
-
const cwd2 = opts.cwd ?
|
|
60467
|
+
const cwd2 = opts.cwd ? path6.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/");
|
|
60507
60468
|
return crawl(opts, cwd2, true);
|
|
60508
60469
|
}
|
|
60509
60470
|
|
|
60510
60471
|
// src/utils/jsonl.ts
|
|
60511
60472
|
import { promisify } from "util";
|
|
60512
|
-
var readFile4 = promisify(
|
|
60513
|
-
var
|
|
60514
|
-
var statSync5 =
|
|
60515
|
-
var writeFileSync3 =
|
|
60516
|
-
var mkdirSync4 =
|
|
60517
|
-
var existsSync8 =
|
|
60473
|
+
var readFile4 = promisify(fs8.readFile);
|
|
60474
|
+
var readFileSync7 = fs8.readFileSync;
|
|
60475
|
+
var statSync5 = fs8.statSync;
|
|
60476
|
+
var writeFileSync3 = fs8.writeFileSync;
|
|
60477
|
+
var mkdirSync4 = fs8.mkdirSync;
|
|
60478
|
+
var existsSync8 = fs8.existsSync;
|
|
60518
60479
|
function normalizeConfigDir(configDir) {
|
|
60519
|
-
return
|
|
60480
|
+
return path7.resolve(configDir);
|
|
60520
60481
|
}
|
|
60521
60482
|
function getBlockCachePath(configDir = getClaudeConfigDir()) {
|
|
60522
60483
|
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
60523
60484
|
const configHash = createHash("sha256").update(normalizedConfigDir).digest("hex").slice(0, 16);
|
|
60524
|
-
return
|
|
60485
|
+
return path7.join(os9.homedir(), ".cache", "ccstatusline", `block-cache-${configHash}.json`);
|
|
60525
60486
|
}
|
|
60526
60487
|
function readBlockCache(expectedConfigDir) {
|
|
60527
60488
|
try {
|
|
@@ -60530,7 +60491,7 @@ function readBlockCache(expectedConfigDir) {
|
|
|
60530
60491
|
if (!existsSync8(cachePath)) {
|
|
60531
60492
|
return null;
|
|
60532
60493
|
}
|
|
60533
|
-
const content =
|
|
60494
|
+
const content = readFileSync7(cachePath, "utf-8");
|
|
60534
60495
|
const cache3 = JSON.parse(content);
|
|
60535
60496
|
if (typeof cache3.startTime !== "string") {
|
|
60536
60497
|
return null;
|
|
@@ -60556,7 +60517,7 @@ function writeBlockCache(startTime, configDir = getClaudeConfigDir()) {
|
|
|
60556
60517
|
try {
|
|
60557
60518
|
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
60558
60519
|
const cachePath = getBlockCachePath(normalizedConfigDir);
|
|
60559
|
-
const cacheDir =
|
|
60520
|
+
const cacheDir = path7.dirname(cachePath);
|
|
60560
60521
|
if (!existsSync8(cacheDir)) {
|
|
60561
60522
|
mkdirSync4(cacheDir, { recursive: true });
|
|
60562
60523
|
}
|
|
@@ -60589,7 +60550,7 @@ function getCachedBlockMetrics(sessionDurationHours = 5) {
|
|
|
60589
60550
|
}
|
|
60590
60551
|
async function getSessionDuration(transcriptPath) {
|
|
60591
60552
|
try {
|
|
60592
|
-
if (!
|
|
60553
|
+
if (!fs8.existsSync(transcriptPath)) {
|
|
60593
60554
|
return null;
|
|
60594
60555
|
}
|
|
60595
60556
|
const content = await readFile4(transcriptPath, "utf-8");
|
|
@@ -60641,7 +60602,7 @@ async function getSessionDuration(transcriptPath) {
|
|
|
60641
60602
|
}
|
|
60642
60603
|
async function getTokenMetrics(transcriptPath) {
|
|
60643
60604
|
try {
|
|
60644
|
-
if (!
|
|
60605
|
+
if (!fs8.existsSync(transcriptPath)) {
|
|
60645
60606
|
return { inputTokens: 0, outputTokens: 0, cachedTokens: 0, totalTokens: 0, contextLength: 0 };
|
|
60646
60607
|
}
|
|
60647
60608
|
const content = await readFile4(transcriptPath, "utf-8");
|
|
@@ -60694,7 +60655,7 @@ function getBlockMetrics() {
|
|
|
60694
60655
|
function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
60695
60656
|
const sessionDurationMs = sessionDurationHours * 60 * 60 * 1000;
|
|
60696
60657
|
const now2 = new Date;
|
|
60697
|
-
const pattern =
|
|
60658
|
+
const pattern = path7.posix.join(rootDir.replace(/\\/g, "/"), "projects", "**", "*.jsonl");
|
|
60698
60659
|
const files = globSync([pattern], {
|
|
60699
60660
|
absolute: true,
|
|
60700
60661
|
cwd: rootDir
|
|
@@ -60788,7 +60749,7 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
60788
60749
|
function getAllTimestampsFromFile(filePath) {
|
|
60789
60750
|
const timestamps = [];
|
|
60790
60751
|
try {
|
|
60791
|
-
const content =
|
|
60752
|
+
const content = readFileSync7(filePath, "utf-8");
|
|
60792
60753
|
const lines = content.trim().split(`
|
|
60793
60754
|
`).filter((line) => line.length > 0);
|
|
60794
60755
|
for (const line of lines) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccstatusline-usage",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.12",
|
|
4
4
|
"description": "A customizable status line formatter for Claude Code CLI",
|
|
5
5
|
"module": "src/ccstatusline.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -17,8 +17,6 @@
|
|
|
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",
|
|
21
|
-
"publish:safe": "bash scripts/safe-publish.sh",
|
|
22
20
|
"docs": "typedoc",
|
|
23
21
|
"docs:clean": "rm -rf docs"
|
|
24
22
|
},
|