@rely-ai/caliber 1.7.0 → 1.7.2

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.
Files changed (2) hide show
  1. package/dist/bin.js +578 -342
  2. package/package.json +3 -2
package/dist/bin.js CHANGED
@@ -165,17 +165,17 @@ var init_constants = __esm({
165
165
 
166
166
  // src/cli.ts
167
167
  import { Command } from "commander";
168
- import fs27 from "fs";
169
- import path21 from "path";
168
+ import fs28 from "fs";
169
+ import path22 from "path";
170
170
  import { fileURLToPath } from "url";
171
171
 
172
172
  // src/commands/onboard.ts
173
- import chalk7 from "chalk";
173
+ import chalk8 from "chalk";
174
174
  import ora2 from "ora";
175
175
  import readline3 from "readline";
176
176
  import select5 from "@inquirer/select";
177
177
  import checkbox from "@inquirer/checkbox";
178
- import fs21 from "fs";
178
+ import fs22 from "fs";
179
179
 
180
180
  // src/fingerprint/index.ts
181
181
  import fs6 from "fs";
@@ -3205,15 +3205,15 @@ function computeGrade(score) {
3205
3205
  // src/scoring/checks/coverage.ts
3206
3206
  import { readFileSync, readdirSync } from "fs";
3207
3207
  import { join } from "path";
3208
- function readFileOrNull(path23) {
3208
+ function readFileOrNull(path24) {
3209
3209
  try {
3210
- return readFileSync(path23, "utf-8");
3210
+ return readFileSync(path24, "utf-8");
3211
3211
  } catch {
3212
3212
  return null;
3213
3213
  }
3214
3214
  }
3215
- function readJsonOrNull(path23) {
3216
- const content = readFileOrNull(path23);
3215
+ function readJsonOrNull(path24) {
3216
+ const content = readFileOrNull(path24);
3217
3217
  if (!content) return null;
3218
3218
  try {
3219
3219
  return JSON.parse(content);
@@ -3581,9 +3581,9 @@ function checkExistence(dir) {
3581
3581
  // src/scoring/checks/quality.ts
3582
3582
  import { readFileSync as readFileSync3 } from "fs";
3583
3583
  import { join as join3 } from "path";
3584
- function readFileOrNull2(path23) {
3584
+ function readFileOrNull2(path24) {
3585
3585
  try {
3586
- return readFileSync3(path23, "utf-8");
3586
+ return readFileSync3(path24, "utf-8");
3587
3587
  } catch {
3588
3588
  return null;
3589
3589
  }
@@ -3736,15 +3736,15 @@ function checkQuality(dir) {
3736
3736
  // src/scoring/checks/accuracy.ts
3737
3737
  import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync } from "fs";
3738
3738
  import { join as join4 } from "path";
3739
- function readFileOrNull3(path23) {
3739
+ function readFileOrNull3(path24) {
3740
3740
  try {
3741
- return readFileSync4(path23, "utf-8");
3741
+ return readFileSync4(path24, "utf-8");
3742
3742
  } catch {
3743
3743
  return null;
3744
3744
  }
3745
3745
  }
3746
- function readJsonOrNull2(path23) {
3747
- const content = readFileOrNull3(path23);
3746
+ function readJsonOrNull2(path24) {
3747
+ const content = readFileOrNull3(path24);
3748
3748
  if (!content) return null;
3749
3749
  try {
3750
3750
  return JSON.parse(content);
@@ -3927,9 +3927,9 @@ function checkAccuracy(dir) {
3927
3927
  // src/scoring/checks/freshness.ts
3928
3928
  import { existsSync as existsSync6, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
3929
3929
  import { join as join5 } from "path";
3930
- function readFileOrNull4(path23) {
3930
+ function readFileOrNull4(path24) {
3931
3931
  try {
3932
- return readFileSync5(path23, "utf-8");
3932
+ return readFileSync5(path24, "utf-8");
3933
3933
  } catch {
3934
3934
  return null;
3935
3935
  }
@@ -4043,9 +4043,9 @@ function checkFreshness(dir) {
4043
4043
  import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "fs";
4044
4044
  import { execSync as execSync7 } from "child_process";
4045
4045
  import { join as join6 } from "path";
4046
- function readFileOrNull5(path23) {
4046
+ function readFileOrNull5(path24) {
4047
4047
  try {
4048
- return readFileSync6(path23, "utf-8");
4048
+ return readFileSync6(path24, "utf-8");
4049
4049
  } catch {
4050
4050
  return null;
4051
4051
  }
@@ -4343,7 +4343,7 @@ function displayScoreDelta(before, after) {
4343
4343
  }
4344
4344
 
4345
4345
  // src/commands/recommend.ts
4346
- import chalk6 from "chalk";
4346
+ import chalk7 from "chalk";
4347
4347
  import ora from "ora";
4348
4348
  import select4 from "@inquirer/select";
4349
4349
  import { mkdirSync, readFileSync as readFileSync7, readdirSync as readdirSync5, existsSync as existsSync9, writeFileSync } from "fs";
@@ -4495,6 +4495,167 @@ function hashJson(obj) {
4495
4495
 
4496
4496
  // src/commands/recommend.ts
4497
4497
  init_config();
4498
+
4499
+ // src/telemetry/index.ts
4500
+ import { PostHog } from "posthog-node";
4501
+ import chalk6 from "chalk";
4502
+
4503
+ // src/telemetry/config.ts
4504
+ import fs21 from "fs";
4505
+ import path17 from "path";
4506
+ import os3 from "os";
4507
+ import crypto3 from "crypto";
4508
+ import { execSync as execSync8 } from "child_process";
4509
+ var CONFIG_DIR2 = path17.join(os3.homedir(), ".caliber");
4510
+ var CONFIG_FILE2 = path17.join(CONFIG_DIR2, "config.json");
4511
+ var runtimeDisabled = false;
4512
+ function readConfig() {
4513
+ try {
4514
+ if (!fs21.existsSync(CONFIG_FILE2)) return {};
4515
+ return JSON.parse(fs21.readFileSync(CONFIG_FILE2, "utf-8"));
4516
+ } catch {
4517
+ return {};
4518
+ }
4519
+ }
4520
+ function writeConfig(config) {
4521
+ if (!fs21.existsSync(CONFIG_DIR2)) {
4522
+ fs21.mkdirSync(CONFIG_DIR2, { recursive: true });
4523
+ }
4524
+ fs21.writeFileSync(CONFIG_FILE2, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
4525
+ }
4526
+ function getMachineId() {
4527
+ const config = readConfig();
4528
+ if (config.machineId) return config.machineId;
4529
+ const machineId = crypto3.randomUUID();
4530
+ writeConfig({ ...config, machineId });
4531
+ return machineId;
4532
+ }
4533
+ function getGitEmailHash() {
4534
+ try {
4535
+ const email = execSync8("git config user.email", { encoding: "utf-8" }).trim();
4536
+ if (!email) return void 0;
4537
+ return crypto3.createHash("sha256").update(email).digest("hex");
4538
+ } catch {
4539
+ return void 0;
4540
+ }
4541
+ }
4542
+ function isTelemetryDisabled() {
4543
+ if (runtimeDisabled) return true;
4544
+ const envVal = process.env.CALIBER_TELEMETRY_DISABLED;
4545
+ return envVal === "1" || envVal === "true";
4546
+ }
4547
+ function setTelemetryDisabled(disabled) {
4548
+ runtimeDisabled = disabled;
4549
+ }
4550
+ function wasNoticeShown() {
4551
+ return readConfig().telemetryNoticeShown === true;
4552
+ }
4553
+ function markNoticeShown() {
4554
+ const config = readConfig();
4555
+ writeConfig({ ...config, telemetryNoticeShown: true });
4556
+ }
4557
+
4558
+ // src/telemetry/index.ts
4559
+ var POSTHOG_KEY = "phc_XXrV0pSX4s2QVxVoOaeuyXDvtlRwPAjovt1ttMGVMPp";
4560
+ var client = null;
4561
+ var distinctId = null;
4562
+ function initTelemetry() {
4563
+ if (isTelemetryDisabled()) return;
4564
+ const machineId = getMachineId();
4565
+ distinctId = machineId;
4566
+ client = new PostHog(POSTHOG_KEY, {
4567
+ host: "https://us.i.posthog.com",
4568
+ flushAt: 20,
4569
+ flushInterval: 1e4
4570
+ });
4571
+ if (!wasNoticeShown()) {
4572
+ console.log(
4573
+ chalk6.dim(" Caliber collects anonymous usage data to improve the product.") + "\n" + chalk6.dim(" Disable with --no-traces or CALIBER_TELEMETRY_DISABLED=1\n")
4574
+ );
4575
+ markNoticeShown();
4576
+ }
4577
+ const gitEmailHash = getGitEmailHash();
4578
+ client.identify({
4579
+ distinctId: machineId,
4580
+ properties: {
4581
+ ...gitEmailHash ? { git_email_hash: gitEmailHash } : {}
4582
+ }
4583
+ });
4584
+ }
4585
+ function trackEvent(name, properties) {
4586
+ if (!client || !distinctId || isTelemetryDisabled()) return;
4587
+ client.capture({
4588
+ distinctId,
4589
+ event: name,
4590
+ properties: properties ?? {}
4591
+ });
4592
+ }
4593
+ async function flushTelemetry() {
4594
+ if (!client) return;
4595
+ try {
4596
+ await client.shutdown();
4597
+ } catch {
4598
+ }
4599
+ client = null;
4600
+ }
4601
+
4602
+ // src/telemetry/events.ts
4603
+ function trackInitProviderSelected(provider, model) {
4604
+ trackEvent("init_provider_selected", { provider, model });
4605
+ }
4606
+ function trackInitProjectDiscovered(languageCount, dependencyCount, fileCount) {
4607
+ trackEvent("init_project_discovered", { language_count: languageCount, dependency_count: dependencyCount, file_count: fileCount });
4608
+ }
4609
+ function trackInitAgentSelected(agents) {
4610
+ trackEvent("init_agent_selected", { agents });
4611
+ }
4612
+ function trackInitScoreComputed(score, passingCount, failingCount, earlyExit) {
4613
+ trackEvent("init_score_computed", { score, passing_count: passingCount, failing_count: failingCount, early_exit: earlyExit });
4614
+ }
4615
+ function trackInitGenerationStarted(isTargetedFix) {
4616
+ trackEvent("init_generation_started", { is_targeted_fix: isTargetedFix });
4617
+ }
4618
+ function trackInitGenerationCompleted(durationMs, retryCount) {
4619
+ trackEvent("init_generation_completed", { duration_ms: durationMs, retry_count: retryCount });
4620
+ }
4621
+ function trackInitReviewAction(action, reviewMethod) {
4622
+ trackEvent("init_review_action", { action, review_method: reviewMethod });
4623
+ }
4624
+ function trackInitRefinementRound(roundNumber, wasValid) {
4625
+ trackEvent("init_refinement_round", { round_number: roundNumber, was_valid: wasValid });
4626
+ }
4627
+ function trackInitFilesWritten(fileCount, createdCount, modifiedCount, deletedCount) {
4628
+ trackEvent("init_files_written", { file_count: fileCount, created_count: createdCount, modified_count: modifiedCount, deleted_count: deletedCount });
4629
+ }
4630
+ function trackInitHookSelected(hookType) {
4631
+ trackEvent("init_hook_selected", { hook_type: hookType });
4632
+ }
4633
+ function trackInitSkillsSearch(searched, installedCount) {
4634
+ trackEvent("init_skills_search", { searched, installed_count: installedCount });
4635
+ }
4636
+ function trackInitScoreRegression(oldScore, newScore) {
4637
+ trackEvent("init_score_regression", { old_score: oldScore, new_score: newScore });
4638
+ }
4639
+ function trackRegenerateCompleted(action, durationMs) {
4640
+ trackEvent("regenerate_completed", { action, duration_ms: durationMs });
4641
+ }
4642
+ function trackRefreshCompleted(changesCount, durationMs) {
4643
+ trackEvent("refresh_completed", { changes_count: changesCount, duration_ms: durationMs });
4644
+ }
4645
+ function trackScoreComputed(score, agent) {
4646
+ trackEvent("score_computed", { score, agent });
4647
+ }
4648
+ function trackConfigProviderSet(provider) {
4649
+ trackEvent("config_provider_set", { provider });
4650
+ }
4651
+ function trackSkillsInstalled(count) {
4652
+ trackEvent("skills_installed", { count });
4653
+ }
4654
+ function trackUndoExecuted() {
4655
+ trackEvent("undo_executed");
4656
+ }
4657
+
4658
+ // src/commands/recommend.ts
4498
4659
  function detectLocalPlatforms() {
4499
4660
  const items = scanLocalState(process.cwd());
4500
4661
  const platforms = /* @__PURE__ */ new Set();
@@ -4802,7 +4963,7 @@ async function recommendCommand() {
4802
4963
  ]
4803
4964
  });
4804
4965
  if (!proceed) {
4805
- console.log(chalk6.dim(" Cancelled.\n"));
4966
+ console.log(chalk7.dim(" Cancelled.\n"));
4806
4967
  return;
4807
4968
  }
4808
4969
  await searchAndInstallSkills();
@@ -4817,7 +4978,7 @@ async function searchAndInstallSkills() {
4817
4978
  ...extractTopDeps()
4818
4979
  ].filter(Boolean))];
4819
4980
  if (technologies.length === 0) {
4820
- console.log(chalk6.yellow("Could not detect any languages or dependencies. Try running from a project root."));
4981
+ console.log(chalk7.yellow("Could not detect any languages or dependencies. Try running from a project root."));
4821
4982
  throw new Error("__exit__");
4822
4983
  }
4823
4984
  const primaryPlatform = platforms.includes("claude") ? "claude" : platforms[0];
@@ -4834,7 +4995,7 @@ async function searchAndInstallSkills() {
4834
4995
  return;
4835
4996
  }
4836
4997
  searchSpinner.succeed(
4837
- `Found ${allCandidates.length} skills` + (filteredCount > 0 ? chalk6.dim(` (${filteredCount} already installed)`) : "")
4998
+ `Found ${allCandidates.length} skills` + (filteredCount > 0 ? chalk7.dim(` (${filteredCount} already installed)`) : "")
4838
4999
  );
4839
5000
  let results;
4840
5001
  const config = loadConfig();
@@ -4868,7 +5029,7 @@ async function searchAndInstallSkills() {
4868
5029
  }
4869
5030
  const unavailableCount = results.length - available.length;
4870
5031
  fetchSpinner.succeed(
4871
- `${available.length} installable skill${available.length > 1 ? "s" : ""}` + (unavailableCount > 0 ? chalk6.dim(` (${unavailableCount} unavailable)`) : "")
5032
+ `${available.length} installable skill${available.length > 1 ? "s" : ""}` + (unavailableCount > 0 ? chalk7.dim(` (${unavailableCount} unavailable)`) : "")
4872
5033
  );
4873
5034
  const selected = await interactiveSelect(available);
4874
5035
  if (selected?.length) {
@@ -4891,30 +5052,30 @@ async function interactiveSelect(recs) {
4891
5052
  const nameWidth = Math.max(...recs.map((r) => r.name.length), 4) + 2;
4892
5053
  const prefixWidth = 8;
4893
5054
  const scoreWidth = 6;
4894
- lines.push(chalk6.bold(" Skills"));
5055
+ lines.push(chalk7.bold(" Skills"));
4895
5056
  lines.push("");
4896
5057
  if (hasScores) {
4897
- const header = " ".repeat(prefixWidth) + chalk6.dim("Score".padEnd(scoreWidth)) + chalk6.dim("Name".padEnd(nameWidth)) + chalk6.dim("Why");
5058
+ const header = " ".repeat(prefixWidth) + chalk7.dim("Score".padEnd(scoreWidth)) + chalk7.dim("Name".padEnd(nameWidth)) + chalk7.dim("Why");
4898
5059
  lines.push(header);
4899
5060
  } else {
4900
- const header = " ".repeat(prefixWidth) + chalk6.dim("Name".padEnd(nameWidth)) + chalk6.dim("Technology".padEnd(18)) + chalk6.dim("Source");
5061
+ const header = " ".repeat(prefixWidth) + chalk7.dim("Name".padEnd(nameWidth)) + chalk7.dim("Technology".padEnd(18)) + chalk7.dim("Source");
4901
5062
  lines.push(header);
4902
5063
  }
4903
- lines.push(chalk6.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
5064
+ lines.push(chalk7.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
4904
5065
  for (let i = 0; i < recs.length; i++) {
4905
5066
  const rec = recs[i];
4906
- const check = selected.has(i) ? chalk6.green("[x]") : "[ ]";
4907
- const ptr = i === cursor ? chalk6.cyan(">") : " ";
5067
+ const check = selected.has(i) ? chalk7.green("[x]") : "[ ]";
5068
+ const ptr = i === cursor ? chalk7.cyan(">") : " ";
4908
5069
  if (hasScores) {
4909
- const scoreColor = rec.score >= 90 ? chalk6.green : rec.score >= 70 ? chalk6.yellow : chalk6.dim;
5070
+ const scoreColor = rec.score >= 90 ? chalk7.green : rec.score >= 70 ? chalk7.yellow : chalk7.dim;
4910
5071
  const reasonMax = Math.max(cols - prefixWidth - scoreWidth - nameWidth - 2, 20);
4911
- lines.push(` ${ptr} ${check} ${scoreColor(String(rec.score).padStart(3))} ${rec.name.padEnd(nameWidth)}${chalk6.dim(rec.reason.slice(0, reasonMax))}`);
5072
+ lines.push(` ${ptr} ${check} ${scoreColor(String(rec.score).padStart(3))} ${rec.name.padEnd(nameWidth)}${chalk7.dim(rec.reason.slice(0, reasonMax))}`);
4912
5073
  } else {
4913
- lines.push(` ${ptr} ${check} ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk6.dim(rec.source_url || "")}`);
5074
+ lines.push(` ${ptr} ${check} ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk7.dim(rec.source_url || "")}`);
4914
5075
  }
4915
5076
  }
4916
5077
  lines.push("");
4917
- lines.push(chalk6.dim(" \u2191\u2193 navigate \u23B5 toggle a all n none \u23CE install q cancel"));
5078
+ lines.push(chalk7.dim(" \u2191\u2193 navigate \u23B5 toggle a all n none \u23CE install q cancel"));
4918
5079
  return lines.join("\n");
4919
5080
  }
4920
5081
  function draw(initial) {
@@ -4963,7 +5124,7 @@ async function interactiveSelect(recs) {
4963
5124
  case "\n":
4964
5125
  cleanup();
4965
5126
  if (selected.size === 0) {
4966
- console.log(chalk6.dim("\n No skills selected.\n"));
5127
+ console.log(chalk7.dim("\n No skills selected.\n"));
4967
5128
  resolve2(null);
4968
5129
  } else {
4969
5130
  resolve2(Array.from(selected).sort().map((i) => recs[i]));
@@ -4973,7 +5134,7 @@ async function interactiveSelect(recs) {
4973
5134
  case "\x1B":
4974
5135
  case "":
4975
5136
  cleanup();
4976
- console.log(chalk6.dim("\n Cancelled.\n"));
5137
+ console.log(chalk7.dim("\n Cancelled.\n"));
4977
5138
  resolve2(null);
4978
5139
  break;
4979
5140
  }
@@ -5034,9 +5195,10 @@ async function installSkills(recs, platforms, contentMap) {
5034
5195
  }
5035
5196
  }
5036
5197
  if (installed.length > 0) {
5198
+ trackSkillsInstalled(installed.length);
5037
5199
  spinner.succeed(`Installed ${installed.length} file${installed.length > 1 ? "s" : ""}`);
5038
5200
  for (const p of installed) {
5039
- console.log(chalk6.green(` \u2713 ${p}`));
5201
+ console.log(chalk7.green(` \u2713 ${p}`));
5040
5202
  }
5041
5203
  } else {
5042
5204
  spinner.fail("No skills were installed");
@@ -5049,19 +5211,19 @@ function printSkills(recs) {
5049
5211
  const nameWidth = Math.max(...recs.map((r) => r.name.length), 4) + 2;
5050
5212
  const scoreWidth = 6;
5051
5213
  const prefixWidth = 2;
5052
- console.log(chalk6.bold("\n Skills\n"));
5214
+ console.log(chalk7.bold("\n Skills\n"));
5053
5215
  if (hasScores) {
5054
- console.log(" ".repeat(prefixWidth) + chalk6.dim("Score".padEnd(scoreWidth)) + chalk6.dim("Name".padEnd(nameWidth)) + chalk6.dim("Why"));
5216
+ console.log(" ".repeat(prefixWidth) + chalk7.dim("Score".padEnd(scoreWidth)) + chalk7.dim("Name".padEnd(nameWidth)) + chalk7.dim("Why"));
5055
5217
  } else {
5056
- console.log(" ".repeat(prefixWidth) + chalk6.dim("Name".padEnd(nameWidth)) + chalk6.dim("Technology".padEnd(18)) + chalk6.dim("Source"));
5218
+ console.log(" ".repeat(prefixWidth) + chalk7.dim("Name".padEnd(nameWidth)) + chalk7.dim("Technology".padEnd(18)) + chalk7.dim("Source"));
5057
5219
  }
5058
- console.log(chalk6.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
5220
+ console.log(chalk7.dim(" " + "\u2500".repeat(Math.min(cols - 4, 90))));
5059
5221
  for (const rec of recs) {
5060
5222
  if (hasScores) {
5061
5223
  const reasonMax = Math.max(cols - prefixWidth - scoreWidth - nameWidth - 2, 20);
5062
- console.log(` ${String(rec.score).padStart(3)} ${rec.name.padEnd(nameWidth)}${chalk6.dim(rec.reason.slice(0, reasonMax))}`);
5224
+ console.log(` ${String(rec.score).padStart(3)} ${rec.name.padEnd(nameWidth)}${chalk7.dim(rec.reason.slice(0, reasonMax))}`);
5063
5225
  } else {
5064
- console.log(` ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk6.dim(rec.source_url || "")}`);
5226
+ console.log(` ${rec.name.padEnd(nameWidth)}${rec.detected_technology.padEnd(16)} ${chalk7.dim(rec.source_url || "")}`);
5065
5227
  }
5066
5228
  }
5067
5229
  console.log("");
@@ -5069,8 +5231,8 @@ function printSkills(recs) {
5069
5231
 
5070
5232
  // src/commands/onboard.ts
5071
5233
  async function initCommand(options) {
5072
- const brand = chalk7.hex("#EB9D83");
5073
- const title = chalk7.hex("#83D1EB");
5234
+ const brand = chalk8.hex("#EB9D83");
5235
+ const title = chalk8.hex("#83D1EB");
5074
5236
  console.log(brand.bold(`
5075
5237
  \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
5076
5238
  \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
@@ -5079,21 +5241,21 @@ async function initCommand(options) {
5079
5241
  \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
5080
5242
  \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
5081
5243
  `));
5082
- console.log(chalk7.dim(" Onboard your project for AI-assisted development\n"));
5244
+ console.log(chalk8.dim(" Onboard your project for AI-assisted development\n"));
5083
5245
  console.log(title.bold(" Welcome to Caliber\n"));
5084
- console.log(chalk7.dim(" Caliber analyzes your codebase and creates tailored config files"));
5085
- console.log(chalk7.dim(" so your AI coding agents understand your project from day one.\n"));
5246
+ console.log(chalk8.dim(" Caliber analyzes your codebase and creates tailored config files"));
5247
+ console.log(chalk8.dim(" so your AI coding agents understand your project from day one.\n"));
5086
5248
  console.log(title.bold(" How onboarding works:\n"));
5087
- console.log(chalk7.dim(" 1. Connect Set up your LLM provider"));
5088
- console.log(chalk7.dim(" 2. Discover Analyze your code, dependencies, and structure"));
5089
- console.log(chalk7.dim(" 3. Generate Create config files tailored to your project"));
5090
- console.log(chalk7.dim(" 4. Review Preview, refine, and apply the changes"));
5091
- console.log(chalk7.dim(" 5. Enhance Discover MCP servers for your tools"));
5092
- console.log(chalk7.dim(" 6. Skills Browse community skills for your stack\n"));
5249
+ console.log(chalk8.dim(" 1. Connect Set up your LLM provider"));
5250
+ console.log(chalk8.dim(" 2. Discover Analyze your code, dependencies, and structure"));
5251
+ console.log(chalk8.dim(" 3. Generate Create config files tailored to your project"));
5252
+ console.log(chalk8.dim(" 4. Review Preview, refine, and apply the changes"));
5253
+ console.log(chalk8.dim(" 5. Enhance Discover MCP servers for your tools"));
5254
+ console.log(chalk8.dim(" 6. Skills Browse community skills for your stack\n"));
5093
5255
  console.log(title.bold(" Step 1/6 \u2014 Connect your LLM\n"));
5094
5256
  let config = loadConfig();
5095
5257
  if (!config) {
5096
- console.log(chalk7.dim(" No LLM provider set yet. Choose how to run Caliber:\n"));
5258
+ console.log(chalk8.dim(" No LLM provider set yet. Choose how to run Caliber:\n"));
5097
5259
  try {
5098
5260
  await runInteractiveProviderSetup({
5099
5261
  selectMessage: "How do you want to use Caliber? (choose LLM provider)"
@@ -5104,25 +5266,28 @@ async function initCommand(options) {
5104
5266
  }
5105
5267
  config = loadConfig();
5106
5268
  if (!config) {
5107
- console.log(chalk7.red(" Setup was cancelled or failed.\n"));
5269
+ console.log(chalk8.red(" Setup was cancelled or failed.\n"));
5108
5270
  throw new Error("__exit__");
5109
5271
  }
5110
- console.log(chalk7.green(" \u2713 Provider saved. Let's continue.\n"));
5272
+ console.log(chalk8.green(" \u2713 Provider saved. Let's continue.\n"));
5111
5273
  }
5274
+ trackInitProviderSelected(config.provider, config.model);
5112
5275
  const displayModel = config.model === "default" && config.provider === "claude-cli" ? process.env.ANTHROPIC_MODEL || "default (inherited from Claude Code)" : config.model;
5113
5276
  const fastModel = getFastModel();
5114
5277
  const modelLine = fastModel ? ` Provider: ${config.provider} | Model: ${displayModel} | Scan: ${fastModel}` : ` Provider: ${config.provider} | Model: ${displayModel}`;
5115
- console.log(chalk7.dim(modelLine + "\n"));
5278
+ console.log(chalk8.dim(modelLine + "\n"));
5116
5279
  await validateModel({ fast: true });
5117
5280
  console.log(title.bold(" Step 2/6 \u2014 Discover your project\n"));
5118
- console.log(chalk7.dim(" Learning about your languages, dependencies, structure, and existing configs.\n"));
5281
+ console.log(chalk8.dim(" Learning about your languages, dependencies, structure, and existing configs.\n"));
5119
5282
  const spinner = ora2("Analyzing project...").start();
5120
5283
  const fingerprint = await collectFingerprint(process.cwd());
5121
5284
  spinner.succeed("Project analyzed");
5122
- console.log(chalk7.dim(` Languages: ${fingerprint.languages.join(", ") || "none detected"}`));
5123
- console.log(chalk7.dim(` Files: ${fingerprint.fileTree.length} found
5285
+ trackInitProjectDiscovered(fingerprint.languages.length, fingerprint.frameworks.length, fingerprint.fileTree.length);
5286
+ console.log(chalk8.dim(` Languages: ${fingerprint.languages.join(", ") || "none detected"}`));
5287
+ console.log(chalk8.dim(` Files: ${fingerprint.fileTree.length} found
5124
5288
  `));
5125
5289
  const targetAgent = options.agent || await promptAgent();
5290
+ trackInitAgentSelected(targetAgent);
5126
5291
  const preScore = computeLocalScore(process.cwd(), targetAgent);
5127
5292
  const failingForDismissal = preScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
5128
5293
  if (failingForDismissal.length > 0) {
@@ -5136,26 +5301,30 @@ async function initCommand(options) {
5136
5301
  }
5137
5302
  const baselineScore = computeLocalScore(process.cwd(), targetAgent);
5138
5303
  displayScoreSummary(baselineScore);
5304
+ const passingCount = baselineScore.checks.filter((c) => c.passed).length;
5305
+ const failingCount = baselineScore.checks.filter((c) => !c.passed).length;
5139
5306
  const hasExistingConfig = !!(fingerprint.existingConfigs.claudeMd || fingerprint.existingConfigs.claudeSettings || fingerprint.existingConfigs.claudeSkills?.length || fingerprint.existingConfigs.cursorrules || fingerprint.existingConfigs.cursorRules?.length || fingerprint.existingConfigs.agentsMd);
5140
5307
  const NON_LLM_CHECKS = /* @__PURE__ */ new Set(["hooks_configured", "agents_md_exists", "permissions_configured", "mcp_servers"]);
5141
5308
  if (hasExistingConfig && baselineScore.score === 100) {
5142
- console.log(chalk7.bold.green(" Your setup is already optimal \u2014 nothing to change.\n"));
5143
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber onboard --force") + chalk7.dim(" to regenerate anyway.\n"));
5309
+ trackInitScoreComputed(baselineScore.score, passingCount, failingCount, true);
5310
+ console.log(chalk8.bold.green(" Your setup is already optimal \u2014 nothing to change.\n"));
5311
+ console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber onboard --force") + chalk8.dim(" to regenerate anyway.\n"));
5144
5312
  if (!options.force) return;
5145
5313
  }
5146
5314
  const allFailingChecks = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
5147
5315
  const llmFixableChecks = allFailingChecks.filter((c) => !NON_LLM_CHECKS.has(c.id));
5316
+ trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
5148
5317
  if (hasExistingConfig && llmFixableChecks.length === 0 && allFailingChecks.length > 0 && !options.force) {
5149
- console.log(chalk7.bold.green("\n Your config is fully optimized for LLM generation.\n"));
5150
- console.log(chalk7.dim(" Remaining items need CLI actions:\n"));
5318
+ console.log(chalk8.bold.green("\n Your config is fully optimized for LLM generation.\n"));
5319
+ console.log(chalk8.dim(" Remaining items need CLI actions:\n"));
5151
5320
  for (const check of allFailingChecks) {
5152
- console.log(chalk7.dim(` \u2022 ${check.name}`));
5321
+ console.log(chalk8.dim(` \u2022 ${check.name}`));
5153
5322
  if (check.suggestion) {
5154
- console.log(` ${chalk7.hex("#83D1EB")(check.suggestion)}`);
5323
+ console.log(` ${chalk8.hex("#83D1EB")(check.suggestion)}`);
5155
5324
  }
5156
5325
  }
5157
5326
  console.log("");
5158
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber onboard --force") + chalk7.dim(" to regenerate anyway.\n"));
5327
+ console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber onboard --force") + chalk8.dim(" to regenerate anyway.\n"));
5159
5328
  return;
5160
5329
  }
5161
5330
  const isEmpty = fingerprint.fileTree.length < 3;
@@ -5171,22 +5340,23 @@ async function initCommand(options) {
5171
5340
  currentScore = baselineScore.score;
5172
5341
  if (failingChecks.length > 0) {
5173
5342
  console.log(title.bold(" Step 3/6 \u2014 Fine-tuning\n"));
5174
- console.log(chalk7.dim(` Your setup scores ${baselineScore.score}/100 \u2014 fixing ${failingChecks.length} remaining issue${failingChecks.length === 1 ? "" : "s"}:
5343
+ console.log(chalk8.dim(` Your setup scores ${baselineScore.score}/100 \u2014 fixing ${failingChecks.length} remaining issue${failingChecks.length === 1 ? "" : "s"}:
5175
5344
  `));
5176
5345
  for (const check of failingChecks) {
5177
- console.log(chalk7.dim(` \u2022 ${check.name}`));
5346
+ console.log(chalk8.dim(` \u2022 ${check.name}`));
5178
5347
  }
5179
5348
  console.log("");
5180
5349
  }
5181
5350
  } else if (hasExistingConfig) {
5182
5351
  console.log(title.bold(" Step 3/6 \u2014 Improve your setup\n"));
5183
- console.log(chalk7.dim(" Reviewing your existing configs against your codebase"));
5184
- console.log(chalk7.dim(" and preparing improvements.\n"));
5352
+ console.log(chalk8.dim(" Reviewing your existing configs against your codebase"));
5353
+ console.log(chalk8.dim(" and preparing improvements.\n"));
5185
5354
  } else {
5186
5355
  console.log(title.bold(" Step 3/6 \u2014 Build your agent setup\n"));
5187
- console.log(chalk7.dim(" Creating config files tailored to your project.\n"));
5356
+ console.log(chalk8.dim(" Creating config files tailored to your project.\n"));
5188
5357
  }
5189
- console.log(chalk7.dim(" This can take a couple of minutes depending on your model and provider.\n"));
5358
+ console.log(chalk8.dim(" This can take a couple of minutes depending on your model and provider.\n"));
5359
+ trackInitGenerationStarted(!!failingChecks);
5190
5360
  const genStartTime = Date.now();
5191
5361
  const genSpinner = ora2("Generating setup...").start();
5192
5362
  const genMessages = new SpinnerMessages(genSpinner, GENERATION_MESSAGES, { showElapsedTime: true });
@@ -5228,16 +5398,17 @@ async function initCommand(options) {
5228
5398
  if (!generatedSetup) {
5229
5399
  genSpinner.fail("Failed to generate setup.");
5230
5400
  if (rawOutput) {
5231
- console.log(chalk7.dim("\nRaw LLM output (JSON parse failed):"));
5232
- console.log(chalk7.dim(rawOutput.slice(0, 500)));
5401
+ console.log(chalk8.dim("\nRaw LLM output (JSON parse failed):"));
5402
+ console.log(chalk8.dim(rawOutput.slice(0, 500)));
5233
5403
  }
5234
5404
  throw new Error("__exit__");
5235
5405
  }
5236
5406
  const elapsedMs = Date.now() - genStartTime;
5407
+ trackInitGenerationCompleted(elapsedMs, 0);
5237
5408
  const mins = Math.floor(elapsedMs / 6e4);
5238
5409
  const secs = Math.floor(elapsedMs % 6e4 / 1e3);
5239
5410
  const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
5240
- genSpinner.succeed(`Setup generated ${chalk7.dim(`in ${timeStr}`)}`);
5411
+ genSpinner.succeed(`Setup generated ${chalk8.dim(`in ${timeStr}`)}`);
5241
5412
  printSetupSummary(generatedSetup);
5242
5413
  const sessionHistory = [];
5243
5414
  sessionHistory.push({
@@ -5248,11 +5419,11 @@ async function initCommand(options) {
5248
5419
  const setupFiles = collectSetupFiles(generatedSetup);
5249
5420
  const staged = stageFiles(setupFiles, process.cwd());
5250
5421
  const totalChanges = staged.newFiles + staged.modifiedFiles;
5251
- console.log(chalk7.dim(` ${chalk7.green(`${staged.newFiles} new`)} / ${chalk7.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
5422
+ console.log(chalk8.dim(` ${chalk8.green(`${staged.newFiles} new`)} / ${chalk8.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
5252
5423
  `));
5253
5424
  let action;
5254
5425
  if (totalChanges === 0) {
5255
- console.log(chalk7.dim(" No changes needed \u2014 your configs are already up to date.\n"));
5426
+ console.log(chalk8.dim(" No changes needed \u2014 your configs are already up to date.\n"));
5256
5427
  cleanupStaging();
5257
5428
  action = "accept";
5258
5429
  } else {
@@ -5262,29 +5433,34 @@ async function initCommand(options) {
5262
5433
  await openReview(reviewMethod, staged.stagedFiles);
5263
5434
  }
5264
5435
  action = await promptReviewAction();
5436
+ trackInitReviewAction(action, wantsReview ? "reviewed" : "skipped");
5265
5437
  }
5438
+ let refinementRound = 0;
5266
5439
  while (action === "refine") {
5440
+ refinementRound++;
5267
5441
  generatedSetup = await refineLoop(generatedSetup, targetAgent, sessionHistory);
5442
+ trackInitRefinementRound(refinementRound, !!generatedSetup);
5268
5443
  if (!generatedSetup) {
5269
5444
  cleanupStaging();
5270
- console.log(chalk7.dim("Refinement cancelled. No files were modified."));
5445
+ console.log(chalk8.dim("Refinement cancelled. No files were modified."));
5271
5446
  return;
5272
5447
  }
5273
5448
  const updatedFiles = collectSetupFiles(generatedSetup);
5274
5449
  const restaged = stageFiles(updatedFiles, process.cwd());
5275
- console.log(chalk7.dim(` ${chalk7.green(`${restaged.newFiles} new`)} / ${chalk7.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
5450
+ console.log(chalk8.dim(` ${chalk8.green(`${restaged.newFiles} new`)} / ${chalk8.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
5276
5451
  `));
5277
5452
  printSetupSummary(generatedSetup);
5278
5453
  await openReview("terminal", restaged.stagedFiles);
5279
5454
  action = await promptReviewAction();
5455
+ trackInitReviewAction(action, "terminal");
5280
5456
  }
5281
5457
  cleanupStaging();
5282
5458
  if (action === "decline") {
5283
- console.log(chalk7.dim("Setup declined. No files were modified."));
5459
+ console.log(chalk8.dim("Setup declined. No files were modified."));
5284
5460
  return;
5285
5461
  }
5286
5462
  if (options.dryRun) {
5287
- console.log(chalk7.yellow("\n[Dry run] Would write the following files:"));
5463
+ console.log(chalk8.yellow("\n[Dry run] Would write the following files:"));
5288
5464
  console.log(JSON.stringify(generatedSetup, null, 2));
5289
5465
  return;
5290
5466
  }
@@ -5292,23 +5468,29 @@ async function initCommand(options) {
5292
5468
  try {
5293
5469
  const result = writeSetup(generatedSetup);
5294
5470
  writeSpinner.succeed("Config files written");
5295
- console.log(chalk7.bold("\nFiles created/updated:"));
5471
+ trackInitFilesWritten(
5472
+ result.written.length + result.deleted.length,
5473
+ result.written.length,
5474
+ 0,
5475
+ result.deleted.length
5476
+ );
5477
+ console.log(chalk8.bold("\nFiles created/updated:"));
5296
5478
  for (const file of result.written) {
5297
- console.log(` ${chalk7.green("\u2713")} ${file}`);
5479
+ console.log(` ${chalk8.green("\u2713")} ${file}`);
5298
5480
  }
5299
5481
  if (result.deleted.length > 0) {
5300
- console.log(chalk7.bold("\nFiles removed:"));
5482
+ console.log(chalk8.bold("\nFiles removed:"));
5301
5483
  for (const file of result.deleted) {
5302
- console.log(` ${chalk7.red("\u2717")} ${file}`);
5484
+ console.log(` ${chalk8.red("\u2717")} ${file}`);
5303
5485
  }
5304
5486
  }
5305
5487
  if (result.backupDir) {
5306
- console.log(chalk7.dim(`
5488
+ console.log(chalk8.dim(`
5307
5489
  Backups saved to ${result.backupDir}`));
5308
5490
  }
5309
5491
  } catch (err) {
5310
5492
  writeSpinner.fail("Failed to write files");
5311
- console.error(chalk7.red(err instanceof Error ? err.message : "Unknown error"));
5493
+ console.error(chalk8.red(err instanceof Error ? err.message : "Unknown error"));
5312
5494
  throw new Error("__exit__");
5313
5495
  }
5314
5496
  ensurePermissions();
@@ -5320,55 +5502,57 @@ async function initCommand(options) {
5320
5502
  });
5321
5503
  console.log("");
5322
5504
  console.log(title.bold(" Keep your configs fresh\n"));
5323
- console.log(chalk7.dim(" Caliber can automatically update your agent configs when your code changes.\n"));
5505
+ console.log(chalk8.dim(" Caliber can automatically update your agent configs when your code changes.\n"));
5324
5506
  const hookChoice = await promptHookType(targetAgent);
5507
+ trackInitHookSelected(hookChoice);
5325
5508
  if (hookChoice === "claude" || hookChoice === "both") {
5326
5509
  const hookResult = installHook();
5327
5510
  if (hookResult.installed) {
5328
- console.log(` ${chalk7.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
5329
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber hooks --remove") + chalk7.dim(" to disable"));
5511
+ console.log(` ${chalk8.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
5512
+ console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber hooks --remove") + chalk8.dim(" to disable"));
5330
5513
  } else if (hookResult.alreadyInstalled) {
5331
- console.log(chalk7.dim(" Claude Code hook already installed"));
5514
+ console.log(chalk8.dim(" Claude Code hook already installed"));
5332
5515
  }
5333
5516
  const learnResult = installLearningHooks();
5334
5517
  if (learnResult.installed) {
5335
- console.log(` ${chalk7.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
5336
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber learn remove") + chalk7.dim(" to disable"));
5518
+ console.log(` ${chalk8.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
5519
+ console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber learn remove") + chalk8.dim(" to disable"));
5337
5520
  } else if (learnResult.alreadyInstalled) {
5338
- console.log(chalk7.dim(" Learning hooks already installed"));
5521
+ console.log(chalk8.dim(" Learning hooks already installed"));
5339
5522
  }
5340
5523
  }
5341
5524
  if (hookChoice === "precommit" || hookChoice === "both") {
5342
5525
  const precommitResult = installPreCommitHook();
5343
5526
  if (precommitResult.installed) {
5344
- console.log(` ${chalk7.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
5345
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber hooks --remove") + chalk7.dim(" to disable"));
5527
+ console.log(` ${chalk8.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
5528
+ console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber hooks --remove") + chalk8.dim(" to disable"));
5346
5529
  } else if (precommitResult.alreadyInstalled) {
5347
- console.log(chalk7.dim(" Pre-commit hook already installed"));
5530
+ console.log(chalk8.dim(" Pre-commit hook already installed"));
5348
5531
  } else {
5349
- console.log(chalk7.yellow(" Could not install pre-commit hook (not a git repository?)"));
5532
+ console.log(chalk8.yellow(" Could not install pre-commit hook (not a git repository?)"));
5350
5533
  }
5351
5534
  }
5352
5535
  if (hookChoice === "skip") {
5353
- console.log(chalk7.dim(" Skipped auto-refresh hooks. Run ") + chalk7.hex("#83D1EB")("caliber hooks --install") + chalk7.dim(" later to enable."));
5536
+ console.log(chalk8.dim(" Skipped auto-refresh hooks. Run ") + chalk8.hex("#83D1EB")("caliber hooks --install") + chalk8.dim(" later to enable."));
5354
5537
  }
5355
5538
  const afterScore = computeLocalScore(process.cwd(), targetAgent);
5356
5539
  if (afterScore.score < baselineScore.score) {
5540
+ trackInitScoreRegression(baselineScore.score, afterScore.score);
5357
5541
  console.log("");
5358
- console.log(chalk7.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
5542
+ console.log(chalk8.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
5359
5543
  try {
5360
5544
  const { restored, removed } = undoSetup();
5361
5545
  if (restored.length > 0 || removed.length > 0) {
5362
- console.log(chalk7.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
5546
+ console.log(chalk8.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
5363
5547
  }
5364
5548
  } catch {
5365
5549
  }
5366
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber onboard --force") + chalk7.dim(" to override.\n"));
5550
+ console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber onboard --force") + chalk8.dim(" to override.\n"));
5367
5551
  return;
5368
5552
  }
5369
5553
  displayScoreDelta(baselineScore, afterScore);
5370
5554
  console.log(title.bold("\n Step 6/6 \u2014 Community skills\n"));
5371
- console.log(chalk7.dim(" Search public skill registries for skills that match your tech stack.\n"));
5555
+ console.log(chalk8.dim(" Search public skill registries for skills that match your tech stack.\n"));
5372
5556
  const wantsSkills = await select5({
5373
5557
  message: "Search public repos for relevant skills to add to this project?",
5374
5558
  choices: [
@@ -5377,20 +5561,22 @@ async function initCommand(options) {
5377
5561
  ]
5378
5562
  });
5379
5563
  if (wantsSkills) {
5564
+ trackInitSkillsSearch(true, 0);
5380
5565
  try {
5381
5566
  await searchAndInstallSkills();
5382
5567
  } catch (err) {
5383
5568
  if (err.message !== "__exit__") {
5384
- console.log(chalk7.dim(" Skills search failed: " + (err.message || "unknown error")));
5569
+ console.log(chalk8.dim(" Skills search failed: " + (err.message || "unknown error")));
5385
5570
  }
5386
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber skills") + chalk7.dim(" later to try again.\n"));
5571
+ console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber skills") + chalk8.dim(" later to try again.\n"));
5387
5572
  }
5388
5573
  } else {
5389
- console.log(chalk7.dim(" Skipped. Run ") + chalk7.hex("#83D1EB")("caliber skills") + chalk7.dim(" later to browse.\n"));
5574
+ trackInitSkillsSearch(false, 0);
5575
+ console.log(chalk8.dim(" Skipped. Run ") + chalk8.hex("#83D1EB")("caliber skills") + chalk8.dim(" later to browse.\n"));
5390
5576
  }
5391
- console.log(chalk7.bold.green(" Onboarding complete! Your project is ready for AI-assisted development."));
5392
- console.log(chalk7.dim(" Run ") + chalk7.hex("#83D1EB")("caliber undo") + chalk7.dim(" to revert changes.\n"));
5393
- console.log(chalk7.bold(" Next steps:\n"));
5577
+ console.log(chalk8.bold.green(" Onboarding complete! Your project is ready for AI-assisted development."));
5578
+ console.log(chalk8.dim(" Run ") + chalk8.hex("#83D1EB")("caliber undo") + chalk8.dim(" to revert changes.\n"));
5579
+ console.log(chalk8.bold(" Next steps:\n"));
5394
5580
  console.log(` ${title("caliber score")} See your full config breakdown`);
5395
5581
  console.log(` ${title("caliber skills")} Discover community skills for your stack`);
5396
5582
  console.log(` ${title("caliber undo")} Revert all changes from this run`);
@@ -5407,9 +5593,9 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
5407
5593
  }
5408
5594
  const isValid = await classifyRefineIntent(message);
5409
5595
  if (!isValid) {
5410
- console.log(chalk7.dim(" This doesn't look like a config change request."));
5411
- console.log(chalk7.dim(" Describe what to add, remove, or modify in your configs."));
5412
- console.log(chalk7.dim(' Type "done" to accept the current setup.\n'));
5596
+ console.log(chalk8.dim(" This doesn't look like a config change request."));
5597
+ console.log(chalk8.dim(" Describe what to add, remove, or modify in your configs."));
5598
+ console.log(chalk8.dim(' Type "done" to accept the current setup.\n'));
5413
5599
  continue;
5414
5600
  }
5415
5601
  const refineSpinner = ora2("Refining setup...").start();
@@ -5430,16 +5616,16 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
5430
5616
  });
5431
5617
  refineSpinner.succeed("Setup updated");
5432
5618
  printSetupSummary(refined);
5433
- console.log(chalk7.dim('Type "done" to accept, or describe more changes.'));
5619
+ console.log(chalk8.dim('Type "done" to accept, or describe more changes.'));
5434
5620
  } else {
5435
5621
  refineSpinner.fail("Refinement failed \u2014 could not parse AI response.");
5436
- console.log(chalk7.dim('Try rephrasing your request, or type "done" to keep the current setup.'));
5622
+ console.log(chalk8.dim('Try rephrasing your request, or type "done" to keep the current setup.'));
5437
5623
  }
5438
5624
  }
5439
5625
  }
5440
5626
  function summarizeSetup(action, setup) {
5441
5627
  const descriptions = setup.fileDescriptions;
5442
- const files = descriptions ? Object.entries(descriptions).map(([path23, desc]) => ` ${path23}: ${desc}`).join("\n") : Object.keys(setup).filter((k) => k !== "targetAgent" && k !== "fileDescriptions").join(", ");
5628
+ const files = descriptions ? Object.entries(descriptions).map(([path24, desc]) => ` ${path24}: ${desc}`).join("\n") : Object.keys(setup).filter((k) => k !== "targetAgent" && k !== "fileDescriptions").join(", ");
5443
5629
  return `${action}. Files:
5444
5630
  ${files}`;
5445
5631
  }
@@ -5493,7 +5679,7 @@ ${JSON.stringify(checkList, null, 2)}`,
5493
5679
  function promptInput2(question) {
5494
5680
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
5495
5681
  return new Promise((resolve2) => {
5496
- rl.question(chalk7.cyan(`${question} `), (answer) => {
5682
+ rl.question(chalk8.cyan(`${question} `), (answer) => {
5497
5683
  rl.close();
5498
5684
  resolve2(answer.trim());
5499
5685
  });
@@ -5546,26 +5732,26 @@ function printSetupSummary(setup) {
5546
5732
  const fileDescriptions = setup.fileDescriptions;
5547
5733
  const deletions = setup.deletions;
5548
5734
  console.log("");
5549
- console.log(chalk7.bold(" Proposed changes:\n"));
5735
+ console.log(chalk8.bold(" Proposed changes:\n"));
5550
5736
  const getDescription = (filePath) => {
5551
5737
  return fileDescriptions?.[filePath];
5552
5738
  };
5553
5739
  if (claude) {
5554
5740
  if (claude.claudeMd) {
5555
- const icon = fs21.existsSync("CLAUDE.md") ? chalk7.yellow("~") : chalk7.green("+");
5741
+ const icon = fs22.existsSync("CLAUDE.md") ? chalk8.yellow("~") : chalk8.green("+");
5556
5742
  const desc = getDescription("CLAUDE.md");
5557
- console.log(` ${icon} ${chalk7.bold("CLAUDE.md")}`);
5558
- if (desc) console.log(chalk7.dim(` ${desc}`));
5743
+ console.log(` ${icon} ${chalk8.bold("CLAUDE.md")}`);
5744
+ if (desc) console.log(chalk8.dim(` ${desc}`));
5559
5745
  console.log("");
5560
5746
  }
5561
5747
  const skills = claude.skills;
5562
5748
  if (Array.isArray(skills) && skills.length > 0) {
5563
5749
  for (const skill of skills) {
5564
5750
  const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
5565
- const icon = fs21.existsSync(skillPath) ? chalk7.yellow("~") : chalk7.green("+");
5751
+ const icon = fs22.existsSync(skillPath) ? chalk8.yellow("~") : chalk8.green("+");
5566
5752
  const desc = getDescription(skillPath);
5567
- console.log(` ${icon} ${chalk7.bold(skillPath)}`);
5568
- console.log(chalk7.dim(` ${desc || skill.description || skill.name}`));
5753
+ console.log(` ${icon} ${chalk8.bold(skillPath)}`);
5754
+ console.log(chalk8.dim(` ${desc || skill.description || skill.name}`));
5569
5755
  console.log("");
5570
5756
  }
5571
5757
  }
@@ -5573,40 +5759,40 @@ function printSetupSummary(setup) {
5573
5759
  const codex = setup.codex;
5574
5760
  if (codex) {
5575
5761
  if (codex.agentsMd) {
5576
- const icon = fs21.existsSync("AGENTS.md") ? chalk7.yellow("~") : chalk7.green("+");
5762
+ const icon = fs22.existsSync("AGENTS.md") ? chalk8.yellow("~") : chalk8.green("+");
5577
5763
  const desc = getDescription("AGENTS.md");
5578
- console.log(` ${icon} ${chalk7.bold("AGENTS.md")}`);
5579
- if (desc) console.log(chalk7.dim(` ${desc}`));
5764
+ console.log(` ${icon} ${chalk8.bold("AGENTS.md")}`);
5765
+ if (desc) console.log(chalk8.dim(` ${desc}`));
5580
5766
  console.log("");
5581
5767
  }
5582
5768
  const codexSkills = codex.skills;
5583
5769
  if (Array.isArray(codexSkills) && codexSkills.length > 0) {
5584
5770
  for (const skill of codexSkills) {
5585
5771
  const skillPath = `.agents/skills/${skill.name}/SKILL.md`;
5586
- const icon = fs21.existsSync(skillPath) ? chalk7.yellow("~") : chalk7.green("+");
5772
+ const icon = fs22.existsSync(skillPath) ? chalk8.yellow("~") : chalk8.green("+");
5587
5773
  const desc = getDescription(skillPath);
5588
- console.log(` ${icon} ${chalk7.bold(skillPath)}`);
5589
- console.log(chalk7.dim(` ${desc || skill.description || skill.name}`));
5774
+ console.log(` ${icon} ${chalk8.bold(skillPath)}`);
5775
+ console.log(chalk8.dim(` ${desc || skill.description || skill.name}`));
5590
5776
  console.log("");
5591
5777
  }
5592
5778
  }
5593
5779
  }
5594
5780
  if (cursor) {
5595
5781
  if (cursor.cursorrules) {
5596
- const icon = fs21.existsSync(".cursorrules") ? chalk7.yellow("~") : chalk7.green("+");
5782
+ const icon = fs22.existsSync(".cursorrules") ? chalk8.yellow("~") : chalk8.green("+");
5597
5783
  const desc = getDescription(".cursorrules");
5598
- console.log(` ${icon} ${chalk7.bold(".cursorrules")}`);
5599
- if (desc) console.log(chalk7.dim(` ${desc}`));
5784
+ console.log(` ${icon} ${chalk8.bold(".cursorrules")}`);
5785
+ if (desc) console.log(chalk8.dim(` ${desc}`));
5600
5786
  console.log("");
5601
5787
  }
5602
5788
  const cursorSkills = cursor.skills;
5603
5789
  if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
5604
5790
  for (const skill of cursorSkills) {
5605
5791
  const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
5606
- const icon = fs21.existsSync(skillPath) ? chalk7.yellow("~") : chalk7.green("+");
5792
+ const icon = fs22.existsSync(skillPath) ? chalk8.yellow("~") : chalk8.green("+");
5607
5793
  const desc = getDescription(skillPath);
5608
- console.log(` ${icon} ${chalk7.bold(skillPath)}`);
5609
- console.log(chalk7.dim(` ${desc || skill.description || skill.name}`));
5794
+ console.log(` ${icon} ${chalk8.bold(skillPath)}`);
5795
+ console.log(chalk8.dim(` ${desc || skill.description || skill.name}`));
5610
5796
  console.log("");
5611
5797
  }
5612
5798
  }
@@ -5614,40 +5800,40 @@ function printSetupSummary(setup) {
5614
5800
  if (Array.isArray(rules) && rules.length > 0) {
5615
5801
  for (const rule of rules) {
5616
5802
  const rulePath = `.cursor/rules/${rule.filename}`;
5617
- const icon = fs21.existsSync(rulePath) ? chalk7.yellow("~") : chalk7.green("+");
5803
+ const icon = fs22.existsSync(rulePath) ? chalk8.yellow("~") : chalk8.green("+");
5618
5804
  const desc = getDescription(rulePath);
5619
- console.log(` ${icon} ${chalk7.bold(rulePath)}`);
5805
+ console.log(` ${icon} ${chalk8.bold(rulePath)}`);
5620
5806
  if (desc) {
5621
- console.log(chalk7.dim(` ${desc}`));
5807
+ console.log(chalk8.dim(` ${desc}`));
5622
5808
  } else {
5623
5809
  const firstLine = rule.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#"))[0];
5624
- if (firstLine) console.log(chalk7.dim(` ${firstLine.trim().slice(0, 80)}`));
5810
+ if (firstLine) console.log(chalk8.dim(` ${firstLine.trim().slice(0, 80)}`));
5625
5811
  }
5626
5812
  console.log("");
5627
5813
  }
5628
5814
  }
5629
5815
  }
5630
- if (!codex && !fs21.existsSync("AGENTS.md")) {
5631
- console.log(` ${chalk7.green("+")} ${chalk7.bold("AGENTS.md")}`);
5632
- console.log(chalk7.dim(" Cross-agent coordination file"));
5816
+ if (!codex && !fs22.existsSync("AGENTS.md")) {
5817
+ console.log(` ${chalk8.green("+")} ${chalk8.bold("AGENTS.md")}`);
5818
+ console.log(chalk8.dim(" Cross-agent coordination file"));
5633
5819
  console.log("");
5634
5820
  }
5635
5821
  if (Array.isArray(deletions) && deletions.length > 0) {
5636
5822
  for (const del of deletions) {
5637
- console.log(` ${chalk7.red("-")} ${chalk7.bold(del.filePath)}`);
5638
- console.log(chalk7.dim(` ${del.reason}`));
5823
+ console.log(` ${chalk8.red("-")} ${chalk8.bold(del.filePath)}`);
5824
+ console.log(chalk8.dim(` ${del.reason}`));
5639
5825
  console.log("");
5640
5826
  }
5641
5827
  }
5642
- console.log(` ${chalk7.green("+")} ${chalk7.dim("new")} ${chalk7.yellow("~")} ${chalk7.dim("modified")} ${chalk7.red("-")} ${chalk7.dim("removed")}`);
5828
+ console.log(` ${chalk8.green("+")} ${chalk8.dim("new")} ${chalk8.yellow("~")} ${chalk8.dim("modified")} ${chalk8.red("-")} ${chalk8.dim("removed")}`);
5643
5829
  console.log("");
5644
5830
  }
5645
5831
  function ensurePermissions() {
5646
5832
  const settingsPath = ".claude/settings.json";
5647
5833
  let settings = {};
5648
5834
  try {
5649
- if (fs21.existsSync(settingsPath)) {
5650
- settings = JSON.parse(fs21.readFileSync(settingsPath, "utf-8"));
5835
+ if (fs22.existsSync(settingsPath)) {
5836
+ settings = JSON.parse(fs22.readFileSync(settingsPath, "utf-8"));
5651
5837
  }
5652
5838
  } catch {
5653
5839
  }
@@ -5661,12 +5847,12 @@ function ensurePermissions() {
5661
5847
  "Bash(git *)"
5662
5848
  ];
5663
5849
  settings.permissions = permissions;
5664
- if (!fs21.existsSync(".claude")) fs21.mkdirSync(".claude", { recursive: true });
5665
- fs21.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
5850
+ if (!fs22.existsSync(".claude")) fs22.mkdirSync(".claude", { recursive: true });
5851
+ fs22.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
5666
5852
  }
5667
5853
 
5668
5854
  // src/commands/undo.ts
5669
- import chalk8 from "chalk";
5855
+ import chalk9 from "chalk";
5670
5856
  import ora3 from "ora";
5671
5857
  function undoCommand() {
5672
5858
  const spinner = ora3("Reverting setup...").start();
@@ -5676,29 +5862,30 @@ function undoCommand() {
5676
5862
  spinner.info("Nothing to undo.");
5677
5863
  return;
5678
5864
  }
5865
+ trackUndoExecuted();
5679
5866
  spinner.succeed("Setup reverted successfully.\n");
5680
5867
  if (restored.length > 0) {
5681
- console.log(chalk8.cyan(" Restored from backup:"));
5868
+ console.log(chalk9.cyan(" Restored from backup:"));
5682
5869
  for (const file of restored) {
5683
- console.log(` ${chalk8.green("\u21A9")} ${file}`);
5870
+ console.log(` ${chalk9.green("\u21A9")} ${file}`);
5684
5871
  }
5685
5872
  }
5686
5873
  if (removed.length > 0) {
5687
- console.log(chalk8.cyan(" Removed:"));
5874
+ console.log(chalk9.cyan(" Removed:"));
5688
5875
  for (const file of removed) {
5689
- console.log(` ${chalk8.red("\u2717")} ${file}`);
5876
+ console.log(` ${chalk9.red("\u2717")} ${file}`);
5690
5877
  }
5691
5878
  }
5692
5879
  console.log("");
5693
5880
  } catch (err) {
5694
- spinner.fail(chalk8.red(err instanceof Error ? err.message : "Undo failed"));
5881
+ spinner.fail(chalk9.red(err instanceof Error ? err.message : "Undo failed"));
5695
5882
  throw new Error("__exit__");
5696
5883
  }
5697
5884
  }
5698
5885
 
5699
5886
  // src/commands/status.ts
5700
- import chalk9 from "chalk";
5701
- import fs22 from "fs";
5887
+ import chalk10 from "chalk";
5888
+ import fs23 from "fs";
5702
5889
  init_config();
5703
5890
  async function statusCommand(options) {
5704
5891
  const config = loadConfig();
@@ -5712,40 +5899,40 @@ async function statusCommand(options) {
5712
5899
  }, null, 2));
5713
5900
  return;
5714
5901
  }
5715
- console.log(chalk9.bold("\nCaliber Status\n"));
5902
+ console.log(chalk10.bold("\nCaliber Status\n"));
5716
5903
  if (config) {
5717
- console.log(` LLM: ${chalk9.green(config.provider)} (${config.model})`);
5904
+ console.log(` LLM: ${chalk10.green(config.provider)} (${config.model})`);
5718
5905
  } else {
5719
- console.log(` LLM: ${chalk9.yellow("Not configured")} \u2014 run ${chalk9.hex("#83D1EB")("caliber config")}`);
5906
+ console.log(` LLM: ${chalk10.yellow("Not configured")} \u2014 run ${chalk10.hex("#83D1EB")("caliber config")}`);
5720
5907
  }
5721
5908
  if (!manifest) {
5722
- console.log(` Setup: ${chalk9.dim("No setup applied")}`);
5723
- console.log(chalk9.dim("\n Run ") + chalk9.hex("#83D1EB")("caliber onboard") + chalk9.dim(" to get started.\n"));
5909
+ console.log(` Setup: ${chalk10.dim("No setup applied")}`);
5910
+ console.log(chalk10.dim("\n Run ") + chalk10.hex("#83D1EB")("caliber onboard") + chalk10.dim(" to get started.\n"));
5724
5911
  return;
5725
5912
  }
5726
- console.log(` Files managed: ${chalk9.cyan(manifest.entries.length.toString())}`);
5913
+ console.log(` Files managed: ${chalk10.cyan(manifest.entries.length.toString())}`);
5727
5914
  for (const entry of manifest.entries) {
5728
- const exists = fs22.existsSync(entry.path);
5729
- const icon = exists ? chalk9.green("\u2713") : chalk9.red("\u2717");
5915
+ const exists = fs23.existsSync(entry.path);
5916
+ const icon = exists ? chalk10.green("\u2713") : chalk10.red("\u2717");
5730
5917
  console.log(` ${icon} ${entry.path} (${entry.action})`);
5731
5918
  }
5732
5919
  console.log("");
5733
5920
  }
5734
5921
 
5735
5922
  // src/commands/regenerate.ts
5736
- import chalk10 from "chalk";
5923
+ import chalk11 from "chalk";
5737
5924
  import ora4 from "ora";
5738
5925
  import select6 from "@inquirer/select";
5739
5926
  init_config();
5740
5927
  async function regenerateCommand(options) {
5741
5928
  const config = loadConfig();
5742
5929
  if (!config) {
5743
- console.log(chalk10.red("No LLM provider configured. Run ") + chalk10.hex("#83D1EB")("caliber config") + chalk10.red(" first."));
5930
+ console.log(chalk11.red("No LLM provider configured. Run ") + chalk11.hex("#83D1EB")("caliber config") + chalk11.red(" first."));
5744
5931
  throw new Error("__exit__");
5745
5932
  }
5746
5933
  const manifest = readManifest();
5747
5934
  if (!manifest) {
5748
- console.log(chalk10.yellow("No existing setup found. Run ") + chalk10.hex("#83D1EB")("caliber onboard") + chalk10.yellow(" first."));
5935
+ console.log(chalk11.yellow("No existing setup found. Run ") + chalk11.hex("#83D1EB")("caliber onboard") + chalk11.yellow(" first."));
5749
5936
  throw new Error("__exit__");
5750
5937
  }
5751
5938
  const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
@@ -5756,7 +5943,7 @@ async function regenerateCommand(options) {
5756
5943
  const baselineScore = computeLocalScore(process.cwd(), targetAgent);
5757
5944
  displayScoreSummary(baselineScore);
5758
5945
  if (baselineScore.score === 100) {
5759
- console.log(chalk10.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
5946
+ console.log(chalk11.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
5760
5947
  return;
5761
5948
  }
5762
5949
  const genSpinner = ora4("Regenerating setup...").start();
@@ -5797,18 +5984,18 @@ async function regenerateCommand(options) {
5797
5984
  const setupFiles = collectSetupFiles(generatedSetup);
5798
5985
  const staged = stageFiles(setupFiles, process.cwd());
5799
5986
  const totalChanges = staged.newFiles + staged.modifiedFiles;
5800
- console.log(chalk10.dim(`
5801
- ${chalk10.green(`${staged.newFiles} new`)} / ${chalk10.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
5987
+ console.log(chalk11.dim(`
5988
+ ${chalk11.green(`${staged.newFiles} new`)} / ${chalk11.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
5802
5989
  `));
5803
5990
  if (totalChanges === 0) {
5804
- console.log(chalk10.dim(" No changes needed \u2014 your configs are already up to date.\n"));
5991
+ console.log(chalk11.dim(" No changes needed \u2014 your configs are already up to date.\n"));
5805
5992
  cleanupStaging();
5806
5993
  return;
5807
5994
  }
5808
5995
  if (options.dryRun) {
5809
- console.log(chalk10.yellow("[Dry run] Would write:"));
5996
+ console.log(chalk11.yellow("[Dry run] Would write:"));
5810
5997
  for (const f of staged.stagedFiles) {
5811
- console.log(` ${f.isNew ? chalk10.green("+") : chalk10.yellow("~")} ${f.relativePath}`);
5998
+ console.log(` ${f.isNew ? chalk11.green("+") : chalk11.yellow("~")} ${f.relativePath}`);
5812
5999
  }
5813
6000
  cleanupStaging();
5814
6001
  return;
@@ -5827,7 +6014,7 @@ async function regenerateCommand(options) {
5827
6014
  });
5828
6015
  cleanupStaging();
5829
6016
  if (action === "decline") {
5830
- console.log(chalk10.dim("Regeneration cancelled. No files were modified."));
6017
+ console.log(chalk11.dim("Regeneration cancelled. No files were modified."));
5831
6018
  return;
5832
6019
  }
5833
6020
  const writeSpinner = ora4("Writing config files...").start();
@@ -5835,20 +6022,20 @@ async function regenerateCommand(options) {
5835
6022
  const result = writeSetup(generatedSetup);
5836
6023
  writeSpinner.succeed("Config files written");
5837
6024
  for (const file of result.written) {
5838
- console.log(` ${chalk10.green("\u2713")} ${file}`);
6025
+ console.log(` ${chalk11.green("\u2713")} ${file}`);
5839
6026
  }
5840
6027
  if (result.deleted.length > 0) {
5841
6028
  for (const file of result.deleted) {
5842
- console.log(` ${chalk10.red("\u2717")} ${file}`);
6029
+ console.log(` ${chalk11.red("\u2717")} ${file}`);
5843
6030
  }
5844
6031
  }
5845
6032
  if (result.backupDir) {
5846
- console.log(chalk10.dim(`
6033
+ console.log(chalk11.dim(`
5847
6034
  Backups saved to ${result.backupDir}`));
5848
6035
  }
5849
6036
  } catch (err) {
5850
6037
  writeSpinner.fail("Failed to write files");
5851
- console.error(chalk10.red(err instanceof Error ? err.message : "Unknown error"));
6038
+ console.error(chalk11.red(err instanceof Error ? err.message : "Unknown error"));
5852
6039
  throw new Error("__exit__");
5853
6040
  }
5854
6041
  const sha = getCurrentHeadSha();
@@ -5860,28 +6047,30 @@ async function regenerateCommand(options) {
5860
6047
  const afterScore = computeLocalScore(process.cwd(), targetAgent);
5861
6048
  if (afterScore.score < baselineScore.score) {
5862
6049
  console.log("");
5863
- console.log(chalk10.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
6050
+ console.log(chalk11.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
5864
6051
  try {
5865
6052
  const { restored, removed } = undoSetup();
5866
6053
  if (restored.length > 0 || removed.length > 0) {
5867
- console.log(chalk10.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
6054
+ console.log(chalk11.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
5868
6055
  }
5869
6056
  } catch {
5870
6057
  }
5871
- console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber onboard --force") + chalk10.dim(" to override.\n"));
6058
+ console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber onboard --force") + chalk11.dim(" to override.\n"));
5872
6059
  return;
5873
6060
  }
5874
6061
  displayScoreDelta(baselineScore, afterScore);
5875
- console.log(chalk10.bold.green(" Regeneration complete!"));
5876
- console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber undo") + chalk10.dim(" to revert changes.\n"));
6062
+ trackRegenerateCompleted(action, Date.now());
6063
+ console.log(chalk11.bold.green(" Regeneration complete!"));
6064
+ console.log(chalk11.dim(" Run ") + chalk11.hex("#83D1EB")("caliber undo") + chalk11.dim(" to revert changes.\n"));
5877
6065
  }
5878
6066
 
5879
6067
  // src/commands/score.ts
5880
- import chalk11 from "chalk";
6068
+ import chalk12 from "chalk";
5881
6069
  async function scoreCommand(options) {
5882
6070
  const dir = process.cwd();
5883
6071
  const target = options.agent ?? readState()?.targetAgent;
5884
6072
  const result = computeLocalScore(dir, target);
6073
+ trackScoreComputed(result.score, target);
5885
6074
  if (options.json) {
5886
6075
  console.log(JSON.stringify(result, null, 2));
5887
6076
  return;
@@ -5891,26 +6080,26 @@ async function scoreCommand(options) {
5891
6080
  return;
5892
6081
  }
5893
6082
  displayScore(result);
5894
- const separator = chalk11.gray(" " + "\u2500".repeat(53));
6083
+ const separator = chalk12.gray(" " + "\u2500".repeat(53));
5895
6084
  console.log(separator);
5896
6085
  if (result.score < 40) {
5897
- console.log(chalk11.gray(" Run ") + chalk11.hex("#83D1EB")("caliber onboard") + chalk11.gray(" to generate a complete, optimized setup."));
6086
+ console.log(chalk12.gray(" Run ") + chalk12.hex("#83D1EB")("caliber onboard") + chalk12.gray(" to generate a complete, optimized setup."));
5898
6087
  } else if (result.score < 70) {
5899
- console.log(chalk11.gray(" Run ") + chalk11.hex("#83D1EB")("caliber onboard") + chalk11.gray(" to improve your setup."));
6088
+ console.log(chalk12.gray(" Run ") + chalk12.hex("#83D1EB")("caliber onboard") + chalk12.gray(" to improve your setup."));
5900
6089
  } else {
5901
- console.log(chalk11.green(" Looking good!") + chalk11.gray(" Run ") + chalk11.hex("#83D1EB")("caliber regenerate") + chalk11.gray(" to rebuild from scratch."));
6090
+ console.log(chalk12.green(" Looking good!") + chalk12.gray(" Run ") + chalk12.hex("#83D1EB")("caliber regenerate") + chalk12.gray(" to rebuild from scratch."));
5902
6091
  }
5903
6092
  console.log("");
5904
6093
  }
5905
6094
 
5906
6095
  // src/commands/refresh.ts
5907
- import fs24 from "fs";
5908
- import path18 from "path";
5909
- import chalk12 from "chalk";
6096
+ import fs25 from "fs";
6097
+ import path19 from "path";
6098
+ import chalk13 from "chalk";
5910
6099
  import ora5 from "ora";
5911
6100
 
5912
6101
  // src/lib/git-diff.ts
5913
- import { execSync as execSync8 } from "child_process";
6102
+ import { execSync as execSync9 } from "child_process";
5914
6103
  var MAX_DIFF_BYTES = 1e5;
5915
6104
  var DOC_PATTERNS = [
5916
6105
  "CLAUDE.md",
@@ -5924,7 +6113,7 @@ function excludeArgs() {
5924
6113
  }
5925
6114
  function safeExec(cmd) {
5926
6115
  try {
5927
- return execSync8(cmd, {
6116
+ return execSync9(cmd, {
5928
6117
  encoding: "utf-8",
5929
6118
  stdio: ["pipe", "pipe", "pipe"],
5930
6119
  maxBuffer: 10 * 1024 * 1024
@@ -5982,37 +6171,37 @@ function collectDiff(lastSha) {
5982
6171
  }
5983
6172
 
5984
6173
  // src/writers/refresh.ts
5985
- import fs23 from "fs";
5986
- import path17 from "path";
6174
+ import fs24 from "fs";
6175
+ import path18 from "path";
5987
6176
  function writeRefreshDocs(docs) {
5988
6177
  const written = [];
5989
6178
  if (docs.claudeMd) {
5990
- fs23.writeFileSync("CLAUDE.md", docs.claudeMd);
6179
+ fs24.writeFileSync("CLAUDE.md", docs.claudeMd);
5991
6180
  written.push("CLAUDE.md");
5992
6181
  }
5993
6182
  if (docs.readmeMd) {
5994
- fs23.writeFileSync("README.md", docs.readmeMd);
6183
+ fs24.writeFileSync("README.md", docs.readmeMd);
5995
6184
  written.push("README.md");
5996
6185
  }
5997
6186
  if (docs.cursorrules) {
5998
- fs23.writeFileSync(".cursorrules", docs.cursorrules);
6187
+ fs24.writeFileSync(".cursorrules", docs.cursorrules);
5999
6188
  written.push(".cursorrules");
6000
6189
  }
6001
6190
  if (docs.cursorRules) {
6002
- const rulesDir = path17.join(".cursor", "rules");
6003
- if (!fs23.existsSync(rulesDir)) fs23.mkdirSync(rulesDir, { recursive: true });
6191
+ const rulesDir = path18.join(".cursor", "rules");
6192
+ if (!fs24.existsSync(rulesDir)) fs24.mkdirSync(rulesDir, { recursive: true });
6004
6193
  for (const rule of docs.cursorRules) {
6005
- const filePath = path17.join(rulesDir, rule.filename);
6006
- fs23.writeFileSync(filePath, rule.content);
6194
+ const filePath = path18.join(rulesDir, rule.filename);
6195
+ fs24.writeFileSync(filePath, rule.content);
6007
6196
  written.push(filePath);
6008
6197
  }
6009
6198
  }
6010
6199
  if (docs.claudeSkills) {
6011
- const skillsDir = path17.join(".claude", "skills");
6012
- if (!fs23.existsSync(skillsDir)) fs23.mkdirSync(skillsDir, { recursive: true });
6200
+ const skillsDir = path18.join(".claude", "skills");
6201
+ if (!fs24.existsSync(skillsDir)) fs24.mkdirSync(skillsDir, { recursive: true });
6013
6202
  for (const skill of docs.claudeSkills) {
6014
- const filePath = path17.join(skillsDir, skill.filename);
6015
- fs23.writeFileSync(filePath, skill.content);
6203
+ const filePath = path18.join(skillsDir, skill.filename);
6204
+ fs24.writeFileSync(filePath, skill.content);
6016
6205
  written.push(filePath);
6017
6206
  }
6018
6207
  }
@@ -6091,11 +6280,11 @@ function log(quiet, ...args) {
6091
6280
  function discoverGitRepos(parentDir) {
6092
6281
  const repos = [];
6093
6282
  try {
6094
- const entries = fs24.readdirSync(parentDir, { withFileTypes: true });
6283
+ const entries = fs25.readdirSync(parentDir, { withFileTypes: true });
6095
6284
  for (const entry of entries) {
6096
6285
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
6097
- const childPath = path18.join(parentDir, entry.name);
6098
- if (fs24.existsSync(path18.join(childPath, ".git"))) {
6286
+ const childPath = path19.join(parentDir, entry.name);
6287
+ if (fs25.existsSync(path19.join(childPath, ".git"))) {
6099
6288
  repos.push(childPath);
6100
6289
  }
6101
6290
  }
@@ -6105,7 +6294,7 @@ function discoverGitRepos(parentDir) {
6105
6294
  }
6106
6295
  async function refreshSingleRepo(repoDir, options) {
6107
6296
  const quiet = !!options.quiet;
6108
- const prefix = options.label ? `${chalk12.bold(options.label)} ` : "";
6297
+ const prefix = options.label ? `${chalk13.bold(options.label)} ` : "";
6109
6298
  const state = readState();
6110
6299
  const lastSha = state?.lastRefreshSha ?? null;
6111
6300
  const diff = collectDiff(lastSha);
@@ -6114,7 +6303,7 @@ async function refreshSingleRepo(repoDir, options) {
6114
6303
  if (currentSha) {
6115
6304
  writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
6116
6305
  }
6117
- log(quiet, chalk12.dim(`${prefix}No changes since last refresh.`));
6306
+ log(quiet, chalk13.dim(`${prefix}No changes since last refresh.`));
6118
6307
  return;
6119
6308
  }
6120
6309
  const spinner = quiet ? null : ora5(`${prefix}Analyzing changes...`).start();
@@ -6146,21 +6335,22 @@ async function refreshSingleRepo(repoDir, options) {
6146
6335
  if (options.dryRun) {
6147
6336
  spinner?.info(`${prefix}Dry run \u2014 would update:`);
6148
6337
  for (const doc of response.docsUpdated) {
6149
- console.log(` ${chalk12.yellow("~")} ${doc}`);
6338
+ console.log(` ${chalk13.yellow("~")} ${doc}`);
6150
6339
  }
6151
6340
  if (response.changesSummary) {
6152
- console.log(chalk12.dim(`
6341
+ console.log(chalk13.dim(`
6153
6342
  ${response.changesSummary}`));
6154
6343
  }
6155
6344
  return;
6156
6345
  }
6157
6346
  const written = writeRefreshDocs(response.updatedDocs);
6347
+ trackRefreshCompleted(written.length, Date.now());
6158
6348
  spinner?.succeed(`${prefix}Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
6159
6349
  for (const file of written) {
6160
- log(quiet, ` ${chalk12.green("\u2713")} ${file}`);
6350
+ log(quiet, ` ${chalk13.green("\u2713")} ${file}`);
6161
6351
  }
6162
6352
  if (response.changesSummary) {
6163
- log(quiet, chalk12.dim(`
6353
+ log(quiet, chalk13.dim(`
6164
6354
  ${response.changesSummary}`));
6165
6355
  }
6166
6356
  if (currentSha) {
@@ -6173,7 +6363,7 @@ async function refreshCommand(options) {
6173
6363
  const config = loadConfig();
6174
6364
  if (!config) {
6175
6365
  if (quiet) return;
6176
- console.log(chalk12.red("No LLM provider configured. Run ") + chalk12.hex("#83D1EB")("caliber config") + chalk12.red(" (e.g. choose Cursor) or set an API key."));
6366
+ console.log(chalk13.red("No LLM provider configured. Run ") + chalk13.hex("#83D1EB")("caliber config") + chalk13.red(" (e.g. choose Cursor) or set an API key."));
6177
6367
  throw new Error("__exit__");
6178
6368
  }
6179
6369
  await validateModel({ fast: true });
@@ -6184,20 +6374,20 @@ async function refreshCommand(options) {
6184
6374
  const repos = discoverGitRepos(process.cwd());
6185
6375
  if (repos.length === 0) {
6186
6376
  if (quiet) return;
6187
- console.log(chalk12.red("Not inside a git repository and no git repos found in child directories."));
6377
+ console.log(chalk13.red("Not inside a git repository and no git repos found in child directories."));
6188
6378
  throw new Error("__exit__");
6189
6379
  }
6190
- log(quiet, chalk12.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
6380
+ log(quiet, chalk13.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
6191
6381
  `));
6192
6382
  const originalDir = process.cwd();
6193
6383
  for (const repo of repos) {
6194
- const repoName = path18.basename(repo);
6384
+ const repoName = path19.basename(repo);
6195
6385
  try {
6196
6386
  process.chdir(repo);
6197
6387
  await refreshSingleRepo(repo, { ...options, label: repoName });
6198
6388
  } catch (err) {
6199
6389
  if (err instanceof Error && err.message === "__exit__") continue;
6200
- log(quiet, chalk12.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
6390
+ log(quiet, chalk13.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
6201
6391
  }
6202
6392
  }
6203
6393
  process.chdir(originalDir);
@@ -6205,13 +6395,13 @@ async function refreshCommand(options) {
6205
6395
  if (err instanceof Error && err.message === "__exit__") throw err;
6206
6396
  if (quiet) return;
6207
6397
  const msg = err instanceof Error ? err.message : "Unknown error";
6208
- console.log(chalk12.red(`Refresh failed: ${msg}`));
6398
+ console.log(chalk13.red(`Refresh failed: ${msg}`));
6209
6399
  throw new Error("__exit__");
6210
6400
  }
6211
6401
  }
6212
6402
 
6213
6403
  // src/commands/hooks.ts
6214
- import chalk13 from "chalk";
6404
+ import chalk14 from "chalk";
6215
6405
  var HOOKS = [
6216
6406
  {
6217
6407
  id: "session-end",
@@ -6231,13 +6421,13 @@ var HOOKS = [
6231
6421
  }
6232
6422
  ];
6233
6423
  function printStatus() {
6234
- console.log(chalk13.bold("\n Hooks\n"));
6424
+ console.log(chalk14.bold("\n Hooks\n"));
6235
6425
  for (const hook of HOOKS) {
6236
6426
  const installed = hook.isInstalled();
6237
- const icon = installed ? chalk13.green("\u2713") : chalk13.dim("\u2717");
6238
- const state = installed ? chalk13.green("enabled") : chalk13.dim("disabled");
6427
+ const icon = installed ? chalk14.green("\u2713") : chalk14.dim("\u2717");
6428
+ const state = installed ? chalk14.green("enabled") : chalk14.dim("disabled");
6239
6429
  console.log(` ${icon} ${hook.label.padEnd(26)} ${state}`);
6240
- console.log(chalk13.dim(` ${hook.description}`));
6430
+ console.log(chalk14.dim(` ${hook.description}`));
6241
6431
  }
6242
6432
  console.log("");
6243
6433
  }
@@ -6246,9 +6436,9 @@ async function hooksCommand(options) {
6246
6436
  for (const hook of HOOKS) {
6247
6437
  const result = hook.install();
6248
6438
  if (result.alreadyInstalled) {
6249
- console.log(chalk13.dim(` ${hook.label} already enabled.`));
6439
+ console.log(chalk14.dim(` ${hook.label} already enabled.`));
6250
6440
  } else {
6251
- console.log(chalk13.green(" \u2713") + ` ${hook.label} enabled`);
6441
+ console.log(chalk14.green(" \u2713") + ` ${hook.label} enabled`);
6252
6442
  }
6253
6443
  }
6254
6444
  return;
@@ -6257,9 +6447,9 @@ async function hooksCommand(options) {
6257
6447
  for (const hook of HOOKS) {
6258
6448
  const result = hook.remove();
6259
6449
  if (result.notFound) {
6260
- console.log(chalk13.dim(` ${hook.label} already disabled.`));
6450
+ console.log(chalk14.dim(` ${hook.label} already disabled.`));
6261
6451
  } else {
6262
- console.log(chalk13.green(" \u2713") + ` ${hook.label} removed`);
6452
+ console.log(chalk14.green(" \u2713") + ` ${hook.label} removed`);
6263
6453
  }
6264
6454
  }
6265
6455
  return;
@@ -6274,18 +6464,18 @@ async function hooksCommand(options) {
6274
6464
  const states = HOOKS.map((h) => h.isInstalled());
6275
6465
  function render() {
6276
6466
  const lines = [];
6277
- lines.push(chalk13.bold(" Hooks"));
6467
+ lines.push(chalk14.bold(" Hooks"));
6278
6468
  lines.push("");
6279
6469
  for (let i = 0; i < HOOKS.length; i++) {
6280
6470
  const hook = HOOKS[i];
6281
6471
  const enabled = states[i];
6282
- const toggle = enabled ? chalk13.green("[on] ") : chalk13.dim("[off]");
6283
- const ptr = i === cursor ? chalk13.cyan(">") : " ";
6472
+ const toggle = enabled ? chalk14.green("[on] ") : chalk14.dim("[off]");
6473
+ const ptr = i === cursor ? chalk14.cyan(">") : " ";
6284
6474
  lines.push(` ${ptr} ${toggle} ${hook.label}`);
6285
- lines.push(chalk13.dim(` ${hook.description}`));
6475
+ lines.push(chalk14.dim(` ${hook.description}`));
6286
6476
  }
6287
6477
  lines.push("");
6288
- lines.push(chalk13.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
6478
+ lines.push(chalk14.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
6289
6479
  return lines.join("\n");
6290
6480
  }
6291
6481
  function draw(initial) {
@@ -6316,16 +6506,16 @@ async function hooksCommand(options) {
6316
6506
  const wantEnabled = states[i];
6317
6507
  if (wantEnabled && !wasInstalled) {
6318
6508
  hook.install();
6319
- console.log(chalk13.green(" \u2713") + ` ${hook.label} enabled`);
6509
+ console.log(chalk14.green(" \u2713") + ` ${hook.label} enabled`);
6320
6510
  changed++;
6321
6511
  } else if (!wantEnabled && wasInstalled) {
6322
6512
  hook.remove();
6323
- console.log(chalk13.green(" \u2713") + ` ${hook.label} disabled`);
6513
+ console.log(chalk14.green(" \u2713") + ` ${hook.label} disabled`);
6324
6514
  changed++;
6325
6515
  }
6326
6516
  }
6327
6517
  if (changed === 0) {
6328
- console.log(chalk13.dim(" No changes."));
6518
+ console.log(chalk14.dim(" No changes."));
6329
6519
  }
6330
6520
  console.log("");
6331
6521
  }
@@ -6361,7 +6551,7 @@ async function hooksCommand(options) {
6361
6551
  case "\x1B":
6362
6552
  case "":
6363
6553
  cleanup();
6364
- console.log(chalk13.dim("\n Cancelled.\n"));
6554
+ console.log(chalk14.dim("\n Cancelled.\n"));
6365
6555
  resolve2();
6366
6556
  break;
6367
6557
  }
@@ -6372,48 +6562,50 @@ async function hooksCommand(options) {
6372
6562
 
6373
6563
  // src/commands/config.ts
6374
6564
  init_config();
6375
- import chalk14 from "chalk";
6565
+ import chalk15 from "chalk";
6376
6566
  async function configCommand() {
6377
6567
  const existing = loadConfig();
6378
6568
  if (existing) {
6379
6569
  const displayModel = existing.model === "default" && existing.provider === "claude-cli" ? process.env.ANTHROPIC_MODEL || "default (inherited from Claude Code)" : existing.model;
6380
6570
  const fastModel = getFastModel();
6381
- console.log(chalk14.bold("\nCurrent Configuration\n"));
6382
- console.log(` Provider: ${chalk14.cyan(existing.provider)}`);
6383
- console.log(` Model: ${chalk14.cyan(displayModel)}`);
6571
+ console.log(chalk15.bold("\nCurrent Configuration\n"));
6572
+ console.log(` Provider: ${chalk15.cyan(existing.provider)}`);
6573
+ console.log(` Model: ${chalk15.cyan(displayModel)}`);
6384
6574
  if (fastModel) {
6385
- console.log(` Scan: ${chalk14.cyan(fastModel)}`);
6575
+ console.log(` Scan: ${chalk15.cyan(fastModel)}`);
6386
6576
  }
6387
6577
  if (existing.apiKey) {
6388
6578
  const masked = existing.apiKey.slice(0, 8) + "..." + existing.apiKey.slice(-4);
6389
- console.log(` API Key: ${chalk14.dim(masked)}`);
6579
+ console.log(` API Key: ${chalk15.dim(masked)}`);
6390
6580
  }
6391
6581
  if (existing.provider === "cursor") {
6392
- console.log(` Seat: ${chalk14.dim("Cursor (agent acp)")}`);
6582
+ console.log(` Seat: ${chalk15.dim("Cursor (agent acp)")}`);
6393
6583
  }
6394
6584
  if (existing.provider === "claude-cli") {
6395
- console.log(` Seat: ${chalk14.dim("Claude Code (claude -p)")}`);
6585
+ console.log(` Seat: ${chalk15.dim("Claude Code (claude -p)")}`);
6396
6586
  }
6397
6587
  if (existing.baseUrl) {
6398
- console.log(` Base URL: ${chalk14.dim(existing.baseUrl)}`);
6588
+ console.log(` Base URL: ${chalk15.dim(existing.baseUrl)}`);
6399
6589
  }
6400
6590
  if (existing.vertexProjectId) {
6401
- console.log(` Vertex Project: ${chalk14.dim(existing.vertexProjectId)}`);
6402
- console.log(` Vertex Region: ${chalk14.dim(existing.vertexRegion || "us-east5")}`);
6591
+ console.log(` Vertex Project: ${chalk15.dim(existing.vertexProjectId)}`);
6592
+ console.log(` Vertex Region: ${chalk15.dim(existing.vertexRegion || "us-east5")}`);
6403
6593
  }
6404
- console.log(` Source: ${chalk14.dim(process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || process.env.VERTEX_PROJECT_ID || process.env.CALIBER_USE_CURSOR_SEAT || process.env.CALIBER_USE_CLAUDE_CLI ? "environment variables" : getConfigFilePath())}`);
6594
+ console.log(` Source: ${chalk15.dim(process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || process.env.VERTEX_PROJECT_ID || process.env.CALIBER_USE_CURSOR_SEAT || process.env.CALIBER_USE_CLAUDE_CLI ? "environment variables" : getConfigFilePath())}`);
6405
6595
  console.log("");
6406
6596
  }
6407
6597
  await runInteractiveProviderSetup();
6408
- console.log(chalk14.green("\n\u2713 Configuration saved"));
6409
- console.log(chalk14.dim(` ${getConfigFilePath()}
6598
+ const updated = loadConfig();
6599
+ if (updated) trackConfigProviderSet(updated.provider);
6600
+ console.log(chalk15.green("\n\u2713 Configuration saved"));
6601
+ console.log(chalk15.dim(` ${getConfigFilePath()}
6410
6602
  `));
6411
- console.log(chalk14.dim(" You can also set environment variables instead:"));
6412
- console.log(chalk14.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
6603
+ console.log(chalk15.dim(" You can also set environment variables instead:"));
6604
+ console.log(chalk15.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
6413
6605
  }
6414
6606
 
6415
6607
  // src/commands/learn.ts
6416
- import chalk15 from "chalk";
6608
+ import chalk16 from "chalk";
6417
6609
 
6418
6610
  // src/learner/stdin.ts
6419
6611
  var STDIN_TIMEOUT_MS = 5e3;
@@ -6444,8 +6636,8 @@ function readStdin() {
6444
6636
 
6445
6637
  // src/learner/storage.ts
6446
6638
  init_constants();
6447
- import fs25 from "fs";
6448
- import path19 from "path";
6639
+ import fs26 from "fs";
6640
+ import path20 from "path";
6449
6641
  var MAX_RESPONSE_LENGTH = 2e3;
6450
6642
  var DEFAULT_STATE = {
6451
6643
  sessionId: null,
@@ -6453,15 +6645,15 @@ var DEFAULT_STATE = {
6453
6645
  lastAnalysisTimestamp: null
6454
6646
  };
6455
6647
  function ensureLearningDir() {
6456
- if (!fs25.existsSync(LEARNING_DIR)) {
6457
- fs25.mkdirSync(LEARNING_DIR, { recursive: true });
6648
+ if (!fs26.existsSync(LEARNING_DIR)) {
6649
+ fs26.mkdirSync(LEARNING_DIR, { recursive: true });
6458
6650
  }
6459
6651
  }
6460
6652
  function sessionFilePath() {
6461
- return path19.join(LEARNING_DIR, LEARNING_SESSION_FILE);
6653
+ return path20.join(LEARNING_DIR, LEARNING_SESSION_FILE);
6462
6654
  }
6463
6655
  function stateFilePath() {
6464
- return path19.join(LEARNING_DIR, LEARNING_STATE_FILE);
6656
+ return path20.join(LEARNING_DIR, LEARNING_STATE_FILE);
6465
6657
  }
6466
6658
  function truncateResponse(response) {
6467
6659
  const str = JSON.stringify(response);
@@ -6472,50 +6664,50 @@ function appendEvent(event) {
6472
6664
  ensureLearningDir();
6473
6665
  const truncated = { ...event, tool_response: truncateResponse(event.tool_response) };
6474
6666
  const filePath = sessionFilePath();
6475
- fs25.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
6667
+ fs26.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
6476
6668
  const count = getEventCount();
6477
6669
  if (count > LEARNING_MAX_EVENTS) {
6478
- const lines = fs25.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
6670
+ const lines = fs26.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
6479
6671
  const kept = lines.slice(lines.length - LEARNING_MAX_EVENTS);
6480
- fs25.writeFileSync(filePath, kept.join("\n") + "\n");
6672
+ fs26.writeFileSync(filePath, kept.join("\n") + "\n");
6481
6673
  }
6482
6674
  }
6483
6675
  function readAllEvents() {
6484
6676
  const filePath = sessionFilePath();
6485
- if (!fs25.existsSync(filePath)) return [];
6486
- const lines = fs25.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
6677
+ if (!fs26.existsSync(filePath)) return [];
6678
+ const lines = fs26.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
6487
6679
  return lines.map((line) => JSON.parse(line));
6488
6680
  }
6489
6681
  function getEventCount() {
6490
6682
  const filePath = sessionFilePath();
6491
- if (!fs25.existsSync(filePath)) return 0;
6492
- const content = fs25.readFileSync(filePath, "utf-8");
6683
+ if (!fs26.existsSync(filePath)) return 0;
6684
+ const content = fs26.readFileSync(filePath, "utf-8");
6493
6685
  return content.split("\n").filter(Boolean).length;
6494
6686
  }
6495
6687
  function clearSession() {
6496
6688
  const filePath = sessionFilePath();
6497
- if (fs25.existsSync(filePath)) fs25.unlinkSync(filePath);
6689
+ if (fs26.existsSync(filePath)) fs26.unlinkSync(filePath);
6498
6690
  }
6499
6691
  function readState2() {
6500
6692
  const filePath = stateFilePath();
6501
- if (!fs25.existsSync(filePath)) return { ...DEFAULT_STATE };
6693
+ if (!fs26.existsSync(filePath)) return { ...DEFAULT_STATE };
6502
6694
  try {
6503
- return JSON.parse(fs25.readFileSync(filePath, "utf-8"));
6695
+ return JSON.parse(fs26.readFileSync(filePath, "utf-8"));
6504
6696
  } catch {
6505
6697
  return { ...DEFAULT_STATE };
6506
6698
  }
6507
6699
  }
6508
6700
  function writeState2(state) {
6509
6701
  ensureLearningDir();
6510
- fs25.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
6702
+ fs26.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
6511
6703
  }
6512
6704
  function resetState() {
6513
6705
  writeState2({ ...DEFAULT_STATE });
6514
6706
  }
6515
6707
 
6516
6708
  // src/learner/writer.ts
6517
- import fs26 from "fs";
6518
- import path20 from "path";
6709
+ import fs27 from "fs";
6710
+ import path21 from "path";
6519
6711
  var LEARNED_START = "<!-- caliber:learned -->";
6520
6712
  var LEARNED_END = "<!-- /caliber:learned -->";
6521
6713
  function writeLearnedContent(update) {
@@ -6535,8 +6727,8 @@ function writeLearnedContent(update) {
6535
6727
  function writeLearnedSection(content) {
6536
6728
  const claudeMdPath = "CLAUDE.md";
6537
6729
  let existing = "";
6538
- if (fs26.existsSync(claudeMdPath)) {
6539
- existing = fs26.readFileSync(claudeMdPath, "utf-8");
6730
+ if (fs27.existsSync(claudeMdPath)) {
6731
+ existing = fs27.readFileSync(claudeMdPath, "utf-8");
6540
6732
  }
6541
6733
  const section = `${LEARNED_START}
6542
6734
  ${content}
@@ -6550,15 +6742,15 @@ ${LEARNED_END}`;
6550
6742
  const separator = existing.endsWith("\n") || existing === "" ? "" : "\n";
6551
6743
  updated = existing + separator + "\n" + section + "\n";
6552
6744
  }
6553
- fs26.writeFileSync(claudeMdPath, updated);
6745
+ fs27.writeFileSync(claudeMdPath, updated);
6554
6746
  }
6555
6747
  function writeLearnedSkill(skill) {
6556
- const skillDir = path20.join(".claude", "skills", skill.name);
6557
- if (!fs26.existsSync(skillDir)) fs26.mkdirSync(skillDir, { recursive: true });
6558
- const skillPath = path20.join(skillDir, "SKILL.md");
6559
- if (!skill.isNew && fs26.existsSync(skillPath)) {
6560
- const existing = fs26.readFileSync(skillPath, "utf-8");
6561
- fs26.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
6748
+ const skillDir = path21.join(".claude", "skills", skill.name);
6749
+ if (!fs27.existsSync(skillDir)) fs27.mkdirSync(skillDir, { recursive: true });
6750
+ const skillPath = path21.join(skillDir, "SKILL.md");
6751
+ if (!skill.isNew && fs27.existsSync(skillPath)) {
6752
+ const existing = fs27.readFileSync(skillPath, "utf-8");
6753
+ fs27.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
6562
6754
  } else {
6563
6755
  const frontmatter = [
6564
6756
  "---",
@@ -6567,14 +6759,14 @@ function writeLearnedSkill(skill) {
6567
6759
  "---",
6568
6760
  ""
6569
6761
  ].join("\n");
6570
- fs26.writeFileSync(skillPath, frontmatter + skill.content);
6762
+ fs27.writeFileSync(skillPath, frontmatter + skill.content);
6571
6763
  }
6572
6764
  return skillPath;
6573
6765
  }
6574
6766
  function readLearnedSection() {
6575
6767
  const claudeMdPath = "CLAUDE.md";
6576
- if (!fs26.existsSync(claudeMdPath)) return null;
6577
- const content = fs26.readFileSync(claudeMdPath, "utf-8");
6768
+ if (!fs27.existsSync(claudeMdPath)) return null;
6769
+ const content = fs27.readFileSync(claudeMdPath, "utf-8");
6578
6770
  const startIdx = content.indexOf(LEARNED_START);
6579
6771
  const endIdx = content.indexOf(LEARNED_END);
6580
6772
  if (startIdx === -1 || endIdx === -1) return null;
@@ -6719,57 +6911,98 @@ async function learnFinalizeCommand() {
6719
6911
  async function learnInstallCommand() {
6720
6912
  const result = installLearningHooks();
6721
6913
  if (result.alreadyInstalled) {
6722
- console.log(chalk15.dim("Learning hooks already installed."));
6914
+ console.log(chalk16.dim("Learning hooks already installed."));
6723
6915
  return;
6724
6916
  }
6725
- console.log(chalk15.green("\u2713") + " Learning hooks installed in .claude/settings.json");
6726
- console.log(chalk15.dim(" PostToolUse, PostToolUseFailure, and SessionEnd hooks active."));
6727
- console.log(chalk15.dim(" Session learnings will be written to CLAUDE.md and skills."));
6917
+ console.log(chalk16.green("\u2713") + " Learning hooks installed in .claude/settings.json");
6918
+ console.log(chalk16.dim(" PostToolUse, PostToolUseFailure, and SessionEnd hooks active."));
6919
+ console.log(chalk16.dim(" Session learnings will be written to CLAUDE.md and skills."));
6728
6920
  }
6729
6921
  async function learnRemoveCommand() {
6730
6922
  const result = removeLearningHooks();
6731
6923
  if (result.notFound) {
6732
- console.log(chalk15.dim("Learning hooks not found."));
6924
+ console.log(chalk16.dim("Learning hooks not found."));
6733
6925
  return;
6734
6926
  }
6735
- console.log(chalk15.green("\u2713") + " Learning hooks removed from .claude/settings.json");
6927
+ console.log(chalk16.green("\u2713") + " Learning hooks removed from .claude/settings.json");
6736
6928
  }
6737
6929
  async function learnStatusCommand() {
6738
6930
  const installed = areLearningHooksInstalled();
6739
6931
  const state = readState2();
6740
6932
  const eventCount = getEventCount();
6741
- console.log(chalk15.bold("Session Learning Status"));
6933
+ console.log(chalk16.bold("Session Learning Status"));
6742
6934
  console.log();
6743
6935
  if (installed) {
6744
- console.log(chalk15.green("\u2713") + " Learning hooks are " + chalk15.green("installed"));
6936
+ console.log(chalk16.green("\u2713") + " Learning hooks are " + chalk16.green("installed"));
6745
6937
  } else {
6746
- console.log(chalk15.dim("\u2717") + " Learning hooks are " + chalk15.yellow("not installed"));
6747
- console.log(chalk15.dim(" Run `caliber learn install` to enable session learning."));
6938
+ console.log(chalk16.dim("\u2717") + " Learning hooks are " + chalk16.yellow("not installed"));
6939
+ console.log(chalk16.dim(" Run `caliber learn install` to enable session learning."));
6748
6940
  }
6749
6941
  console.log();
6750
- console.log(`Events recorded: ${chalk15.cyan(String(eventCount))}`);
6751
- console.log(`Total this session: ${chalk15.cyan(String(state.eventCount))}`);
6942
+ console.log(`Events recorded: ${chalk16.cyan(String(eventCount))}`);
6943
+ console.log(`Total this session: ${chalk16.cyan(String(state.eventCount))}`);
6752
6944
  if (state.lastAnalysisTimestamp) {
6753
- console.log(`Last analysis: ${chalk15.cyan(state.lastAnalysisTimestamp)}`);
6945
+ console.log(`Last analysis: ${chalk16.cyan(state.lastAnalysisTimestamp)}`);
6754
6946
  } else {
6755
- console.log(`Last analysis: ${chalk15.dim("none")}`);
6947
+ console.log(`Last analysis: ${chalk16.dim("none")}`);
6756
6948
  }
6757
6949
  const learnedSection = readLearnedSection();
6758
6950
  if (learnedSection) {
6759
6951
  const lineCount = learnedSection.split("\n").filter(Boolean).length;
6760
6952
  console.log(`
6761
- Learned items in CLAUDE.md: ${chalk15.cyan(String(lineCount))}`);
6953
+ Learned items in CLAUDE.md: ${chalk16.cyan(String(lineCount))}`);
6762
6954
  }
6763
6955
  }
6764
6956
 
6765
6957
  // src/cli.ts
6766
- var __dirname = path21.dirname(fileURLToPath(import.meta.url));
6958
+ var __dirname = path22.dirname(fileURLToPath(import.meta.url));
6767
6959
  var pkg = JSON.parse(
6768
- fs27.readFileSync(path21.resolve(__dirname, "..", "package.json"), "utf-8")
6960
+ fs28.readFileSync(path22.resolve(__dirname, "..", "package.json"), "utf-8")
6769
6961
  );
6770
6962
  var program = new Command();
6771
6963
  var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
6772
- program.name(process.env.CALIBER_LOCAL ? "caloc" : "caliber").description("Configure your coding agent environment").version(displayVersion);
6964
+ program.name(process.env.CALIBER_LOCAL ? "caloc" : "caliber").description("Configure your coding agent environment").version(displayVersion).option("--no-traces", "Disable anonymous telemetry for this run");
6965
+ function tracked(commandName, handler) {
6966
+ const wrapper = async (...args) => {
6967
+ const start = Date.now();
6968
+ trackEvent("command_started", {
6969
+ command: commandName,
6970
+ cli_version: pkg.version
6971
+ });
6972
+ try {
6973
+ await handler(...args);
6974
+ trackEvent("command_completed", {
6975
+ command: commandName,
6976
+ duration_ms: Date.now() - start,
6977
+ success: true
6978
+ });
6979
+ } catch (err) {
6980
+ const errorMessage = err instanceof Error ? err.message : "Unknown error";
6981
+ const errorType = err instanceof Error ? err.constructor.name : typeof err;
6982
+ if (errorMessage !== "__exit__") {
6983
+ trackEvent("command_error", {
6984
+ command: commandName,
6985
+ error_type: errorType,
6986
+ error_message: errorMessage
6987
+ });
6988
+ }
6989
+ trackEvent("command_completed", {
6990
+ command: commandName,
6991
+ duration_ms: Date.now() - start,
6992
+ success: false
6993
+ });
6994
+ throw err;
6995
+ }
6996
+ };
6997
+ return wrapper;
6998
+ }
6999
+ program.hook("preAction", (thisCommand) => {
7000
+ const opts = thisCommand.optsWithGlobals();
7001
+ if (opts.traces === false) {
7002
+ setTelemetryDisabled(true);
7003
+ }
7004
+ initTelemetry();
7005
+ });
6773
7006
  function parseAgentOption(value) {
6774
7007
  if (value === "both") return ["claude", "cursor"];
6775
7008
  if (value === "all") return ["claude", "cursor", "codex"];
@@ -6781,39 +7014,39 @@ function parseAgentOption(value) {
6781
7014
  }
6782
7015
  return agents;
6783
7016
  }
6784
- program.command("onboard").alias("init").description("Onboard your project for AI-assisted development").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).option("--dry-run", "Preview changes without writing files").option("--force", "Overwrite existing setup without prompting").action(initCommand);
6785
- program.command("undo").description("Revert all config changes made by Caliber").action(undoCommand);
6786
- program.command("status").description("Show current Caliber setup status").option("--json", "Output as JSON").action(statusCommand);
6787
- program.command("regenerate").alias("regen").alias("re").description("Re-analyze project and regenerate setup").option("--dry-run", "Preview changes without writing files").action(regenerateCommand);
6788
- program.command("config").description("Configure LLM provider, API key, and model").action(configCommand);
6789
- program.command("skills").description("Discover and install community skills for your project").action(recommendCommand);
6790
- program.command("score").description("Score your current agent config setup (deterministic, no network)").option("--json", "Output as JSON").option("--quiet", "One-line output for scripts/hooks").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).action(scoreCommand);
6791
- program.command("refresh").description("Update docs based on recent code changes").option("--quiet", "Suppress output (for use in hooks)").option("--dry-run", "Preview changes without writing files").action(refreshCommand);
6792
- program.command("hooks").description("Manage auto-refresh hooks (toggle interactively)").option("--install", "Enable all hooks non-interactively").option("--remove", "Disable all hooks non-interactively").action(hooksCommand);
7017
+ program.command("onboard").alias("init").description("Onboard your project for AI-assisted development").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).option("--dry-run", "Preview changes without writing files").option("--force", "Overwrite existing setup without prompting").action(tracked("onboard", initCommand));
7018
+ program.command("undo").description("Revert all config changes made by Caliber").action(tracked("undo", undoCommand));
7019
+ program.command("status").description("Show current Caliber setup status").option("--json", "Output as JSON").action(tracked("status", statusCommand));
7020
+ program.command("regenerate").alias("regen").alias("re").description("Re-analyze project and regenerate setup").option("--dry-run", "Preview changes without writing files").action(tracked("regenerate", regenerateCommand));
7021
+ program.command("config").description("Configure LLM provider, API key, and model").action(tracked("config", configCommand));
7022
+ program.command("skills").description("Discover and install community skills for your project").action(tracked("skills", recommendCommand));
7023
+ program.command("score").description("Score your current agent config setup (deterministic, no network)").option("--json", "Output as JSON").option("--quiet", "One-line output for scripts/hooks").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).action(tracked("score", scoreCommand));
7024
+ program.command("refresh").description("Update docs based on recent code changes").option("--quiet", "Suppress output (for use in hooks)").option("--dry-run", "Preview changes without writing files").action(tracked("refresh", refreshCommand));
7025
+ program.command("hooks").description("Manage auto-refresh hooks (toggle interactively)").option("--install", "Enable all hooks non-interactively").option("--remove", "Disable all hooks non-interactively").action(tracked("hooks", hooksCommand));
6793
7026
  var learn = program.command("learn", { hidden: true }).description("[dev] Session learning \u2014 observe tool usage and extract reusable instructions");
6794
- learn.command("observe").description("Record a tool event from stdin (called by hooks)").option("--failure", "Mark event as a tool failure").action(learnObserveCommand);
6795
- learn.command("finalize").description("Analyze session events and update CLAUDE.md (called on SessionEnd)").action(learnFinalizeCommand);
6796
- learn.command("install").description("Install learning hooks into .claude/settings.json").action(learnInstallCommand);
6797
- learn.command("remove").description("Remove learning hooks from .claude/settings.json").action(learnRemoveCommand);
6798
- learn.command("status").description("Show learning system status").action(learnStatusCommand);
7027
+ learn.command("observe").description("Record a tool event from stdin (called by hooks)").option("--failure", "Mark event as a tool failure").action(tracked("learn:observe", learnObserveCommand));
7028
+ learn.command("finalize").description("Analyze session events and update CLAUDE.md (called on SessionEnd)").action(tracked("learn:finalize", learnFinalizeCommand));
7029
+ learn.command("install").description("Install learning hooks into .claude/settings.json").action(tracked("learn:install", learnInstallCommand));
7030
+ learn.command("remove").description("Remove learning hooks from .claude/settings.json").action(tracked("learn:remove", learnRemoveCommand));
7031
+ learn.command("status").description("Show learning system status").action(tracked("learn:status", learnStatusCommand));
6799
7032
 
6800
7033
  // src/utils/version-check.ts
6801
- import fs28 from "fs";
6802
- import path22 from "path";
7034
+ import fs29 from "fs";
7035
+ import path23 from "path";
6803
7036
  import { fileURLToPath as fileURLToPath2 } from "url";
6804
- import { execSync as execSync9 } from "child_process";
6805
- import chalk16 from "chalk";
7037
+ import { execSync as execSync10 } from "child_process";
7038
+ import chalk17 from "chalk";
6806
7039
  import ora6 from "ora";
6807
7040
  import confirm from "@inquirer/confirm";
6808
- var __dirname_vc = path22.dirname(fileURLToPath2(import.meta.url));
7041
+ var __dirname_vc = path23.dirname(fileURLToPath2(import.meta.url));
6809
7042
  var pkg2 = JSON.parse(
6810
- fs28.readFileSync(path22.resolve(__dirname_vc, "..", "package.json"), "utf-8")
7043
+ fs29.readFileSync(path23.resolve(__dirname_vc, "..", "package.json"), "utf-8")
6811
7044
  );
6812
7045
  function getInstalledVersion() {
6813
7046
  try {
6814
- const globalRoot = execSync9("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
6815
- const pkgPath = path22.join(globalRoot, "@rely-ai", "caliber", "package.json");
6816
- return JSON.parse(fs28.readFileSync(pkgPath, "utf-8")).version;
7047
+ const globalRoot = execSync10("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
7048
+ const pkgPath = path23.join(globalRoot, "@rely-ai", "caliber", "package.json");
7049
+ return JSON.parse(fs29.readFileSync(pkgPath, "utf-8")).version;
6817
7050
  } catch {
6818
7051
  return null;
6819
7052
  }
@@ -6836,17 +7069,17 @@ async function checkForUpdates() {
6836
7069
  const isInteractive = process.stdin.isTTY === true;
6837
7070
  if (!isInteractive) {
6838
7071
  console.log(
6839
- chalk16.yellow(
7072
+ chalk17.yellow(
6840
7073
  `
6841
7074
  Update available: ${current} -> ${latest}
6842
- Run ${chalk16.bold("npm install -g @rely-ai/caliber")} to upgrade.
7075
+ Run ${chalk17.bold("npm install -g @rely-ai/caliber")} to upgrade.
6843
7076
  `
6844
7077
  )
6845
7078
  );
6846
7079
  return;
6847
7080
  }
6848
7081
  console.log(
6849
- chalk16.yellow(`
7082
+ chalk17.yellow(`
6850
7083
  Update available: ${current} -> ${latest}`)
6851
7084
  );
6852
7085
  const shouldUpdate = await confirm({ message: "Would you like to update now? (Y/n)", default: true });
@@ -6856,7 +7089,7 @@ Update available: ${current} -> ${latest}`)
6856
7089
  }
6857
7090
  const spinner = ora6("Updating caliber...").start();
6858
7091
  try {
6859
- execSync9(`npm install -g @rely-ai/caliber@${latest}`, {
7092
+ execSync10(`npm install -g @rely-ai/caliber@${latest}`, {
6860
7093
  stdio: "pipe",
6861
7094
  timeout: 12e4,
6862
7095
  env: { ...process.env, npm_config_fund: "false", npm_config_audit: "false" }
@@ -6864,16 +7097,16 @@ Update available: ${current} -> ${latest}`)
6864
7097
  const installed = getInstalledVersion();
6865
7098
  if (installed !== latest) {
6866
7099
  spinner.fail(`Update incomplete \u2014 got ${installed ?? "unknown"}, expected ${latest}`);
6867
- console.log(chalk16.yellow(`Run ${chalk16.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually.
7100
+ console.log(chalk17.yellow(`Run ${chalk17.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually.
6868
7101
  `));
6869
7102
  return;
6870
7103
  }
6871
- spinner.succeed(chalk16.green(`Updated to ${latest}`));
7104
+ spinner.succeed(chalk17.green(`Updated to ${latest}`));
6872
7105
  const args = process.argv.slice(2);
6873
- console.log(chalk16.dim(`
7106
+ console.log(chalk17.dim(`
6874
7107
  Restarting: caliber ${args.join(" ")}
6875
7108
  `));
6876
- execSync9(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
7109
+ execSync10(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
6877
7110
  stdio: "inherit",
6878
7111
  env: { ...process.env, CALIBER_SKIP_UPDATE_CHECK: "1" }
6879
7112
  });
@@ -6883,11 +7116,11 @@ Restarting: caliber ${args.join(" ")}
6883
7116
  if (err instanceof Error) {
6884
7117
  const stderr = err.stderr;
6885
7118
  const errMsg = stderr ? String(stderr).trim().split("\n").pop() : err.message.split("\n")[0];
6886
- if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk16.dim(` ${errMsg}`));
7119
+ if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk17.dim(` ${errMsg}`));
6887
7120
  }
6888
7121
  console.log(
6889
- chalk16.yellow(
6890
- `Run ${chalk16.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually to upgrade.
7122
+ chalk17.yellow(
7123
+ `Run ${chalk17.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually to upgrade.
6891
7124
  `
6892
7125
  )
6893
7126
  );
@@ -6907,5 +7140,8 @@ program.parseAsync().catch((err) => {
6907
7140
  console.error(msg);
6908
7141
  }
6909
7142
  process.exitCode = 1;
6910
- }).finally(() => process.exit(Number(process.exitCode ?? 0)));
7143
+ }).finally(async () => {
7144
+ await flushTelemetry();
7145
+ process.exit(Number(process.exitCode ?? 0));
7146
+ });
6911
7147
  //# sourceMappingURL=bin.js.map