@caik.dev/cli 0.1.6 → 0.1.8
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/index.js +256 -17
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import { readFileSync as
|
|
5
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
|
-
import { dirname as dirname5, join as
|
|
7
|
+
import { dirname as dirname5, join as join10 } from "path";
|
|
8
8
|
import chalk3 from "chalk";
|
|
9
9
|
|
|
10
10
|
// src/errors.ts
|
|
@@ -2585,12 +2585,57 @@ function registerKarmaCommand(program2) {
|
|
|
2585
2585
|
}
|
|
2586
2586
|
|
|
2587
2587
|
// src/commands/hook.ts
|
|
2588
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, existsSync as existsSync11 } from "fs";
|
|
2588
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, existsSync as existsSync11, appendFileSync } from "fs";
|
|
2589
2589
|
import { join as join7 } from "path";
|
|
2590
2590
|
import { homedir as homedir6 } from "os";
|
|
2591
|
-
var
|
|
2591
|
+
var CAIK_DIR = join7(homedir6(), ".caik");
|
|
2592
|
+
var PENDING_EVENTS_PATH = join7(CAIK_DIR, "pending-events.json");
|
|
2593
|
+
var AUDIT_LOG_PATH = join7(CAIK_DIR, "audit.log");
|
|
2592
2594
|
var FLUSH_THRESHOLD = 50;
|
|
2593
2595
|
var API_TIMEOUT_MS = 2e3;
|
|
2596
|
+
function readStdin() {
|
|
2597
|
+
return new Promise((resolve3) => {
|
|
2598
|
+
if (process.stdin.isTTY) {
|
|
2599
|
+
resolve3("");
|
|
2600
|
+
return;
|
|
2601
|
+
}
|
|
2602
|
+
let data = "";
|
|
2603
|
+
process.stdin.setEncoding("utf-8");
|
|
2604
|
+
process.stdin.on("data", (chunk) => {
|
|
2605
|
+
data += chunk;
|
|
2606
|
+
});
|
|
2607
|
+
process.stdin.on("end", () => resolve3(data));
|
|
2608
|
+
setTimeout(() => resolve3(data), 500);
|
|
2609
|
+
});
|
|
2610
|
+
}
|
|
2611
|
+
function parseStdin(raw) {
|
|
2612
|
+
if (!raw.trim()) return null;
|
|
2613
|
+
try {
|
|
2614
|
+
return JSON.parse(raw);
|
|
2615
|
+
} catch {
|
|
2616
|
+
return null;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
function shouldSendTelemetry() {
|
|
2620
|
+
const config = readConfig();
|
|
2621
|
+
const level = config.contributionLevel ?? "contributor";
|
|
2622
|
+
return level !== "none";
|
|
2623
|
+
}
|
|
2624
|
+
function shouldSendToolUse() {
|
|
2625
|
+
const config = readConfig();
|
|
2626
|
+
const level = config.contributionLevel ?? "contributor";
|
|
2627
|
+
return level === "contributor" || level === "collective";
|
|
2628
|
+
}
|
|
2629
|
+
function auditLog(event) {
|
|
2630
|
+
try {
|
|
2631
|
+
if (!existsSync11(CAIK_DIR)) {
|
|
2632
|
+
mkdirSync8(CAIK_DIR, { recursive: true, mode: 448 });
|
|
2633
|
+
}
|
|
2634
|
+
const line = JSON.stringify(event) + "\n";
|
|
2635
|
+
appendFileSync(AUDIT_LOG_PATH, line, "utf-8");
|
|
2636
|
+
} catch {
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2594
2639
|
function readPendingEvents() {
|
|
2595
2640
|
try {
|
|
2596
2641
|
if (!existsSync11(PENDING_EVENTS_PATH)) return [];
|
|
@@ -2602,9 +2647,8 @@ function readPendingEvents() {
|
|
|
2602
2647
|
}
|
|
2603
2648
|
}
|
|
2604
2649
|
function writePendingEvents(events) {
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
mkdirSync8(dir, { recursive: true, mode: 448 });
|
|
2650
|
+
if (!existsSync11(CAIK_DIR)) {
|
|
2651
|
+
mkdirSync8(CAIK_DIR, { recursive: true, mode: 448 });
|
|
2608
2652
|
}
|
|
2609
2653
|
writeFileSync8(PENDING_EVENTS_PATH, JSON.stringify(events, null, 2) + "\n", "utf-8");
|
|
2610
2654
|
}
|
|
@@ -2654,12 +2698,20 @@ function registerHookCommand(program2) {
|
|
|
2654
2698
|
const hook = program2.command("hook").description("Platform hook callbacks (observation only, never gates agent actions)");
|
|
2655
2699
|
hook.command("session-start").description("Log session start event").option("--platform <name>", "Platform name", "claude-code").action(async (opts) => {
|
|
2656
2700
|
try {
|
|
2657
|
-
|
|
2701
|
+
if (!shouldSendTelemetry()) {
|
|
2702
|
+
process.exit(0);
|
|
2703
|
+
return;
|
|
2704
|
+
}
|
|
2705
|
+
const raw = await readStdin();
|
|
2706
|
+
const input = parseStdin(raw);
|
|
2658
2707
|
const event = {
|
|
2659
2708
|
type: "session_start",
|
|
2660
2709
|
platform: opts.platform ?? "claude-code",
|
|
2710
|
+
sessionId: input?.session_id,
|
|
2661
2711
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2662
2712
|
};
|
|
2713
|
+
auditLog(event);
|
|
2714
|
+
const client = createClient(program2);
|
|
2663
2715
|
await postSingleEventWithTimeout(client, event);
|
|
2664
2716
|
} catch {
|
|
2665
2717
|
}
|
|
@@ -2667,28 +2719,47 @@ function registerHookCommand(program2) {
|
|
|
2667
2719
|
});
|
|
2668
2720
|
hook.command("session-end").description("Flush pending events and log session end").option("--platform <name>", "Platform name", "claude-code").action(async (opts) => {
|
|
2669
2721
|
try {
|
|
2670
|
-
|
|
2722
|
+
if (!shouldSendTelemetry()) {
|
|
2723
|
+
clearPendingEvents();
|
|
2724
|
+
process.exit(0);
|
|
2725
|
+
return;
|
|
2726
|
+
}
|
|
2727
|
+
const raw = await readStdin();
|
|
2728
|
+
const input = parseStdin(raw);
|
|
2671
2729
|
const pending = readPendingEvents();
|
|
2672
2730
|
const endEvent = {
|
|
2673
2731
|
type: "session_end",
|
|
2674
2732
|
platform: opts.platform ?? "claude-code",
|
|
2733
|
+
sessionId: input?.session_id,
|
|
2675
2734
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2676
2735
|
};
|
|
2677
2736
|
pending.push(endEvent);
|
|
2737
|
+
auditLog(endEvent);
|
|
2738
|
+
const client = createClient(program2);
|
|
2678
2739
|
await postEventsWithTimeout(client, pending);
|
|
2679
2740
|
} catch {
|
|
2680
2741
|
}
|
|
2681
2742
|
process.exit(0);
|
|
2682
2743
|
});
|
|
2683
|
-
hook.command("post-tool-use").description("Buffer a tool-use event").option("--platform <name>", "Platform name", "claude-code").option("--tool <name>", "Tool name").option("--success <bool>", "
|
|
2744
|
+
hook.command("post-tool-use").description("Buffer a tool-use event").option("--platform <name>", "Platform name", "claude-code").option("--tool <name>", "Tool name (fallback if stdin unavailable)").option("--success <bool>", "Success flag (fallback if stdin unavailable)").action(async (opts) => {
|
|
2684
2745
|
try {
|
|
2746
|
+
if (!shouldSendToolUse()) {
|
|
2747
|
+
process.exit(0);
|
|
2748
|
+
return;
|
|
2749
|
+
}
|
|
2750
|
+
const raw = await readStdin();
|
|
2751
|
+
const input = parseStdin(raw);
|
|
2752
|
+
const toolName = input?.tool_name ?? opts.tool;
|
|
2753
|
+
const success2 = input?.tool_response?.success ?? opts.success === "true" ?? false;
|
|
2685
2754
|
const event = {
|
|
2686
2755
|
type: "tool_use",
|
|
2687
2756
|
platform: opts.platform ?? "claude-code",
|
|
2688
|
-
|
|
2689
|
-
|
|
2757
|
+
sessionId: input?.session_id,
|
|
2758
|
+
tool: toolName,
|
|
2759
|
+
success: Boolean(success2),
|
|
2690
2760
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2691
2761
|
};
|
|
2762
|
+
auditLog(event);
|
|
2692
2763
|
const events = bufferEvent(event);
|
|
2693
2764
|
if (events.length >= FLUSH_THRESHOLD) {
|
|
2694
2765
|
const client = createClient(program2);
|
|
@@ -2700,12 +2771,17 @@ function registerHookCommand(program2) {
|
|
|
2700
2771
|
});
|
|
2701
2772
|
hook.command("cursor-session-start").description("Log Cursor session start event").action(async () => {
|
|
2702
2773
|
try {
|
|
2703
|
-
|
|
2774
|
+
if (!shouldSendTelemetry()) {
|
|
2775
|
+
process.exit(0);
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2704
2778
|
const event = {
|
|
2705
2779
|
type: "session_start",
|
|
2706
2780
|
platform: "cursor",
|
|
2707
2781
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2708
2782
|
};
|
|
2783
|
+
auditLog(event);
|
|
2784
|
+
const client = createClient(program2);
|
|
2709
2785
|
await postSingleEventWithTimeout(client, event);
|
|
2710
2786
|
} catch {
|
|
2711
2787
|
}
|
|
@@ -2713,6 +2789,10 @@ function registerHookCommand(program2) {
|
|
|
2713
2789
|
});
|
|
2714
2790
|
hook.command("cursor-mcp-exec").description("Buffer a Cursor MCP tool execution event").option("--server <name>", "MCP server name").option("--tool <name>", "Tool name").action(async (opts) => {
|
|
2715
2791
|
try {
|
|
2792
|
+
if (!shouldSendToolUse()) {
|
|
2793
|
+
process.exit(0);
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2716
2796
|
const event = {
|
|
2717
2797
|
type: "mcp_exec",
|
|
2718
2798
|
platform: "cursor",
|
|
@@ -2720,6 +2800,7 @@ function registerHookCommand(program2) {
|
|
|
2720
2800
|
tool: opts.tool,
|
|
2721
2801
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2722
2802
|
};
|
|
2803
|
+
auditLog(event);
|
|
2723
2804
|
const events = bufferEvent(event);
|
|
2724
2805
|
if (events.length >= FLUSH_THRESHOLD) {
|
|
2725
2806
|
const client = createClient(program2);
|
|
@@ -2731,7 +2812,11 @@ function registerHookCommand(program2) {
|
|
|
2731
2812
|
});
|
|
2732
2813
|
hook.command("cursor-session-end").description("Flush pending events and log Cursor session end").action(async () => {
|
|
2733
2814
|
try {
|
|
2734
|
-
|
|
2815
|
+
if (!shouldSendTelemetry()) {
|
|
2816
|
+
clearPendingEvents();
|
|
2817
|
+
process.exit(0);
|
|
2818
|
+
return;
|
|
2819
|
+
}
|
|
2735
2820
|
const pending = readPendingEvents();
|
|
2736
2821
|
const endEvent = {
|
|
2737
2822
|
type: "session_end",
|
|
@@ -2739,6 +2824,8 @@ function registerHookCommand(program2) {
|
|
|
2739
2824
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2740
2825
|
};
|
|
2741
2826
|
pending.push(endEvent);
|
|
2827
|
+
auditLog(endEvent);
|
|
2828
|
+
const client = createClient(program2);
|
|
2742
2829
|
await postEventsWithTimeout(client, pending);
|
|
2743
2830
|
} catch {
|
|
2744
2831
|
}
|
|
@@ -3343,7 +3430,7 @@ function registerUpgradeCommand(program2) {
|
|
|
3343
3430
|
});
|
|
3344
3431
|
spinner.stop();
|
|
3345
3432
|
console.log(success(`Upgraded to ${update.latest}`));
|
|
3346
|
-
} catch
|
|
3433
|
+
} catch {
|
|
3347
3434
|
spinner.stop();
|
|
3348
3435
|
console.log(error("Upgrade failed. Try manually:"));
|
|
3349
3436
|
console.log(info("npm install -g @caik.dev/cli@latest"));
|
|
@@ -3351,13 +3438,164 @@ function registerUpgradeCommand(program2) {
|
|
|
3351
3438
|
});
|
|
3352
3439
|
}
|
|
3353
3440
|
|
|
3441
|
+
// src/commands/audit.ts
|
|
3442
|
+
import { readFileSync as readFileSync9, existsSync as existsSync14, writeFileSync as writeFileSync10 } from "fs";
|
|
3443
|
+
import { join as join9 } from "path";
|
|
3444
|
+
import { homedir as homedir8 } from "os";
|
|
3445
|
+
var CAIK_DIR2 = join9(homedir8(), ".caik");
|
|
3446
|
+
var AUDIT_LOG_PATH2 = join9(CAIK_DIR2, "audit.log");
|
|
3447
|
+
var PENDING_EVENTS_PATH2 = join9(CAIK_DIR2, "pending-events.json");
|
|
3448
|
+
function registerAuditCommand(program2) {
|
|
3449
|
+
const cmd = program2.command("audit").description("See exactly what telemetry CAIK collects \u2014 full transparency");
|
|
3450
|
+
cmd.command("log").description("Show recent telemetry events (from local audit log)").option("-n, --lines <count>", "Number of recent events to show", "20").option("--all", "Show all events").action((opts) => {
|
|
3451
|
+
console.log(heading("\nCAIK Telemetry Audit Log"));
|
|
3452
|
+
console.log("\u2550".repeat(50));
|
|
3453
|
+
const config = readConfig();
|
|
3454
|
+
const level = config.contributionLevel ?? "contributor";
|
|
3455
|
+
console.log(info(`Contribution level: ${level}`));
|
|
3456
|
+
console.log(dim(`Log path: ${AUDIT_LOG_PATH2}`));
|
|
3457
|
+
console.log();
|
|
3458
|
+
if (!existsSync14(AUDIT_LOG_PATH2)) {
|
|
3459
|
+
console.log(dim("No events logged yet. Events appear here after your next Claude Code session."));
|
|
3460
|
+
return;
|
|
3461
|
+
}
|
|
3462
|
+
const raw = readFileSync9(AUDIT_LOG_PATH2, "utf-8").trim();
|
|
3463
|
+
if (!raw) {
|
|
3464
|
+
console.log(dim("Audit log is empty."));
|
|
3465
|
+
return;
|
|
3466
|
+
}
|
|
3467
|
+
const lines = raw.split("\n");
|
|
3468
|
+
const limit = opts.all ? lines.length : Math.min(parseInt(opts.lines, 10) || 20, lines.length);
|
|
3469
|
+
const recent = lines.slice(-limit);
|
|
3470
|
+
if (!opts.all && lines.length > limit) {
|
|
3471
|
+
console.log(dim(`Showing last ${limit} of ${lines.length} events. Use --all to see everything.
|
|
3472
|
+
`));
|
|
3473
|
+
}
|
|
3474
|
+
for (const line of recent) {
|
|
3475
|
+
try {
|
|
3476
|
+
const event = JSON.parse(line);
|
|
3477
|
+
const time = new Date(event.timestamp).toLocaleTimeString();
|
|
3478
|
+
const type = event.type.padEnd(14);
|
|
3479
|
+
const platform2 = (event.platform ?? "").padEnd(12);
|
|
3480
|
+
const tool = event.tool ? ` tool=${event.tool}` : "";
|
|
3481
|
+
const ok = event.success !== void 0 ? ` success=${event.success}` : "";
|
|
3482
|
+
const sid = event.sessionId ? ` sid=${event.sessionId.slice(0, 8)}\u2026` : "";
|
|
3483
|
+
console.log(` ${dim(time)} ${type} ${dim(platform2)}${tool}${ok}${sid}`);
|
|
3484
|
+
} catch {
|
|
3485
|
+
console.log(` ${dim(line)}`);
|
|
3486
|
+
}
|
|
3487
|
+
}
|
|
3488
|
+
console.log();
|
|
3489
|
+
console.log(dim("This is everything CAIK sends. No prompts, files, or personal data \u2014 ever."));
|
|
3490
|
+
console.log(dim("Change your level: caik config contribution"));
|
|
3491
|
+
});
|
|
3492
|
+
cmd.command("pending").description("Show events buffered locally (not yet sent to API)").action(() => {
|
|
3493
|
+
console.log(heading("\nPending Events (buffered locally)"));
|
|
3494
|
+
console.log("\u2500".repeat(50));
|
|
3495
|
+
console.log(dim(`Path: ${PENDING_EVENTS_PATH2}
|
|
3496
|
+
`));
|
|
3497
|
+
if (!existsSync14(PENDING_EVENTS_PATH2)) {
|
|
3498
|
+
console.log(dim("No pending events."));
|
|
3499
|
+
return;
|
|
3500
|
+
}
|
|
3501
|
+
try {
|
|
3502
|
+
const raw = readFileSync9(PENDING_EVENTS_PATH2, "utf-8");
|
|
3503
|
+
const events = JSON.parse(raw);
|
|
3504
|
+
if (events.length === 0) {
|
|
3505
|
+
console.log(dim("No pending events."));
|
|
3506
|
+
return;
|
|
3507
|
+
}
|
|
3508
|
+
console.log(info(`${events.length} event(s) buffered, waiting for session end to flush:
|
|
3509
|
+
`));
|
|
3510
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3511
|
+
const tools = /* @__PURE__ */ new Map();
|
|
3512
|
+
let successCount = 0;
|
|
3513
|
+
let failCount = 0;
|
|
3514
|
+
for (const e of events) {
|
|
3515
|
+
counts.set(e.type, (counts.get(e.type) ?? 0) + 1);
|
|
3516
|
+
if (e.tool) tools.set(e.tool, (tools.get(e.tool) ?? 0) + 1);
|
|
3517
|
+
if (e.success === true) successCount++;
|
|
3518
|
+
if (e.success === false) failCount++;
|
|
3519
|
+
}
|
|
3520
|
+
for (const [type, count] of counts) {
|
|
3521
|
+
console.log(` ${type}: ${count}`);
|
|
3522
|
+
}
|
|
3523
|
+
if (tools.size > 0) {
|
|
3524
|
+
console.log();
|
|
3525
|
+
console.log(info("Tools used:"));
|
|
3526
|
+
const sorted = [...tools.entries()].sort((a, b) => b[1] - a[1]);
|
|
3527
|
+
for (const [tool, count] of sorted.slice(0, 10)) {
|
|
3528
|
+
console.log(` ${tool}: ${count}`);
|
|
3529
|
+
}
|
|
3530
|
+
if (sorted.length > 10) {
|
|
3531
|
+
console.log(dim(` \u2026 and ${sorted.length - 10} more`));
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
if (successCount + failCount > 0) {
|
|
3535
|
+
console.log();
|
|
3536
|
+
console.log(` ${success(`${successCount} succeeded`)} / ${warn(`${failCount} failed`)}`);
|
|
3537
|
+
}
|
|
3538
|
+
} catch {
|
|
3539
|
+
console.log(warn("Could not parse pending events file."));
|
|
3540
|
+
}
|
|
3541
|
+
});
|
|
3542
|
+
cmd.command("clear").description("Clear the local audit log and pending events").action(() => {
|
|
3543
|
+
if (existsSync14(AUDIT_LOG_PATH2)) {
|
|
3544
|
+
writeFileSync10(AUDIT_LOG_PATH2, "", "utf-8");
|
|
3545
|
+
}
|
|
3546
|
+
if (existsSync14(PENDING_EVENTS_PATH2)) {
|
|
3547
|
+
writeFileSync10(PENDING_EVENTS_PATH2, "[]", "utf-8");
|
|
3548
|
+
}
|
|
3549
|
+
console.log(success("Audit log and pending events cleared."));
|
|
3550
|
+
});
|
|
3551
|
+
cmd.action(() => {
|
|
3552
|
+
const config = readConfig();
|
|
3553
|
+
const level = config.contributionLevel ?? "contributor";
|
|
3554
|
+
console.log(heading("\nCAIK Telemetry Transparency"));
|
|
3555
|
+
console.log("\u2550".repeat(50));
|
|
3556
|
+
console.log();
|
|
3557
|
+
console.log(` Contribution Level: ${level}`);
|
|
3558
|
+
let logCount = 0;
|
|
3559
|
+
if (existsSync14(AUDIT_LOG_PATH2)) {
|
|
3560
|
+
const raw = readFileSync9(AUDIT_LOG_PATH2, "utf-8").trim();
|
|
3561
|
+
if (raw) logCount = raw.split("\n").length;
|
|
3562
|
+
}
|
|
3563
|
+
console.log(` Events Logged: ${logCount}`);
|
|
3564
|
+
let pendingCount = 0;
|
|
3565
|
+
if (existsSync14(PENDING_EVENTS_PATH2)) {
|
|
3566
|
+
try {
|
|
3567
|
+
const parsed = JSON.parse(readFileSync9(PENDING_EVENTS_PATH2, "utf-8"));
|
|
3568
|
+
if (Array.isArray(parsed)) pendingCount = parsed.length;
|
|
3569
|
+
} catch {
|
|
3570
|
+
}
|
|
3571
|
+
}
|
|
3572
|
+
console.log(` Pending (unsent): ${pendingCount}`);
|
|
3573
|
+
console.log(` Audit Log: ${dim(AUDIT_LOG_PATH2)}`);
|
|
3574
|
+
console.log();
|
|
3575
|
+
console.log(heading("What each level sends:"));
|
|
3576
|
+
console.log(` ${dim("none")} Nothing. Directory access only.`);
|
|
3577
|
+
console.log(` ${dim("minimal")} Install/uninstall events (artifact ID + timestamp).`);
|
|
3578
|
+
console.log(` ${dim("contributor")} + Tool-use signals (tool name, success/fail). No content.`);
|
|
3579
|
+
console.log(` ${dim("collective")} + Workflow patterns, stack signals. Anonymized.`);
|
|
3580
|
+
console.log();
|
|
3581
|
+
console.log(dim("NEVER sent: prompts, file contents, conversation text, file paths, personal data."));
|
|
3582
|
+
console.log();
|
|
3583
|
+
console.log(info("Commands:"));
|
|
3584
|
+
console.log(` ${dim("caik audit log")} Show recent events`);
|
|
3585
|
+
console.log(` ${dim("caik audit pending")} Show buffered events`);
|
|
3586
|
+
console.log(` ${dim("caik audit clear")} Clear all local telemetry data`);
|
|
3587
|
+
console.log(` ${dim("caik config contribution")} Change your contribution level`);
|
|
3588
|
+
console.log();
|
|
3589
|
+
});
|
|
3590
|
+
}
|
|
3591
|
+
|
|
3354
3592
|
// src/index.ts
|
|
3355
3593
|
var __filename = fileURLToPath(import.meta.url);
|
|
3356
3594
|
var __dirname = dirname5(__filename);
|
|
3357
3595
|
var version = "0.0.1";
|
|
3358
3596
|
try {
|
|
3359
|
-
const pkgPath =
|
|
3360
|
-
const pkg = JSON.parse(
|
|
3597
|
+
const pkgPath = join10(__dirname, "..", "package.json");
|
|
3598
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
3361
3599
|
version = pkg.version;
|
|
3362
3600
|
} catch {
|
|
3363
3601
|
}
|
|
@@ -3378,6 +3616,7 @@ registerKarmaCommand(program);
|
|
|
3378
3616
|
registerHookCommand(program);
|
|
3379
3617
|
registerSetupCommand(program);
|
|
3380
3618
|
registerUpgradeCommand(program);
|
|
3619
|
+
registerAuditCommand(program);
|
|
3381
3620
|
program.exitOverride();
|
|
3382
3621
|
async function main() {
|
|
3383
3622
|
const updateHint = printUpdateHint();
|