claude-scope 0.2.5 → 0.3.1
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/dist/claude-scope.cjs +324 -49
- package/package.json +2 -1
package/dist/claude-scope.cjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
9
|
var __export = (target, all) => {
|
|
8
10
|
for (var name in all)
|
|
@@ -16,6 +18,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
18
|
}
|
|
17
19
|
return to;
|
|
18
20
|
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
19
29
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
30
|
|
|
21
31
|
// src/index.ts
|
|
@@ -108,12 +118,6 @@ var COST_THRESHOLDS = {
|
|
|
108
118
|
/** Above this value, show no decimal places ($123) */
|
|
109
119
|
LARGE: 100
|
|
110
120
|
};
|
|
111
|
-
var CONTEXT_THRESHOLDS = {
|
|
112
|
-
/** Below this: green (low usage) */
|
|
113
|
-
LOW_MEDIUM: 50,
|
|
114
|
-
/** Below this: yellow (medium usage), above: red (high usage) */
|
|
115
|
-
MEDIUM_HIGH: 80
|
|
116
|
-
};
|
|
117
121
|
var DEFAULTS = {
|
|
118
122
|
/** Default separator between widgets */
|
|
119
123
|
SEPARATOR: " ",
|
|
@@ -143,34 +147,51 @@ var Renderer = class {
|
|
|
143
147
|
this.showErrors = options.showErrors ?? false;
|
|
144
148
|
}
|
|
145
149
|
/**
|
|
146
|
-
* Render widgets into
|
|
150
|
+
* Render widgets into multiple lines with error boundaries
|
|
147
151
|
*
|
|
148
|
-
* Widgets
|
|
149
|
-
*
|
|
152
|
+
* Widgets are grouped by their metadata.line property and rendered
|
|
153
|
+
* on separate lines. Widgets that throw errors are logged (via onError
|
|
154
|
+
* callback) and skipped, allowing other widgets to continue rendering.
|
|
150
155
|
*
|
|
151
156
|
* @param widgets - Array of widgets to render
|
|
152
157
|
* @param context - Render context with width and timestamp
|
|
153
|
-
* @returns
|
|
158
|
+
* @returns Array of rendered lines (one per line number)
|
|
154
159
|
*/
|
|
155
160
|
async render(widgets, context) {
|
|
156
|
-
const
|
|
161
|
+
const lineMap = /* @__PURE__ */ new Map();
|
|
157
162
|
for (const widget of widgets) {
|
|
158
163
|
if (!widget.isEnabled()) {
|
|
159
164
|
continue;
|
|
160
165
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
const line = widget.metadata.line ?? 0;
|
|
167
|
+
if (!lineMap.has(line)) {
|
|
168
|
+
lineMap.set(line, []);
|
|
169
|
+
}
|
|
170
|
+
lineMap.get(line).push(widget);
|
|
171
|
+
}
|
|
172
|
+
const lines = [];
|
|
173
|
+
const sortedLines = Array.from(lineMap.entries()).sort((a, b) => a[0] - b[0]);
|
|
174
|
+
for (const [, widgetsForLine] of sortedLines) {
|
|
175
|
+
const outputs = [];
|
|
176
|
+
for (const widget of widgetsForLine) {
|
|
177
|
+
try {
|
|
178
|
+
const output = await widget.render(context);
|
|
179
|
+
if (output !== null) {
|
|
180
|
+
outputs.push(output);
|
|
181
|
+
}
|
|
182
|
+
} catch (error) {
|
|
183
|
+
this.handleError(error, widget);
|
|
184
|
+
if (this.showErrors) {
|
|
185
|
+
outputs.push(`${widget.id}:<err>`);
|
|
186
|
+
}
|
|
170
187
|
}
|
|
171
188
|
}
|
|
189
|
+
const line = outputs.join(this.separator);
|
|
190
|
+
if (line) {
|
|
191
|
+
lines.push(line);
|
|
192
|
+
}
|
|
172
193
|
}
|
|
173
|
-
return
|
|
194
|
+
return lines;
|
|
174
195
|
}
|
|
175
196
|
/**
|
|
176
197
|
* Set custom separator
|
|
@@ -193,12 +214,13 @@ var Renderer = class {
|
|
|
193
214
|
};
|
|
194
215
|
|
|
195
216
|
// src/core/widget-types.ts
|
|
196
|
-
function createWidgetMetadata(name, description, version = "1.0.0", author = "claude-scope") {
|
|
217
|
+
function createWidgetMetadata(name, description, version = "1.0.0", author = "claude-scope", line = 0) {
|
|
197
218
|
return {
|
|
198
219
|
name,
|
|
199
220
|
description,
|
|
200
221
|
version,
|
|
201
|
-
author
|
|
222
|
+
author,
|
|
223
|
+
line
|
|
202
224
|
};
|
|
203
225
|
}
|
|
204
226
|
|
|
@@ -252,7 +274,11 @@ var GitWidget = class {
|
|
|
252
274
|
id = "git";
|
|
253
275
|
metadata = createWidgetMetadata(
|
|
254
276
|
"Git Widget",
|
|
255
|
-
"Displays current git branch"
|
|
277
|
+
"Displays current git branch",
|
|
278
|
+
"1.0.0",
|
|
279
|
+
"claude-scope",
|
|
280
|
+
0
|
|
281
|
+
// First line
|
|
256
282
|
);
|
|
257
283
|
gitFactory;
|
|
258
284
|
git = null;
|
|
@@ -360,7 +386,11 @@ var ModelWidget = class extends StdinDataWidget {
|
|
|
360
386
|
id = "model";
|
|
361
387
|
metadata = createWidgetMetadata(
|
|
362
388
|
"Model",
|
|
363
|
-
"Displays the current Claude model name"
|
|
389
|
+
"Displays the current Claude model name",
|
|
390
|
+
"1.0.0",
|
|
391
|
+
"claude-scope",
|
|
392
|
+
0
|
|
393
|
+
// First line
|
|
364
394
|
);
|
|
365
395
|
renderWithData(data, context) {
|
|
366
396
|
return data.model.display_name;
|
|
@@ -405,36 +435,61 @@ function progressBar(percent, width = DEFAULTS.PROGRESS_BAR_WIDTH) {
|
|
|
405
435
|
const empty = width - filled;
|
|
406
436
|
return "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
407
437
|
}
|
|
408
|
-
function getContextColor(percent) {
|
|
409
|
-
const clampedPercent = Math.max(0, Math.min(100, percent));
|
|
410
|
-
if (clampedPercent < CONTEXT_THRESHOLDS.LOW_MEDIUM) {
|
|
411
|
-
return ANSI_COLORS.GREEN;
|
|
412
|
-
} else if (clampedPercent < CONTEXT_THRESHOLDS.MEDIUM_HIGH) {
|
|
413
|
-
return ANSI_COLORS.YELLOW;
|
|
414
|
-
} else {
|
|
415
|
-
return ANSI_COLORS.RED;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
438
|
function colorize(text, color) {
|
|
419
439
|
return `${color}${text}${ANSI_COLORS.RESET}`;
|
|
420
440
|
}
|
|
421
441
|
|
|
442
|
+
// src/ui/utils/colors.ts
|
|
443
|
+
var gray = "\x1B[90m";
|
|
444
|
+
|
|
445
|
+
// src/ui/theme/default-theme.ts
|
|
446
|
+
var DEFAULT_THEME = {
|
|
447
|
+
context: {
|
|
448
|
+
low: gray,
|
|
449
|
+
medium: gray,
|
|
450
|
+
high: gray
|
|
451
|
+
},
|
|
452
|
+
lines: {
|
|
453
|
+
added: gray,
|
|
454
|
+
removed: gray
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
|
|
422
458
|
// src/widgets/context-widget.ts
|
|
423
459
|
var ContextWidget = class extends StdinDataWidget {
|
|
424
460
|
id = "context";
|
|
425
461
|
metadata = createWidgetMetadata(
|
|
426
462
|
"Context",
|
|
427
|
-
"Displays context window usage with progress bar"
|
|
463
|
+
"Displays context window usage with progress bar",
|
|
464
|
+
"1.0.0",
|
|
465
|
+
"claude-scope",
|
|
466
|
+
0
|
|
467
|
+
// First line
|
|
428
468
|
);
|
|
469
|
+
colors;
|
|
470
|
+
constructor(colors) {
|
|
471
|
+
super();
|
|
472
|
+
this.colors = colors ?? DEFAULT_THEME.context;
|
|
473
|
+
}
|
|
429
474
|
renderWithData(data, context) {
|
|
430
475
|
const { current_usage, context_window_size } = data.context_window;
|
|
431
476
|
if (!current_usage) return null;
|
|
432
477
|
const used = current_usage.input_tokens + current_usage.cache_creation_input_tokens + current_usage.cache_read_input_tokens + current_usage.output_tokens;
|
|
433
478
|
const percent = Math.round(used / context_window_size * 100);
|
|
434
479
|
const bar = progressBar(percent, DEFAULTS.PROGRESS_BAR_WIDTH);
|
|
435
|
-
const color = getContextColor(percent);
|
|
480
|
+
const color = this.getContextColor(percent);
|
|
436
481
|
return colorize(`[${bar}] ${percent}%`, color);
|
|
437
482
|
}
|
|
483
|
+
getContextColor(percent) {
|
|
484
|
+
const clampedPercent = Math.max(0, Math.min(100, percent));
|
|
485
|
+
if (clampedPercent < 50) {
|
|
486
|
+
return this.colors.low;
|
|
487
|
+
} else if (clampedPercent < 80) {
|
|
488
|
+
return this.colors.medium;
|
|
489
|
+
} else {
|
|
490
|
+
return this.colors.high;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
438
493
|
};
|
|
439
494
|
|
|
440
495
|
// src/widgets/cost-widget.ts
|
|
@@ -442,7 +497,11 @@ var CostWidget = class extends StdinDataWidget {
|
|
|
442
497
|
id = "cost";
|
|
443
498
|
metadata = createWidgetMetadata(
|
|
444
499
|
"Cost",
|
|
445
|
-
"Displays session cost in USD"
|
|
500
|
+
"Displays session cost in USD",
|
|
501
|
+
"1.0.0",
|
|
502
|
+
"claude-scope",
|
|
503
|
+
0
|
|
504
|
+
// First line
|
|
446
505
|
);
|
|
447
506
|
renderWithData(data, context) {
|
|
448
507
|
if (!data.cost || data.cost.total_cost_usd === void 0) return null;
|
|
@@ -455,13 +514,22 @@ var LinesWidget = class extends StdinDataWidget {
|
|
|
455
514
|
id = "lines";
|
|
456
515
|
metadata = createWidgetMetadata(
|
|
457
516
|
"Lines",
|
|
458
|
-
"Displays lines added/removed in session"
|
|
517
|
+
"Displays lines added/removed in session",
|
|
518
|
+
"1.0.0",
|
|
519
|
+
"claude-scope",
|
|
520
|
+
0
|
|
521
|
+
// First line
|
|
459
522
|
);
|
|
523
|
+
colors;
|
|
524
|
+
constructor(colors) {
|
|
525
|
+
super();
|
|
526
|
+
this.colors = colors ?? DEFAULT_THEME.lines;
|
|
527
|
+
}
|
|
460
528
|
renderWithData(data, context) {
|
|
461
529
|
const added = data.cost?.total_lines_added ?? 0;
|
|
462
530
|
const removed = data.cost?.total_lines_removed ?? 0;
|
|
463
|
-
const addedStr = colorize(`+${added}`,
|
|
464
|
-
const removedStr = colorize(`-${removed}`,
|
|
531
|
+
const addedStr = colorize(`+${added}`, this.colors.added);
|
|
532
|
+
const removedStr = colorize(`-${removed}`, this.colors.removed);
|
|
465
533
|
return `${addedStr}/${removedStr}`;
|
|
466
534
|
}
|
|
467
535
|
};
|
|
@@ -471,7 +539,11 @@ var DurationWidget = class extends StdinDataWidget {
|
|
|
471
539
|
id = "duration";
|
|
472
540
|
metadata = createWidgetMetadata(
|
|
473
541
|
"Duration",
|
|
474
|
-
"Displays elapsed session time"
|
|
542
|
+
"Displays elapsed session time",
|
|
543
|
+
"1.0.0",
|
|
544
|
+
"claude-scope",
|
|
545
|
+
0
|
|
546
|
+
// First line
|
|
475
547
|
);
|
|
476
548
|
renderWithData(data, context) {
|
|
477
549
|
if (!data.cost || data.cost.total_duration_ms === void 0) return null;
|
|
@@ -484,7 +556,11 @@ var GitChangesWidget = class {
|
|
|
484
556
|
id = "git-changes";
|
|
485
557
|
metadata = createWidgetMetadata(
|
|
486
558
|
"Git Changes",
|
|
487
|
-
"Displays git diff statistics"
|
|
559
|
+
"Displays git diff statistics",
|
|
560
|
+
"1.0.0",
|
|
561
|
+
"claude-scope",
|
|
562
|
+
0
|
|
563
|
+
// First line
|
|
488
564
|
);
|
|
489
565
|
gitFactory;
|
|
490
566
|
git = null;
|
|
@@ -549,16 +625,214 @@ var GitChangesWidget = class {
|
|
|
549
625
|
}
|
|
550
626
|
};
|
|
551
627
|
|
|
628
|
+
// src/providers/config-provider.ts
|
|
629
|
+
var fs = __toESM(require("fs/promises"), 1);
|
|
630
|
+
var path = __toESM(require("path"), 1);
|
|
631
|
+
var os = __toESM(require("os"), 1);
|
|
632
|
+
var ConfigProvider = class {
|
|
633
|
+
cachedCounts;
|
|
634
|
+
lastScan = 0;
|
|
635
|
+
cacheInterval = 5e3;
|
|
636
|
+
// 5 seconds
|
|
637
|
+
/**
|
|
638
|
+
* Get config counts with hybrid caching
|
|
639
|
+
* Scans filesystem if cache is stale (>5 seconds)
|
|
640
|
+
*/
|
|
641
|
+
async getConfigs(options = {}) {
|
|
642
|
+
const now = Date.now();
|
|
643
|
+
if (this.cachedCounts && now - this.lastScan < this.cacheInterval) {
|
|
644
|
+
return this.cachedCounts;
|
|
645
|
+
}
|
|
646
|
+
this.cachedCounts = await this.scanConfigs(options);
|
|
647
|
+
this.lastScan = now;
|
|
648
|
+
return this.cachedCounts;
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Scan filesystem for Claude Code configurations
|
|
652
|
+
*/
|
|
653
|
+
async scanConfigs(options) {
|
|
654
|
+
let claudeMdCount = 0;
|
|
655
|
+
let rulesCount = 0;
|
|
656
|
+
let mcpCount = 0;
|
|
657
|
+
let hooksCount = 0;
|
|
658
|
+
const homeDir = os.homedir();
|
|
659
|
+
const claudeDir = path.join(homeDir, ".claude");
|
|
660
|
+
const cwd = options.cwd;
|
|
661
|
+
if (await this.fileExists(path.join(claudeDir, "CLAUDE.md"))) {
|
|
662
|
+
claudeMdCount++;
|
|
663
|
+
}
|
|
664
|
+
rulesCount += await this.countRulesInDir(path.join(claudeDir, "rules"));
|
|
665
|
+
const userSettings = path.join(claudeDir, "settings.json");
|
|
666
|
+
const userSettingsData = await this.readJsonFile(userSettings);
|
|
667
|
+
if (userSettingsData) {
|
|
668
|
+
mcpCount += this.countMcpServers(userSettingsData);
|
|
669
|
+
hooksCount += this.countHooks(userSettingsData);
|
|
670
|
+
}
|
|
671
|
+
const userClaudeJson = path.join(homeDir, ".claude.json");
|
|
672
|
+
const userClaudeData = await this.readJsonFile(userClaudeJson);
|
|
673
|
+
if (userClaudeData) {
|
|
674
|
+
const userMcpCount = this.countMcpServers(userClaudeData);
|
|
675
|
+
mcpCount += Math.max(0, userMcpCount - this.countMcpServers(userSettingsData || {}));
|
|
676
|
+
}
|
|
677
|
+
if (cwd) {
|
|
678
|
+
if (await this.fileExists(path.join(cwd, "CLAUDE.md"))) {
|
|
679
|
+
claudeMdCount++;
|
|
680
|
+
}
|
|
681
|
+
if (await this.fileExists(path.join(cwd, "CLAUDE.local.md"))) {
|
|
682
|
+
claudeMdCount++;
|
|
683
|
+
}
|
|
684
|
+
if (await this.fileExists(path.join(cwd, ".claude", "CLAUDE.md"))) {
|
|
685
|
+
claudeMdCount++;
|
|
686
|
+
}
|
|
687
|
+
if (await this.fileExists(path.join(cwd, ".claude", "CLAUDE.local.md"))) {
|
|
688
|
+
claudeMdCount++;
|
|
689
|
+
}
|
|
690
|
+
rulesCount += await this.countRulesInDir(path.join(cwd, ".claude", "rules"));
|
|
691
|
+
const mcpJson = path.join(cwd, ".mcp.json");
|
|
692
|
+
const mcpData = await this.readJsonFile(mcpJson);
|
|
693
|
+
if (mcpData) {
|
|
694
|
+
mcpCount += this.countMcpServers(mcpData);
|
|
695
|
+
}
|
|
696
|
+
const projectSettings = path.join(cwd, ".claude", "settings.json");
|
|
697
|
+
const projectSettingsData = await this.readJsonFile(projectSettings);
|
|
698
|
+
if (projectSettingsData) {
|
|
699
|
+
mcpCount += this.countMcpServers(projectSettingsData);
|
|
700
|
+
hooksCount += this.countHooks(projectSettingsData);
|
|
701
|
+
}
|
|
702
|
+
const localSettings = path.join(cwd, ".claude", "settings.local.json");
|
|
703
|
+
const localSettingsData = await this.readJsonFile(localSettings);
|
|
704
|
+
if (localSettingsData) {
|
|
705
|
+
mcpCount += this.countMcpServers(localSettingsData);
|
|
706
|
+
hooksCount += this.countHooks(localSettingsData);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
return { claudeMdCount, rulesCount, mcpCount, hooksCount };
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Check if file exists
|
|
713
|
+
*/
|
|
714
|
+
async fileExists(filePath) {
|
|
715
|
+
try {
|
|
716
|
+
await fs.access(filePath);
|
|
717
|
+
return true;
|
|
718
|
+
} catch {
|
|
719
|
+
return false;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Read and parse JSON file
|
|
724
|
+
*/
|
|
725
|
+
async readJsonFile(filePath) {
|
|
726
|
+
try {
|
|
727
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
728
|
+
return JSON.parse(content);
|
|
729
|
+
} catch {
|
|
730
|
+
return null;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Count MCP servers in config object
|
|
735
|
+
*/
|
|
736
|
+
countMcpServers(config) {
|
|
737
|
+
if (!config || !config.mcpServers || typeof config.mcpServers !== "object") {
|
|
738
|
+
return 0;
|
|
739
|
+
}
|
|
740
|
+
return Object.keys(config.mcpServers).length;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Count hooks in config object
|
|
744
|
+
*/
|
|
745
|
+
countHooks(config) {
|
|
746
|
+
if (!config || !config.hooks || typeof config.hooks !== "object") {
|
|
747
|
+
return 0;
|
|
748
|
+
}
|
|
749
|
+
return Object.keys(config.hooks).length;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Recursively count .md files in directory
|
|
753
|
+
*/
|
|
754
|
+
async countRulesInDir(rulesDir) {
|
|
755
|
+
const exists = await this.fileExists(rulesDir);
|
|
756
|
+
if (!exists) return 0;
|
|
757
|
+
try {
|
|
758
|
+
let count = 0;
|
|
759
|
+
const entries = await fs.readdir(rulesDir, { withFileTypes: true });
|
|
760
|
+
for (const entry of entries) {
|
|
761
|
+
const fullPath = path.join(rulesDir, entry.name);
|
|
762
|
+
if (entry.isDirectory()) {
|
|
763
|
+
count += await this.countRulesInDir(fullPath);
|
|
764
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
765
|
+
count++;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
return count;
|
|
769
|
+
} catch {
|
|
770
|
+
return 0;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
// src/widgets/config-count-widget.ts
|
|
776
|
+
var ConfigCountWidget = class {
|
|
777
|
+
id = "config-count";
|
|
778
|
+
metadata = createWidgetMetadata(
|
|
779
|
+
"Config Count",
|
|
780
|
+
"Displays Claude Code configuration counts",
|
|
781
|
+
"1.0.0",
|
|
782
|
+
"claude-scope",
|
|
783
|
+
1
|
|
784
|
+
// Second line
|
|
785
|
+
);
|
|
786
|
+
configProvider = new ConfigProvider();
|
|
787
|
+
configs;
|
|
788
|
+
cwd;
|
|
789
|
+
async initialize() {
|
|
790
|
+
}
|
|
791
|
+
async update(data) {
|
|
792
|
+
this.cwd = data.cwd;
|
|
793
|
+
this.configs = await this.configProvider.getConfigs({ cwd: data.cwd });
|
|
794
|
+
}
|
|
795
|
+
isEnabled() {
|
|
796
|
+
if (!this.configs) {
|
|
797
|
+
return false;
|
|
798
|
+
}
|
|
799
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = this.configs;
|
|
800
|
+
return claudeMdCount > 0 || rulesCount > 0 || mcpCount > 0 || hooksCount > 0;
|
|
801
|
+
}
|
|
802
|
+
async render(context) {
|
|
803
|
+
if (!this.configs) {
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
const { claudeMdCount, rulesCount, mcpCount, hooksCount } = this.configs;
|
|
807
|
+
const parts = [];
|
|
808
|
+
if (claudeMdCount > 0) {
|
|
809
|
+
parts.push(`\u{1F4C4} ${claudeMdCount} CLAUDE.md`);
|
|
810
|
+
}
|
|
811
|
+
if (rulesCount > 0) {
|
|
812
|
+
parts.push(`\u{1F4DC} ${rulesCount} rules`);
|
|
813
|
+
}
|
|
814
|
+
if (mcpCount > 0) {
|
|
815
|
+
parts.push(`\u{1F50C} ${mcpCount} MCPs`);
|
|
816
|
+
}
|
|
817
|
+
if (hooksCount > 0) {
|
|
818
|
+
parts.push(`\u{1FA9D} ${hooksCount} hooks`);
|
|
819
|
+
}
|
|
820
|
+
return parts.join(" \u2502 ") || null;
|
|
821
|
+
}
|
|
822
|
+
async cleanup() {
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
|
|
552
826
|
// src/validation/result.ts
|
|
553
827
|
function success(data) {
|
|
554
828
|
return { success: true, data };
|
|
555
829
|
}
|
|
556
|
-
function failure(
|
|
557
|
-
return { success: false, error: { path, message, value } };
|
|
830
|
+
function failure(path2, message, value) {
|
|
831
|
+
return { success: false, error: { path: path2, message, value } };
|
|
558
832
|
}
|
|
559
833
|
function formatError(error) {
|
|
560
|
-
const
|
|
561
|
-
return `${
|
|
834
|
+
const path2 = error.path.length > 0 ? error.path.join(".") : "root";
|
|
835
|
+
return `${path2}: ${error.message}`;
|
|
562
836
|
}
|
|
563
837
|
|
|
564
838
|
// src/validation/validators.ts
|
|
@@ -751,6 +1025,7 @@ async function main() {
|
|
|
751
1025
|
await registry.register(new DurationWidget());
|
|
752
1026
|
await registry.register(new GitWidget());
|
|
753
1027
|
await registry.register(new GitChangesWidget());
|
|
1028
|
+
await registry.register(new ConfigCountWidget());
|
|
754
1029
|
const renderer = new Renderer({
|
|
755
1030
|
separator: " \u2502 ",
|
|
756
1031
|
onError: (error, widget) => {
|
|
@@ -760,11 +1035,11 @@ async function main() {
|
|
|
760
1035
|
for (const widget of registry.getAll()) {
|
|
761
1036
|
await widget.update(stdinData);
|
|
762
1037
|
}
|
|
763
|
-
const
|
|
1038
|
+
const lines = await renderer.render(
|
|
764
1039
|
registry.getEnabledWidgets(),
|
|
765
1040
|
{ width: 80, timestamp: Date.now() }
|
|
766
1041
|
);
|
|
767
|
-
return
|
|
1042
|
+
return lines.join("\n");
|
|
768
1043
|
} catch (error) {
|
|
769
1044
|
const fallback = await tryGitFallback();
|
|
770
1045
|
return fallback;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-scope",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Claude Code plugin for session status and analytics",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"c8": "^10.1.3",
|
|
33
33
|
"chai": "^6.2.2",
|
|
34
34
|
"esbuild": "^0.24.2",
|
|
35
|
+
"rimraf": "^6.1.2",
|
|
35
36
|
"tsx": "^4.19.2",
|
|
36
37
|
"typescript": "^5.7.2"
|
|
37
38
|
},
|