ccus-cli 0.1.2 → 0.1.3
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 +2 -1
- package/dist/cli.js +6 -3
- package/dist/lib/aggregate-dashboard.js +50 -25
- package/dist/lib/git.js +23 -4
- package/dist/lib/payload.js +11 -4
- package/dist/lib/time.js +23 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ npm install -g ccus-cli
|
|
|
31
31
|
ccus install
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
然后照常使用 Claude Code,statusline 会显示 5 小时额度使用率(`5h`)、7 天额度使用率(`7d
|
|
34
|
+
然后照常使用 Claude Code,statusline 会显示 5 小时额度使用率(`5h`)、7 天额度使用率(`7d`)、context window 占用百分比(`ctx`)、模型名、工作区名,以及当前 git 分支(`⎇ <branch>`,实时读取,非 git 仓库或处于 detached HEAD 时省略该段);原始 payload 也会落到本地日志,供后续 dashboard / export 使用。
|
|
35
35
|
|
|
36
36
|
攒了一段时间数据后,最常用的几条命令:
|
|
37
37
|
|
|
@@ -107,6 +107,7 @@ ccus aggregate serve --input-dir ./team-exports
|
|
|
107
107
|
## 导出
|
|
108
108
|
|
|
109
109
|
- 默认导出 `this-week`;如需导出上一个完整周(周一到周日),用 `--range last-week`,或位置参数简写 `ccus export lw`(`tw` = 本周)
|
|
110
|
+
- 周度导出固定覆盖**完整一周(周一到周日)**:`this-week` 即使本周还没过完、后面几天还没有任何数据,文件名的起止日期也会补齐到本周日,`dailySummaries` 同样按整周 7 天逐日输出
|
|
110
111
|
- 默认输出一个 `json` 数据包,里面同时包含 `rawEvents`、`weeklySummary`、`dailySummaries`
|
|
111
112
|
- 当前导出 bundle / weeklySummary 的 `schemaVersion` 为 `6`,用于标识已使用 `fiveHourLatestUsagePct`、`fiveHourPeakUsagePct`、`sevenDayLatestUsagePct`、`sevenDayPeakUsagePct` 字段的新导出契约
|
|
112
113
|
- 默认文件名会带 git email 的帐号名前缀和起止日期,例如:`alice_export_2026-05-26_to_2026-06-01.json`
|
package/dist/cli.js
CHANGED
|
@@ -152,7 +152,8 @@ async function handleStatuslineEmit(options) {
|
|
|
152
152
|
(0, debug_1.debugLog)("statusline", "payload received", { length: raw.length });
|
|
153
153
|
const payload = (0, payload_1.parseStatuslinePayload)(raw);
|
|
154
154
|
const record = (0, payload_1.createPersistedStatuslineEvent)(payload);
|
|
155
|
-
const
|
|
155
|
+
const workspaceDir = (0, payload_1.extractWorkspaceDir)(payload);
|
|
156
|
+
const [gitIdentity, gitBranch] = await Promise.all([(0, git_1.readGitIdentity)(), (0, git_1.readGitBranch)(workspaceDir)]);
|
|
156
157
|
record.gitUserName = gitIdentity.userName;
|
|
157
158
|
record.gitUserEmail = gitIdentity.userEmail;
|
|
158
159
|
record.gitUserAccount = (0, time_1.extractGitEmailAccount)(gitIdentity.userEmail);
|
|
@@ -162,7 +163,7 @@ async function handleStatuslineEmit(options) {
|
|
|
162
163
|
else {
|
|
163
164
|
await (0, storage_1.appendEvent)(dataDir, record);
|
|
164
165
|
}
|
|
165
|
-
const event = (0, payload_1.computeStatuslineEvent)(record);
|
|
166
|
+
const event = (0, payload_1.computeStatuslineEvent)(record, { gitBranch });
|
|
166
167
|
(0, debug_1.debugLog)("statusline", "event computed", {
|
|
167
168
|
sessionId: event.sessionId,
|
|
168
169
|
usagePct: event.usagePct,
|
|
@@ -171,6 +172,7 @@ async function handleStatuslineEmit(options) {
|
|
|
171
172
|
modelName: event.modelName,
|
|
172
173
|
workspaceName: event.workspaceName,
|
|
173
174
|
gitUserAccount: event.gitUserAccount,
|
|
175
|
+
gitBranch,
|
|
174
176
|
});
|
|
175
177
|
process.stdout.write(`${event.statusLine}\n`);
|
|
176
178
|
}
|
|
@@ -280,7 +282,8 @@ async function handleExport(options) {
|
|
|
280
282
|
throw new Error("--format has been removed. Export now always writes a weekly bundle json.");
|
|
281
283
|
}
|
|
282
284
|
const now = new Date();
|
|
283
|
-
|
|
285
|
+
// 周度导出固定覆盖完整一周:this-week 即使本周还没过完,文件名与 dailySummaries 也补齐到周日。
|
|
286
|
+
const window = (0, time_1.expandToFullWeekWindow)((0, time_1.resolveRange)(range, now));
|
|
284
287
|
(0, debug_1.debugLog)("export", "range resolved", { range, label: window.label, start: window.start.toISOString(), end: window.end.toISOString() });
|
|
285
288
|
const records = await (0, storage_1.readEventsForRange)(dataDir, range, now);
|
|
286
289
|
const events = records.map((record) => (0, payload_1.computeStatuslineEvent)(record));
|
|
@@ -6,6 +6,13 @@ exports.buildAggregateDashboardHtml = buildAggregateDashboardHtml;
|
|
|
6
6
|
const time_1 = require("./time");
|
|
7
7
|
/** 折线 / 图例统一的调色板,保证同一个人在不同图表里颜色一致。 */
|
|
8
8
|
const CHART_PALETTE = ["#5eead4", "#f59e0b", "#a855f7", "#22c55e", "#f87171", "#60a5fa", "#fbbf24", "#34d399"];
|
|
9
|
+
/**
|
|
10
|
+
* 7d 虚线专用的配套色板,和 CHART_PALETTE 同序号但色相强反差。
|
|
11
|
+
*
|
|
12
|
+
* 5h / 7d 同图叠加时,5h 用 CHART_PALETTE 实线、7d 用这套对比色虚线,
|
|
13
|
+
* 避免两条线颜色太接近看不清;人物对应关系靠图例里的双色点维持。
|
|
14
|
+
*/
|
|
15
|
+
const SEVEN_DAY_PALETTE = ["#fb7185", "#38bdf8", "#facc15", "#e879f9", "#4ade80", "#fb923c", "#818cf8", "#f472b6"];
|
|
9
16
|
/** 所有插入到 HTML 的文本字段都要先转义,避免本地页面被注入。 */
|
|
10
17
|
function escapeHtml(value) {
|
|
11
18
|
return value
|
|
@@ -270,33 +277,39 @@ function formatTickTime(t) {
|
|
|
270
277
|
return `${mm}-${dd} ${hh}:${mi}`;
|
|
271
278
|
}
|
|
272
279
|
/**
|
|
273
|
-
* 用事件级 detail 行画出 5h
|
|
280
|
+
* 用事件级 detail 行画出 5h 额度与 7d 周额度使用率的详细曲线。
|
|
274
281
|
*
|
|
275
282
|
* 与按天聚合的图不同,这里直接用每条 statusline 采样的真实时间戳,粒度最细,
|
|
276
|
-
* 能看出每个人 5
|
|
283
|
+
* 能看出每个人 5 小时额度在一天里的爬升与重置节奏,同时叠加 7 天周额度的走势。
|
|
284
|
+
* X 轴是连续时间,Y 轴是百分比;同一个人 5h 用实线、7d 用虚线,共用颜色和 Y 轴。
|
|
277
285
|
*/
|
|
278
286
|
function renderFiveHourUsageChart(people, detailRows) {
|
|
279
287
|
const series = people
|
|
280
|
-
.map((person, index) =>
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
.filter((row) => row.personKey === person.personKey && row.usagePct !== null)
|
|
285
|
-
.map((row) => ({ t: new Date(row.timestamp).getTime(), v: row.usagePct }))
|
|
288
|
+
.map((person, index) => {
|
|
289
|
+
const personRows = detailRows
|
|
290
|
+
.filter((row) => row.personKey === person.personKey)
|
|
291
|
+
.map((row) => ({ t: new Date(row.timestamp).getTime(), five: row.usagePct, seven: row.sevenDayUsagePct }))
|
|
286
292
|
.filter((point) => Number.isFinite(point.t))
|
|
287
|
-
.sort((left, right) => left.t - right.t)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
293
|
+
.sort((left, right) => left.t - right.t);
|
|
294
|
+
const fivePoints = personRows
|
|
295
|
+
.filter((point) => point.five !== null)
|
|
296
|
+
.map((point) => ({ t: point.t, v: point.five }));
|
|
297
|
+
const sevenPoints = personRows
|
|
298
|
+
.filter((point) => point.seven !== null)
|
|
299
|
+
.map((point) => ({ t: point.t, v: point.seven }));
|
|
300
|
+
return { person, index, fivePoints, sevenPoints };
|
|
301
|
+
})
|
|
302
|
+
.filter((entry) => entry.fivePoints.length > 0 || entry.sevenPoints.length > 0);
|
|
303
|
+
const allPoints = series.flatMap((entry) => [...entry.fivePoints, ...entry.sevenPoints]);
|
|
291
304
|
if (allPoints.length === 0) {
|
|
292
305
|
return `
|
|
293
306
|
<section class="panel chart-panel">
|
|
294
307
|
<div class="panel-header">
|
|
295
308
|
<div>
|
|
296
|
-
<p class="eyebrow">
|
|
297
|
-
<h2>5h 使用率详细曲线</h2>
|
|
309
|
+
<p class="eyebrow">Usage Detail</p>
|
|
310
|
+
<h2>5h / 7d 使用率详细曲线</h2>
|
|
298
311
|
</div>
|
|
299
|
-
<p class="muted"
|
|
312
|
+
<p class="muted">还没有带使用率的 statusline 采样。</p>
|
|
300
313
|
</div>
|
|
301
314
|
</section>
|
|
302
315
|
`;
|
|
@@ -327,32 +340,42 @@ function renderFiveHourUsageChart(people, detailRows) {
|
|
|
327
340
|
return `<g><line x1="${x}" x2="${x}" y1="${height - paddingY}" y2="${height - paddingY + 6}" class="chart-axis-line" /><text x="${x}" y="${height - 4}" text-anchor="middle" class="chart-axis">${escapeHtml(formatTickTime(t))}</text></g>`;
|
|
328
341
|
})
|
|
329
342
|
.join("");
|
|
343
|
+
const pathFor = (points) => points.map((point, pointIndex) => `${pointIndex === 0 ? "M" : "L"}${xFor(point.t).toFixed(2)} ${yFor(point.v).toFixed(2)}`).join(" ");
|
|
330
344
|
const seriesPaths = series
|
|
331
345
|
.map((entry) => {
|
|
332
346
|
const color = CHART_PALETTE[entry.index % CHART_PALETTE.length];
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
.
|
|
336
|
-
|
|
347
|
+
const sevenColor = SEVEN_DAY_PALETTE[entry.index % SEVEN_DAY_PALETTE.length];
|
|
348
|
+
const fivePath = entry.fivePoints.length > 0
|
|
349
|
+
? `<path d="${pathFor(entry.fivePoints)}" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title>${escapeHtml(entry.person.personKey)} · 5h</title></path>`
|
|
350
|
+
: "";
|
|
351
|
+
const sevenPath = entry.sevenPoints.length > 0
|
|
352
|
+
? `<path d="${pathFor(entry.sevenPoints)}" fill="none" stroke="${sevenColor}" stroke-width="2" stroke-dasharray="5 4" stroke-linecap="round" stroke-linejoin="round"><title>${escapeHtml(entry.person.personKey)} · 7d</title></path>`
|
|
353
|
+
: "";
|
|
354
|
+
return `<g>${fivePath}${sevenPath}</g>`;
|
|
337
355
|
})
|
|
338
356
|
.join("");
|
|
339
357
|
const legend = series
|
|
340
358
|
.map((entry) => {
|
|
341
359
|
const color = CHART_PALETTE[entry.index % CHART_PALETTE.length];
|
|
342
|
-
|
|
360
|
+
const sevenColor = SEVEN_DAY_PALETTE[entry.index % SEVEN_DAY_PALETTE.length];
|
|
361
|
+
return `<span class="legend-chip"><span class="legend-dot" style="background:${color}"></span><span class="legend-dot" style="background:${sevenColor}"></span>${escapeHtml(entry.person.personKey)}</span>`;
|
|
343
362
|
})
|
|
344
363
|
.join("");
|
|
345
364
|
return `
|
|
346
365
|
<section class="panel chart-panel">
|
|
347
366
|
<div class="panel-header">
|
|
348
367
|
<div>
|
|
349
|
-
<p class="eyebrow">
|
|
350
|
-
<h2>5h 使用率详细曲线</h2>
|
|
368
|
+
<p class="eyebrow">Usage Detail</p>
|
|
369
|
+
<h2>5h / 7d 使用率详细曲线</h2>
|
|
351
370
|
</div>
|
|
352
|
-
<p class="muted">每条 statusline 采样的 5
|
|
371
|
+
<p class="muted">每条 statusline 采样的 5 小时额度(实线)与 7 天周额度(对比色虚线)使用率,按真实时间戳绘制、共用 Y 轴。</p>
|
|
353
372
|
</div>
|
|
354
|
-
<div class="legend"
|
|
355
|
-
|
|
373
|
+
<div class="legend">
|
|
374
|
+
${legend}
|
|
375
|
+
<span class="legend-chip"><span class="legend-line legend-line-solid"></span>5h 使用率(实线)</span>
|
|
376
|
+
<span class="legend-chip"><span class="legend-line legend-line-dashed"></span>7d 周使用量(对比色虚线)</span>
|
|
377
|
+
</div>
|
|
378
|
+
<svg viewBox="0 0 ${width} ${height}" class="chart" role="img" aria-label="5h / 7d 使用率详细曲线">
|
|
356
379
|
${ticks}
|
|
357
380
|
${xLabels}
|
|
358
381
|
${seriesPaths}
|
|
@@ -656,6 +679,8 @@ function buildAggregateDashboardHtml(detailRows, dailyRows, weeklyRows, generate
|
|
|
656
679
|
}
|
|
657
680
|
.legend-chip { display: inline-flex; align-items: center; gap: 8px; }
|
|
658
681
|
.legend-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; }
|
|
682
|
+
.legend-line { display: inline-block; width: 22px; height: 0; border-top-width: 2px; border-top-style: solid; border-top-color: var(--muted); }
|
|
683
|
+
.legend-line-dashed { border-top-style: dashed; }
|
|
659
684
|
.table-panel { margin-top: 22px; }
|
|
660
685
|
.table-wrap { overflow: auto; padding: 16px 20px 22px; }
|
|
661
686
|
table { width: 100%; border-collapse: collapse; min-width: 760px; }
|
package/dist/lib/git.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readGitBranch = readGitBranch;
|
|
3
4
|
exports.readGitIdentity = readGitIdentity;
|
|
4
5
|
const node_child_process_1 = require("node:child_process");
|
|
5
6
|
const node_util_1 = require("node:util");
|
|
@@ -9,8 +10,8 @@ function normalizeGitValue(value) {
|
|
|
9
10
|
const trimmed = value.replaceAll(/[\r\n\0]+/g, " ").trim();
|
|
10
11
|
return trimmed.length > 0 ? trimmed : null;
|
|
11
12
|
}
|
|
12
|
-
/**
|
|
13
|
-
async function
|
|
13
|
+
/** 跑一次 git 命令并归一化其 stdout,失败一律返回 null。 */
|
|
14
|
+
async function runGitCommand(args) {
|
|
14
15
|
try {
|
|
15
16
|
const { stdout } = await execFileAsync("git", args, {
|
|
16
17
|
windowsHide: true,
|
|
@@ -21,6 +22,24 @@ async function readGitConfigValue(args) {
|
|
|
21
22
|
return null;
|
|
22
23
|
}
|
|
23
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* 读取指定工作目录当前所在的 git 分支名。
|
|
27
|
+
*
|
|
28
|
+
* 仅用于 statusline 实时展示,不落盘、不进导出契约。
|
|
29
|
+
* detached HEAD 等无分支场景下 `rev-parse` 会返回 `HEAD`,这里归一化为 null,避免误导。
|
|
30
|
+
* 读取失败(非 git 仓库、git 不存在等)一律降级为 null。
|
|
31
|
+
*/
|
|
32
|
+
async function readGitBranch(cwd) {
|
|
33
|
+
const args = ["rev-parse", "--abbrev-ref", "HEAD"];
|
|
34
|
+
if (cwd) {
|
|
35
|
+
args.unshift("-C", cwd);
|
|
36
|
+
}
|
|
37
|
+
const branch = await runGitCommand(args);
|
|
38
|
+
if (branch === null || branch === "HEAD") {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return branch;
|
|
42
|
+
}
|
|
24
43
|
/**
|
|
25
44
|
* 读取全局 Git 用户名和邮箱。
|
|
26
45
|
*
|
|
@@ -28,8 +47,8 @@ async function readGitConfigValue(args) {
|
|
|
28
47
|
*/
|
|
29
48
|
async function readGitIdentity() {
|
|
30
49
|
const [globalUserName, globalUserEmail] = await Promise.all([
|
|
31
|
-
|
|
32
|
-
|
|
50
|
+
runGitCommand(["config", "--global", "--get", "user.name"]),
|
|
51
|
+
runGitCommand(["config", "--global", "--get", "user.email"]),
|
|
33
52
|
]);
|
|
34
53
|
return {
|
|
35
54
|
userName: globalUserName,
|
package/dist/lib/payload.js
CHANGED
|
@@ -151,14 +151,21 @@ function parseStatuslinePayload(input) {
|
|
|
151
151
|
*
|
|
152
152
|
* 这里必须保持单行、紧凑,避免污染 statusline 展示区域。
|
|
153
153
|
*/
|
|
154
|
-
function formatStatusLine(event) {
|
|
154
|
+
function formatStatusLine(event, gitBranch = null) {
|
|
155
155
|
const timeLabel = (0, time_1.formatClock)(new Date(event.timestamp));
|
|
156
156
|
const usageLabel = event.usagePct === null ? "5h --" : `5h ${event.usagePct.toFixed(1)}%`;
|
|
157
157
|
const sevenDayLabel = event.sevenDayUsagePct === null ? "7d --" : `7d ${event.sevenDayUsagePct.toFixed(1)}%`;
|
|
158
158
|
const contextLabel = event.contextWindowPct === null ? "ctx --" : `ctx ${event.contextWindowPct.toFixed(1)}%`;
|
|
159
159
|
const modelLabel = event.modelName ?? "model --";
|
|
160
160
|
const workspaceLabel = event.workspaceName ?? "workspace --";
|
|
161
|
-
|
|
161
|
+
const segments = [usageLabel, sevenDayLabel, contextLabel, modelLabel, workspaceLabel];
|
|
162
|
+
// 分支名是 statusline 实时读取的展示信息,仅在拿得到时追加一段;
|
|
163
|
+
// 历史日志重算时通常没有分支,省略该段比硬塞 "branch --" 更干净。
|
|
164
|
+
if (gitBranch) {
|
|
165
|
+
segments.push(`⎇ ${gitBranch}`);
|
|
166
|
+
}
|
|
167
|
+
segments.push(timeLabel);
|
|
168
|
+
return segments.join(" | ");
|
|
162
169
|
}
|
|
163
170
|
/**
|
|
164
171
|
* 基于原始 payload 创建一条最小持久化事件。
|
|
@@ -180,7 +187,7 @@ function createPersistedStatuslineEvent(payload, now = new Date()) {
|
|
|
180
187
|
*
|
|
181
188
|
* 对旧日志会优先使用 rawPayload 重新推导;若个别旧字段缺失,再回退到历史持久化字段。
|
|
182
189
|
*/
|
|
183
|
-
function computeStatuslineEvent(record) {
|
|
190
|
+
function computeStatuslineEvent(record, options = {}) {
|
|
184
191
|
const legacy = record;
|
|
185
192
|
const payload = record.rawPayload ?? {};
|
|
186
193
|
const sessionId = readSessionId(payload) ?? legacy.sessionId ?? null;
|
|
@@ -213,7 +220,7 @@ function computeStatuslineEvent(record) {
|
|
|
213
220
|
};
|
|
214
221
|
return {
|
|
215
222
|
...baseEvent,
|
|
216
|
-
statusLine: legacy.statusLine ?? formatStatusLine(baseEvent),
|
|
223
|
+
statusLine: legacy.statusLine ?? formatStatusLine(baseEvent, options.gitBranch ?? null),
|
|
217
224
|
};
|
|
218
225
|
}
|
|
219
226
|
//# sourceMappingURL=payload.js.map
|
package/dist/lib/time.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveRange = resolveRange;
|
|
4
|
+
exports.expandToFullWeekWindow = expandToFullWeekWindow;
|
|
4
5
|
exports.localDateKey = localDateKey;
|
|
5
6
|
exports.formatRangeFileLabel = formatRangeFileLabel;
|
|
6
7
|
exports.extractGitEmailAccount = extractGitEmailAccount;
|
|
@@ -27,6 +28,15 @@ function startOfLocalWeek(date) {
|
|
|
27
28
|
start.setDate(date.getDate() + diff);
|
|
28
29
|
return startOfLocalDay(start);
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* 以周日 23:59:59.999 作为一周结束(周一为起始)。
|
|
33
|
+
*
|
|
34
|
+
* 和 `startOfLocalWeek` 对称,用来把 `this-week` 补齐成完整一周。
|
|
35
|
+
*/
|
|
36
|
+
function endOfLocalWeek(date) {
|
|
37
|
+
const start = startOfLocalWeek(date);
|
|
38
|
+
return new Date(start.getFullYear(), start.getMonth(), start.getDate() + 6, 23, 59, 59, 999);
|
|
39
|
+
}
|
|
30
40
|
/** range 短别名:保持解析后的 label 仍为规范名,避免影响文件名与 bundle 契约。 */
|
|
31
41
|
const RANGE_ALIASES = {
|
|
32
42
|
lw: "last-week",
|
|
@@ -66,6 +76,19 @@ function resolveRange(range, now = new Date()) {
|
|
|
66
76
|
end: now,
|
|
67
77
|
};
|
|
68
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* 把 `this-week` 窗口补齐成完整一周(周一 ~ 周日)。
|
|
81
|
+
*
|
|
82
|
+
* export 用它保证文件名与 dailySummaries 始终覆盖整周:即使本周尚未结束、
|
|
83
|
+
* 后面几天还没有任何数据,文件名也固定是「周一_to_周日」,每天一条 daily。
|
|
84
|
+
* `last-week` 等已经是完整周的窗口原样返回,其它相对窗口不受影响。
|
|
85
|
+
*/
|
|
86
|
+
function expandToFullWeekWindow(window) {
|
|
87
|
+
if (window.label !== "this-week") {
|
|
88
|
+
return window;
|
|
89
|
+
}
|
|
90
|
+
return { ...window, end: endOfLocalWeek(window.start) };
|
|
91
|
+
}
|
|
69
92
|
/**
|
|
70
93
|
* 把日期映射成稳定的本地日键,用于事件按天分桶存储。
|
|
71
94
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccus-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Claude Code statusline usage logger and dashboard CLI",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"build": "tsc -p tsconfig.json",
|
|
16
16
|
"prepublishOnly": "npm run build",
|
|
17
17
|
"test": "node --test dist/test",
|
|
18
|
-
"test:src": "node --import tsx --test src/test/payload.test.ts src/test/dashboard.test.ts src/test/export.test.ts src/test/storage.test.ts src/test/claude.test.ts src/test/aggregate.test.ts src/test/aggregate-dashboard.test.ts src/test/install.test.ts src/test/debug.test.ts"
|
|
18
|
+
"test:src": "node --import tsx --test src/test/payload.test.ts src/test/dashboard.test.ts src/test/export.test.ts src/test/storage.test.ts src/test/claude.test.ts src/test/aggregate.test.ts src/test/aggregate-dashboard.test.ts src/test/install.test.ts src/test/debug.test.ts src/test/time.test.ts"
|
|
19
19
|
},
|
|
20
20
|
"keywords": [
|
|
21
21
|
"claude-code",
|