ccstatusline-usage 2.1.5 → 2.1.7
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 +47 -42
- package/dist/ccstatusline.js +554 -96
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,30 +46,29 @@
|
|
|
46
46
|
|
|
47
47
|
## 🆕 Recent Updates
|
|
48
48
|
|
|
49
|
-
### [v2.1.
|
|
49
|
+
### [v2.1.7](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.7) - Battery widget, extra usage fix & upstream sync
|
|
50
50
|
|
|
51
|
-
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **
|
|
51
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Battery widget** — shows `B: xx%` on macOS and Linux when on battery power (hidden when charging)
|
|
52
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Extra usage conditional display** — Extra spending widget now only appears when the weekly budget is fully used (100%), instead of always when extra usage is enabled
|
|
53
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Upstream sync** — Memory Usage widget (v2.0.29)
|
|
52
54
|
|
|
53
|
-
### [v2.1.
|
|
55
|
+
### [v2.1.6](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.6) - Upstream sync
|
|
54
56
|
|
|
55
|
-
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **
|
|
56
|
-
```
|
|
57
|
-
S: [░░░░] 2.0% | W: [██░░] 43.0% | 4:36 hr
|
|
58
|
-
M: o4.6 ▌▌▌ | S: 5647528d | C: [██░░] 119k/200k
|
|
59
|
-
```
|
|
60
|
-
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Terminal-agnostic compact detection** — compact mode now triggers on any narrow terminal (< 80 columns), not just tmux
|
|
57
|
+
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Upstream sync** — merged 9 upstream commits: Session Name widget, Git Root Dir widget, CWD home abbreviation, block timer caching, git widget refactor, Windows UTF-8 fix, widget picker UX, TUI editor input fix
|
|
61
58
|
|
|
62
|
-
###
|
|
59
|
+
### v2.0.26 - v2.0.29 - Performance, git internals, and workflow improvements
|
|
63
60
|
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
61
|
+
- **🧠 Memory Usage widget (v2.0.29)** - Added a new widget that shows current system memory usage (`Mem: used/total`).
|
|
62
|
+
- **⚡ Block timer cache (v2.0.28)** - Cache block timer metrics to reduce JSONL parsing on every render, with per-config hashed cache files and automatic 5-hour block invalidation.
|
|
63
|
+
- **🧱 Git widget command refactor (v2.0.28)** - Refactored git widgets to use shared git command helpers and expanded coverage for failure and edge-case tests.
|
|
64
|
+
- **🪟 Windows UTF-8 piped output fix (v2.0.28)** - Sets the Windows UTF-8 code page for piped status line rendering.
|
|
65
|
+
- **📁 Git Root Dir widget (v2.0.27)** - Added a new Git widget that shows the repository root directory name.
|
|
66
|
+
- **🏷️ Session Name widget (v2.0.26)** - Added a new widget that shows the current Claude Code session name from `/rename`.
|
|
67
|
+
- **🏠 Current Working Directory home abbreviation (v2.0.26)** - Added a `~` abbreviation option for CWD display in both preview and live rendering.
|
|
68
|
+
- **🧠 Context model suffix fix (v2.0.26)** - Context widgets now recognize the `[1m]` suffix across models, not just a single model path.
|
|
69
|
+
- **🧭 Widget picker UX updates (v2.0.26)** - Improved widget discovery/navigation and added clearer, safer clear-line behavior.
|
|
70
|
+
- **⌨️ TUI editor input fix (v2.0.26)** - Prevented shortcut/input leakage into widget editor flows.
|
|
71
|
+
- **📄 Repo docs update (v2.0.26)** - Migrated guidance from `CLAUDE.md` to `AGENTS.md` (with symlink compatibility).
|
|
73
72
|
|
|
74
73
|
### v2.0.16 - Add fish style path abbreviation toggle to Current Working Directory widget
|
|
75
74
|
|
|
@@ -374,12 +373,13 @@ Once configured, ccstatusline automatically formats your Claude Code status line
|
|
|
374
373
|
|
|
375
374
|
### 📊 Available Widgets
|
|
376
375
|
|
|
377
|
-
- **Model Name** - Shows the current Claude model
|
|
376
|
+
- **Model Name** - Shows the current Claude model (e.g., "Claude 3.5 Sonnet")
|
|
378
377
|
- **Git Branch** - Displays current git branch name
|
|
379
378
|
- **Git Changes** - Shows uncommitted insertions/deletions (e.g., "+42,-10")
|
|
380
379
|
- **Git Worktree** - Shows the name of the current git worktree
|
|
381
380
|
- **Session Clock** - Shows elapsed time since session start (e.g., "2hr 15m")
|
|
382
381
|
- **Session Cost** - Shows total session cost in USD (e.g., "$1.23")
|
|
382
|
+
- **Session Name** - Shows the session name set via `/rename` command in Claude Code
|
|
383
383
|
- **Block Timer** - Shows time elapsed in current 5-hour block or progress bar
|
|
384
384
|
- **Current Working Directory** - Shows current working directory with configurable path segments
|
|
385
385
|
- **Version** - Shows Claude Code version
|
|
@@ -389,9 +389,11 @@ Once configured, ccstatusline automatically formats your Claude Code status line
|
|
|
389
389
|
- **Tokens Cached** - Shows cached tokens used
|
|
390
390
|
- **Tokens Total** - Shows total tokens used
|
|
391
391
|
- **Context Length** - Shows current context length in tokens
|
|
392
|
-
- **Context Percentage** - Shows percentage of context limit used (dynamic: 1M for Sonnet 4.5
|
|
393
|
-
- **Context Percentage (usable)** - Shows percentage of usable context (dynamic: 800k for Sonnet 4.5
|
|
392
|
+
- **Context Percentage** - Shows percentage of context limit used (dynamic: 1M for Sonnet 4.5 with `[1m]` suffix, 200k otherwise)
|
|
393
|
+
- **Context Percentage (usable)** - Shows percentage of usable context (dynamic: 800k for Sonnet 4.5 with `[1m]` suffix, 160k otherwise, accounting for auto-compact at 80%)
|
|
394
394
|
- **Terminal Width** - Shows detected terminal width (for debugging)
|
|
395
|
+
- **Memory Usage** - Shows system memory usage (used/total, e.g., "Mem: 12.4G/16.0G")
|
|
396
|
+
- **Battery** - Shows battery percentage on macOS and Linux (only visible when on battery power, hidden when charging)
|
|
395
397
|
- **Custom Text** - Add your own custom text to the status line
|
|
396
398
|
- **Custom Command** - Execute shell commands and display their output (refreshes whenever the statusline is updated by Claude Code)
|
|
397
399
|
- **Separator** - Visual divider between widgets (customizable: |, -, comma, space)
|
|
@@ -460,7 +462,7 @@ The Block Timer widget helps you track your progress through Claude Code's 5-hou
|
|
|
460
462
|
### 🔤 Raw Value Mode
|
|
461
463
|
|
|
462
464
|
Some widgets support "raw value" mode which displays just the value without a label:
|
|
463
|
-
- Normal: `Model: Claude
|
|
465
|
+
- Normal: `Model: Claude 3.5 Sonnet` → Raw: `Claude 3.5 Sonnet`
|
|
464
466
|
- Normal: `Session: 2hr 15m` → Raw: `2hr 15m`
|
|
465
467
|
- Normal: `Block: 3hr 45m` → Raw: `3hr 45m`
|
|
466
468
|
- Normal: `Ctx: 18.6k` → Raw: `18.6k`
|
|
@@ -625,6 +627,14 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
625
627
|
|
|
626
628
|
---
|
|
627
629
|
|
|
630
|
+
## Support
|
|
631
|
+
|
|
632
|
+
If ccstatusline is useful to you, consider buying me a coffee:
|
|
633
|
+
|
|
634
|
+
<a href="https://www.buymeacoffee.com/sirmalloc" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
628
638
|
## 📄 License
|
|
629
639
|
|
|
630
640
|
[MIT](LICENSE) © Matthew Breedlove
|
|
@@ -637,11 +647,6 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
637
647
|
|
|
638
648
|
- GitHub: [@sirmalloc](https://github.com/sirmalloc)
|
|
639
649
|
|
|
640
|
-
**Fork maintained by Peter van Velzen**
|
|
641
|
-
|
|
642
|
-
- GitHub: [@pcvelz](https://github.com/pcvelz)
|
|
643
|
-
- Fork: [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage)
|
|
644
|
-
|
|
645
650
|
---
|
|
646
651
|
|
|
647
652
|
## 🔗 Related Projects
|
|
@@ -661,11 +666,11 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
661
666
|
|
|
662
667
|
## Star History
|
|
663
668
|
|
|
664
|
-
<a href="https://www.star-history.com/#
|
|
669
|
+
<a href="https://www.star-history.com/#sirmalloc/ccstatusline&Timeline">
|
|
665
670
|
<picture>
|
|
666
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=
|
|
667
|
-
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=
|
|
668
|
-
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=
|
|
671
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=sirmalloc/ccstatusline&type=Timeline&theme=dark" />
|
|
672
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=sirmalloc/ccstatusline&type=Timeline" />
|
|
673
|
+
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=sirmalloc/ccstatusline&type=Timeline" />
|
|
669
674
|
</picture>
|
|
670
675
|
</a>
|
|
671
676
|
|
|
@@ -675,21 +680,21 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
675
680
|
|
|
676
681
|
Give a ⭐ if this project helped you!
|
|
677
682
|
|
|
678
|
-
[](https://github.com/sirmalloc/ccstatusline/stargazers)
|
|
684
|
+
[](https://github.com/sirmalloc/ccstatusline/network/members)
|
|
685
|
+
[](https://github.com/sirmalloc/ccstatusline/watchers)
|
|
681
686
|
|
|
682
|
-
[](https://github.com/
|
|
687
|
+
[](https://www.npmjs.com/package/ccstatusline)
|
|
688
|
+
[](https://www.npmjs.com/package/ccstatusline)
|
|
689
|
+
[](https://github.com/sirmalloc/ccstatusline/blob/main/LICENSE)
|
|
685
690
|
[](https://bun.sh)
|
|
686
691
|
|
|
687
|
-
[](https://github.com/sirmalloc/ccstatusline/issues)
|
|
693
|
+
[](https://github.com/sirmalloc/ccstatusline/pulls)
|
|
694
|
+
[](https://github.com/sirmalloc/ccstatusline/graphs/contributors)
|
|
690
695
|
|
|
691
696
|
### 💬 Connect
|
|
692
697
|
|
|
693
|
-
[Report Bug](https://github.com/
|
|
698
|
+
[Report Bug](https://github.com/sirmalloc/ccstatusline/issues) · [Request Feature](https://github.com/sirmalloc/ccstatusline/issues) · [Discussions](https://github.com/sirmalloc/ccstatusline/discussions)
|
|
694
699
|
|
|
695
700
|
</div>
|
package/dist/ccstatusline.js
CHANGED
|
@@ -50987,6 +50987,8 @@ var SettingsSchema = exports_external.object({
|
|
|
50987
50987
|
{ id: "weekly-usage", type: "weekly-usage", color: "brightBlue" },
|
|
50988
50988
|
{ id: "sep2", type: "separator" },
|
|
50989
50989
|
{ id: "reset-timer", type: "reset-timer", color: "brightBlue" },
|
|
50990
|
+
{ id: "sep-battery", type: "separator" },
|
|
50991
|
+
{ id: "battery", type: "battery", color: "yellow" },
|
|
50990
50992
|
{ id: "sep3", type: "separator" },
|
|
50991
50993
|
{ id: "model", type: "model", color: "ansi256:124" },
|
|
50992
50994
|
{ id: "sep4", type: "separator" },
|
|
@@ -51450,7 +51452,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51450
51452
|
import * as fs5 from "fs";
|
|
51451
51453
|
import * as path4 from "path";
|
|
51452
51454
|
var __dirname = "/Users/peter/Documents/Code/ccstatusline-usage/src/utils";
|
|
51453
|
-
var PACKAGE_VERSION = "2.1.
|
|
51455
|
+
var PACKAGE_VERSION = "2.1.7";
|
|
51454
51456
|
function getPackageVersion() {
|
|
51455
51457
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51456
51458
|
return PACKAGE_VERSION;
|
|
@@ -52425,9 +52427,39 @@ class OutputStyleWidget {
|
|
|
52425
52427
|
return true;
|
|
52426
52428
|
}
|
|
52427
52429
|
}
|
|
52428
|
-
// src/
|
|
52430
|
+
// src/utils/git.ts
|
|
52429
52431
|
import { execSync as execSync4 } from "child_process";
|
|
52432
|
+
function resolveGitCwd(context) {
|
|
52433
|
+
const candidates = [
|
|
52434
|
+
context.data?.cwd,
|
|
52435
|
+
context.data?.workspace?.current_dir,
|
|
52436
|
+
context.data?.workspace?.project_dir
|
|
52437
|
+
];
|
|
52438
|
+
for (const candidate of candidates) {
|
|
52439
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
52440
|
+
return candidate;
|
|
52441
|
+
}
|
|
52442
|
+
}
|
|
52443
|
+
return;
|
|
52444
|
+
}
|
|
52445
|
+
function runGit(command, context) {
|
|
52446
|
+
try {
|
|
52447
|
+
const cwd2 = resolveGitCwd(context);
|
|
52448
|
+
const output = execSync4(`git ${command}`, {
|
|
52449
|
+
encoding: "utf8",
|
|
52450
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
52451
|
+
...cwd2 ? { cwd: cwd2 } : {}
|
|
52452
|
+
}).trim();
|
|
52453
|
+
return output.length > 0 ? output : null;
|
|
52454
|
+
} catch {
|
|
52455
|
+
return null;
|
|
52456
|
+
}
|
|
52457
|
+
}
|
|
52458
|
+
function isInsideGitWorkTree(context) {
|
|
52459
|
+
return runGit("rev-parse --is-inside-work-tree", context) === "true";
|
|
52460
|
+
}
|
|
52430
52461
|
|
|
52462
|
+
// src/widgets/GitBranch.ts
|
|
52431
52463
|
class GitBranchWidget {
|
|
52432
52464
|
getDefaultColor() {
|
|
52433
52465
|
return "magenta";
|
|
@@ -52470,21 +52502,16 @@ class GitBranchWidget {
|
|
|
52470
52502
|
if (context.isPreview) {
|
|
52471
52503
|
return item.rawValue ? "main" : "⎇ main";
|
|
52472
52504
|
}
|
|
52473
|
-
|
|
52505
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52506
|
+
return hideNoGit ? null : "⎇ no git";
|
|
52507
|
+
}
|
|
52508
|
+
const branch = this.getGitBranch(context);
|
|
52474
52509
|
if (branch)
|
|
52475
52510
|
return item.rawValue ? branch : `⎇ ${branch}`;
|
|
52476
52511
|
return hideNoGit ? null : "⎇ no git";
|
|
52477
52512
|
}
|
|
52478
|
-
getGitBranch() {
|
|
52479
|
-
|
|
52480
|
-
const branch = execSync4("git branch --show-current", {
|
|
52481
|
-
encoding: "utf8",
|
|
52482
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
52483
|
-
}).trim();
|
|
52484
|
-
return branch || null;
|
|
52485
|
-
} catch {
|
|
52486
|
-
return null;
|
|
52487
|
-
}
|
|
52513
|
+
getGitBranch(context) {
|
|
52514
|
+
return runGit("branch --show-current", context);
|
|
52488
52515
|
}
|
|
52489
52516
|
getCustomKeybinds() {
|
|
52490
52517
|
return [
|
|
@@ -52499,8 +52526,6 @@ class GitBranchWidget {
|
|
|
52499
52526
|
}
|
|
52500
52527
|
}
|
|
52501
52528
|
// src/widgets/GitChanges.ts
|
|
52502
|
-
import { execSync as execSync5 } from "child_process";
|
|
52503
|
-
|
|
52504
52529
|
class GitChangesWidget {
|
|
52505
52530
|
getDefaultColor() {
|
|
52506
52531
|
return "yellow";
|
|
@@ -52543,40 +52568,107 @@ class GitChangesWidget {
|
|
|
52543
52568
|
if (context.isPreview) {
|
|
52544
52569
|
return "(+42,-10)";
|
|
52545
52570
|
}
|
|
52546
|
-
|
|
52571
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52572
|
+
return hideNoGit ? null : "(no git)";
|
|
52573
|
+
}
|
|
52574
|
+
const changes = this.getGitChanges(context);
|
|
52547
52575
|
if (changes)
|
|
52548
52576
|
return `(+${changes.insertions},-${changes.deletions})`;
|
|
52549
52577
|
else
|
|
52550
52578
|
return hideNoGit ? null : "(no git)";
|
|
52551
52579
|
}
|
|
52552
|
-
getGitChanges() {
|
|
52553
|
-
|
|
52554
|
-
|
|
52555
|
-
|
|
52556
|
-
|
|
52557
|
-
|
|
52558
|
-
|
|
52559
|
-
|
|
52560
|
-
|
|
52561
|
-
|
|
52562
|
-
|
|
52563
|
-
|
|
52564
|
-
|
|
52565
|
-
|
|
52566
|
-
|
|
52567
|
-
|
|
52568
|
-
|
|
52569
|
-
|
|
52570
|
-
|
|
52571
|
-
|
|
52572
|
-
|
|
52573
|
-
|
|
52574
|
-
|
|
52575
|
-
|
|
52576
|
-
|
|
52577
|
-
|
|
52578
|
-
|
|
52580
|
+
getGitChanges(context) {
|
|
52581
|
+
let totalInsertions = 0;
|
|
52582
|
+
let totalDeletions = 0;
|
|
52583
|
+
const unstagedStat = runGit("diff --shortstat", context) ?? "";
|
|
52584
|
+
const stagedStat = runGit("diff --cached --shortstat", context) ?? "";
|
|
52585
|
+
if (unstagedStat) {
|
|
52586
|
+
const insertMatch = /(\d+) insertion/.exec(unstagedStat);
|
|
52587
|
+
const deleteMatch = /(\d+) deletion/.exec(unstagedStat);
|
|
52588
|
+
totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
|
|
52589
|
+
totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
|
|
52590
|
+
}
|
|
52591
|
+
if (stagedStat) {
|
|
52592
|
+
const insertMatch = /(\d+) insertion/.exec(stagedStat);
|
|
52593
|
+
const deleteMatch = /(\d+) deletion/.exec(stagedStat);
|
|
52594
|
+
totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
|
|
52595
|
+
totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
|
|
52596
|
+
}
|
|
52597
|
+
return { insertions: totalInsertions, deletions: totalDeletions };
|
|
52598
|
+
}
|
|
52599
|
+
getCustomKeybinds() {
|
|
52600
|
+
return [
|
|
52601
|
+
{ key: "h", label: "(h)ide 'no git' message", action: "toggle-nogit" }
|
|
52602
|
+
];
|
|
52603
|
+
}
|
|
52604
|
+
supportsRawValue() {
|
|
52605
|
+
return false;
|
|
52606
|
+
}
|
|
52607
|
+
supportsColors(item) {
|
|
52608
|
+
return true;
|
|
52609
|
+
}
|
|
52610
|
+
}
|
|
52611
|
+
// src/widgets/GitRootDir.ts
|
|
52612
|
+
class GitRootDirWidget {
|
|
52613
|
+
getDefaultColor() {
|
|
52614
|
+
return "cyan";
|
|
52615
|
+
}
|
|
52616
|
+
getDescription() {
|
|
52617
|
+
return "Shows the git repository root directory name";
|
|
52618
|
+
}
|
|
52619
|
+
getDisplayName() {
|
|
52620
|
+
return "Git Root Dir";
|
|
52621
|
+
}
|
|
52622
|
+
getCategory() {
|
|
52623
|
+
return "Git";
|
|
52624
|
+
}
|
|
52625
|
+
getEditorDisplay(item) {
|
|
52626
|
+
const hideNoGit = item.metadata?.hideNoGit === "true";
|
|
52627
|
+
const modifiers = [];
|
|
52628
|
+
if (hideNoGit) {
|
|
52629
|
+
modifiers.push("hide 'no git'");
|
|
52630
|
+
}
|
|
52631
|
+
return {
|
|
52632
|
+
displayText: this.getDisplayName(),
|
|
52633
|
+
modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
|
|
52634
|
+
};
|
|
52635
|
+
}
|
|
52636
|
+
handleEditorAction(action, item) {
|
|
52637
|
+
if (action === "toggle-nogit") {
|
|
52638
|
+
const currentState = item.metadata?.hideNoGit === "true";
|
|
52639
|
+
return {
|
|
52640
|
+
...item,
|
|
52641
|
+
metadata: {
|
|
52642
|
+
...item.metadata,
|
|
52643
|
+
hideNoGit: (!currentState).toString()
|
|
52644
|
+
}
|
|
52645
|
+
};
|
|
52646
|
+
}
|
|
52647
|
+
return null;
|
|
52648
|
+
}
|
|
52649
|
+
render(item, context, _settings) {
|
|
52650
|
+
const hideNoGit = item.metadata?.hideNoGit === "true";
|
|
52651
|
+
if (context.isPreview) {
|
|
52652
|
+
return "my-repo";
|
|
52653
|
+
}
|
|
52654
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52655
|
+
return hideNoGit ? null : "no git";
|
|
52579
52656
|
}
|
|
52657
|
+
const rootDir = this.getGitRootDir(context);
|
|
52658
|
+
if (rootDir) {
|
|
52659
|
+
return this.getRootDirName(rootDir);
|
|
52660
|
+
}
|
|
52661
|
+
return hideNoGit ? null : "no git";
|
|
52662
|
+
}
|
|
52663
|
+
getGitRootDir(context) {
|
|
52664
|
+
return runGit("rev-parse --show-toplevel", context);
|
|
52665
|
+
}
|
|
52666
|
+
getRootDirName(rootDir) {
|
|
52667
|
+
const trimmedRootDir = rootDir.replace(/[\\/]+$/, "");
|
|
52668
|
+
const normalizedRootDir = trimmedRootDir.length > 0 ? trimmedRootDir : rootDir;
|
|
52669
|
+
const parts = normalizedRootDir.split(/[\\/]/).filter(Boolean);
|
|
52670
|
+
const lastPart = parts[parts.length - 1];
|
|
52671
|
+
return lastPart && lastPart.length > 0 ? lastPart : normalizedRootDir;
|
|
52580
52672
|
}
|
|
52581
52673
|
getCustomKeybinds() {
|
|
52582
52674
|
return [
|
|
@@ -52591,8 +52683,6 @@ class GitChangesWidget {
|
|
|
52591
52683
|
}
|
|
52592
52684
|
}
|
|
52593
52685
|
// src/widgets/GitWorktree.ts
|
|
52594
|
-
import { execSync as execSync6 } from "child_process";
|
|
52595
|
-
|
|
52596
52686
|
class GitWorktreeWidget {
|
|
52597
52687
|
getDefaultColor() {
|
|
52598
52688
|
return "blue";
|
|
@@ -52634,24 +52724,29 @@ class GitWorktreeWidget {
|
|
|
52634
52724
|
const hideNoGit = item.metadata?.hideNoGit === "true";
|
|
52635
52725
|
if (context.isPreview)
|
|
52636
52726
|
return item.rawValue ? "main" : "\uD81A\uDC30 main";
|
|
52637
|
-
|
|
52727
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52728
|
+
return hideNoGit ? null : "\uD81A\uDC30 no git";
|
|
52729
|
+
}
|
|
52730
|
+
const worktree = this.getGitWorktree(context);
|
|
52638
52731
|
if (worktree)
|
|
52639
52732
|
return item.rawValue ? worktree : `\uD81A\uDC30 ${worktree}`;
|
|
52640
52733
|
return hideNoGit ? null : "\uD81A\uDC30 no git";
|
|
52641
52734
|
}
|
|
52642
|
-
getGitWorktree() {
|
|
52643
|
-
|
|
52644
|
-
|
|
52645
|
-
|
|
52646
|
-
|
|
52647
|
-
|
|
52648
|
-
|
|
52649
|
-
|
|
52650
|
-
|
|
52651
|
-
|
|
52652
|
-
|
|
52735
|
+
getGitWorktree(context) {
|
|
52736
|
+
const worktreeDir = runGit("rev-parse --git-dir", context);
|
|
52737
|
+
if (!worktreeDir) {
|
|
52738
|
+
return null;
|
|
52739
|
+
}
|
|
52740
|
+
const normalizedGitDir = worktreeDir.replace(/\\/g, "/");
|
|
52741
|
+
if (normalizedGitDir.endsWith("/.git") || normalizedGitDir === ".git")
|
|
52742
|
+
return "main";
|
|
52743
|
+
const marker = ".git/worktrees/";
|
|
52744
|
+
const markerIndex = normalizedGitDir.lastIndexOf(marker);
|
|
52745
|
+
if (markerIndex === -1) {
|
|
52653
52746
|
return null;
|
|
52654
52747
|
}
|
|
52748
|
+
const worktree = normalizedGitDir.slice(markerIndex + marker.length);
|
|
52749
|
+
return worktree.length > 0 ? worktree : null;
|
|
52655
52750
|
}
|
|
52656
52751
|
getCustomKeybinds() {
|
|
52657
52752
|
return [
|
|
@@ -53935,7 +54030,7 @@ var CustomTextEditor = ({ widget, onComplete, onCancel }) => {
|
|
|
53935
54030
|
}, undefined, true, undefined, this);
|
|
53936
54031
|
};
|
|
53937
54032
|
// src/widgets/CustomCommand.tsx
|
|
53938
|
-
import { execSync as
|
|
54033
|
+
import { execSync as execSync5 } from "child_process";
|
|
53939
54034
|
var import_react30 = __toESM(require_react(), 1);
|
|
53940
54035
|
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
53941
54036
|
|
|
@@ -53984,7 +54079,7 @@ class CustomCommandWidget {
|
|
|
53984
54079
|
try {
|
|
53985
54080
|
const timeout = item.timeout ?? 1000;
|
|
53986
54081
|
const jsonInput = JSON.stringify(context.data);
|
|
53987
|
-
let output =
|
|
54082
|
+
let output = execSync5(item.commandPath, {
|
|
53988
54083
|
encoding: "utf8",
|
|
53989
54084
|
input: jsonInput,
|
|
53990
54085
|
timeout,
|
|
@@ -54324,7 +54419,11 @@ class CurrentWorkingDirWidget {
|
|
|
54324
54419
|
getEditorDisplay(item) {
|
|
54325
54420
|
const segments = item.metadata?.segments ? parseInt(item.metadata.segments, 10) : undefined;
|
|
54326
54421
|
const fishStyle = item.metadata?.fishStyle === "true";
|
|
54422
|
+
const abbreviateHome = item.metadata?.abbreviateHome === "true";
|
|
54327
54423
|
const modifiers = [];
|
|
54424
|
+
if (abbreviateHome) {
|
|
54425
|
+
modifiers.push("~");
|
|
54426
|
+
}
|
|
54328
54427
|
if (fishStyle) {
|
|
54329
54428
|
modifiers.push("fish-style");
|
|
54330
54429
|
} else if (segments && segments > 0) {
|
|
@@ -54336,11 +54435,31 @@ class CurrentWorkingDirWidget {
|
|
|
54336
54435
|
};
|
|
54337
54436
|
}
|
|
54338
54437
|
handleEditorAction(action, item) {
|
|
54438
|
+
if (action === "toggle-abbreviate-home") {
|
|
54439
|
+
const currentAbbreviateHome = item.metadata?.abbreviateHome === "true";
|
|
54440
|
+
const newAbbreviateHome = !currentAbbreviateHome;
|
|
54441
|
+
if (newAbbreviateHome) {
|
|
54442
|
+
const { fishStyle, ...restMetadata } = item.metadata ?? {};
|
|
54443
|
+
return {
|
|
54444
|
+
...item,
|
|
54445
|
+
metadata: {
|
|
54446
|
+
...restMetadata,
|
|
54447
|
+
abbreviateHome: "true"
|
|
54448
|
+
}
|
|
54449
|
+
};
|
|
54450
|
+
} else {
|
|
54451
|
+
const { abbreviateHome, ...restMetadata } = item.metadata ?? {};
|
|
54452
|
+
return {
|
|
54453
|
+
...item,
|
|
54454
|
+
metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
|
|
54455
|
+
};
|
|
54456
|
+
}
|
|
54457
|
+
}
|
|
54339
54458
|
if (action === "toggle-fish-style") {
|
|
54340
54459
|
const currentFishStyle = item.metadata?.fishStyle === "true";
|
|
54341
54460
|
const newFishStyle = !currentFishStyle;
|
|
54342
54461
|
if (newFishStyle) {
|
|
54343
|
-
const { segments, ...restMetadata } = item.metadata ?? {};
|
|
54462
|
+
const { segments, abbreviateHome, ...restMetadata } = item.metadata ?? {};
|
|
54344
54463
|
return {
|
|
54345
54464
|
...item,
|
|
54346
54465
|
metadata: {
|
|
@@ -54361,10 +54480,19 @@ class CurrentWorkingDirWidget {
|
|
|
54361
54480
|
render(item, context, settings) {
|
|
54362
54481
|
const segments = item.metadata?.segments ? parseInt(item.metadata.segments, 10) : undefined;
|
|
54363
54482
|
const fishStyle = item.metadata?.fishStyle === "true";
|
|
54483
|
+
const abbreviateHome = item.metadata?.abbreviateHome === "true";
|
|
54364
54484
|
if (context.isPreview) {
|
|
54365
54485
|
let previewPath;
|
|
54366
54486
|
if (fishStyle) {
|
|
54367
54487
|
previewPath = "~/D/P/my-project";
|
|
54488
|
+
} else if (abbreviateHome && segments && segments > 0) {
|
|
54489
|
+
if (segments === 1) {
|
|
54490
|
+
previewPath = "~/.../my-project";
|
|
54491
|
+
} else {
|
|
54492
|
+
previewPath = "~/.../Projects/my-project";
|
|
54493
|
+
}
|
|
54494
|
+
} else if (abbreviateHome) {
|
|
54495
|
+
previewPath = "~/Documents/Projects/my-project";
|
|
54368
54496
|
} else if (segments && segments > 0) {
|
|
54369
54497
|
if (segments === 1) {
|
|
54370
54498
|
previewPath = ".../project";
|
|
@@ -54382,20 +54510,27 @@ class CurrentWorkingDirWidget {
|
|
|
54382
54510
|
let displayPath = cwd2;
|
|
54383
54511
|
if (fishStyle) {
|
|
54384
54512
|
displayPath = this.abbreviatePath(cwd2);
|
|
54385
|
-
} else
|
|
54386
|
-
|
|
54387
|
-
|
|
54388
|
-
|
|
54389
|
-
|
|
54390
|
-
|
|
54391
|
-
const
|
|
54392
|
-
|
|
54513
|
+
} else {
|
|
54514
|
+
if (abbreviateHome) {
|
|
54515
|
+
displayPath = this.abbreviateHomeDir(displayPath);
|
|
54516
|
+
}
|
|
54517
|
+
if (segments && segments > 0) {
|
|
54518
|
+
const useBackslash = displayPath.includes("\\") && !displayPath.includes("/");
|
|
54519
|
+
const outSep = useBackslash ? "\\" : "/";
|
|
54520
|
+
const pathParts = displayPath.split(/[\\/]+/);
|
|
54521
|
+
const filteredParts = pathParts.filter((part) => part !== "");
|
|
54522
|
+
if (filteredParts.length > segments) {
|
|
54523
|
+
const selectedSegments = filteredParts.slice(-segments);
|
|
54524
|
+
const prefix = displayPath.startsWith("~") ? `~${outSep}` : "";
|
|
54525
|
+
displayPath = prefix + "..." + outSep + selectedSegments.join(outSep);
|
|
54526
|
+
}
|
|
54393
54527
|
}
|
|
54394
54528
|
}
|
|
54395
54529
|
return item.rawValue ? displayPath : `cwd: ${displayPath}`;
|
|
54396
54530
|
}
|
|
54397
54531
|
getCustomKeybinds() {
|
|
54398
54532
|
return [
|
|
54533
|
+
{ key: "h", label: "(h)ome ~", action: "toggle-abbreviate-home" },
|
|
54399
54534
|
{ key: "s", label: "(s)egments", action: "edit-segments" },
|
|
54400
54535
|
{ key: "f", label: "(f)ish style", action: "toggle-fish-style" }
|
|
54401
54536
|
];
|
|
@@ -54411,6 +54546,20 @@ class CurrentWorkingDirWidget {
|
|
|
54411
54546
|
supportsColors(item) {
|
|
54412
54547
|
return true;
|
|
54413
54548
|
}
|
|
54549
|
+
abbreviateHomeDir(path6) {
|
|
54550
|
+
const homeDir = os5.homedir();
|
|
54551
|
+
if (path6 === homeDir) {
|
|
54552
|
+
return "~";
|
|
54553
|
+
}
|
|
54554
|
+
if (path6.startsWith(homeDir)) {
|
|
54555
|
+
const boundaryChar = path6[homeDir.length];
|
|
54556
|
+
if (boundaryChar !== "/" && boundaryChar !== "\\") {
|
|
54557
|
+
return path6;
|
|
54558
|
+
}
|
|
54559
|
+
return "~" + path6.slice(homeDir.length);
|
|
54560
|
+
}
|
|
54561
|
+
return path6;
|
|
54562
|
+
}
|
|
54414
54563
|
abbreviatePath(path6) {
|
|
54415
54564
|
const homeDir = os5.homedir();
|
|
54416
54565
|
const useBackslash = path6.includes("\\") && !path6.includes("/");
|
|
@@ -54538,7 +54687,7 @@ class ClaudeSessionIdWidget {
|
|
|
54538
54687
|
}
|
|
54539
54688
|
// src/widgets/ApiUsage.tsx
|
|
54540
54689
|
import {
|
|
54541
|
-
execSync as
|
|
54690
|
+
execSync as execSync6,
|
|
54542
54691
|
spawnSync
|
|
54543
54692
|
} from "child_process";
|
|
54544
54693
|
import * as fs7 from "fs";
|
|
@@ -54563,7 +54712,7 @@ function readTokenFromFile() {
|
|
|
54563
54712
|
}
|
|
54564
54713
|
function readTokenFromKeychain() {
|
|
54565
54714
|
try {
|
|
54566
|
-
const result =
|
|
54715
|
+
const result = execSync6('security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null', { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
54567
54716
|
const parsed = JSON.parse(result);
|
|
54568
54717
|
return parsed?.claudeAiOauth?.accessToken ?? null;
|
|
54569
54718
|
} catch {
|
|
@@ -54856,7 +55005,7 @@ class ResetTimerWidget {
|
|
|
54856
55005
|
const data = fetchApiData();
|
|
54857
55006
|
if (data.error)
|
|
54858
55007
|
return getErrorMessage(data.error);
|
|
54859
|
-
if (data.extraUsageEnabled && data.extraUsageUsed !== undefined && data.extraUsageLimit !== undefined) {
|
|
55008
|
+
if (data.extraUsageEnabled && data.weeklyUsage !== undefined && data.weeklyUsage >= 100 && data.extraUsageUsed !== undefined && data.extraUsageLimit !== undefined) {
|
|
54860
55009
|
const used = formatCents(data.extraUsageUsed);
|
|
54861
55010
|
const limit = formatCents(data.extraUsageLimit);
|
|
54862
55011
|
return `Extra: ${used}/${limit}`;
|
|
@@ -54944,12 +55093,226 @@ class ContextBarWidget {
|
|
|
54944
55093
|
return true;
|
|
54945
55094
|
}
|
|
54946
55095
|
}
|
|
55096
|
+
// src/widgets/SessionName.ts
|
|
55097
|
+
import * as fs8 from "fs";
|
|
55098
|
+
|
|
55099
|
+
class SessionNameWidget {
|
|
55100
|
+
getDefaultColor() {
|
|
55101
|
+
return "cyan";
|
|
55102
|
+
}
|
|
55103
|
+
getDescription() {
|
|
55104
|
+
return "Shows the session name set via /rename command in Claude Code";
|
|
55105
|
+
}
|
|
55106
|
+
getDisplayName() {
|
|
55107
|
+
return "Session Name";
|
|
55108
|
+
}
|
|
55109
|
+
getCategory() {
|
|
55110
|
+
return "Session";
|
|
55111
|
+
}
|
|
55112
|
+
getEditorDisplay(item) {
|
|
55113
|
+
return { displayText: this.getDisplayName() };
|
|
55114
|
+
}
|
|
55115
|
+
render(item, context, settings) {
|
|
55116
|
+
if (context.isPreview) {
|
|
55117
|
+
return item.rawValue ? "my-session" : "Session: my-session";
|
|
55118
|
+
}
|
|
55119
|
+
const transcriptPath = context.data?.transcript_path;
|
|
55120
|
+
if (!transcriptPath) {
|
|
55121
|
+
return null;
|
|
55122
|
+
}
|
|
55123
|
+
try {
|
|
55124
|
+
const content = fs8.readFileSync(transcriptPath, "utf-8");
|
|
55125
|
+
const lines = content.split(`
|
|
55126
|
+
`);
|
|
55127
|
+
for (let i = lines.length - 1;i >= 0; i--) {
|
|
55128
|
+
const line = lines[i]?.trim();
|
|
55129
|
+
if (!line)
|
|
55130
|
+
continue;
|
|
55131
|
+
try {
|
|
55132
|
+
const entry = JSON.parse(line);
|
|
55133
|
+
if (entry.type === "custom-title" && entry.customTitle) {
|
|
55134
|
+
return item.rawValue ? entry.customTitle : `Session: ${entry.customTitle}`;
|
|
55135
|
+
}
|
|
55136
|
+
} catch {}
|
|
55137
|
+
}
|
|
55138
|
+
} catch {}
|
|
55139
|
+
return null;
|
|
55140
|
+
}
|
|
55141
|
+
supportsRawValue() {
|
|
55142
|
+
return true;
|
|
55143
|
+
}
|
|
55144
|
+
supportsColors(item) {
|
|
55145
|
+
return true;
|
|
55146
|
+
}
|
|
55147
|
+
}
|
|
55148
|
+
// src/widgets/FreeMemory.ts
|
|
55149
|
+
import { execSync as execSync7 } from "child_process";
|
|
55150
|
+
import os6 from "os";
|
|
55151
|
+
function formatBytes(bytes) {
|
|
55152
|
+
const GB = 1024 ** 3;
|
|
55153
|
+
const MB = 1024 ** 2;
|
|
55154
|
+
const KB = 1024;
|
|
55155
|
+
if (bytes >= GB)
|
|
55156
|
+
return `${(bytes / GB).toFixed(1)}G`;
|
|
55157
|
+
if (bytes >= MB)
|
|
55158
|
+
return `${(bytes / MB).toFixed(0)}M`;
|
|
55159
|
+
if (bytes >= KB)
|
|
55160
|
+
return `${(bytes / KB).toFixed(0)}K`;
|
|
55161
|
+
return `${bytes}B`;
|
|
55162
|
+
}
|
|
55163
|
+
function getUsedMemoryMacOS() {
|
|
55164
|
+
try {
|
|
55165
|
+
const output = execSync7("vm_stat", { encoding: "utf8" });
|
|
55166
|
+
const lines = output.split(`
|
|
55167
|
+
`);
|
|
55168
|
+
const firstLine = lines[0];
|
|
55169
|
+
if (!firstLine)
|
|
55170
|
+
return null;
|
|
55171
|
+
const pageSizeMatch = /page size of (\d+) bytes/.exec(firstLine);
|
|
55172
|
+
const pageSizeString = pageSizeMatch?.[1];
|
|
55173
|
+
if (!pageSizeString)
|
|
55174
|
+
return null;
|
|
55175
|
+
const pageSize = parseInt(pageSizeString, 10);
|
|
55176
|
+
let activePages = 0;
|
|
55177
|
+
let wiredPages = 0;
|
|
55178
|
+
for (const line of lines) {
|
|
55179
|
+
const activeMatch = /Pages active:\s+(\d+)/.exec(line);
|
|
55180
|
+
const activeValue = activeMatch?.[1];
|
|
55181
|
+
if (activeValue)
|
|
55182
|
+
activePages = parseInt(activeValue, 10);
|
|
55183
|
+
const wiredMatch = /Pages wired down:\s+(\d+)/.exec(line);
|
|
55184
|
+
const wiredValue = wiredMatch?.[1];
|
|
55185
|
+
if (wiredValue)
|
|
55186
|
+
wiredPages = parseInt(wiredValue, 10);
|
|
55187
|
+
}
|
|
55188
|
+
return (activePages + wiredPages) * pageSize;
|
|
55189
|
+
} catch {
|
|
55190
|
+
return null;
|
|
55191
|
+
}
|
|
55192
|
+
}
|
|
55193
|
+
|
|
55194
|
+
class FreeMemoryWidget {
|
|
55195
|
+
getDefaultColor() {
|
|
55196
|
+
return "cyan";
|
|
55197
|
+
}
|
|
55198
|
+
getDescription() {
|
|
55199
|
+
return "Shows system memory usage (used/total)";
|
|
55200
|
+
}
|
|
55201
|
+
getDisplayName() {
|
|
55202
|
+
return "Memory Usage";
|
|
55203
|
+
}
|
|
55204
|
+
getCategory() {
|
|
55205
|
+
return "Environment";
|
|
55206
|
+
}
|
|
55207
|
+
getEditorDisplay(item) {
|
|
55208
|
+
return { displayText: this.getDisplayName() };
|
|
55209
|
+
}
|
|
55210
|
+
render(item, context, settings) {
|
|
55211
|
+
if (context.isPreview) {
|
|
55212
|
+
return item.rawValue ? "12.4G/16.0G" : "Mem: 12.4G/16.0G";
|
|
55213
|
+
}
|
|
55214
|
+
const total = os6.totalmem();
|
|
55215
|
+
let used;
|
|
55216
|
+
if (os6.platform() === "darwin") {
|
|
55217
|
+
used = getUsedMemoryMacOS() ?? total - os6.freemem();
|
|
55218
|
+
} else {
|
|
55219
|
+
used = total - os6.freemem();
|
|
55220
|
+
}
|
|
55221
|
+
const value = `${formatBytes(used)}/${formatBytes(total)}`;
|
|
55222
|
+
return item.rawValue ? value : `Mem: ${value}`;
|
|
55223
|
+
}
|
|
55224
|
+
supportsRawValue() {
|
|
55225
|
+
return true;
|
|
55226
|
+
}
|
|
55227
|
+
supportsColors(item) {
|
|
55228
|
+
return true;
|
|
55229
|
+
}
|
|
55230
|
+
}
|
|
55231
|
+
// src/widgets/Battery.ts
|
|
55232
|
+
import { execSync as execSync8 } from "child_process";
|
|
55233
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
55234
|
+
function getMacBatteryInfo() {
|
|
55235
|
+
try {
|
|
55236
|
+
const output = execSync8("pmset -g batt", { encoding: "utf-8", timeout: 2000 });
|
|
55237
|
+
const match = /(\d+)%;\s*(charging|discharging|charged|finishing charge|AC attached)/i.exec(output);
|
|
55238
|
+
const percentStr = match?.[1];
|
|
55239
|
+
const stateStr = match?.[2];
|
|
55240
|
+
if (!percentStr || !stateStr) {
|
|
55241
|
+
return null;
|
|
55242
|
+
}
|
|
55243
|
+
const percent = parseInt(percentStr, 10);
|
|
55244
|
+
const state = stateStr.toLowerCase();
|
|
55245
|
+
const charging = state !== "discharging";
|
|
55246
|
+
return { percent, charging };
|
|
55247
|
+
} catch {
|
|
55248
|
+
return null;
|
|
55249
|
+
}
|
|
55250
|
+
}
|
|
55251
|
+
function getLinuxBatteryInfo() {
|
|
55252
|
+
try {
|
|
55253
|
+
const capacity = readFileSync6("/sys/class/power_supply/BAT0/capacity", "utf-8").trim();
|
|
55254
|
+
const status = readFileSync6("/sys/class/power_supply/BAT0/status", "utf-8").trim().toLowerCase();
|
|
55255
|
+
const percent = parseInt(capacity, 10);
|
|
55256
|
+
if (isNaN(percent)) {
|
|
55257
|
+
return null;
|
|
55258
|
+
}
|
|
55259
|
+
const charging = status !== "discharging";
|
|
55260
|
+
return { percent, charging };
|
|
55261
|
+
} catch {
|
|
55262
|
+
return null;
|
|
55263
|
+
}
|
|
55264
|
+
}
|
|
55265
|
+
function getBatteryInfo() {
|
|
55266
|
+
if (process.platform === "darwin") {
|
|
55267
|
+
return getMacBatteryInfo();
|
|
55268
|
+
}
|
|
55269
|
+
if (process.platform === "linux") {
|
|
55270
|
+
return getLinuxBatteryInfo();
|
|
55271
|
+
}
|
|
55272
|
+
return null;
|
|
55273
|
+
}
|
|
55274
|
+
|
|
55275
|
+
class BatteryWidget {
|
|
55276
|
+
getDefaultColor() {
|
|
55277
|
+
return "yellow";
|
|
55278
|
+
}
|
|
55279
|
+
getDescription() {
|
|
55280
|
+
return "Shows battery percentage (only when on battery, hidden when charging)";
|
|
55281
|
+
}
|
|
55282
|
+
getDisplayName() {
|
|
55283
|
+
return "Battery";
|
|
55284
|
+
}
|
|
55285
|
+
getCategory() {
|
|
55286
|
+
return "Environment";
|
|
55287
|
+
}
|
|
55288
|
+
getEditorDisplay(item) {
|
|
55289
|
+
return { displayText: this.getDisplayName() };
|
|
55290
|
+
}
|
|
55291
|
+
render(item, context, settings) {
|
|
55292
|
+
if (context.isPreview) {
|
|
55293
|
+
return item.rawValue ? "72%" : "B: 72%";
|
|
55294
|
+
}
|
|
55295
|
+
const info = getBatteryInfo();
|
|
55296
|
+
if (!info || info.charging) {
|
|
55297
|
+
return null;
|
|
55298
|
+
}
|
|
55299
|
+
const label = item.rawValue ? "" : "B: ";
|
|
55300
|
+
return `${label}${info.percent}%`;
|
|
55301
|
+
}
|
|
55302
|
+
supportsRawValue() {
|
|
55303
|
+
return true;
|
|
55304
|
+
}
|
|
55305
|
+
supportsColors(item) {
|
|
55306
|
+
return true;
|
|
55307
|
+
}
|
|
55308
|
+
}
|
|
54947
55309
|
// src/utils/widgets.ts
|
|
54948
55310
|
var widgetRegistry = new Map([
|
|
54949
55311
|
["model", new ModelWidget],
|
|
54950
55312
|
["output-style", new OutputStyleWidget],
|
|
54951
55313
|
["git-branch", new GitBranchWidget],
|
|
54952
55314
|
["git-changes", new GitChangesWidget],
|
|
55315
|
+
["git-root-dir", new GitRootDirWidget],
|
|
54953
55316
|
["git-worktree", new GitWorktreeWidget],
|
|
54954
55317
|
["current-working-dir", new CurrentWorkingDirWidget],
|
|
54955
55318
|
["tokens-input", new TokensInputWidget],
|
|
@@ -54970,7 +55333,10 @@ var widgetRegistry = new Map([
|
|
|
54970
55333
|
["session-usage", new SessionUsageWidget],
|
|
54971
55334
|
["weekly-usage", new WeeklyUsageWidget],
|
|
54972
55335
|
["reset-timer", new ResetTimerWidget],
|
|
54973
|
-
["context-bar", new ContextBarWidget]
|
|
55336
|
+
["context-bar", new ContextBarWidget],
|
|
55337
|
+
["session-name", new SessionNameWidget],
|
|
55338
|
+
["free-memory", new FreeMemoryWidget],
|
|
55339
|
+
["battery", new BatteryWidget]
|
|
54974
55340
|
]);
|
|
54975
55341
|
function getWidget(type) {
|
|
54976
55342
|
return widgetRegistry.get(type) ?? null;
|
|
@@ -56466,7 +56832,11 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
|
|
|
56466
56832
|
}
|
|
56467
56833
|
} else if (input === "r" && widgets.length > 0) {
|
|
56468
56834
|
const currentWidget2 = widgets[selectedIndex];
|
|
56469
|
-
if (currentWidget2 && currentWidget2.type !== "separator" && currentWidget2.type !== "flex-separator"
|
|
56835
|
+
if (currentWidget2 && currentWidget2.type !== "separator" && currentWidget2.type !== "flex-separator") {
|
|
56836
|
+
const widgetImpl = getWidget(currentWidget2.type);
|
|
56837
|
+
if (!widgetImpl?.supportsRawValue()) {
|
|
56838
|
+
return;
|
|
56839
|
+
}
|
|
56470
56840
|
const newWidgets = [...widgets];
|
|
56471
56841
|
newWidgets[selectedIndex] = { ...currentWidget2, rawValue: !currentWidget2.rawValue };
|
|
56472
56842
|
onUpdate(newWidgets);
|
|
@@ -56875,6 +57245,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
|
|
|
56875
57245
|
const isSelected = index === selectedIndex;
|
|
56876
57246
|
const widgetImpl = widget.type !== "separator" && widget.type !== "flex-separator" ? getWidget(widget.type) : null;
|
|
56877
57247
|
const { displayText, modifierText } = widgetImpl?.getEditorDisplay(widget) ?? { displayText: getWidgetDisplay(widget) };
|
|
57248
|
+
const supportsRawValue = widgetImpl?.supportsRawValue() ?? false;
|
|
56878
57249
|
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
56879
57250
|
flexDirection: "row",
|
|
56880
57251
|
flexWrap: "nowrap",
|
|
@@ -56897,7 +57268,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
|
|
|
56897
57268
|
modifierText
|
|
56898
57269
|
]
|
|
56899
57270
|
}, undefined, true, undefined, this),
|
|
56900
|
-
widget.rawValue && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
57271
|
+
supportsRawValue && widget.rawValue && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
56901
57272
|
dimColor: true,
|
|
56902
57273
|
children: " (raw value)"
|
|
56903
57274
|
}, undefined, false, undefined, this),
|
|
@@ -57325,7 +57696,7 @@ var MainMenu = ({ onSelect, isClaudeInstalled, hasChanges, initialSelection = 0,
|
|
|
57325
57696
|
};
|
|
57326
57697
|
// src/tui/components/PowerlineSetup.tsx
|
|
57327
57698
|
var import_react41 = __toESM(require_react(), 1);
|
|
57328
|
-
import * as
|
|
57699
|
+
import * as os7 from "os";
|
|
57329
57700
|
|
|
57330
57701
|
// src/tui/components/PowerlineSeparatorEditor.tsx
|
|
57331
57702
|
var import_react39 = __toESM(require_react(), 1);
|
|
@@ -58042,7 +58413,7 @@ var PowerlineSetup = ({
|
|
|
58042
58413
|
}, undefined, false, undefined, this)
|
|
58043
58414
|
]
|
|
58044
58415
|
}, undefined, true, undefined, this),
|
|
58045
|
-
|
|
58416
|
+
os7.platform() === "darwin" && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(jsx_dev_runtime13.Fragment, {
|
|
58046
58417
|
children: [
|
|
58047
58418
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
58048
58419
|
dimColor: true,
|
|
@@ -58058,7 +58429,7 @@ var PowerlineSetup = ({
|
|
|
58058
58429
|
}, undefined, false, undefined, this)
|
|
58059
58430
|
]
|
|
58060
58431
|
}, undefined, true, undefined, this),
|
|
58061
|
-
|
|
58432
|
+
os7.platform() === "linux" && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(jsx_dev_runtime13.Fragment, {
|
|
58062
58433
|
children: [
|
|
58063
58434
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
58064
58435
|
dimColor: true,
|
|
@@ -58074,7 +58445,7 @@ var PowerlineSetup = ({
|
|
|
58074
58445
|
}, undefined, false, undefined, this)
|
|
58075
58446
|
]
|
|
58076
58447
|
}, undefined, true, undefined, this),
|
|
58077
|
-
|
|
58448
|
+
os7.platform() === "win32" && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(jsx_dev_runtime13.Fragment, {
|
|
58078
58449
|
children: [
|
|
58079
58450
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
58080
58451
|
dimColor: true,
|
|
@@ -59329,7 +59700,9 @@ function renderCompactOutput(preRenderedLines, settings, maxWidth) {
|
|
|
59329
59700
|
}
|
|
59330
59701
|
|
|
59331
59702
|
// src/utils/jsonl.ts
|
|
59332
|
-
import * as
|
|
59703
|
+
import * as fs9 from "fs";
|
|
59704
|
+
import { createHash } from "node:crypto";
|
|
59705
|
+
import os8 from "node:os";
|
|
59333
59706
|
import path8 from "node:path";
|
|
59334
59707
|
|
|
59335
59708
|
// node_modules/tinyglobby/dist/index.mjs
|
|
@@ -59464,12 +59837,12 @@ function build$3(options) {
|
|
|
59464
59837
|
return options.group ? groupFiles : empty;
|
|
59465
59838
|
}
|
|
59466
59839
|
var resolveSymlinksAsync = function(path7, state, callback$1) {
|
|
59467
|
-
const { queue, fs:
|
|
59840
|
+
const { queue, fs: fs9, options: { suppressErrors } } = state;
|
|
59468
59841
|
queue.enqueue();
|
|
59469
|
-
|
|
59842
|
+
fs9.realpath(path7, (error43, resolvedPath) => {
|
|
59470
59843
|
if (error43)
|
|
59471
59844
|
return queue.dequeue(suppressErrors ? null : error43, state);
|
|
59472
|
-
|
|
59845
|
+
fs9.stat(resolvedPath, (error$1, stat) => {
|
|
59473
59846
|
if (error$1)
|
|
59474
59847
|
return queue.dequeue(suppressErrors ? null : error$1, state);
|
|
59475
59848
|
if (stat.isDirectory() && isRecursive(path7, resolvedPath, state))
|
|
@@ -59480,11 +59853,11 @@ var resolveSymlinksAsync = function(path7, state, callback$1) {
|
|
|
59480
59853
|
});
|
|
59481
59854
|
};
|
|
59482
59855
|
var resolveSymlinks = function(path7, state, callback$1) {
|
|
59483
|
-
const { queue, fs:
|
|
59856
|
+
const { queue, fs: fs9, options: { suppressErrors } } = state;
|
|
59484
59857
|
queue.enqueue();
|
|
59485
59858
|
try {
|
|
59486
|
-
const resolvedPath =
|
|
59487
|
-
const stat =
|
|
59859
|
+
const resolvedPath = fs9.realpathSync(path7);
|
|
59860
|
+
const stat = fs9.statSync(resolvedPath);
|
|
59488
59861
|
if (stat.isDirectory() && isRecursive(path7, resolvedPath, state))
|
|
59489
59862
|
return;
|
|
59490
59863
|
callback$1(stat, resolvedPath);
|
|
@@ -59567,23 +59940,23 @@ var walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
|
59567
59940
|
state.queue.enqueue();
|
|
59568
59941
|
if (currentDepth < 0)
|
|
59569
59942
|
return state.queue.dequeue(null, state);
|
|
59570
|
-
const { fs:
|
|
59943
|
+
const { fs: fs9 } = state;
|
|
59571
59944
|
state.visited.push(crawlPath);
|
|
59572
59945
|
state.counts.directories++;
|
|
59573
|
-
|
|
59946
|
+
fs9.readdir(crawlPath || ".", readdirOpts, (error43, entries = []) => {
|
|
59574
59947
|
callback$1(entries, directoryPath, currentDepth);
|
|
59575
59948
|
state.queue.dequeue(state.options.suppressErrors ? null : error43, state);
|
|
59576
59949
|
});
|
|
59577
59950
|
};
|
|
59578
59951
|
var walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
59579
|
-
const { fs:
|
|
59952
|
+
const { fs: fs9 } = state;
|
|
59580
59953
|
if (currentDepth < 0)
|
|
59581
59954
|
return;
|
|
59582
59955
|
state.visited.push(crawlPath);
|
|
59583
59956
|
state.counts.directories++;
|
|
59584
59957
|
let entries = [];
|
|
59585
59958
|
try {
|
|
59586
|
-
entries =
|
|
59959
|
+
entries = fs9.readdirSync(crawlPath || ".", readdirOpts);
|
|
59587
59960
|
} catch (e) {
|
|
59588
59961
|
if (!state.options.suppressErrors)
|
|
59589
59962
|
throw e;
|
|
@@ -60118,12 +60491,87 @@ function globSync(patternsOrOptions, options) {
|
|
|
60118
60491
|
|
|
60119
60492
|
// src/utils/jsonl.ts
|
|
60120
60493
|
import { promisify } from "util";
|
|
60121
|
-
var readFile4 = promisify(
|
|
60122
|
-
var
|
|
60123
|
-
var statSync5 =
|
|
60494
|
+
var readFile4 = promisify(fs9.readFile);
|
|
60495
|
+
var readFileSync8 = fs9.readFileSync;
|
|
60496
|
+
var statSync5 = fs9.statSync;
|
|
60497
|
+
var writeFileSync3 = fs9.writeFileSync;
|
|
60498
|
+
var mkdirSync4 = fs9.mkdirSync;
|
|
60499
|
+
var existsSync8 = fs9.existsSync;
|
|
60500
|
+
function normalizeConfigDir(configDir) {
|
|
60501
|
+
return path8.resolve(configDir);
|
|
60502
|
+
}
|
|
60503
|
+
function getBlockCachePath(configDir = getClaudeConfigDir()) {
|
|
60504
|
+
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
60505
|
+
const configHash = createHash("sha256").update(normalizedConfigDir).digest("hex").slice(0, 16);
|
|
60506
|
+
return path8.join(os8.homedir(), ".cache", "ccstatusline", `block-cache-${configHash}.json`);
|
|
60507
|
+
}
|
|
60508
|
+
function readBlockCache(expectedConfigDir) {
|
|
60509
|
+
try {
|
|
60510
|
+
const normalizedExpectedConfigDir = expectedConfigDir !== undefined ? normalizeConfigDir(expectedConfigDir) : undefined;
|
|
60511
|
+
const cachePath = getBlockCachePath(normalizedExpectedConfigDir);
|
|
60512
|
+
if (!existsSync8(cachePath)) {
|
|
60513
|
+
return null;
|
|
60514
|
+
}
|
|
60515
|
+
const content = readFileSync8(cachePath, "utf-8");
|
|
60516
|
+
const cache3 = JSON.parse(content);
|
|
60517
|
+
if (typeof cache3.startTime !== "string") {
|
|
60518
|
+
return null;
|
|
60519
|
+
}
|
|
60520
|
+
if (normalizedExpectedConfigDir !== undefined) {
|
|
60521
|
+
if (typeof cache3.configDir !== "string") {
|
|
60522
|
+
return null;
|
|
60523
|
+
}
|
|
60524
|
+
if (cache3.configDir !== normalizedExpectedConfigDir) {
|
|
60525
|
+
return null;
|
|
60526
|
+
}
|
|
60527
|
+
}
|
|
60528
|
+
const date5 = new Date(cache3.startTime);
|
|
60529
|
+
if (Number.isNaN(date5.getTime())) {
|
|
60530
|
+
return null;
|
|
60531
|
+
}
|
|
60532
|
+
return date5;
|
|
60533
|
+
} catch {
|
|
60534
|
+
return null;
|
|
60535
|
+
}
|
|
60536
|
+
}
|
|
60537
|
+
function writeBlockCache(startTime, configDir = getClaudeConfigDir()) {
|
|
60538
|
+
try {
|
|
60539
|
+
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
60540
|
+
const cachePath = getBlockCachePath(normalizedConfigDir);
|
|
60541
|
+
const cacheDir = path8.dirname(cachePath);
|
|
60542
|
+
if (!existsSync8(cacheDir)) {
|
|
60543
|
+
mkdirSync4(cacheDir, { recursive: true });
|
|
60544
|
+
}
|
|
60545
|
+
const cache3 = {
|
|
60546
|
+
startTime: startTime.toISOString(),
|
|
60547
|
+
configDir: normalizedConfigDir
|
|
60548
|
+
};
|
|
60549
|
+
writeFileSync3(cachePath, JSON.stringify(cache3), "utf-8");
|
|
60550
|
+
} catch {}
|
|
60551
|
+
}
|
|
60552
|
+
function getCachedBlockMetrics(sessionDurationHours = 5) {
|
|
60553
|
+
const sessionDurationMs = sessionDurationHours * 60 * 60 * 1000;
|
|
60554
|
+
const now = new Date;
|
|
60555
|
+
const activeConfigDir = getClaudeConfigDir();
|
|
60556
|
+
const cachedStartTime = readBlockCache(activeConfigDir);
|
|
60557
|
+
if (cachedStartTime) {
|
|
60558
|
+
const blockEndTime = new Date(cachedStartTime.getTime() + sessionDurationMs);
|
|
60559
|
+
if (now.getTime() <= blockEndTime.getTime()) {
|
|
60560
|
+
return {
|
|
60561
|
+
startTime: cachedStartTime,
|
|
60562
|
+
lastActivity: now
|
|
60563
|
+
};
|
|
60564
|
+
}
|
|
60565
|
+
}
|
|
60566
|
+
const metrics = getBlockMetrics();
|
|
60567
|
+
if (metrics) {
|
|
60568
|
+
writeBlockCache(metrics.startTime, activeConfigDir);
|
|
60569
|
+
}
|
|
60570
|
+
return metrics;
|
|
60571
|
+
}
|
|
60124
60572
|
async function getSessionDuration(transcriptPath) {
|
|
60125
60573
|
try {
|
|
60126
|
-
if (!
|
|
60574
|
+
if (!fs9.existsSync(transcriptPath)) {
|
|
60127
60575
|
return null;
|
|
60128
60576
|
}
|
|
60129
60577
|
const content = await readFile4(transcriptPath, "utf-8");
|
|
@@ -60175,7 +60623,7 @@ async function getSessionDuration(transcriptPath) {
|
|
|
60175
60623
|
}
|
|
60176
60624
|
async function getTokenMetrics(transcriptPath) {
|
|
60177
60625
|
try {
|
|
60178
|
-
if (!
|
|
60626
|
+
if (!fs9.existsSync(transcriptPath)) {
|
|
60179
60627
|
return { inputTokens: 0, outputTokens: 0, cachedTokens: 0, totalTokens: 0, contextLength: 0 };
|
|
60180
60628
|
}
|
|
60181
60629
|
const content = await readFile4(transcriptPath, "utf-8");
|
|
@@ -60322,7 +60770,7 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
60322
60770
|
function getAllTimestampsFromFile(filePath) {
|
|
60323
60771
|
const timestamps = [];
|
|
60324
60772
|
try {
|
|
60325
|
-
const content =
|
|
60773
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
60326
60774
|
const lines = content.trim().split(`
|
|
60327
60775
|
`).filter((line) => line.length > 0);
|
|
60328
60776
|
for (const line of lines) {
|
|
@@ -60390,6 +60838,15 @@ async function readStdin() {
|
|
|
60390
60838
|
return null;
|
|
60391
60839
|
}
|
|
60392
60840
|
}
|
|
60841
|
+
async function ensureWindowsUtf8CodePage() {
|
|
60842
|
+
if (process.platform !== "win32") {
|
|
60843
|
+
return;
|
|
60844
|
+
}
|
|
60845
|
+
try {
|
|
60846
|
+
const { execFileSync } = await import("child_process");
|
|
60847
|
+
execFileSync("chcp.com", ["65001"], { stdio: "ignore" });
|
|
60848
|
+
} catch {}
|
|
60849
|
+
}
|
|
60393
60850
|
async function renderMultipleLines(data) {
|
|
60394
60851
|
const settings = await loadSettings();
|
|
60395
60852
|
source_default.level = settings.colorLevel;
|
|
@@ -60408,7 +60865,7 @@ async function renderMultipleLines(data) {
|
|
|
60408
60865
|
}
|
|
60409
60866
|
let blockMetrics = null;
|
|
60410
60867
|
if (hasBlockTimer) {
|
|
60411
|
-
blockMetrics =
|
|
60868
|
+
blockMetrics = getCachedBlockMetrics();
|
|
60412
60869
|
}
|
|
60413
60870
|
const terminalWidth = getTerminalWidth();
|
|
60414
60871
|
const compact = shouldUseCompactMode(terminalWidth, data);
|
|
@@ -60465,6 +60922,7 @@ async function renderMultipleLines(data) {
|
|
|
60465
60922
|
}
|
|
60466
60923
|
async function main() {
|
|
60467
60924
|
if (!process.stdin.isTTY) {
|
|
60925
|
+
await ensureWindowsUtf8CodePage();
|
|
60468
60926
|
const input = await readStdin();
|
|
60469
60927
|
if (input && input.trim() !== "") {
|
|
60470
60928
|
try {
|