ccstatusline 2.0.26 → 2.0.28
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 +13 -0
- package/dist/ccstatusline.js +248 -62
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -46,6 +46,19 @@
|
|
|
46
46
|
|
|
47
47
|
## 🆕 Recent Updates
|
|
48
48
|
|
|
49
|
+
### v2.0.26 - v2.0.28 - Performance, git internals, and workflow improvements
|
|
50
|
+
|
|
51
|
+
- **⚡ 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.
|
|
52
|
+
- **🧱 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.
|
|
53
|
+
- **🪟 Windows UTF-8 piped output fix (v2.0.28)** - Sets the Windows UTF-8 code page for piped status line rendering.
|
|
54
|
+
- **📁 Git Root Dir widget (v2.0.27)** - Added a new Git widget that shows the repository root directory name.
|
|
55
|
+
- **🏷️ Session Name widget (v2.0.26)** - Added a new widget that shows the current Claude Code session name from `/rename`.
|
|
56
|
+
- **🏠 Current Working Directory home abbreviation (v2.0.26)** - Added a `~` abbreviation option for CWD display in both preview and live rendering.
|
|
57
|
+
- **🧠 Context model suffix fix (v2.0.26)** - Context widgets now recognize the `[1m]` suffix across models, not just a single model path.
|
|
58
|
+
- **🧭 Widget picker UX updates (v2.0.26)** - Improved widget discovery/navigation and added clearer, safer clear-line behavior.
|
|
59
|
+
- **⌨️ TUI editor input fix (v2.0.26)** - Prevented shortcut/input leakage into widget editor flows.
|
|
60
|
+
- **📄 Repo docs update (v2.0.26)** - Migrated guidance from `CLAUDE.md` to `AGENTS.md` (with symlink compatibility).
|
|
61
|
+
|
|
49
62
|
### v2.0.16 - Add fish style path abbreviation toggle to Current Working Directory widget
|
|
50
63
|
|
|
51
64
|
### v2.0.15 - Block Timer calculation fixes
|
package/dist/ccstatusline.js
CHANGED
|
@@ -51405,7 +51405,7 @@ import { execSync as execSync3 } from "child_process";
|
|
|
51405
51405
|
import * as fs5 from "fs";
|
|
51406
51406
|
import * as path4 from "path";
|
|
51407
51407
|
var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils";
|
|
51408
|
-
var PACKAGE_VERSION = "2.0.
|
|
51408
|
+
var PACKAGE_VERSION = "2.0.28";
|
|
51409
51409
|
function getPackageVersion() {
|
|
51410
51410
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
51411
51411
|
return PACKAGE_VERSION;
|
|
@@ -52313,9 +52313,39 @@ class OutputStyleWidget {
|
|
|
52313
52313
|
return true;
|
|
52314
52314
|
}
|
|
52315
52315
|
}
|
|
52316
|
-
// src/
|
|
52316
|
+
// src/utils/git.ts
|
|
52317
52317
|
import { execSync as execSync4 } from "child_process";
|
|
52318
|
+
function resolveGitCwd(context) {
|
|
52319
|
+
const candidates = [
|
|
52320
|
+
context.data?.cwd,
|
|
52321
|
+
context.data?.workspace?.current_dir,
|
|
52322
|
+
context.data?.workspace?.project_dir
|
|
52323
|
+
];
|
|
52324
|
+
for (const candidate of candidates) {
|
|
52325
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
52326
|
+
return candidate;
|
|
52327
|
+
}
|
|
52328
|
+
}
|
|
52329
|
+
return;
|
|
52330
|
+
}
|
|
52331
|
+
function runGit(command, context) {
|
|
52332
|
+
try {
|
|
52333
|
+
const cwd2 = resolveGitCwd(context);
|
|
52334
|
+
const output = execSync4(`git ${command}`, {
|
|
52335
|
+
encoding: "utf8",
|
|
52336
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
52337
|
+
...cwd2 ? { cwd: cwd2 } : {}
|
|
52338
|
+
}).trim();
|
|
52339
|
+
return output.length > 0 ? output : null;
|
|
52340
|
+
} catch {
|
|
52341
|
+
return null;
|
|
52342
|
+
}
|
|
52343
|
+
}
|
|
52344
|
+
function isInsideGitWorkTree(context) {
|
|
52345
|
+
return runGit("rev-parse --is-inside-work-tree", context) === "true";
|
|
52346
|
+
}
|
|
52318
52347
|
|
|
52348
|
+
// src/widgets/GitBranch.ts
|
|
52319
52349
|
class GitBranchWidget {
|
|
52320
52350
|
getDefaultColor() {
|
|
52321
52351
|
return "magenta";
|
|
@@ -52358,21 +52388,16 @@ class GitBranchWidget {
|
|
|
52358
52388
|
if (context.isPreview) {
|
|
52359
52389
|
return item.rawValue ? "main" : "⎇ main";
|
|
52360
52390
|
}
|
|
52361
|
-
|
|
52391
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52392
|
+
return hideNoGit ? null : "⎇ no git";
|
|
52393
|
+
}
|
|
52394
|
+
const branch = this.getGitBranch(context);
|
|
52362
52395
|
if (branch)
|
|
52363
52396
|
return item.rawValue ? branch : `⎇ ${branch}`;
|
|
52364
52397
|
return hideNoGit ? null : "⎇ no git";
|
|
52365
52398
|
}
|
|
52366
|
-
getGitBranch() {
|
|
52367
|
-
|
|
52368
|
-
const branch = execSync4("git branch --show-current", {
|
|
52369
|
-
encoding: "utf8",
|
|
52370
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
52371
|
-
}).trim();
|
|
52372
|
-
return branch || null;
|
|
52373
|
-
} catch {
|
|
52374
|
-
return null;
|
|
52375
|
-
}
|
|
52399
|
+
getGitBranch(context) {
|
|
52400
|
+
return runGit("branch --show-current", context);
|
|
52376
52401
|
}
|
|
52377
52402
|
getCustomKeybinds() {
|
|
52378
52403
|
return [
|
|
@@ -52387,8 +52412,6 @@ class GitBranchWidget {
|
|
|
52387
52412
|
}
|
|
52388
52413
|
}
|
|
52389
52414
|
// src/widgets/GitChanges.ts
|
|
52390
|
-
import { execSync as execSync5 } from "child_process";
|
|
52391
|
-
|
|
52392
52415
|
class GitChangesWidget {
|
|
52393
52416
|
getDefaultColor() {
|
|
52394
52417
|
return "yellow";
|
|
@@ -52431,40 +52454,107 @@ class GitChangesWidget {
|
|
|
52431
52454
|
if (context.isPreview) {
|
|
52432
52455
|
return "(+42,-10)";
|
|
52433
52456
|
}
|
|
52434
|
-
|
|
52457
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52458
|
+
return hideNoGit ? null : "(no git)";
|
|
52459
|
+
}
|
|
52460
|
+
const changes = this.getGitChanges(context);
|
|
52435
52461
|
if (changes)
|
|
52436
52462
|
return `(+${changes.insertions},-${changes.deletions})`;
|
|
52437
52463
|
else
|
|
52438
52464
|
return hideNoGit ? null : "(no git)";
|
|
52439
52465
|
}
|
|
52440
|
-
getGitChanges() {
|
|
52441
|
-
|
|
52442
|
-
|
|
52443
|
-
|
|
52444
|
-
|
|
52445
|
-
|
|
52446
|
-
|
|
52447
|
-
|
|
52448
|
-
|
|
52449
|
-
|
|
52450
|
-
|
|
52451
|
-
|
|
52452
|
-
|
|
52453
|
-
|
|
52454
|
-
|
|
52455
|
-
|
|
52456
|
-
|
|
52457
|
-
|
|
52458
|
-
|
|
52459
|
-
|
|
52460
|
-
|
|
52461
|
-
|
|
52462
|
-
|
|
52463
|
-
|
|
52464
|
-
|
|
52465
|
-
|
|
52466
|
-
|
|
52466
|
+
getGitChanges(context) {
|
|
52467
|
+
let totalInsertions = 0;
|
|
52468
|
+
let totalDeletions = 0;
|
|
52469
|
+
const unstagedStat = runGit("diff --shortstat", context) ?? "";
|
|
52470
|
+
const stagedStat = runGit("diff --cached --shortstat", context) ?? "";
|
|
52471
|
+
if (unstagedStat) {
|
|
52472
|
+
const insertMatch = /(\d+) insertion/.exec(unstagedStat);
|
|
52473
|
+
const deleteMatch = /(\d+) deletion/.exec(unstagedStat);
|
|
52474
|
+
totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
|
|
52475
|
+
totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
|
|
52476
|
+
}
|
|
52477
|
+
if (stagedStat) {
|
|
52478
|
+
const insertMatch = /(\d+) insertion/.exec(stagedStat);
|
|
52479
|
+
const deleteMatch = /(\d+) deletion/.exec(stagedStat);
|
|
52480
|
+
totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
|
|
52481
|
+
totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
|
|
52482
|
+
}
|
|
52483
|
+
return { insertions: totalInsertions, deletions: totalDeletions };
|
|
52484
|
+
}
|
|
52485
|
+
getCustomKeybinds() {
|
|
52486
|
+
return [
|
|
52487
|
+
{ key: "h", label: "(h)ide 'no git' message", action: "toggle-nogit" }
|
|
52488
|
+
];
|
|
52489
|
+
}
|
|
52490
|
+
supportsRawValue() {
|
|
52491
|
+
return false;
|
|
52492
|
+
}
|
|
52493
|
+
supportsColors(item) {
|
|
52494
|
+
return true;
|
|
52495
|
+
}
|
|
52496
|
+
}
|
|
52497
|
+
// src/widgets/GitRootDir.ts
|
|
52498
|
+
class GitRootDirWidget {
|
|
52499
|
+
getDefaultColor() {
|
|
52500
|
+
return "cyan";
|
|
52501
|
+
}
|
|
52502
|
+
getDescription() {
|
|
52503
|
+
return "Shows the git repository root directory name";
|
|
52504
|
+
}
|
|
52505
|
+
getDisplayName() {
|
|
52506
|
+
return "Git Root Dir";
|
|
52507
|
+
}
|
|
52508
|
+
getCategory() {
|
|
52509
|
+
return "Git";
|
|
52510
|
+
}
|
|
52511
|
+
getEditorDisplay(item) {
|
|
52512
|
+
const hideNoGit = item.metadata?.hideNoGit === "true";
|
|
52513
|
+
const modifiers = [];
|
|
52514
|
+
if (hideNoGit) {
|
|
52515
|
+
modifiers.push("hide 'no git'");
|
|
52467
52516
|
}
|
|
52517
|
+
return {
|
|
52518
|
+
displayText: this.getDisplayName(),
|
|
52519
|
+
modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
|
|
52520
|
+
};
|
|
52521
|
+
}
|
|
52522
|
+
handleEditorAction(action, item) {
|
|
52523
|
+
if (action === "toggle-nogit") {
|
|
52524
|
+
const currentState = item.metadata?.hideNoGit === "true";
|
|
52525
|
+
return {
|
|
52526
|
+
...item,
|
|
52527
|
+
metadata: {
|
|
52528
|
+
...item.metadata,
|
|
52529
|
+
hideNoGit: (!currentState).toString()
|
|
52530
|
+
}
|
|
52531
|
+
};
|
|
52532
|
+
}
|
|
52533
|
+
return null;
|
|
52534
|
+
}
|
|
52535
|
+
render(item, context, _settings) {
|
|
52536
|
+
const hideNoGit = item.metadata?.hideNoGit === "true";
|
|
52537
|
+
if (context.isPreview) {
|
|
52538
|
+
return "my-repo";
|
|
52539
|
+
}
|
|
52540
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52541
|
+
return hideNoGit ? null : "no git";
|
|
52542
|
+
}
|
|
52543
|
+
const rootDir = this.getGitRootDir(context);
|
|
52544
|
+
if (rootDir) {
|
|
52545
|
+
return this.getRootDirName(rootDir);
|
|
52546
|
+
}
|
|
52547
|
+
return hideNoGit ? null : "no git";
|
|
52548
|
+
}
|
|
52549
|
+
getGitRootDir(context) {
|
|
52550
|
+
return runGit("rev-parse --show-toplevel", context);
|
|
52551
|
+
}
|
|
52552
|
+
getRootDirName(rootDir) {
|
|
52553
|
+
const trimmedRootDir = rootDir.replace(/[\\/]+$/, "");
|
|
52554
|
+
const normalizedRootDir = trimmedRootDir.length > 0 ? trimmedRootDir : rootDir;
|
|
52555
|
+
const parts = normalizedRootDir.split(/[\\/]/).filter(Boolean);
|
|
52556
|
+
const lastPart = parts[parts.length - 1];
|
|
52557
|
+
return lastPart && lastPart.length > 0 ? lastPart : normalizedRootDir;
|
|
52468
52558
|
}
|
|
52469
52559
|
getCustomKeybinds() {
|
|
52470
52560
|
return [
|
|
@@ -52479,8 +52569,6 @@ class GitChangesWidget {
|
|
|
52479
52569
|
}
|
|
52480
52570
|
}
|
|
52481
52571
|
// src/widgets/GitWorktree.ts
|
|
52482
|
-
import { execSync as execSync6 } from "child_process";
|
|
52483
|
-
|
|
52484
52572
|
class GitWorktreeWidget {
|
|
52485
52573
|
getDefaultColor() {
|
|
52486
52574
|
return "blue";
|
|
@@ -52522,24 +52610,29 @@ class GitWorktreeWidget {
|
|
|
52522
52610
|
const hideNoGit = item.metadata?.hideNoGit === "true";
|
|
52523
52611
|
if (context.isPreview)
|
|
52524
52612
|
return item.rawValue ? "main" : "\uD81A\uDC30 main";
|
|
52525
|
-
|
|
52613
|
+
if (!isInsideGitWorkTree(context)) {
|
|
52614
|
+
return hideNoGit ? null : "\uD81A\uDC30 no git";
|
|
52615
|
+
}
|
|
52616
|
+
const worktree = this.getGitWorktree(context);
|
|
52526
52617
|
if (worktree)
|
|
52527
52618
|
return item.rawValue ? worktree : `\uD81A\uDC30 ${worktree}`;
|
|
52528
52619
|
return hideNoGit ? null : "\uD81A\uDC30 no git";
|
|
52529
52620
|
}
|
|
52530
|
-
getGitWorktree() {
|
|
52531
|
-
|
|
52532
|
-
|
|
52533
|
-
encoding: "utf8",
|
|
52534
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
52535
|
-
}).trim();
|
|
52536
|
-
if (worktreeDir.endsWith("/.git") || worktreeDir === ".git")
|
|
52537
|
-
return "main";
|
|
52538
|
-
const [, worktree] = worktreeDir.split(".git/worktrees/");
|
|
52539
|
-
return worktree ?? null;
|
|
52540
|
-
} catch {
|
|
52621
|
+
getGitWorktree(context) {
|
|
52622
|
+
const worktreeDir = runGit("rev-parse --git-dir", context);
|
|
52623
|
+
if (!worktreeDir) {
|
|
52541
52624
|
return null;
|
|
52542
52625
|
}
|
|
52626
|
+
const normalizedGitDir = worktreeDir.replace(/\\/g, "/");
|
|
52627
|
+
if (normalizedGitDir.endsWith("/.git") || normalizedGitDir === ".git")
|
|
52628
|
+
return "main";
|
|
52629
|
+
const marker = ".git/worktrees/";
|
|
52630
|
+
const markerIndex = normalizedGitDir.lastIndexOf(marker);
|
|
52631
|
+
if (markerIndex === -1) {
|
|
52632
|
+
return null;
|
|
52633
|
+
}
|
|
52634
|
+
const worktree = normalizedGitDir.slice(markerIndex + marker.length);
|
|
52635
|
+
return worktree.length > 0 ? worktree : null;
|
|
52543
52636
|
}
|
|
52544
52637
|
getCustomKeybinds() {
|
|
52545
52638
|
return [
|
|
@@ -53823,7 +53916,7 @@ var CustomTextEditor = ({ widget, onComplete, onCancel }) => {
|
|
|
53823
53916
|
}, undefined, true, undefined, this);
|
|
53824
53917
|
};
|
|
53825
53918
|
// src/widgets/CustomCommand.tsx
|
|
53826
|
-
import { execSync as
|
|
53919
|
+
import { execSync as execSync5 } from "child_process";
|
|
53827
53920
|
var import_react30 = __toESM(require_react(), 1);
|
|
53828
53921
|
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
53829
53922
|
|
|
@@ -53872,7 +53965,7 @@ class CustomCommandWidget {
|
|
|
53872
53965
|
try {
|
|
53873
53966
|
const timeout = item.timeout ?? 1000;
|
|
53874
53967
|
const jsonInput = JSON.stringify(context.data);
|
|
53875
|
-
let output =
|
|
53968
|
+
let output = execSync5(item.commandPath, {
|
|
53876
53969
|
encoding: "utf8",
|
|
53877
53970
|
input: jsonInput,
|
|
53878
53971
|
timeout,
|
|
@@ -54533,6 +54626,7 @@ var widgetRegistry = new Map([
|
|
|
54533
54626
|
["output-style", new OutputStyleWidget],
|
|
54534
54627
|
["git-branch", new GitBranchWidget],
|
|
54535
54628
|
["git-changes", new GitChangesWidget],
|
|
54629
|
+
["git-root-dir", new GitRootDirWidget],
|
|
54536
54630
|
["git-worktree", new GitWorktreeWidget],
|
|
54537
54631
|
["current-working-dir", new CurrentWorkingDirWidget],
|
|
54538
54632
|
["tokens-input", new TokensInputWidget],
|
|
@@ -56046,7 +56140,11 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
|
|
|
56046
56140
|
}
|
|
56047
56141
|
} else if (input === "r" && widgets.length > 0) {
|
|
56048
56142
|
const currentWidget2 = widgets[selectedIndex];
|
|
56049
|
-
if (currentWidget2 && currentWidget2.type !== "separator" && currentWidget2.type !== "flex-separator"
|
|
56143
|
+
if (currentWidget2 && currentWidget2.type !== "separator" && currentWidget2.type !== "flex-separator") {
|
|
56144
|
+
const widgetImpl = getWidget(currentWidget2.type);
|
|
56145
|
+
if (!widgetImpl?.supportsRawValue()) {
|
|
56146
|
+
return;
|
|
56147
|
+
}
|
|
56050
56148
|
const newWidgets = [...widgets];
|
|
56051
56149
|
newWidgets[selectedIndex] = { ...currentWidget2, rawValue: !currentWidget2.rawValue };
|
|
56052
56150
|
onUpdate(newWidgets);
|
|
@@ -56455,6 +56553,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
|
|
|
56455
56553
|
const isSelected = index === selectedIndex;
|
|
56456
56554
|
const widgetImpl = widget.type !== "separator" && widget.type !== "flex-separator" ? getWidget(widget.type) : null;
|
|
56457
56555
|
const { displayText, modifierText } = widgetImpl?.getEditorDisplay(widget) ?? { displayText: getWidgetDisplay(widget) };
|
|
56556
|
+
const supportsRawValue = widgetImpl?.supportsRawValue() ?? false;
|
|
56458
56557
|
return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
|
|
56459
56558
|
flexDirection: "row",
|
|
56460
56559
|
flexWrap: "nowrap",
|
|
@@ -56477,7 +56576,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
|
|
|
56477
56576
|
modifierText
|
|
56478
56577
|
]
|
|
56479
56578
|
}, undefined, true, undefined, this),
|
|
56480
|
-
widget.rawValue && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
56579
|
+
supportsRawValue && widget.rawValue && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
|
|
56481
56580
|
dimColor: true,
|
|
56482
56581
|
children: " (raw value)"
|
|
56483
56582
|
}, undefined, false, undefined, this),
|
|
@@ -58836,6 +58935,8 @@ var StatusJSONSchema = exports_external.looseObject({
|
|
|
58836
58935
|
|
|
58837
58936
|
// src/utils/jsonl.ts
|
|
58838
58937
|
import * as fs7 from "fs";
|
|
58938
|
+
import { createHash } from "node:crypto";
|
|
58939
|
+
import os7 from "node:os";
|
|
58839
58940
|
import path6 from "node:path";
|
|
58840
58941
|
|
|
58841
58942
|
// node_modules/tinyglobby/dist/index.mjs
|
|
@@ -59627,6 +59728,81 @@ import { promisify } from "util";
|
|
|
59627
59728
|
var readFile4 = promisify(fs7.readFile);
|
|
59628
59729
|
var readFileSync5 = fs7.readFileSync;
|
|
59629
59730
|
var statSync4 = fs7.statSync;
|
|
59731
|
+
var writeFileSync2 = fs7.writeFileSync;
|
|
59732
|
+
var mkdirSync3 = fs7.mkdirSync;
|
|
59733
|
+
var existsSync7 = fs7.existsSync;
|
|
59734
|
+
function normalizeConfigDir(configDir) {
|
|
59735
|
+
return path6.resolve(configDir);
|
|
59736
|
+
}
|
|
59737
|
+
function getBlockCachePath(configDir = getClaudeConfigDir()) {
|
|
59738
|
+
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
59739
|
+
const configHash = createHash("sha256").update(normalizedConfigDir).digest("hex").slice(0, 16);
|
|
59740
|
+
return path6.join(os7.homedir(), ".cache", "ccstatusline", `block-cache-${configHash}.json`);
|
|
59741
|
+
}
|
|
59742
|
+
function readBlockCache(expectedConfigDir) {
|
|
59743
|
+
try {
|
|
59744
|
+
const normalizedExpectedConfigDir = expectedConfigDir !== undefined ? normalizeConfigDir(expectedConfigDir) : undefined;
|
|
59745
|
+
const cachePath = getBlockCachePath(normalizedExpectedConfigDir);
|
|
59746
|
+
if (!existsSync7(cachePath)) {
|
|
59747
|
+
return null;
|
|
59748
|
+
}
|
|
59749
|
+
const content = readFileSync5(cachePath, "utf-8");
|
|
59750
|
+
const cache3 = JSON.parse(content);
|
|
59751
|
+
if (typeof cache3.startTime !== "string") {
|
|
59752
|
+
return null;
|
|
59753
|
+
}
|
|
59754
|
+
if (normalizedExpectedConfigDir !== undefined) {
|
|
59755
|
+
if (typeof cache3.configDir !== "string") {
|
|
59756
|
+
return null;
|
|
59757
|
+
}
|
|
59758
|
+
if (cache3.configDir !== normalizedExpectedConfigDir) {
|
|
59759
|
+
return null;
|
|
59760
|
+
}
|
|
59761
|
+
}
|
|
59762
|
+
const date5 = new Date(cache3.startTime);
|
|
59763
|
+
if (Number.isNaN(date5.getTime())) {
|
|
59764
|
+
return null;
|
|
59765
|
+
}
|
|
59766
|
+
return date5;
|
|
59767
|
+
} catch {
|
|
59768
|
+
return null;
|
|
59769
|
+
}
|
|
59770
|
+
}
|
|
59771
|
+
function writeBlockCache(startTime, configDir = getClaudeConfigDir()) {
|
|
59772
|
+
try {
|
|
59773
|
+
const normalizedConfigDir = normalizeConfigDir(configDir);
|
|
59774
|
+
const cachePath = getBlockCachePath(normalizedConfigDir);
|
|
59775
|
+
const cacheDir = path6.dirname(cachePath);
|
|
59776
|
+
if (!existsSync7(cacheDir)) {
|
|
59777
|
+
mkdirSync3(cacheDir, { recursive: true });
|
|
59778
|
+
}
|
|
59779
|
+
const cache3 = {
|
|
59780
|
+
startTime: startTime.toISOString(),
|
|
59781
|
+
configDir: normalizedConfigDir
|
|
59782
|
+
};
|
|
59783
|
+
writeFileSync2(cachePath, JSON.stringify(cache3), "utf-8");
|
|
59784
|
+
} catch {}
|
|
59785
|
+
}
|
|
59786
|
+
function getCachedBlockMetrics(sessionDurationHours = 5) {
|
|
59787
|
+
const sessionDurationMs = sessionDurationHours * 60 * 60 * 1000;
|
|
59788
|
+
const now = new Date;
|
|
59789
|
+
const activeConfigDir = getClaudeConfigDir();
|
|
59790
|
+
const cachedStartTime = readBlockCache(activeConfigDir);
|
|
59791
|
+
if (cachedStartTime) {
|
|
59792
|
+
const blockEndTime = new Date(cachedStartTime.getTime() + sessionDurationMs);
|
|
59793
|
+
if (now.getTime() <= blockEndTime.getTime()) {
|
|
59794
|
+
return {
|
|
59795
|
+
startTime: cachedStartTime,
|
|
59796
|
+
lastActivity: now
|
|
59797
|
+
};
|
|
59798
|
+
}
|
|
59799
|
+
}
|
|
59800
|
+
const metrics = getBlockMetrics();
|
|
59801
|
+
if (metrics) {
|
|
59802
|
+
writeBlockCache(metrics.startTime, activeConfigDir);
|
|
59803
|
+
}
|
|
59804
|
+
return metrics;
|
|
59805
|
+
}
|
|
59630
59806
|
async function getSessionDuration(transcriptPath) {
|
|
59631
59807
|
try {
|
|
59632
59808
|
if (!fs7.existsSync(transcriptPath)) {
|
|
@@ -59887,6 +60063,15 @@ async function readStdin() {
|
|
|
59887
60063
|
return null;
|
|
59888
60064
|
}
|
|
59889
60065
|
}
|
|
60066
|
+
async function ensureWindowsUtf8CodePage() {
|
|
60067
|
+
if (process.platform !== "win32") {
|
|
60068
|
+
return;
|
|
60069
|
+
}
|
|
60070
|
+
try {
|
|
60071
|
+
const { execFileSync } = await import("child_process");
|
|
60072
|
+
execFileSync("chcp.com", ["65001"], { stdio: "ignore" });
|
|
60073
|
+
} catch {}
|
|
60074
|
+
}
|
|
59890
60075
|
async function renderMultipleLines(data) {
|
|
59891
60076
|
const settings = await loadSettings();
|
|
59892
60077
|
source_default.level = settings.colorLevel;
|
|
@@ -59905,7 +60090,7 @@ async function renderMultipleLines(data) {
|
|
|
59905
60090
|
}
|
|
59906
60091
|
let blockMetrics = null;
|
|
59907
60092
|
if (hasBlockTimer) {
|
|
59908
|
-
blockMetrics =
|
|
60093
|
+
blockMetrics = getCachedBlockMetrics();
|
|
59909
60094
|
}
|
|
59910
60095
|
const context = {
|
|
59911
60096
|
data,
|
|
@@ -59953,6 +60138,7 @@ async function renderMultipleLines(data) {
|
|
|
59953
60138
|
}
|
|
59954
60139
|
async function main() {
|
|
59955
60140
|
if (!process.stdin.isTTY) {
|
|
60141
|
+
await ensureWindowsUtf8CodePage();
|
|
59956
60142
|
const input = await readStdin();
|
|
59957
60143
|
if (input && input.trim() !== "") {
|
|
59958
60144
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccstatusline",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.28",
|
|
4
4
|
"description": "A customizable status line formatter for Claude Code CLI",
|
|
5
5
|
"module": "src/ccstatusline.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -70,4 +70,4 @@
|
|
|
70
70
|
"patchedDependencies": {
|
|
71
71
|
"ink@6.2.0": "patches/ink@6.2.0.patch"
|
|
72
72
|
}
|
|
73
|
-
}
|
|
73
|
+
}
|