ccstatusline-usage 2.1.5 → 2.1.6
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 +32 -44
- package/dist/ccstatusline.js +384 -91
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,30 +46,22 @@
|
|
|
46
46
|
|
|
47
47
|
## 🆕 Recent Updates
|
|
48
48
|
|
|
49
|
-
### [v2.1.
|
|
49
|
+
### [v2.1.6](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.6) - Upstream sync
|
|
50
50
|
|
|
51
|
-
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **
|
|
51
|
+
- [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
|
|
52
52
|
|
|
53
|
-
###
|
|
53
|
+
### v2.0.26 - v2.0.28 - Performance, git internals, and workflow improvements
|
|
54
54
|
|
|
55
|
-
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
-
|
|
65
|
-
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Thinking effort bars** — Model widget shows `▌▌▌` bars indicating Claude Code's effort level (1=low, 2=medium, 3=high). Reads from `CLAUDE_CODE_EFFORT_LEVEL` env var or `~/.claude/settings.json`
|
|
66
|
-
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): **Tmux pane width detection** — correctly detects actual pane width via `tmux display-message` instead of falling back to default 80 columns
|
|
67
|
-
|
|
68
|
-
### [v2.1.2](https://github.com/pcvelz/ccstatusline-usage/releases/tag/v2.1.2) - Token auth fallback and 401 handling
|
|
69
|
-
|
|
70
|
-
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): macOS file credential fallback — reads `~/.claude/.credentials.json` when Keychain entry is missing
|
|
71
|
-
- [pcvelz/ccstatusline-usage](https://github.com/pcvelz/ccstatusline-usage): 401 auth error handling — invalidates cached token so next call re-reads from disk after `/login`
|
|
72
|
-
- Synced with upstream (101 commits)
|
|
55
|
+
- **⚡ 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.
|
|
56
|
+
- **🧱 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.
|
|
57
|
+
- **🪟 Windows UTF-8 piped output fix (v2.0.28)** - Sets the Windows UTF-8 code page for piped status line rendering.
|
|
58
|
+
- **📁 Git Root Dir widget (v2.0.27)** - Added a new Git widget that shows the repository root directory name.
|
|
59
|
+
- **🏷️ Session Name widget (v2.0.26)** - Added a new widget that shows the current Claude Code session name from `/rename`.
|
|
60
|
+
- **🏠 Current Working Directory home abbreviation (v2.0.26)** - Added a `~` abbreviation option for CWD display in both preview and live rendering.
|
|
61
|
+
- **🧠 Context model suffix fix (v2.0.26)** - Context widgets now recognize the `[1m]` suffix across models, not just a single model path.
|
|
62
|
+
- **🧭 Widget picker UX updates (v2.0.26)** - Improved widget discovery/navigation and added clearer, safer clear-line behavior.
|
|
63
|
+
- **⌨️ TUI editor input fix (v2.0.26)** - Prevented shortcut/input leakage into widget editor flows.
|
|
64
|
+
- **📄 Repo docs update (v2.0.26)** - Migrated guidance from `CLAUDE.md` to `AGENTS.md` (with symlink compatibility).
|
|
73
65
|
|
|
74
66
|
### v2.0.16 - Add fish style path abbreviation toggle to Current Working Directory widget
|
|
75
67
|
|
|
@@ -374,12 +366,13 @@ Once configured, ccstatusline automatically formats your Claude Code status line
|
|
|
374
366
|
|
|
375
367
|
### 📊 Available Widgets
|
|
376
368
|
|
|
377
|
-
- **Model Name** - Shows the current Claude model
|
|
369
|
+
- **Model Name** - Shows the current Claude model (e.g., "Claude 3.5 Sonnet")
|
|
378
370
|
- **Git Branch** - Displays current git branch name
|
|
379
371
|
- **Git Changes** - Shows uncommitted insertions/deletions (e.g., "+42,-10")
|
|
380
372
|
- **Git Worktree** - Shows the name of the current git worktree
|
|
381
373
|
- **Session Clock** - Shows elapsed time since session start (e.g., "2hr 15m")
|
|
382
374
|
- **Session Cost** - Shows total session cost in USD (e.g., "$1.23")
|
|
375
|
+
- **Session Name** - Shows the session name set via `/rename` command in Claude Code
|
|
383
376
|
- **Block Timer** - Shows time elapsed in current 5-hour block or progress bar
|
|
384
377
|
- **Current Working Directory** - Shows current working directory with configurable path segments
|
|
385
378
|
- **Version** - Shows Claude Code version
|
|
@@ -389,8 +382,8 @@ Once configured, ccstatusline automatically formats your Claude Code status line
|
|
|
389
382
|
- **Tokens Cached** - Shows cached tokens used
|
|
390
383
|
- **Tokens Total** - Shows total tokens used
|
|
391
384
|
- **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
|
|
385
|
+
- **Context Percentage** - Shows percentage of context limit used (dynamic: 1M for Sonnet 4.5 with `[1m]` suffix, 200k otherwise)
|
|
386
|
+
- **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
387
|
- **Terminal Width** - Shows detected terminal width (for debugging)
|
|
395
388
|
- **Custom Text** - Add your own custom text to the status line
|
|
396
389
|
- **Custom Command** - Execute shell commands and display their output (refreshes whenever the statusline is updated by Claude Code)
|
|
@@ -460,7 +453,7 @@ The Block Timer widget helps you track your progress through Claude Code's 5-hou
|
|
|
460
453
|
### 🔤 Raw Value Mode
|
|
461
454
|
|
|
462
455
|
Some widgets support "raw value" mode which displays just the value without a label:
|
|
463
|
-
- Normal: `Model: Claude
|
|
456
|
+
- Normal: `Model: Claude 3.5 Sonnet` → Raw: `Claude 3.5 Sonnet`
|
|
464
457
|
- Normal: `Session: 2hr 15m` → Raw: `2hr 15m`
|
|
465
458
|
- Normal: `Block: 3hr 45m` → Raw: `3hr 45m`
|
|
466
459
|
- Normal: `Ctx: 18.6k` → Raw: `18.6k`
|
|
@@ -637,11 +630,6 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
637
630
|
|
|
638
631
|
- GitHub: [@sirmalloc](https://github.com/sirmalloc)
|
|
639
632
|
|
|
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
633
|
---
|
|
646
634
|
|
|
647
635
|
## 🔗 Related Projects
|
|
@@ -661,11 +649,11 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
661
649
|
|
|
662
650
|
## Star History
|
|
663
651
|
|
|
664
|
-
<a href="https://www.star-history.com/#
|
|
652
|
+
<a href="https://www.star-history.com/#sirmalloc/ccstatusline&Timeline">
|
|
665
653
|
<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=
|
|
654
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=sirmalloc/ccstatusline&type=Timeline&theme=dark" />
|
|
655
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=sirmalloc/ccstatusline&type=Timeline" />
|
|
656
|
+
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=sirmalloc/ccstatusline&type=Timeline" />
|
|
669
657
|
</picture>
|
|
670
658
|
</a>
|
|
671
659
|
|
|
@@ -675,21 +663,21 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
675
663
|
|
|
676
664
|
Give a ⭐ if this project helped you!
|
|
677
665
|
|
|
678
|
-
[](https://github.com/sirmalloc/ccstatusline/stargazers)
|
|
667
|
+
[](https://github.com/sirmalloc/ccstatusline/network/members)
|
|
668
|
+
[](https://github.com/sirmalloc/ccstatusline/watchers)
|
|
681
669
|
|
|
682
|
-
[](https://github.com/
|
|
670
|
+
[](https://www.npmjs.com/package/ccstatusline)
|
|
671
|
+
[](https://www.npmjs.com/package/ccstatusline)
|
|
672
|
+
[](https://github.com/sirmalloc/ccstatusline/blob/main/LICENSE)
|
|
685
673
|
[](https://bun.sh)
|
|
686
674
|
|
|
687
|
-
[](https://github.com/sirmalloc/ccstatusline/issues)
|
|
676
|
+
[](https://github.com/sirmalloc/ccstatusline/pulls)
|
|
677
|
+
[](https://github.com/sirmalloc/ccstatusline/graphs/contributors)
|
|
690
678
|
|
|
691
679
|
### 💬 Connect
|
|
692
680
|
|
|
693
|
-
[Report Bug](https://github.com/
|
|
681
|
+
[Report Bug](https://github.com/sirmalloc/ccstatusline/issues) · [Request Feature](https://github.com/sirmalloc/ccstatusline/issues) · [Discussions](https://github.com/sirmalloc/ccstatusline/discussions)
|
|
694
682
|
|
|
695
683
|
</div>
|
package/dist/ccstatusline.js
CHANGED
|
@@ -51450,7 +51450,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51450
51450
|
import * as fs5 from "fs";
|
|
51451
51451
|
import * as path4 from "path";
|
|
51452
51452
|
var __dirname = "/Users/peter/Documents/Code/ccstatusline-usage/src/utils";
|
|
51453
|
-
var PACKAGE_VERSION = "2.1.
|
|
51453
|
+
var PACKAGE_VERSION = "2.1.6";
|
|
51454
51454
|
function getPackageVersion() {
|
|
51455
51455
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51456
51456
|
return PACKAGE_VERSION;
|
|
@@ -52425,9 +52425,39 @@ class OutputStyleWidget {
|
|
|
52425
52425
|
return true;
|
|
52426
52426
|
}
|
|
52427
52427
|
}
|
|
52428
|
-
// src/
|
|
52428
|
+
// src/utils/git.ts
|
|
52429
52429
|
import { execSync as execSync4 } from "child_process";
|
|
52430
|
+
function resolveGitCwd(context) {
|
|
52431
|
+
const candidates = [
|
|
52432
|
+
context.data?.cwd,
|
|
52433
|
+
context.data?.workspace?.current_dir,
|
|
52434
|
+
context.data?.workspace?.project_dir
|
|
52435
|
+
];
|
|
52436
|
+
for (const candidate of candidates) {
|
|
52437
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
52438
|
+
return candidate;
|
|
52439
|
+
}
|
|
52440
|
+
}
|
|
52441
|
+
return;
|
|
52442
|
+
}
|
|
52443
|
+
function runGit(command, context) {
|
|
52444
|
+
try {
|
|
52445
|
+
const cwd2 = resolveGitCwd(context);
|
|
52446
|
+
const output = execSync4(`git ${command}`, {
|
|
52447
|
+
encoding: "utf8",
|
|
52448
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
52449
|
+
...cwd2 ? { cwd: cwd2 } : {}
|
|
52450
|
+
}).trim();
|
|
52451
|
+
return output.length > 0 ? output : null;
|
|
52452
|
+
} catch {
|
|
52453
|
+
return null;
|
|
52454
|
+
}
|
|
52455
|
+
}
|
|
52456
|
+
function isInsideGitWorkTree(context) {
|
|
52457
|
+
return runGit("rev-parse --is-inside-work-tree", context) === "true";
|
|
52458
|
+
}
|
|
52430
52459
|
|
|
52460
|
+
// src/widgets/GitBranch.ts
|
|
52431
52461
|
class GitBranchWidget {
|
|
52432
52462
|
getDefaultColor() {
|
|
52433
52463
|
return "magenta";
|
|
@@ -52470,21 +52500,16 @@ class GitBranchWidget {
|
|
|
52470
52500
|
if (context.isPreview) {
|
|
52471
52501
|
return item.rawValue ? "main" : "⎇ main";
|
|
52472
52502
|
}
|
|
52473
|
-
|
|
52503
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52504
|
+
return hideNoGit ? null : "⎇ no git";
|
|
52505
|
+
}
|
|
52506
|
+
const branch = this.getGitBranch(context);
|
|
52474
52507
|
if (branch)
|
|
52475
52508
|
return item.rawValue ? branch : `⎇ ${branch}`;
|
|
52476
52509
|
return hideNoGit ? null : "⎇ no git";
|
|
52477
52510
|
}
|
|
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
|
-
}
|
|
52511
|
+
getGitBranch(context) {
|
|
52512
|
+
return runGit("branch --show-current", context);
|
|
52488
52513
|
}
|
|
52489
52514
|
getCustomKeybinds() {
|
|
52490
52515
|
return [
|
|
@@ -52499,8 +52524,6 @@ class GitBranchWidget {
|
|
|
52499
52524
|
}
|
|
52500
52525
|
}
|
|
52501
52526
|
// src/widgets/GitChanges.ts
|
|
52502
|
-
import { execSync as execSync5 } from "child_process";
|
|
52503
|
-
|
|
52504
52527
|
class GitChangesWidget {
|
|
52505
52528
|
getDefaultColor() {
|
|
52506
52529
|
return "yellow";
|
|
@@ -52543,40 +52566,107 @@ class GitChangesWidget {
|
|
|
52543
52566
|
if (context.isPreview) {
|
|
52544
52567
|
return "(+42,-10)";
|
|
52545
52568
|
}
|
|
52546
|
-
|
|
52569
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52570
|
+
return hideNoGit ? null : "(no git)";
|
|
52571
|
+
}
|
|
52572
|
+
const changes = this.getGitChanges(context);
|
|
52547
52573
|
if (changes)
|
|
52548
52574
|
return `(+${changes.insertions},-${changes.deletions})`;
|
|
52549
52575
|
else
|
|
52550
52576
|
return hideNoGit ? null : "(no git)";
|
|
52551
52577
|
}
|
|
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
|
-
|
|
52578
|
+
getGitChanges(context) {
|
|
52579
|
+
let totalInsertions = 0;
|
|
52580
|
+
let totalDeletions = 0;
|
|
52581
|
+
const unstagedStat = runGit("diff --shortstat", context) ?? "";
|
|
52582
|
+
const stagedStat = runGit("diff --cached --shortstat", context) ?? "";
|
|
52583
|
+
if (unstagedStat) {
|
|
52584
|
+
const insertMatch = /(\d+) insertion/.exec(unstagedStat);
|
|
52585
|
+
const deleteMatch = /(\d+) deletion/.exec(unstagedStat);
|
|
52586
|
+
totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
|
|
52587
|
+
totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
|
|
52588
|
+
}
|
|
52589
|
+
if (stagedStat) {
|
|
52590
|
+
const insertMatch = /(\d+) insertion/.exec(stagedStat);
|
|
52591
|
+
const deleteMatch = /(\d+) deletion/.exec(stagedStat);
|
|
52592
|
+
totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
|
|
52593
|
+
totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
|
|
52594
|
+
}
|
|
52595
|
+
return { insertions: totalInsertions, deletions: totalDeletions };
|
|
52596
|
+
}
|
|
52597
|
+
getCustomKeybinds() {
|
|
52598
|
+
return [
|
|
52599
|
+
{ key: "h", label: "(h)ide 'no git' message", action: "toggle-nogit" }
|
|
52600
|
+
];
|
|
52601
|
+
}
|
|
52602
|
+
supportsRawValue() {
|
|
52603
|
+
return false;
|
|
52604
|
+
}
|
|
52605
|
+
supportsColors(item) {
|
|
52606
|
+
return true;
|
|
52607
|
+
}
|
|
52608
|
+
}
|
|
52609
|
+
// src/widgets/GitRootDir.ts
|
|
52610
|
+
class GitRootDirWidget {
|
|
52611
|
+
getDefaultColor() {
|
|
52612
|
+
return "cyan";
|
|
52613
|
+
}
|
|
52614
|
+
getDescription() {
|
|
52615
|
+
return "Shows the git repository root directory name";
|
|
52616
|
+
}
|
|
52617
|
+
getDisplayName() {
|
|
52618
|
+
return "Git Root Dir";
|
|
52619
|
+
}
|
|
52620
|
+
getCategory() {
|
|
52621
|
+
return "Git";
|
|
52622
|
+
}
|
|
52623
|
+
getEditorDisplay(item) {
|
|
52624
|
+
const hideNoGit = item.metadata?.hideNoGit === "true";
|
|
52625
|
+
const modifiers = [];
|
|
52626
|
+
if (hideNoGit) {
|
|
52627
|
+
modifiers.push("hide 'no git'");
|
|
52628
|
+
}
|
|
52629
|
+
return {
|
|
52630
|
+
displayText: this.getDisplayName(),
|
|
52631
|
+
modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
|
|
52632
|
+
};
|
|
52633
|
+
}
|
|
52634
|
+
handleEditorAction(action, item) {
|
|
52635
|
+
if (action === "toggle-nogit") {
|
|
52636
|
+
const currentState = item.metadata?.hideNoGit === "true";
|
|
52637
|
+
return {
|
|
52638
|
+
...item,
|
|
52639
|
+
metadata: {
|
|
52640
|
+
...item.metadata,
|
|
52641
|
+
hideNoGit: (!currentState).toString()
|
|
52642
|
+
}
|
|
52643
|
+
};
|
|
52579
52644
|
}
|
|
52645
|
+
return null;
|
|
52646
|
+
}
|
|
52647
|
+
render(item, context, _settings) {
|
|
52648
|
+
const hideNoGit = item.metadata?.hideNoGit === "true";
|
|
52649
|
+
if (context.isPreview) {
|
|
52650
|
+
return "my-repo";
|
|
52651
|
+
}
|
|
52652
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52653
|
+
return hideNoGit ? null : "no git";
|
|
52654
|
+
}
|
|
52655
|
+
const rootDir = this.getGitRootDir(context);
|
|
52656
|
+
if (rootDir) {
|
|
52657
|
+
return this.getRootDirName(rootDir);
|
|
52658
|
+
}
|
|
52659
|
+
return hideNoGit ? null : "no git";
|
|
52660
|
+
}
|
|
52661
|
+
getGitRootDir(context) {
|
|
52662
|
+
return runGit("rev-parse --show-toplevel", context);
|
|
52663
|
+
}
|
|
52664
|
+
getRootDirName(rootDir) {
|
|
52665
|
+
const trimmedRootDir = rootDir.replace(/[\\/]+$/, "");
|
|
52666
|
+
const normalizedRootDir = trimmedRootDir.length > 0 ? trimmedRootDir : rootDir;
|
|
52667
|
+
const parts = normalizedRootDir.split(/[\\/]/).filter(Boolean);
|
|
52668
|
+
const lastPart = parts[parts.length - 1];
|
|
52669
|
+
return lastPart && lastPart.length > 0 ? lastPart : normalizedRootDir;
|
|
52580
52670
|
}
|
|
52581
52671
|
getCustomKeybinds() {
|
|
52582
52672
|
return [
|
|
@@ -52591,8 +52681,6 @@ class GitChangesWidget {
|
|
|
52591
52681
|
}
|
|
52592
52682
|
}
|
|
52593
52683
|
// src/widgets/GitWorktree.ts
|
|
52594
|
-
import { execSync as execSync6 } from "child_process";
|
|
52595
|
-
|
|
52596
52684
|
class GitWorktreeWidget {
|
|
52597
52685
|
getDefaultColor() {
|
|
52598
52686
|
return "blue";
|
|
@@ -52634,24 +52722,29 @@ class GitWorktreeWidget {
|
|
|
52634
52722
|
const hideNoGit = item.metadata?.hideNoGit === "true";
|
|
52635
52723
|
if (context.isPreview)
|
|
52636
52724
|
return item.rawValue ? "main" : "\uD81A\uDC30 main";
|
|
52637
|
-
|
|
52725
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52726
|
+
return hideNoGit ? null : "\uD81A\uDC30 no git";
|
|
52727
|
+
}
|
|
52728
|
+
const worktree = this.getGitWorktree(context);
|
|
52638
52729
|
if (worktree)
|
|
52639
52730
|
return item.rawValue ? worktree : `\uD81A\uDC30 ${worktree}`;
|
|
52640
52731
|
return hideNoGit ? null : "\uD81A\uDC30 no git";
|
|
52641
52732
|
}
|
|
52642
|
-
getGitWorktree() {
|
|
52643
|
-
|
|
52644
|
-
|
|
52645
|
-
|
|
52646
|
-
|
|
52647
|
-
|
|
52648
|
-
|
|
52649
|
-
|
|
52650
|
-
|
|
52651
|
-
|
|
52652
|
-
|
|
52733
|
+
getGitWorktree(context) {
|
|
52734
|
+
const worktreeDir = runGit("rev-parse --git-dir", context);
|
|
52735
|
+
if (!worktreeDir) {
|
|
52736
|
+
return null;
|
|
52737
|
+
}
|
|
52738
|
+
const normalizedGitDir = worktreeDir.replace(/\\/g, "/");
|
|
52739
|
+
if (normalizedGitDir.endsWith("/.git") || normalizedGitDir === ".git")
|
|
52740
|
+
return "main";
|
|
52741
|
+
const marker = ".git/worktrees/";
|
|
52742
|
+
const markerIndex = normalizedGitDir.lastIndexOf(marker);
|
|
52743
|
+
if (markerIndex === -1) {
|
|
52653
52744
|
return null;
|
|
52654
52745
|
}
|
|
52746
|
+
const worktree = normalizedGitDir.slice(markerIndex + marker.length);
|
|
52747
|
+
return worktree.length > 0 ? worktree : null;
|
|
52655
52748
|
}
|
|
52656
52749
|
getCustomKeybinds() {
|
|
52657
52750
|
return [
|
|
@@ -53935,7 +54028,7 @@ var CustomTextEditor = ({ widget, onComplete, onCancel }) => {
|
|
|
53935
54028
|
}, undefined, true, undefined, this);
|
|
53936
54029
|
};
|
|
53937
54030
|
// src/widgets/CustomCommand.tsx
|
|
53938
|
-
import { execSync as
|
|
54031
|
+
import { execSync as execSync5 } from "child_process";
|
|
53939
54032
|
var import_react30 = __toESM(require_react(), 1);
|
|
53940
54033
|
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
53941
54034
|
|
|
@@ -53984,7 +54077,7 @@ class CustomCommandWidget {
|
|
|
53984
54077
|
try {
|
|
53985
54078
|
const timeout = item.timeout ?? 1000;
|
|
53986
54079
|
const jsonInput = JSON.stringify(context.data);
|
|
53987
|
-
let output =
|
|
54080
|
+
let output = execSync5(item.commandPath, {
|
|
53988
54081
|
encoding: "utf8",
|
|
53989
54082
|
input: jsonInput,
|
|
53990
54083
|
timeout,
|
|
@@ -54324,7 +54417,11 @@ class CurrentWorkingDirWidget {
|
|
|
54324
54417
|
getEditorDisplay(item) {
|
|
54325
54418
|
const segments = item.metadata?.segments ? parseInt(item.metadata.segments, 10) : undefined;
|
|
54326
54419
|
const fishStyle = item.metadata?.fishStyle === "true";
|
|
54420
|
+
const abbreviateHome = item.metadata?.abbreviateHome === "true";
|
|
54327
54421
|
const modifiers = [];
|
|
54422
|
+
if (abbreviateHome) {
|
|
54423
|
+
modifiers.push("~");
|
|
54424
|
+
}
|
|
54328
54425
|
if (fishStyle) {
|
|
54329
54426
|
modifiers.push("fish-style");
|
|
54330
54427
|
} else if (segments && segments > 0) {
|
|
@@ -54336,11 +54433,31 @@ class CurrentWorkingDirWidget {
|
|
|
54336
54433
|
};
|
|
54337
54434
|
}
|
|
54338
54435
|
handleEditorAction(action, item) {
|
|
54436
|
+
if (action === "toggle-abbreviate-home") {
|
|
54437
|
+
const currentAbbreviateHome = item.metadata?.abbreviateHome === "true";
|
|
54438
|
+
const newAbbreviateHome = !currentAbbreviateHome;
|
|
54439
|
+
if (newAbbreviateHome) {
|
|
54440
|
+
const { fishStyle, ...restMetadata } = item.metadata ?? {};
|
|
54441
|
+
return {
|
|
54442
|
+
...item,
|
|
54443
|
+
metadata: {
|
|
54444
|
+
...restMetadata,
|
|
54445
|
+
abbreviateHome: "true"
|
|
54446
|
+
}
|
|
54447
|
+
};
|
|
54448
|
+
} else {
|
|
54449
|
+
const { abbreviateHome, ...restMetadata } = item.metadata ?? {};
|
|
54450
|
+
return {
|
|
54451
|
+
...item,
|
|
54452
|
+
metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
|
|
54453
|
+
};
|
|
54454
|
+
}
|
|
54455
|
+
}
|
|
54339
54456
|
if (action === "toggle-fish-style") {
|
|
54340
54457
|
const currentFishStyle = item.metadata?.fishStyle === "true";
|
|
54341
54458
|
const newFishStyle = !currentFishStyle;
|
|
54342
54459
|
if (newFishStyle) {
|
|
54343
|
-
const { segments, ...restMetadata } = item.metadata ?? {};
|
|
54460
|
+
const { segments, abbreviateHome, ...restMetadata } = item.metadata ?? {};
|
|
54344
54461
|
return {
|
|
54345
54462
|
...item,
|
|
54346
54463
|
metadata: {
|
|
@@ -54361,10 +54478,19 @@ class CurrentWorkingDirWidget {
|
|
|
54361
54478
|
render(item, context, settings) {
|
|
54362
54479
|
const segments = item.metadata?.segments ? parseInt(item.metadata.segments, 10) : undefined;
|
|
54363
54480
|
const fishStyle = item.metadata?.fishStyle === "true";
|
|
54481
|
+
const abbreviateHome = item.metadata?.abbreviateHome === "true";
|
|
54364
54482
|
if (context.isPreview) {
|
|
54365
54483
|
let previewPath;
|
|
54366
54484
|
if (fishStyle) {
|
|
54367
54485
|
previewPath = "~/D/P/my-project";
|
|
54486
|
+
} else if (abbreviateHome && segments && segments > 0) {
|
|
54487
|
+
if (segments === 1) {
|
|
54488
|
+
previewPath = "~/.../my-project";
|
|
54489
|
+
} else {
|
|
54490
|
+
previewPath = "~/.../Projects/my-project";
|
|
54491
|
+
}
|
|
54492
|
+
} else if (abbreviateHome) {
|
|
54493
|
+
previewPath = "~/Documents/Projects/my-project";
|
|
54368
54494
|
} else if (segments && segments > 0) {
|
|
54369
54495
|
if (segments === 1) {
|
|
54370
54496
|
previewPath = ".../project";
|
|
@@ -54382,20 +54508,27 @@ class CurrentWorkingDirWidget {
|
|
|
54382
54508
|
let displayPath = cwd2;
|
|
54383
54509
|
if (fishStyle) {
|
|
54384
54510
|
displayPath = this.abbreviatePath(cwd2);
|
|
54385
|
-
} else
|
|
54386
|
-
|
|
54387
|
-
|
|
54388
|
-
|
|
54389
|
-
|
|
54390
|
-
|
|
54391
|
-
const
|
|
54392
|
-
|
|
54511
|
+
} else {
|
|
54512
|
+
if (abbreviateHome) {
|
|
54513
|
+
displayPath = this.abbreviateHomeDir(displayPath);
|
|
54514
|
+
}
|
|
54515
|
+
if (segments && segments > 0) {
|
|
54516
|
+
const useBackslash = displayPath.includes("\\") && !displayPath.includes("/");
|
|
54517
|
+
const outSep = useBackslash ? "\\" : "/";
|
|
54518
|
+
const pathParts = displayPath.split(/[\\/]+/);
|
|
54519
|
+
const filteredParts = pathParts.filter((part) => part !== "");
|
|
54520
|
+
if (filteredParts.length > segments) {
|
|
54521
|
+
const selectedSegments = filteredParts.slice(-segments);
|
|
54522
|
+
const prefix = displayPath.startsWith("~") ? `~${outSep}` : "";
|
|
54523
|
+
displayPath = prefix + "..." + outSep + selectedSegments.join(outSep);
|
|
54524
|
+
}
|
|
54393
54525
|
}
|
|
54394
54526
|
}
|
|
54395
54527
|
return item.rawValue ? displayPath : `cwd: ${displayPath}`;
|
|
54396
54528
|
}
|
|
54397
54529
|
getCustomKeybinds() {
|
|
54398
54530
|
return [
|
|
54531
|
+
{ key: "h", label: "(h)ome ~", action: "toggle-abbreviate-home" },
|
|
54399
54532
|
{ key: "s", label: "(s)egments", action: "edit-segments" },
|
|
54400
54533
|
{ key: "f", label: "(f)ish style", action: "toggle-fish-style" }
|
|
54401
54534
|
];
|
|
@@ -54411,6 +54544,20 @@ class CurrentWorkingDirWidget {
|
|
|
54411
54544
|
supportsColors(item) {
|
|
54412
54545
|
return true;
|
|
54413
54546
|
}
|
|
54547
|
+
abbreviateHomeDir(path6) {
|
|
54548
|
+
const homeDir = os5.homedir();
|
|
54549
|
+
if (path6 === homeDir) {
|
|
54550
|
+
return "~";
|
|
54551
|
+
}
|
|
54552
|
+
if (path6.startsWith(homeDir)) {
|
|
54553
|
+
const boundaryChar = path6[homeDir.length];
|
|
54554
|
+
if (boundaryChar !== "/" && boundaryChar !== "\\") {
|
|
54555
|
+
return path6;
|
|
54556
|
+
}
|
|
54557
|
+
return "~" + path6.slice(homeDir.length);
|
|
54558
|
+
}
|
|
54559
|
+
return path6;
|
|
54560
|
+
}
|
|
54414
54561
|
abbreviatePath(path6) {
|
|
54415
54562
|
const homeDir = os5.homedir();
|
|
54416
54563
|
const useBackslash = path6.includes("\\") && !path6.includes("/");
|
|
@@ -54538,7 +54685,7 @@ class ClaudeSessionIdWidget {
|
|
|
54538
54685
|
}
|
|
54539
54686
|
// src/widgets/ApiUsage.tsx
|
|
54540
54687
|
import {
|
|
54541
|
-
execSync as
|
|
54688
|
+
execSync as execSync6,
|
|
54542
54689
|
spawnSync
|
|
54543
54690
|
} from "child_process";
|
|
54544
54691
|
import * as fs7 from "fs";
|
|
@@ -54563,7 +54710,7 @@ function readTokenFromFile() {
|
|
|
54563
54710
|
}
|
|
54564
54711
|
function readTokenFromKeychain() {
|
|
54565
54712
|
try {
|
|
54566
|
-
const result =
|
|
54713
|
+
const result = execSync6('security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null', { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
54567
54714
|
const parsed = JSON.parse(result);
|
|
54568
54715
|
return parsed?.claudeAiOauth?.accessToken ?? null;
|
|
54569
54716
|
} catch {
|
|
@@ -54944,12 +55091,65 @@ class ContextBarWidget {
|
|
|
54944
55091
|
return true;
|
|
54945
55092
|
}
|
|
54946
55093
|
}
|
|
55094
|
+
// src/widgets/SessionName.ts
|
|
55095
|
+
import * as fs8 from "fs";
|
|
55096
|
+
|
|
55097
|
+
class SessionNameWidget {
|
|
55098
|
+
getDefaultColor() {
|
|
55099
|
+
return "cyan";
|
|
55100
|
+
}
|
|
55101
|
+
getDescription() {
|
|
55102
|
+
return "Shows the session name set via /rename command in Claude Code";
|
|
55103
|
+
}
|
|
55104
|
+
getDisplayName() {
|
|
55105
|
+
return "Session Name";
|
|
55106
|
+
}
|
|
55107
|
+
getCategory() {
|
|
55108
|
+
return "Session";
|
|
55109
|
+
}
|
|
55110
|
+
getEditorDisplay(item) {
|
|
55111
|
+
return { displayText: this.getDisplayName() };
|
|
55112
|
+
}
|
|
55113
|
+
render(item, context, settings) {
|
|
55114
|
+
if (context.isPreview) {
|
|
55115
|
+
return item.rawValue ? "my-session" : "Session: my-session";
|
|
55116
|
+
}
|
|
55117
|
+
const transcriptPath = context.data?.transcript_path;
|
|
55118
|
+
if (!transcriptPath) {
|
|
55119
|
+
return null;
|
|
55120
|
+
}
|
|
55121
|
+
try {
|
|
55122
|
+
const content = fs8.readFileSync(transcriptPath, "utf-8");
|
|
55123
|
+
const lines = content.split(`
|
|
55124
|
+
`);
|
|
55125
|
+
for (let i = lines.length - 1;i >= 0; i--) {
|
|
55126
|
+
const line = lines[i]?.trim();
|
|
55127
|
+
if (!line)
|
|
55128
|
+
continue;
|
|
55129
|
+
try {
|
|
55130
|
+
const entry = JSON.parse(line);
|
|
55131
|
+
if (entry.type === "custom-title" && entry.customTitle) {
|
|
55132
|
+
return item.rawValue ? entry.customTitle : `Session: ${entry.customTitle}`;
|
|
55133
|
+
}
|
|
55134
|
+
} catch {}
|
|
55135
|
+
}
|
|
55136
|
+
} catch {}
|
|
55137
|
+
return null;
|
|
55138
|
+
}
|
|
55139
|
+
supportsRawValue() {
|
|
55140
|
+
return true;
|
|
55141
|
+
}
|
|
55142
|
+
supportsColors(item) {
|
|
55143
|
+
return true;
|
|
55144
|
+
}
|
|
55145
|
+
}
|
|
54947
55146
|
// src/utils/widgets.ts
|
|
54948
55147
|
var widgetRegistry = new Map([
|
|
54949
55148
|
["model", new ModelWidget],
|
|
54950
55149
|
["output-style", new OutputStyleWidget],
|
|
54951
55150
|
["git-branch", new GitBranchWidget],
|
|
54952
55151
|
["git-changes", new GitChangesWidget],
|
|
55152
|
+
["git-root-dir", new GitRootDirWidget],
|
|
54953
55153
|
["git-worktree", new GitWorktreeWidget],
|
|
54954
55154
|
["current-working-dir", new CurrentWorkingDirWidget],
|
|
54955
55155
|
["tokens-input", new TokensInputWidget],
|
|
@@ -54970,7 +55170,8 @@ var widgetRegistry = new Map([
|
|
|
54970
55170
|
["session-usage", new SessionUsageWidget],
|
|
54971
55171
|
["weekly-usage", new WeeklyUsageWidget],
|
|
54972
55172
|
["reset-timer", new ResetTimerWidget],
|
|
54973
|
-
["context-bar", new ContextBarWidget]
|
|
55173
|
+
["context-bar", new ContextBarWidget],
|
|
55174
|
+
["session-name", new SessionNameWidget]
|
|
54974
55175
|
]);
|
|
54975
55176
|
function getWidget(type) {
|
|
54976
55177
|
return widgetRegistry.get(type) ?? null;
|
|
@@ -56466,7 +56667,11 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
|
|
|
56466
56667
|
}
|
|
56467
56668
|
} else if (input === "r" && widgets.length > 0) {
|
|
56468
56669
|
const currentWidget2 = widgets[selectedIndex];
|
|
56469
|
-
if (currentWidget2 && currentWidget2.type !== "separator" && currentWidget2.type !== "flex-separator"
|
|
56670
|
+
if (currentWidget2 && currentWidget2.type !== "separator" && currentWidget2.type !== "flex-separator") {
|
|
56671
|
+
const widgetImpl = getWidget(currentWidget2.type);
|
|
56672
|
+
if (!widgetImpl?.supportsRawValue()) {
|
|
56673
|
+
return;
|
|
56674
|
+
}
|
|
56470
56675
|
const newWidgets = [...widgets];
|
|
56471
56676
|
newWidgets[selectedIndex] = { ...currentWidget2, rawValue: !currentWidget2.rawValue };
|
|
56472
56677
|
onUpdate(newWidgets);
|
|
@@ -56875,6 +57080,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
|
|
|
56875
57080
|
const isSelected = index === selectedIndex;
|
|
56876
57081
|
const widgetImpl = widget.type !== "separator" && widget.type !== "flex-separator" ? getWidget(widget.type) : null;
|
|
56877
57082
|
const { displayText, modifierText } = widgetImpl?.getEditorDisplay(widget) ?? { displayText: getWidgetDisplay(widget) };
|
|
57083
|
+
const supportsRawValue = widgetImpl?.supportsRawValue() ?? false;
|
|
56878
57084
|
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
56879
57085
|
flexDirection: "row",
|
|
56880
57086
|
flexWrap: "nowrap",
|
|
@@ -56897,7 +57103,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
|
|
|
56897
57103
|
modifierText
|
|
56898
57104
|
]
|
|
56899
57105
|
}, undefined, true, undefined, this),
|
|
56900
|
-
widget.rawValue && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
57106
|
+
supportsRawValue && widget.rawValue && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
56901
57107
|
dimColor: true,
|
|
56902
57108
|
children: " (raw value)"
|
|
56903
57109
|
}, undefined, false, undefined, this),
|
|
@@ -59329,7 +59535,9 @@ function renderCompactOutput(preRenderedLines, settings, maxWidth) {
|
|
|
59329
59535
|
}
|
|
59330
59536
|
|
|
59331
59537
|
// src/utils/jsonl.ts
|
|
59332
|
-
import * as
|
|
59538
|
+
import * as fs9 from "fs";
|
|
59539
|
+
import { createHash } from "node:crypto";
|
|
59540
|
+
import os7 from "node:os";
|
|
59333
59541
|
import path8 from "node:path";
|
|
59334
59542
|
|
|
59335
59543
|
// node_modules/tinyglobby/dist/index.mjs
|
|
@@ -59464,12 +59672,12 @@ function build$3(options) {
|
|
|
59464
59672
|
return options.group ? groupFiles : empty;
|
|
59465
59673
|
}
|
|
59466
59674
|
var resolveSymlinksAsync = function(path7, state, callback$1) {
|
|
59467
|
-
const { queue, fs:
|
|
59675
|
+
const { queue, fs: fs9, options: { suppressErrors } } = state;
|
|
59468
59676
|
queue.enqueue();
|
|
59469
|
-
|
|
59677
|
+
fs9.realpath(path7, (error43, resolvedPath) => {
|
|
59470
59678
|
if (error43)
|
|
59471
59679
|
return queue.dequeue(suppressErrors ? null : error43, state);
|
|
59472
|
-
|
|
59680
|
+
fs9.stat(resolvedPath, (error$1, stat) => {
|
|
59473
59681
|
if (error$1)
|
|
59474
59682
|
return queue.dequeue(suppressErrors ? null : error$1, state);
|
|
59475
59683
|
if (stat.isDirectory() && isRecursive(path7, resolvedPath, state))
|
|
@@ -59480,11 +59688,11 @@ var resolveSymlinksAsync = function(path7, state, callback$1) {
|
|
|
59480
59688
|
});
|
|
59481
59689
|
};
|
|
59482
59690
|
var resolveSymlinks = function(path7, state, callback$1) {
|
|
59483
|
-
const { queue, fs:
|
|
59691
|
+
const { queue, fs: fs9, options: { suppressErrors } } = state;
|
|
59484
59692
|
queue.enqueue();
|
|
59485
59693
|
try {
|
|
59486
|
-
const resolvedPath =
|
|
59487
|
-
const stat =
|
|
59694
|
+
const resolvedPath = fs9.realpathSync(path7);
|
|
59695
|
+
const stat = fs9.statSync(resolvedPath);
|
|
59488
59696
|
if (stat.isDirectory() && isRecursive(path7, resolvedPath, state))
|
|
59489
59697
|
return;
|
|
59490
59698
|
callback$1(stat, resolvedPath);
|
|
@@ -59567,23 +59775,23 @@ var walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
|
59567
59775
|
state.queue.enqueue();
|
|
59568
59776
|
if (currentDepth < 0)
|
|
59569
59777
|
return state.queue.dequeue(null, state);
|
|
59570
|
-
const { fs:
|
|
59778
|
+
const { fs: fs9 } = state;
|
|
59571
59779
|
state.visited.push(crawlPath);
|
|
59572
59780
|
state.counts.directories++;
|
|
59573
|
-
|
|
59781
|
+
fs9.readdir(crawlPath || ".", readdirOpts, (error43, entries = []) => {
|
|
59574
59782
|
callback$1(entries, directoryPath, currentDepth);
|
|
59575
59783
|
state.queue.dequeue(state.options.suppressErrors ? null : error43, state);
|
|
59576
59784
|
});
|
|
59577
59785
|
};
|
|
59578
59786
|
var walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
|
|
59579
|
-
const { fs:
|
|
59787
|
+
const { fs: fs9 } = state;
|
|
59580
59788
|
if (currentDepth < 0)
|
|
59581
59789
|
return;
|
|
59582
59790
|
state.visited.push(crawlPath);
|
|
59583
59791
|
state.counts.directories++;
|
|
59584
59792
|
let entries = [];
|
|
59585
59793
|
try {
|
|
59586
|
-
entries =
|
|
59794
|
+
entries = fs9.readdirSync(crawlPath || ".", readdirOpts);
|
|
59587
59795
|
} catch (e) {
|
|
59588
59796
|
if (!state.options.suppressErrors)
|
|
59589
59797
|
throw e;
|
|
@@ -60118,12 +60326,87 @@ function globSync(patternsOrOptions, options) {
|
|
|
60118
60326
|
|
|
60119
60327
|
// src/utils/jsonl.ts
|
|
60120
60328
|
import { promisify } from "util";
|
|
60121
|
-
var readFile4 = promisify(
|
|
60122
|
-
var
|
|
60123
|
-
var statSync5 =
|
|
60329
|
+
var readFile4 = promisify(fs9.readFile);
|
|
60330
|
+
var readFileSync7 = fs9.readFileSync;
|
|
60331
|
+
var statSync5 = fs9.statSync;
|
|
60332
|
+
var writeFileSync3 = fs9.writeFileSync;
|
|
60333
|
+
var mkdirSync4 = fs9.mkdirSync;
|
|
60334
|
+
var existsSync8 = fs9.existsSync;
|
|
60335
|
+
function normalizeConfigDir(configDir) {
|
|
60336
|
+
return path8.resolve(configDir);
|
|
60337
|
+
}
|
|
60338
|
+
function getBlockCachePath(configDir = getClaudeConfigDir()) {
|
|
60339
|
+
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
60340
|
+
const configHash = createHash("sha256").update(normalizedConfigDir).digest("hex").slice(0, 16);
|
|
60341
|
+
return path8.join(os7.homedir(), ".cache", "ccstatusline", `block-cache-${configHash}.json`);
|
|
60342
|
+
}
|
|
60343
|
+
function readBlockCache(expectedConfigDir) {
|
|
60344
|
+
try {
|
|
60345
|
+
const normalizedExpectedConfigDir = expectedConfigDir !== undefined ? normalizeConfigDir(expectedConfigDir) : undefined;
|
|
60346
|
+
const cachePath = getBlockCachePath(normalizedExpectedConfigDir);
|
|
60347
|
+
if (!existsSync8(cachePath)) {
|
|
60348
|
+
return null;
|
|
60349
|
+
}
|
|
60350
|
+
const content = readFileSync7(cachePath, "utf-8");
|
|
60351
|
+
const cache3 = JSON.parse(content);
|
|
60352
|
+
if (typeof cache3.startTime !== "string") {
|
|
60353
|
+
return null;
|
|
60354
|
+
}
|
|
60355
|
+
if (normalizedExpectedConfigDir !== undefined) {
|
|
60356
|
+
if (typeof cache3.configDir !== "string") {
|
|
60357
|
+
return null;
|
|
60358
|
+
}
|
|
60359
|
+
if (cache3.configDir !== normalizedExpectedConfigDir) {
|
|
60360
|
+
return null;
|
|
60361
|
+
}
|
|
60362
|
+
}
|
|
60363
|
+
const date5 = new Date(cache3.startTime);
|
|
60364
|
+
if (Number.isNaN(date5.getTime())) {
|
|
60365
|
+
return null;
|
|
60366
|
+
}
|
|
60367
|
+
return date5;
|
|
60368
|
+
} catch {
|
|
60369
|
+
return null;
|
|
60370
|
+
}
|
|
60371
|
+
}
|
|
60372
|
+
function writeBlockCache(startTime, configDir = getClaudeConfigDir()) {
|
|
60373
|
+
try {
|
|
60374
|
+
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
60375
|
+
const cachePath = getBlockCachePath(normalizedConfigDir);
|
|
60376
|
+
const cacheDir = path8.dirname(cachePath);
|
|
60377
|
+
if (!existsSync8(cacheDir)) {
|
|
60378
|
+
mkdirSync4(cacheDir, { recursive: true });
|
|
60379
|
+
}
|
|
60380
|
+
const cache3 = {
|
|
60381
|
+
startTime: startTime.toISOString(),
|
|
60382
|
+
configDir: normalizedConfigDir
|
|
60383
|
+
};
|
|
60384
|
+
writeFileSync3(cachePath, JSON.stringify(cache3), "utf-8");
|
|
60385
|
+
} catch {}
|
|
60386
|
+
}
|
|
60387
|
+
function getCachedBlockMetrics(sessionDurationHours = 5) {
|
|
60388
|
+
const sessionDurationMs = sessionDurationHours * 60 * 60 * 1000;
|
|
60389
|
+
const now = new Date;
|
|
60390
|
+
const activeConfigDir = getClaudeConfigDir();
|
|
60391
|
+
const cachedStartTime = readBlockCache(activeConfigDir);
|
|
60392
|
+
if (cachedStartTime) {
|
|
60393
|
+
const blockEndTime = new Date(cachedStartTime.getTime() + sessionDurationMs);
|
|
60394
|
+
if (now.getTime() <= blockEndTime.getTime()) {
|
|
60395
|
+
return {
|
|
60396
|
+
startTime: cachedStartTime,
|
|
60397
|
+
lastActivity: now
|
|
60398
|
+
};
|
|
60399
|
+
}
|
|
60400
|
+
}
|
|
60401
|
+
const metrics = getBlockMetrics();
|
|
60402
|
+
if (metrics) {
|
|
60403
|
+
writeBlockCache(metrics.startTime, activeConfigDir);
|
|
60404
|
+
}
|
|
60405
|
+
return metrics;
|
|
60406
|
+
}
|
|
60124
60407
|
async function getSessionDuration(transcriptPath) {
|
|
60125
60408
|
try {
|
|
60126
|
-
if (!
|
|
60409
|
+
if (!fs9.existsSync(transcriptPath)) {
|
|
60127
60410
|
return null;
|
|
60128
60411
|
}
|
|
60129
60412
|
const content = await readFile4(transcriptPath, "utf-8");
|
|
@@ -60175,7 +60458,7 @@ async function getSessionDuration(transcriptPath) {
|
|
|
60175
60458
|
}
|
|
60176
60459
|
async function getTokenMetrics(transcriptPath) {
|
|
60177
60460
|
try {
|
|
60178
|
-
if (!
|
|
60461
|
+
if (!fs9.existsSync(transcriptPath)) {
|
|
60179
60462
|
return { inputTokens: 0, outputTokens: 0, cachedTokens: 0, totalTokens: 0, contextLength: 0 };
|
|
60180
60463
|
}
|
|
60181
60464
|
const content = await readFile4(transcriptPath, "utf-8");
|
|
@@ -60322,7 +60605,7 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
|
|
|
60322
60605
|
function getAllTimestampsFromFile(filePath) {
|
|
60323
60606
|
const timestamps = [];
|
|
60324
60607
|
try {
|
|
60325
|
-
const content =
|
|
60608
|
+
const content = readFileSync7(filePath, "utf-8");
|
|
60326
60609
|
const lines = content.trim().split(`
|
|
60327
60610
|
`).filter((line) => line.length > 0);
|
|
60328
60611
|
for (const line of lines) {
|
|
@@ -60390,6 +60673,15 @@ async function readStdin() {
|
|
|
60390
60673
|
return null;
|
|
60391
60674
|
}
|
|
60392
60675
|
}
|
|
60676
|
+
async function ensureWindowsUtf8CodePage() {
|
|
60677
|
+
if (process.platform !== "win32") {
|
|
60678
|
+
return;
|
|
60679
|
+
}
|
|
60680
|
+
try {
|
|
60681
|
+
const { execFileSync } = await import("child_process");
|
|
60682
|
+
execFileSync("chcp.com", ["65001"], { stdio: "ignore" });
|
|
60683
|
+
} catch {}
|
|
60684
|
+
}
|
|
60393
60685
|
async function renderMultipleLines(data) {
|
|
60394
60686
|
const settings = await loadSettings();
|
|
60395
60687
|
source_default.level = settings.colorLevel;
|
|
@@ -60408,7 +60700,7 @@ async function renderMultipleLines(data) {
|
|
|
60408
60700
|
}
|
|
60409
60701
|
let blockMetrics = null;
|
|
60410
60702
|
if (hasBlockTimer) {
|
|
60411
|
-
blockMetrics =
|
|
60703
|
+
blockMetrics = getCachedBlockMetrics();
|
|
60412
60704
|
}
|
|
60413
60705
|
const terminalWidth = getTerminalWidth();
|
|
60414
60706
|
const compact = shouldUseCompactMode(terminalWidth, data);
|
|
@@ -60465,6 +60757,7 @@ async function renderMultipleLines(data) {
|
|
|
60465
60757
|
}
|
|
60466
60758
|
async function main() {
|
|
60467
60759
|
if (!process.stdin.isTTY) {
|
|
60760
|
+
await ensureWindowsUtf8CodePage();
|
|
60468
60761
|
const input = await readStdin();
|
|
60469
60762
|
if (input && input.trim() !== "") {
|
|
60470
60763
|
try {
|