@rely-ai/caliber 1.20.0-dev.1773685589 → 1.20.0-dev.1773685636

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 +606 -382
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -225,7 +225,7 @@ import { fileURLToPath } from "url";
225
225
 
226
226
  // src/commands/init.ts
227
227
  import path19 from "path";
228
- import chalk9 from "chalk";
228
+ import chalk10 from "chalk";
229
229
  import ora2 from "ora";
230
230
  import select5 from "@inquirer/select";
231
231
  import checkbox from "@inquirer/checkbox";
@@ -2686,6 +2686,37 @@ async function generateMonolithic(fingerprint, targetAgent, prompt, callbacks, f
2686
2686
  };
2687
2687
  return attemptGeneration();
2688
2688
  }
2689
+ async function generateSkillsForSetup(setup, fingerprint, targetAgent, onStatus) {
2690
+ const skillTopics = collectSkillTopics(setup, targetAgent, fingerprint);
2691
+ if (skillTopics.length === 0) return 0;
2692
+ onStatus?.(`Generating ${skillTopics.length} skills...`);
2693
+ const allDeps = extractAllDeps(process.cwd());
2694
+ const skillContext = buildSkillContext(fingerprint, setup, allDeps);
2695
+ const fastModel = getFastModel();
2696
+ const skillResults = await Promise.allSettled(
2697
+ skillTopics.map(
2698
+ ({ platform, topic }) => generateSkill(skillContext, topic, fastModel).then((skill) => ({ platform, skill }))
2699
+ )
2700
+ );
2701
+ for (const result of skillResults) {
2702
+ if (result.status === "fulfilled") {
2703
+ const { platform, skill } = result.value;
2704
+ const platformObj = setup[platform] ?? {};
2705
+ const skills = platformObj.skills ?? [];
2706
+ skills.push(skill);
2707
+ platformObj.skills = skills;
2708
+ setup[platform] = platformObj;
2709
+ const skillPath = platform === "codex" ? `.agents/skills/${skill.name}/SKILL.md` : `.${platform}/skills/${skill.name}/SKILL.md`;
2710
+ const descriptions = setup.fileDescriptions ?? {};
2711
+ descriptions[skillPath] = skill.description.slice(0, 80);
2712
+ setup.fileDescriptions = descriptions;
2713
+ }
2714
+ }
2715
+ const succeeded = skillResults.filter((r) => r.status === "fulfilled").length;
2716
+ const failed = skillResults.filter((r) => r.status === "rejected").length;
2717
+ if (failed > 0) onStatus?.(`${succeeded} generated, ${failed} failed`);
2718
+ return succeeded;
2719
+ }
2689
2720
  var LIMITS = {
2690
2721
  FILE_TREE_ENTRIES: 500,
2691
2722
  EXISTING_CONFIG_CHARS: 8e3,
@@ -3679,8 +3710,8 @@ function removePreCommitHook() {
3679
3710
  if (!content.includes(PRECOMMIT_START)) {
3680
3711
  return { removed: false, notFound: true };
3681
3712
  }
3682
- const regex = new RegExp(`\\n?${PRECOMMIT_START}[\\s\\S]*?${PRECOMMIT_END}\\n?`);
3683
- content = content.replace(regex, "\n");
3713
+ const regex2 = new RegExp(`\\n?${PRECOMMIT_START}[\\s\\S]*?${PRECOMMIT_END}\\n?`);
3714
+ content = content.replace(regex2, "\n");
3684
3715
  if (content.trim() === "#!/bin/sh" || content.trim() === "") {
3685
3716
  fs17.unlinkSync(hookPath);
3686
3717
  } else {
@@ -6007,6 +6038,51 @@ function extractTopDeps() {
6007
6038
  return [];
6008
6039
  }
6009
6040
  }
6041
+ async function searchSkills(fingerprint, targetPlatforms, onStatus) {
6042
+ const installedSkills = getInstalledSkills(targetPlatforms);
6043
+ const technologies = [...new Set([
6044
+ ...fingerprint.languages,
6045
+ ...fingerprint.frameworks,
6046
+ ...extractTopDeps()
6047
+ ].filter(Boolean))];
6048
+ if (technologies.length === 0) {
6049
+ return { results: [], contentMap: /* @__PURE__ */ new Map() };
6050
+ }
6051
+ const primaryPlatform = targetPlatforms.includes("claude") ? "claude" : targetPlatforms[0];
6052
+ onStatus?.("Searching skill registries...");
6053
+ const allCandidates = await searchAllProviders(technologies, primaryPlatform);
6054
+ if (!allCandidates.length) {
6055
+ return { results: [], contentMap: /* @__PURE__ */ new Map() };
6056
+ }
6057
+ const newCandidates = allCandidates.filter((c) => !installedSkills.has(c.slug.toLowerCase()));
6058
+ if (!newCandidates.length) {
6059
+ return { results: [], contentMap: /* @__PURE__ */ new Map() };
6060
+ }
6061
+ onStatus?.(`Scoring ${newCandidates.length} candidates...`);
6062
+ let results;
6063
+ const config = loadConfig();
6064
+ if (config) {
6065
+ try {
6066
+ const projectContext = buildProjectContext(fingerprint, targetPlatforms);
6067
+ results = await scoreWithLLM(newCandidates, projectContext, technologies);
6068
+ } catch {
6069
+ results = newCandidates.slice(0, 20);
6070
+ }
6071
+ } else {
6072
+ results = newCandidates.slice(0, 20);
6073
+ }
6074
+ if (results.length === 0) {
6075
+ return { results: [], contentMap: /* @__PURE__ */ new Map() };
6076
+ }
6077
+ onStatus?.("Fetching skill content...");
6078
+ const contentMap = /* @__PURE__ */ new Map();
6079
+ await Promise.all(results.map(async (rec) => {
6080
+ const content = await fetchSkillContent(rec);
6081
+ if (content) contentMap.set(rec.slug, content);
6082
+ }));
6083
+ const available = results.filter((r) => contentMap.has(r.slug));
6084
+ return { results: available, contentMap };
6085
+ }
6010
6086
  async function recommendCommand() {
6011
6087
  const proceed = await select4({
6012
6088
  message: "Search public repos for relevant skills to add to this project?",
@@ -6371,13 +6447,144 @@ function formatMs(ms) {
6371
6447
  return `${secs}s`;
6372
6448
  }
6373
6449
 
6450
+ // src/utils/parallel-tasks.ts
6451
+ import chalk9 from "chalk";
6452
+
6453
+ // node_modules/ansi-regex/index.js
6454
+ function ansiRegex({ onlyFirst = false } = {}) {
6455
+ const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
6456
+ const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
6457
+ const csi = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";
6458
+ const pattern = `${osc}|${csi}`;
6459
+ return new RegExp(pattern, onlyFirst ? void 0 : "g");
6460
+ }
6461
+
6462
+ // node_modules/strip-ansi/index.js
6463
+ var regex = ansiRegex();
6464
+ function stripAnsi(string) {
6465
+ if (typeof string !== "string") {
6466
+ throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
6467
+ }
6468
+ if (!string.includes("\x1B") && !string.includes("\x9B")) {
6469
+ return string;
6470
+ }
6471
+ return string.replace(regex, "");
6472
+ }
6473
+
6474
+ // src/utils/parallel-tasks.ts
6475
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
6476
+ var SPINNER_INTERVAL_MS = 80;
6477
+ var ParallelTaskDisplay = class {
6478
+ tasks = [];
6479
+ lineCount = 0;
6480
+ spinnerFrame = 0;
6481
+ timer = null;
6482
+ startTime = 0;
6483
+ rendered = false;
6484
+ add(name) {
6485
+ const index = this.tasks.length;
6486
+ this.tasks.push({ name, status: "pending", message: "" });
6487
+ return index;
6488
+ }
6489
+ start() {
6490
+ this.startTime = Date.now();
6491
+ this.draw(true);
6492
+ this.timer = setInterval(() => {
6493
+ this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER_FRAMES.length;
6494
+ this.draw(false);
6495
+ }, SPINNER_INTERVAL_MS);
6496
+ }
6497
+ update(index, status, message) {
6498
+ const task = this.tasks[index];
6499
+ if (!task) return;
6500
+ if (status === "running" && task.status === "pending") {
6501
+ task.startTime = Date.now();
6502
+ }
6503
+ if ((status === "done" || status === "failed") && !task.endTime) {
6504
+ task.endTime = Date.now();
6505
+ }
6506
+ task.status = status;
6507
+ if (message !== void 0) task.message = message;
6508
+ }
6509
+ stop() {
6510
+ if (this.timer) {
6511
+ clearInterval(this.timer);
6512
+ this.timer = null;
6513
+ }
6514
+ this.draw(false);
6515
+ }
6516
+ formatTime(ms) {
6517
+ const secs = Math.floor(ms / 1e3);
6518
+ if (secs < 60) return `${secs}s`;
6519
+ return `${Math.floor(secs / 60)}m ${secs % 60}s`;
6520
+ }
6521
+ truncate(text, maxVisible) {
6522
+ const plain = stripAnsi(text);
6523
+ if (plain.length <= maxVisible) return text;
6524
+ let visible = 0;
6525
+ let i = 0;
6526
+ while (i < text.length && visible < maxVisible - 3) {
6527
+ if (text[i] === "\x1B") {
6528
+ const end = text.indexOf("m", i);
6529
+ if (end !== -1) {
6530
+ i = end + 1;
6531
+ continue;
6532
+ }
6533
+ }
6534
+ visible++;
6535
+ i++;
6536
+ }
6537
+ return text.slice(0, i) + "...";
6538
+ }
6539
+ renderLine(task) {
6540
+ const maxWidth = process.stdout.columns || 80;
6541
+ const elapsed = task.startTime ? this.formatTime((task.endTime ?? Date.now()) - task.startTime) : "";
6542
+ let line;
6543
+ switch (task.status) {
6544
+ case "pending":
6545
+ line = ` ${chalk9.dim("\u25CB")} ${chalk9.dim(task.name)}${task.message ? chalk9.dim(` \u2014 ${task.message}`) : ""}`;
6546
+ break;
6547
+ case "running": {
6548
+ const spinner = chalk9.cyan(SPINNER_FRAMES[this.spinnerFrame]);
6549
+ const time = elapsed ? chalk9.dim(` (${elapsed})`) : "";
6550
+ line = ` ${spinner} ${task.name}${task.message ? chalk9.dim(` \u2014 ${task.message}`) : ""}${time}`;
6551
+ break;
6552
+ }
6553
+ case "done": {
6554
+ const time = elapsed ? chalk9.dim(` (${elapsed})`) : "";
6555
+ line = ` ${chalk9.green("\u2713")} ${task.name}${task.message ? chalk9.dim(` \u2014 ${task.message}`) : ""}${time}`;
6556
+ break;
6557
+ }
6558
+ case "failed":
6559
+ line = ` ${chalk9.red("\u2717")} ${task.name}${task.message ? chalk9.red(` \u2014 ${task.message}`) : ""}`;
6560
+ break;
6561
+ }
6562
+ return this.truncate(line, maxWidth - 1);
6563
+ }
6564
+ draw(initial) {
6565
+ const { stdout } = process;
6566
+ if (!initial && this.rendered && this.lineCount > 0) {
6567
+ stdout.write(`\x1B[${this.lineCount}A`);
6568
+ }
6569
+ stdout.write("\x1B[0J");
6570
+ const lines = this.tasks.map((t) => this.renderLine(t));
6571
+ const totalElapsed = this.formatTime(Date.now() - this.startTime);
6572
+ lines.push(chalk9.dim(`
6573
+ Total: ${totalElapsed}`));
6574
+ const output = lines.join("\n");
6575
+ stdout.write(output + "\n");
6576
+ this.lineCount = output.split("\n").length;
6577
+ this.rendered = true;
6578
+ }
6579
+ };
6580
+
6374
6581
  // src/commands/init.ts
6375
6582
  function log(verbose, ...args) {
6376
- if (verbose) console.log(chalk9.dim(` [verbose] ${args.map(String).join(" ")}`));
6583
+ if (verbose) console.log(chalk10.dim(` [verbose] ${args.map(String).join(" ")}`));
6377
6584
  }
6378
6585
  async function initCommand(options) {
6379
- const brand = chalk9.hex("#EB9D83");
6380
- const title = chalk9.hex("#83D1EB");
6586
+ const brand = chalk10.hex("#EB9D83");
6587
+ const title = chalk10.hex("#83D1EB");
6381
6588
  console.log(brand.bold(`
6382
6589
  \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
6383
6590
  \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
@@ -6386,34 +6593,33 @@ async function initCommand(options) {
6386
6593
  \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
6387
6594
  \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
6388
6595
  `));
6389
- console.log(chalk9.dim(" Scan your project and generate tailored config files for"));
6390
- console.log(chalk9.dim(" Claude Code, Cursor, and Codex.\n"));
6596
+ console.log(chalk10.dim(" Scan your project and generate tailored config files for"));
6597
+ console.log(chalk10.dim(" Claude Code, Cursor, and Codex.\n"));
6391
6598
  const report = options.debugReport ? new DebugReport() : null;
6392
6599
  console.log(title.bold(" How it works:\n"));
6393
- console.log(chalk9.dim(" 1. Connect Choose your LLM provider"));
6394
- console.log(chalk9.dim(" 2. Discover Scan code, dependencies, and existing configs"));
6395
- console.log(chalk9.dim(" 3. Generate Build CLAUDE.md, rules, and skills for your codebase"));
6396
- console.log(chalk9.dim(" 4. Review See a diff \u2014 accept, refine via chat, or decline"));
6397
- console.log(chalk9.dim(" 5. Skills Search community registries and install skills\n"));
6398
- console.log(title.bold(" Step 1/5 \u2014 Connect\n"));
6600
+ console.log(chalk10.dim(" 1. Setup Connect your LLM provider and select your agents"));
6601
+ console.log(chalk10.dim(" 2. Engine Detect stack, generate configs & skills in parallel"));
6602
+ console.log(chalk10.dim(" 3. Review See all changes \u2014 accept, refine, or decline"));
6603
+ console.log(chalk10.dim(" 4. Finalize Score check and auto-sync hooks\n"));
6604
+ console.log(title.bold(" Step 1/4 \u2014 Setup\n"));
6399
6605
  let config = loadConfig();
6400
6606
  if (!config) {
6401
- console.log(chalk9.dim(" No LLM provider set yet. Choose how to run Caliber:\n"));
6607
+ console.log(chalk10.dim(" No LLM provider configured yet.\n"));
6402
6608
  await runInteractiveProviderSetup({
6403
6609
  selectMessage: "How do you want to use Caliber? (choose LLM provider)"
6404
6610
  });
6405
6611
  config = loadConfig();
6406
6612
  if (!config) {
6407
- console.log(chalk9.red(" Setup was cancelled or failed.\n"));
6613
+ console.log(chalk10.red(" Setup was cancelled or failed.\n"));
6408
6614
  throw new Error("__exit__");
6409
6615
  }
6410
- console.log(chalk9.green(" \u2713 Provider saved. Let's continue.\n"));
6616
+ console.log(chalk10.green(" \u2713 Provider saved\n"));
6411
6617
  }
6412
6618
  trackInitProviderSelected(config.provider, config.model);
6413
6619
  const displayModel = getDisplayModel(config);
6414
6620
  const fastModel = getFastModel();
6415
6621
  const modelLine = fastModel ? ` Provider: ${config.provider} | Model: ${displayModel} | Scan: ${fastModel}` : ` Provider: ${config.provider} | Model: ${displayModel}`;
6416
- console.log(chalk9.dim(modelLine + "\n"));
6622
+ console.log(chalk10.dim(modelLine + "\n"));
6417
6623
  if (report) {
6418
6624
  report.markStep("Provider setup");
6419
6625
  report.addSection("LLM Provider", `- **Provider**: ${config.provider}
@@ -6421,30 +6627,6 @@ async function initCommand(options) {
6421
6627
  - **Fast model**: ${fastModel || "none"}`);
6422
6628
  }
6423
6629
  await validateModel({ fast: true });
6424
- console.log(title.bold(" Step 2/5 \u2014 Discover\n"));
6425
- const spinner = ora2("Scanning code, dependencies, and existing configs...").start();
6426
- const fingerprint = await collectFingerprint(process.cwd());
6427
- spinner.succeed("Project scanned");
6428
- log(options.verbose, `Fingerprint: ${fingerprint.languages.length} languages, ${fingerprint.frameworks.length} frameworks, ${fingerprint.fileTree.length} files`);
6429
- if (options.verbose && fingerprint.codeAnalysis) {
6430
- log(options.verbose, `Code analysis: ${fingerprint.codeAnalysis.filesIncluded}/${fingerprint.codeAnalysis.filesAnalyzed} files, ~${fingerprint.codeAnalysis.includedTokens.toLocaleString()} tokens, ${fingerprint.codeAnalysis.duplicateGroups} dedup groups`);
6431
- }
6432
- trackInitProjectDiscovered(fingerprint.languages.length, fingerprint.frameworks.length, fingerprint.fileTree.length);
6433
- const langDisplay = fingerprint.languages.join(", ") || "none detected";
6434
- const frameworkDisplay = fingerprint.frameworks.length > 0 ? ` (${fingerprint.frameworks.join(", ")})` : "";
6435
- console.log(chalk9.dim(` Languages: ${langDisplay}${frameworkDisplay}`));
6436
- console.log(chalk9.dim(` Files: ${fingerprint.fileTree.length} found
6437
- `));
6438
- if (report) {
6439
- report.markStep("Fingerprint");
6440
- report.addJson("Fingerprint: Git", { remote: fingerprint.gitRemoteUrl, packageName: fingerprint.packageName });
6441
- report.addCodeBlock("Fingerprint: File Tree", fingerprint.fileTree.join("\n"));
6442
- report.addJson("Fingerprint: Detected Stack", { languages: fingerprint.languages, frameworks: fingerprint.frameworks, tools: fingerprint.tools });
6443
- report.addJson("Fingerprint: Existing Configs", fingerprint.existingConfigs);
6444
- if (fingerprint.codeAnalysis) {
6445
- report.addJson("Fingerprint: Code Analysis", fingerprint.codeAnalysis);
6446
- }
6447
- }
6448
6630
  let targetAgent;
6449
6631
  if (options.agent) {
6450
6632
  targetAgent = options.agent;
@@ -6454,30 +6636,27 @@ async function initCommand(options) {
6454
6636
  } else {
6455
6637
  targetAgent = await promptAgent();
6456
6638
  }
6457
- console.log(chalk9.dim(` Target: ${targetAgent.join(", ")}
6639
+ console.log(chalk10.dim(` Target: ${targetAgent.join(", ")}
6458
6640
  `));
6459
6641
  trackInitAgentSelected(targetAgent);
6460
- const preScore = computeLocalScore(process.cwd(), targetAgent);
6461
- const failingForDismissal = preScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
6462
- if (failingForDismissal.length > 0) {
6463
- const newDismissals = await evaluateDismissals(failingForDismissal, fingerprint);
6464
- if (newDismissals.length > 0) {
6465
- const existing = readDismissedChecks();
6466
- const existingIds = new Set(existing.map((d) => d.id));
6467
- const merged = [...existing, ...newDismissals.filter((d) => !existingIds.has(d.id))];
6468
- writeDismissedChecks(merged);
6469
- }
6642
+ let wantsSkills = false;
6643
+ if (!options.autoApprove) {
6644
+ wantsSkills = await select5({
6645
+ message: "Discover community-maintained skills that match your stack?",
6646
+ choices: [
6647
+ { name: "Yes, find skills for my project", value: true },
6648
+ { name: "Skip for now", value: false }
6649
+ ]
6650
+ });
6470
6651
  }
6471
- const baselineScore = computeLocalScore(process.cwd(), targetAgent);
6472
- console.log(chalk9.dim(" Current setup score:"));
6652
+ let baselineScore = computeLocalScore(process.cwd(), targetAgent);
6653
+ console.log(chalk10.dim("\n Current setup score:"));
6473
6654
  displayScoreSummary(baselineScore);
6474
6655
  if (options.verbose) {
6475
6656
  for (const c of baselineScore.checks) {
6476
6657
  log(options.verbose, ` ${c.passed ? "\u2713" : "\u2717"} ${c.name}: ${c.earnedPoints}/${c.maxPoints}${c.suggestion ? ` \u2014 ${c.suggestion}` : ""}`);
6477
6658
  }
6478
6659
  }
6479
- const passingCount = baselineScore.checks.filter((c) => c.passed).length;
6480
- const failingCount = baselineScore.checks.filter((c) => !c.passed).length;
6481
6660
  if (report) {
6482
6661
  report.markStep("Baseline scoring");
6483
6662
  report.addSection("Scoring: Baseline", `**Score**: ${baselineScore.score}/100
@@ -6487,7 +6666,7 @@ async function initCommand(options) {
6487
6666
  ` + baselineScore.checks.map((c) => `| ${c.name} | ${c.passed ? "Yes" : "No"} | ${c.earnedPoints} | ${c.maxPoints} |`).join("\n"));
6488
6667
  report.addSection("Generation: Target Agents", targetAgent.join(", "));
6489
6668
  }
6490
- const hasExistingConfig = !!(fingerprint.existingConfigs.claudeMd || fingerprint.existingConfigs.claudeSettings || fingerprint.existingConfigs.claudeSkills?.length || fingerprint.existingConfigs.cursorrules || fingerprint.existingConfigs.cursorRules?.length || fingerprint.existingConfigs.agentsMd);
6669
+ const hasExistingConfig = !!(baselineScore.checks.some((c) => c.id === "claude_md_exists" && c.passed) || baselineScore.checks.some((c) => c.id === "cursorrules_exists" && c.passed));
6491
6670
  const NON_LLM_CHECKS = /* @__PURE__ */ new Set([
6492
6671
  "hooks_configured",
6493
6672
  "agents_md_exists",
@@ -6496,111 +6675,175 @@ async function initCommand(options) {
6496
6675
  "service_coverage",
6497
6676
  "mcp_completeness"
6498
6677
  ]);
6678
+ const passingCount = baselineScore.checks.filter((c) => c.passed).length;
6679
+ const failingCount = baselineScore.checks.filter((c) => !c.passed).length;
6499
6680
  if (hasExistingConfig && baselineScore.score === 100) {
6500
6681
  trackInitScoreComputed(baselineScore.score, passingCount, failingCount, true);
6501
- console.log(chalk9.bold.green(" Your setup is already optimal \u2014 nothing to change.\n"));
6502
- console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber init --force") + chalk9.dim(" to regenerate anyway.\n"));
6682
+ console.log(chalk10.bold.green(" Your setup is already optimal \u2014 nothing to change.\n"));
6683
+ console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber init --force") + chalk10.dim(" to regenerate anyway.\n"));
6503
6684
  if (!options.force) return;
6504
6685
  }
6505
6686
  const allFailingChecks = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
6506
6687
  const llmFixableChecks = allFailingChecks.filter((c) => !NON_LLM_CHECKS.has(c.id));
6507
6688
  trackInitScoreComputed(baselineScore.score, passingCount, failingCount, false);
6508
6689
  if (hasExistingConfig && llmFixableChecks.length === 0 && allFailingChecks.length > 0 && !options.force) {
6509
- console.log(chalk9.bold.green("\n Your config is fully optimized for LLM generation.\n"));
6510
- console.log(chalk9.dim(" Remaining items need CLI actions:\n"));
6690
+ console.log(chalk10.bold.green("\n Your config is fully optimized for LLM generation.\n"));
6691
+ console.log(chalk10.dim(" Remaining items need CLI actions:\n"));
6511
6692
  for (const check of allFailingChecks) {
6512
- console.log(chalk9.dim(` \u2022 ${check.name}`));
6693
+ console.log(chalk10.dim(` \u2022 ${check.name}`));
6513
6694
  if (check.suggestion) {
6514
- console.log(` ${chalk9.hex("#83D1EB")(check.suggestion)}`);
6695
+ console.log(` ${chalk10.hex("#83D1EB")(check.suggestion)}`);
6515
6696
  }
6516
6697
  }
6517
6698
  console.log("");
6518
- console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber init --force") + chalk9.dim(" to regenerate anyway.\n"));
6699
+ console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber init --force") + chalk10.dim(" to regenerate anyway.\n"));
6519
6700
  return;
6520
6701
  }
6702
+ console.log(title.bold(" Step 2/4 \u2014 Engine\n"));
6703
+ const genModelInfo = fastModel ? ` Using ${displayModel} for docs, ${fastModel} for skills` : ` Using ${displayModel}`;
6704
+ console.log(chalk10.dim(genModelInfo + "\n"));
6705
+ if (report) report.markStep("Generation");
6706
+ trackInitGenerationStarted(false);
6707
+ const genStartTime = Date.now();
6708
+ let generatedSetup = null;
6709
+ let rawOutput;
6710
+ let genStopReason;
6711
+ let skillSearchResult = { results: [], contentMap: /* @__PURE__ */ new Map() };
6712
+ let fingerprint;
6713
+ const fpSpinner = ora2("Scanning project...").start();
6714
+ try {
6715
+ fingerprint = await collectFingerprint(process.cwd());
6716
+ fpSpinner.succeed(`Stack detected \u2014 ${fingerprint.languages.join(", ") || "no languages"}${fingerprint.frameworks.length > 0 ? `, ${fingerprint.frameworks.join(", ")}` : ""}`);
6717
+ } catch (err) {
6718
+ fpSpinner.fail("Failed to scan project");
6719
+ throw new Error("__exit__");
6720
+ }
6721
+ trackInitProjectDiscovered(fingerprint.languages.length, fingerprint.frameworks.length, fingerprint.fileTree.length);
6722
+ log(options.verbose, `Fingerprint: ${fingerprint.languages.length} languages, ${fingerprint.frameworks.length} frameworks, ${fingerprint.fileTree.length} files`);
6723
+ if (report) {
6724
+ report.addJson("Fingerprint: Git", { remote: fingerprint.gitRemoteUrl, packageName: fingerprint.packageName });
6725
+ report.addCodeBlock("Fingerprint: File Tree", fingerprint.fileTree.join("\n"));
6726
+ report.addJson("Fingerprint: Detected Stack", { languages: fingerprint.languages, frameworks: fingerprint.frameworks, tools: fingerprint.tools });
6727
+ report.addJson("Fingerprint: Existing Configs", fingerprint.existingConfigs);
6728
+ if (fingerprint.codeAnalysis) report.addJson("Fingerprint: Code Analysis", fingerprint.codeAnalysis);
6729
+ }
6521
6730
  const isEmpty = fingerprint.fileTree.length < 3;
6522
6731
  if (isEmpty) {
6523
6732
  fingerprint.description = await promptInput("What will you build in this project?");
6524
6733
  }
6734
+ const failingForDismissal = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0);
6735
+ if (failingForDismissal.length > 0) {
6736
+ const newDismissals = await evaluateDismissals(failingForDismissal, fingerprint);
6737
+ if (newDismissals.length > 0) {
6738
+ const existing = readDismissedChecks();
6739
+ const existingIds = new Set(existing.map((d) => d.id));
6740
+ const merged = [...existing, ...newDismissals.filter((d) => !existingIds.has(d.id))];
6741
+ writeDismissedChecks(merged);
6742
+ baselineScore = computeLocalScore(process.cwd(), targetAgent);
6743
+ }
6744
+ }
6525
6745
  let failingChecks;
6526
6746
  let passingChecks;
6527
6747
  let currentScore;
6528
6748
  if (hasExistingConfig && baselineScore.score >= 95 && !options.force) {
6529
- failingChecks = llmFixableChecks.map((c) => ({ name: c.name, suggestion: c.suggestion, fix: c.fix }));
6749
+ const currentLlmFixable = baselineScore.checks.filter((c) => !c.passed && c.maxPoints > 0 && !NON_LLM_CHECKS.has(c.id));
6750
+ failingChecks = currentLlmFixable.map((c) => ({ name: c.name, suggestion: c.suggestion, fix: c.fix }));
6530
6751
  passingChecks = baselineScore.checks.filter((c) => c.passed).map((c) => ({ name: c.name }));
6531
6752
  currentScore = baselineScore.score;
6532
- if (failingChecks.length > 0) {
6533
- console.log(title.bold(" Step 3/5 \u2014 Generate\n"));
6534
- console.log(chalk9.dim(` Score is ${baselineScore.score}/100 \u2014 fine-tuning ${failingChecks.length} remaining issue${failingChecks.length === 1 ? "" : "s"}:
6535
- `));
6536
- for (const check of failingChecks) {
6537
- console.log(chalk9.dim(` \u2022 ${check.name}`));
6538
- }
6539
- console.log("");
6540
- }
6541
- } else if (hasExistingConfig) {
6542
- console.log(title.bold(" Step 3/5 \u2014 Generate\n"));
6543
- console.log(chalk9.dim(" Auditing your existing configs against your codebase and improving them.\n"));
6544
- } else {
6545
- console.log(title.bold(" Step 3/5 \u2014 Generate\n"));
6546
- console.log(chalk9.dim(" Building CLAUDE.md, rules, and skills tailored to your project.\n"));
6547
6753
  }
6548
- const genModelInfo = fastModel ? ` Using ${displayModel} for docs, ${fastModel} for skills` : ` Using ${displayModel}`;
6549
- console.log(chalk9.dim(genModelInfo));
6550
- console.log(chalk9.dim(" This can take a couple of minutes depending on your model and provider.\n"));
6551
6754
  if (report) {
6552
- report.markStep("Generation");
6553
6755
  const fullPrompt = buildGeneratePrompt(fingerprint, targetAgent, fingerprint.description, failingChecks, currentScore, passingChecks);
6554
6756
  report.addCodeBlock("Generation: Full LLM Prompt", fullPrompt);
6555
6757
  }
6556
- trackInitGenerationStarted(!!failingChecks);
6557
- const genStartTime = Date.now();
6558
- const genSpinner = ora2("Generating setup...").start();
6559
- const genMessages = new SpinnerMessages(genSpinner, GENERATION_MESSAGES, { showElapsedTime: true });
6560
- genMessages.start();
6561
- let generatedSetup = null;
6562
- let rawOutput;
6563
- let genStopReason;
6758
+ const display = new ParallelTaskDisplay();
6759
+ const TASK_CONFIG = display.add("Generating configs");
6760
+ const TASK_SKILLS_GEN = display.add("Generating skills");
6761
+ const TASK_SKILLS_SEARCH = wantsSkills ? display.add("Searching community skills") : -1;
6762
+ display.start();
6564
6763
  try {
6565
- const result = await generateSetup(
6566
- fingerprint,
6567
- targetAgent,
6568
- fingerprint.description,
6569
- {
6570
- onStatus: (status) => {
6571
- genMessages.handleServerStatus(status);
6572
- },
6573
- onComplete: (setup) => {
6574
- generatedSetup = setup;
6764
+ display.update(TASK_CONFIG, "running");
6765
+ const generatePromise = (async () => {
6766
+ const result = await generateSetup(
6767
+ fingerprint,
6768
+ targetAgent,
6769
+ fingerprint.description,
6770
+ {
6771
+ onStatus: (status) => display.update(TASK_CONFIG, "running", status),
6772
+ onComplete: (setup) => {
6773
+ generatedSetup = setup;
6774
+ },
6775
+ onError: (error) => display.update(TASK_CONFIG, "failed", error)
6575
6776
  },
6576
- onError: (error) => {
6577
- genMessages.stop();
6578
- genSpinner.fail(`Generation error: ${error}`);
6579
- }
6580
- },
6581
- failingChecks,
6582
- currentScore,
6583
- passingChecks
6584
- );
6585
- if (!generatedSetup) {
6586
- generatedSetup = result.setup;
6777
+ failingChecks,
6778
+ currentScore,
6779
+ passingChecks,
6780
+ { skipSkills: true }
6781
+ );
6782
+ if (!generatedSetup) generatedSetup = result.setup;
6587
6783
  rawOutput = result.raw;
6588
- }
6589
- genStopReason = result.stopReason;
6784
+ genStopReason = result.stopReason;
6785
+ if (!generatedSetup) {
6786
+ display.update(TASK_CONFIG, "failed", "Could not parse LLM response");
6787
+ display.update(TASK_SKILLS_GEN, "failed", "Skipped");
6788
+ return;
6789
+ }
6790
+ display.update(TASK_CONFIG, "done");
6791
+ display.update(TASK_SKILLS_GEN, "running");
6792
+ const skillCount = await generateSkillsForSetup(
6793
+ generatedSetup,
6794
+ fingerprint,
6795
+ targetAgent,
6796
+ (status) => display.update(TASK_SKILLS_GEN, "running", status)
6797
+ );
6798
+ display.update(TASK_SKILLS_GEN, "done", `${skillCount} skills`);
6799
+ })();
6800
+ const SEARCH_TIMEOUT_MS = 6e4;
6801
+ const searchPromise = wantsSkills ? (async () => {
6802
+ display.update(TASK_SKILLS_SEARCH, "running");
6803
+ try {
6804
+ const searchWithTimeout = Promise.race([
6805
+ searchSkills(
6806
+ fingerprint,
6807
+ targetAgent,
6808
+ (status) => display.update(TASK_SKILLS_SEARCH, "running", status)
6809
+ ),
6810
+ new Promise(
6811
+ (_, reject) => setTimeout(() => reject(new Error("timeout")), SEARCH_TIMEOUT_MS)
6812
+ )
6813
+ ]);
6814
+ skillSearchResult = await searchWithTimeout;
6815
+ const count = skillSearchResult.results.length;
6816
+ display.update(TASK_SKILLS_SEARCH, "done", count > 0 ? `${count} skills found` : "No matches");
6817
+ } catch (err) {
6818
+ const reason = err instanceof Error && err.message === "timeout" ? "Timed out" : "Search failed";
6819
+ display.update(TASK_SKILLS_SEARCH, "failed", reason);
6820
+ }
6821
+ })() : Promise.resolve();
6822
+ await Promise.all([generatePromise, searchPromise]);
6590
6823
  } catch (err) {
6591
- genMessages.stop();
6824
+ display.stop();
6592
6825
  const msg = err instanceof Error ? err.message : "Unknown error";
6593
- genSpinner.fail(`Generation failed: ${msg}`);
6826
+ console.log(chalk10.red(`
6827
+ Engine failed: ${msg}
6828
+ `));
6594
6829
  writeErrorLog(config, void 0, msg, "exception");
6595
6830
  throw new Error("__exit__");
6596
6831
  }
6597
- genMessages.stop();
6832
+ display.stop();
6833
+ const elapsedMs = Date.now() - genStartTime;
6834
+ trackInitGenerationCompleted(elapsedMs, 0);
6835
+ const mins = Math.floor(elapsedMs / 6e4);
6836
+ const secs = Math.floor(elapsedMs % 6e4 / 1e3);
6837
+ const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
6838
+ console.log(chalk10.dim(`
6839
+ Completed in ${timeStr}
6840
+ `));
6598
6841
  if (!generatedSetup) {
6599
- genSpinner.fail("Failed to generate setup.");
6842
+ console.log(chalk10.red(" Failed to generate setup."));
6600
6843
  writeErrorLog(config, rawOutput, void 0, genStopReason);
6601
6844
  if (rawOutput) {
6602
- console.log(chalk9.dim("\nRaw LLM output (JSON parse failed):"));
6603
- console.log(chalk9.dim(rawOutput.slice(0, 500)));
6845
+ console.log(chalk10.dim("\nRaw LLM output (JSON parse failed):"));
6846
+ console.log(chalk10.dim(rawOutput.slice(0, 500)));
6604
6847
  }
6605
6848
  throw new Error("__exit__");
6606
6849
  }
@@ -6608,12 +6851,6 @@ async function initCommand(options) {
6608
6851
  if (rawOutput) report.addCodeBlock("Generation: Raw LLM Response", rawOutput);
6609
6852
  report.addJson("Generation: Parsed Setup", generatedSetup);
6610
6853
  }
6611
- const elapsedMs = Date.now() - genStartTime;
6612
- trackInitGenerationCompleted(elapsedMs, 0);
6613
- const mins = Math.floor(elapsedMs / 6e4);
6614
- const secs = Math.floor(elapsedMs % 6e4 / 1e3);
6615
- const timeStr = mins > 0 ? `${mins}m ${secs}s` : `${secs}s`;
6616
- genSpinner.succeed(`Setup generated ${chalk9.dim(`in ${timeStr}`)}`);
6617
6854
  log(options.verbose, `Generation completed: ${elapsedMs}ms, stopReason: ${genStopReason || "end_turn"}`);
6618
6855
  printSetupSummary(generatedSetup);
6619
6856
  const sessionHistory = [];
@@ -6621,15 +6858,20 @@ async function initCommand(options) {
6621
6858
  role: "assistant",
6622
6859
  content: summarizeSetup("Initial generation", generatedSetup)
6623
6860
  });
6624
- console.log(title.bold(" Step 4/5 \u2014 Review\n"));
6861
+ console.log(title.bold(" Step 3/4 \u2014 Review\n"));
6625
6862
  const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
6626
6863
  const staged = stageFiles(setupFiles, process.cwd());
6627
6864
  const totalChanges = staged.newFiles + staged.modifiedFiles;
6628
- console.log(chalk9.dim(` ${chalk9.green(`${staged.newFiles} new`)} / ${chalk9.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
6865
+ console.log(chalk10.dim(` ${chalk10.green(`${staged.newFiles} new`)} / ${chalk10.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}`));
6866
+ if (skillSearchResult.results.length > 0) {
6867
+ console.log(chalk10.dim(` ${chalk10.cyan(`${skillSearchResult.results.length}`)} community skills available to install
6629
6868
  `));
6869
+ } else {
6870
+ console.log("");
6871
+ }
6630
6872
  let action;
6631
- if (totalChanges === 0) {
6632
- console.log(chalk9.dim(" No changes needed \u2014 your configs are already up to date.\n"));
6873
+ if (totalChanges === 0 && skillSearchResult.results.length === 0) {
6874
+ console.log(chalk10.dim(" No changes needed \u2014 your configs are already up to date.\n"));
6633
6875
  cleanupStaging();
6634
6876
  action = "accept";
6635
6877
  } else if (options.autoApprove) {
@@ -6637,13 +6879,15 @@ async function initCommand(options) {
6637
6879
  action = "accept";
6638
6880
  trackInitReviewAction(action, "auto-approved");
6639
6881
  } else {
6640
- const wantsReview = await promptWantsReview();
6641
- if (wantsReview) {
6642
- const reviewMethod = await promptReviewMethod();
6643
- await openReview(reviewMethod, staged.stagedFiles);
6882
+ if (totalChanges > 0) {
6883
+ const wantsReview = await promptWantsReview();
6884
+ if (wantsReview) {
6885
+ const reviewMethod = await promptReviewMethod();
6886
+ await openReview(reviewMethod, staged.stagedFiles);
6887
+ }
6644
6888
  }
6645
6889
  action = await promptReviewAction();
6646
- trackInitReviewAction(action, wantsReview ? "reviewed" : "skipped");
6890
+ trackInitReviewAction(action, totalChanges > 0 ? "reviewed" : "skipped");
6647
6891
  }
6648
6892
  let refinementRound = 0;
6649
6893
  while (action === "refine") {
@@ -6652,12 +6896,12 @@ async function initCommand(options) {
6652
6896
  trackInitRefinementRound(refinementRound, !!generatedSetup);
6653
6897
  if (!generatedSetup) {
6654
6898
  cleanupStaging();
6655
- console.log(chalk9.dim("Refinement cancelled. No files were modified."));
6899
+ console.log(chalk10.dim("Refinement cancelled. No files were modified."));
6656
6900
  return;
6657
6901
  }
6658
6902
  const updatedFiles = collectSetupFiles(generatedSetup, targetAgent);
6659
6903
  const restaged = stageFiles(updatedFiles, process.cwd());
6660
- console.log(chalk9.dim(` ${chalk9.green(`${restaged.newFiles} new`)} / ${chalk9.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
6904
+ console.log(chalk10.dim(` ${chalk10.green(`${restaged.newFiles} new`)} / ${chalk10.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
6661
6905
  `));
6662
6906
  printSetupSummary(generatedSetup);
6663
6907
  await openReview("terminal", restaged.stagedFiles);
@@ -6666,11 +6910,12 @@ async function initCommand(options) {
6666
6910
  }
6667
6911
  cleanupStaging();
6668
6912
  if (action === "decline") {
6669
- console.log(chalk9.dim("Setup declined. No files were modified."));
6913
+ console.log(chalk10.dim("Setup declined. No files were modified."));
6670
6914
  return;
6671
6915
  }
6916
+ console.log(title.bold("\n Step 4/4 \u2014 Finalize\n"));
6672
6917
  if (options.dryRun) {
6673
- console.log(chalk9.yellow("\n[Dry run] Would write the following files:"));
6918
+ console.log(chalk10.yellow("\n[Dry run] Would write the following files:"));
6674
6919
  console.log(JSON.stringify(generatedSetup, null, 2));
6675
6920
  return;
6676
6921
  }
@@ -6699,85 +6944,45 @@ ${agentRefs.join(" ")}
6699
6944
  0,
6700
6945
  result.deleted.length
6701
6946
  );
6702
- console.log(chalk9.bold("\nFiles created/updated:"));
6947
+ console.log(chalk10.bold("\nFiles created/updated:"));
6703
6948
  for (const file of result.written) {
6704
- console.log(` ${chalk9.green("\u2713")} ${file}`);
6949
+ console.log(` ${chalk10.green("\u2713")} ${file}`);
6705
6950
  }
6706
6951
  if (result.deleted.length > 0) {
6707
- console.log(chalk9.bold("\nFiles removed:"));
6952
+ console.log(chalk10.bold("\nFiles removed:"));
6708
6953
  for (const file of result.deleted) {
6709
- console.log(` ${chalk9.red("\u2717")} ${file}`);
6954
+ console.log(` ${chalk10.red("\u2717")} ${file}`);
6710
6955
  }
6711
6956
  }
6712
6957
  if (result.backupDir) {
6713
- console.log(chalk9.dim(`
6958
+ console.log(chalk10.dim(`
6714
6959
  Backups saved to ${result.backupDir}`));
6715
6960
  }
6716
6961
  } catch (err) {
6717
6962
  writeSpinner.fail("Failed to write files");
6718
- console.error(chalk9.red(err instanceof Error ? err.message : "Unknown error"));
6963
+ console.error(chalk10.red(err instanceof Error ? err.message : "Unknown error"));
6719
6964
  throw new Error("__exit__");
6720
6965
  }
6721
- ensurePermissions(fingerprint);
6966
+ if (fingerprint) ensurePermissions(fingerprint);
6722
6967
  const sha = getCurrentHeadSha();
6723
6968
  writeState({
6724
6969
  lastRefreshSha: sha ?? "",
6725
6970
  lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
6726
6971
  targetAgent
6727
6972
  });
6728
- console.log("");
6729
- console.log(chalk9.dim(" Auto-refresh: keep your configs in sync as your code changes.\n"));
6730
- let hookChoice;
6731
- if (options.autoApprove) {
6732
- hookChoice = "skip";
6733
- log(options.verbose, "Auto-approve: skipping hook installation");
6734
- } else {
6735
- hookChoice = await promptHookType(targetAgent);
6736
- }
6737
- trackInitHookSelected(hookChoice);
6738
- if (hookChoice === "claude" || hookChoice === "both") {
6739
- const hookResult = installHook();
6740
- if (hookResult.installed) {
6741
- console.log(` ${chalk9.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
6742
- console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber hooks --remove") + chalk9.dim(" to disable"));
6743
- } else if (hookResult.alreadyInstalled) {
6744
- console.log(chalk9.dim(" Claude Code hook already installed"));
6745
- }
6746
- const learnResult = installLearningHooks();
6747
- if (learnResult.installed) {
6748
- console.log(` ${chalk9.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
6749
- console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber learn remove") + chalk9.dim(" to disable"));
6750
- } else if (learnResult.alreadyInstalled) {
6751
- console.log(chalk9.dim(" Learning hooks already installed"));
6752
- }
6753
- }
6754
- if (hookChoice === "precommit" || hookChoice === "both") {
6755
- const precommitResult = installPreCommitHook();
6756
- if (precommitResult.installed) {
6757
- console.log(` ${chalk9.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
6758
- console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber hooks --remove") + chalk9.dim(" to disable"));
6759
- } else if (precommitResult.alreadyInstalled) {
6760
- console.log(chalk9.dim(" Pre-commit hook already installed"));
6761
- } else {
6762
- console.log(chalk9.yellow(" Could not install pre-commit hook (not a git repository?)"));
6763
- }
6764
- }
6765
- if (hookChoice === "skip") {
6766
- console.log(chalk9.dim(" Skipped auto-refresh hooks. Run ") + chalk9.hex("#83D1EB")("caliber hooks --install") + chalk9.dim(" later to enable."));
6767
- }
6768
6973
  const afterScore = computeLocalScore(process.cwd(), targetAgent);
6769
6974
  if (afterScore.score < baselineScore.score) {
6770
6975
  trackInitScoreRegression(baselineScore.score, afterScore.score);
6771
6976
  console.log("");
6772
- console.log(chalk9.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
6977
+ console.log(chalk10.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
6773
6978
  try {
6774
6979
  const { restored, removed } = undoSetup();
6775
6980
  if (restored.length > 0 || removed.length > 0) {
6776
- console.log(chalk9.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
6981
+ console.log(chalk10.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
6777
6982
  }
6778
6983
  } catch {
6779
6984
  }
6780
- console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber init --force") + chalk9.dim(" to override.\n"));
6985
+ console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber init --force") + chalk10.dim(" to override.\n"));
6781
6986
  return;
6782
6987
  }
6783
6988
  if (report) {
@@ -6795,39 +7000,57 @@ ${agentRefs.join(" ")}
6795
7000
  log(options.verbose, ` Still failing: ${c.name} (${c.earnedPoints}/${c.maxPoints})${c.suggestion ? ` \u2014 ${c.suggestion}` : ""}`);
6796
7001
  }
6797
7002
  }
6798
- console.log(title.bold("\n Step 5/5 \u2014 Skills\n"));
6799
- console.log(chalk9.dim(" Search community registries for skills that match your tech stack.\n"));
6800
- let wantsSkills;
7003
+ if (skillSearchResult.results.length > 0 && !options.autoApprove) {
7004
+ console.log(chalk10.dim(" Community skills matched to your project:\n"));
7005
+ const selected = await interactiveSelect(skillSearchResult.results);
7006
+ if (selected?.length) {
7007
+ await installSkills(selected, targetAgent, skillSearchResult.contentMap);
7008
+ trackInitSkillsSearch(true, selected.length);
7009
+ }
7010
+ }
7011
+ console.log("");
7012
+ let hookChoice;
6801
7013
  if (options.autoApprove) {
6802
- wantsSkills = false;
6803
- log(options.verbose, "Auto-approve: skipping skills search");
7014
+ hookChoice = "skip";
7015
+ log(options.verbose, "Auto-approve: skipping hook installation");
6804
7016
  } else {
6805
- wantsSkills = await select5({
6806
- message: "Search public repos for relevant skills to add to this project?",
6807
- choices: [
6808
- { name: "Yes, find skills for my project", value: true },
6809
- { name: "Skip for now", value: false }
6810
- ]
6811
- });
7017
+ hookChoice = await promptHookType(targetAgent);
6812
7018
  }
6813
- if (wantsSkills) {
6814
- trackInitSkillsSearch(true, 0);
6815
- try {
6816
- await searchAndInstallSkills(targetAgent);
6817
- } catch (err) {
6818
- if (err.message !== "__exit__") {
6819
- console.log(chalk9.dim(" Skills search failed: " + (err.message || "unknown error")));
6820
- }
6821
- console.log(chalk9.dim(" Run ") + chalk9.hex("#83D1EB")("caliber skills") + chalk9.dim(" later to try again.\n"));
7019
+ trackInitHookSelected(hookChoice);
7020
+ if (hookChoice === "claude" || hookChoice === "both") {
7021
+ const hookResult = installHook();
7022
+ if (hookResult.installed) {
7023
+ console.log(` ${chalk10.green("\u2713")} Claude Code hook installed \u2014 docs update on session end`);
7024
+ console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber hooks --remove") + chalk10.dim(" to disable"));
7025
+ } else if (hookResult.alreadyInstalled) {
7026
+ console.log(chalk10.dim(" Claude Code hook already installed"));
6822
7027
  }
6823
- } else {
6824
- trackInitSkillsSearch(false, 0);
6825
- console.log(chalk9.dim(" Skipped. Run ") + chalk9.hex("#83D1EB")("caliber skills") + chalk9.dim(" later to browse.\n"));
7028
+ const learnResult = installLearningHooks();
7029
+ if (learnResult.installed) {
7030
+ console.log(` ${chalk10.green("\u2713")} Learning hooks installed \u2014 session insights captured automatically`);
7031
+ console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber learn remove") + chalk10.dim(" to disable"));
7032
+ } else if (learnResult.alreadyInstalled) {
7033
+ console.log(chalk10.dim(" Learning hooks already installed"));
7034
+ }
7035
+ }
7036
+ if (hookChoice === "precommit" || hookChoice === "both") {
7037
+ const precommitResult = installPreCommitHook();
7038
+ if (precommitResult.installed) {
7039
+ console.log(` ${chalk10.green("\u2713")} Pre-commit hook installed \u2014 docs refresh before each commit`);
7040
+ console.log(chalk10.dim(" Run ") + chalk10.hex("#83D1EB")("caliber hooks --remove") + chalk10.dim(" to disable"));
7041
+ } else if (precommitResult.alreadyInstalled) {
7042
+ console.log(chalk10.dim(" Pre-commit hook already installed"));
7043
+ } else {
7044
+ console.log(chalk10.yellow(" Could not install pre-commit hook (not a git repository?)"));
7045
+ }
7046
+ }
7047
+ if (hookChoice === "skip") {
7048
+ console.log(chalk10.dim(" Skipped auto-sync hooks. Run ") + chalk10.hex("#83D1EB")("caliber hooks --install") + chalk10.dim(" later to enable."));
6826
7049
  }
6827
- console.log(chalk9.bold.green(" Setup complete!"));
6828
- console.log(chalk9.dim(" Your AI agents now understand your project's architecture, build commands,"));
6829
- console.log(chalk9.dim(" testing patterns, and conventions. All changes are backed up automatically.\n"));
6830
- console.log(chalk9.bold(" Next steps:\n"));
7050
+ console.log(chalk10.bold.green("\n Setup complete!"));
7051
+ console.log(chalk10.dim(" Your AI agents now understand your project's architecture, build commands,"));
7052
+ console.log(chalk10.dim(" testing patterns, and conventions. All changes are backed up automatically.\n"));
7053
+ console.log(chalk10.bold(" Next steps:\n"));
6831
7054
  console.log(` ${title("caliber score")} See your full config breakdown`);
6832
7055
  console.log(` ${title("caliber refresh")} Update docs after code changes`);
6833
7056
  console.log(` ${title("caliber hooks")} Toggle auto-refresh hooks`);
@@ -6841,7 +7064,7 @@ ${agentRefs.join(" ")}
6841
7064
  report.markStep("Finished");
6842
7065
  const reportPath = path19.join(process.cwd(), ".caliber", "debug-report.md");
6843
7066
  report.write(reportPath);
6844
- console.log(chalk9.dim(` Debug report written to ${path19.relative(process.cwd(), reportPath)}
7067
+ console.log(chalk10.dim(` Debug report written to ${path19.relative(process.cwd(), reportPath)}
6845
7068
  `));
6846
7069
  }
6847
7070
  }
@@ -6856,9 +7079,9 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
6856
7079
  }
6857
7080
  const isValid = await classifyRefineIntent(message);
6858
7081
  if (!isValid) {
6859
- console.log(chalk9.dim(" This doesn't look like a config change request."));
6860
- console.log(chalk9.dim(" Describe what to add, remove, or modify in your configs."));
6861
- console.log(chalk9.dim(' Type "done" to accept the current setup.\n'));
7082
+ console.log(chalk10.dim(" This doesn't look like a config change request."));
7083
+ console.log(chalk10.dim(" Describe what to add, remove, or modify in your configs."));
7084
+ console.log(chalk10.dim(' Type "done" to accept the current setup.\n'));
6862
7085
  continue;
6863
7086
  }
6864
7087
  const refineSpinner = ora2("Refining setup...").start();
@@ -6879,10 +7102,10 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
6879
7102
  });
6880
7103
  refineSpinner.succeed("Setup updated");
6881
7104
  printSetupSummary(refined);
6882
- console.log(chalk9.dim('Type "done" to accept, or describe more changes.'));
7105
+ console.log(chalk10.dim('Type "done" to accept, or describe more changes.'));
6883
7106
  } else {
6884
7107
  refineSpinner.fail("Refinement failed \u2014 could not parse AI response.");
6885
- console.log(chalk9.dim('Try rephrasing your request, or type "done" to keep the current setup.'));
7108
+ console.log(chalk10.dim('Try rephrasing your request, or type "done" to keep the current setup.'));
6886
7109
  }
6887
7110
  }
6888
7111
  }
@@ -6910,6 +7133,7 @@ Return {"valid": true} or {"valid": false}. Nothing else.`,
6910
7133
  }
6911
7134
  }
6912
7135
  async function evaluateDismissals(failingChecks, fingerprint) {
7136
+ if (failingChecks.length === 0) return [];
6913
7137
  const fastModel = getFastModel();
6914
7138
  const checkList = failingChecks.map((c) => ({
6915
7139
  id: c.id,
@@ -6977,7 +7201,7 @@ async function promptHookType(targetAgent) {
6977
7201
  }
6978
7202
  choices.push({ name: "Skip for now", value: "skip" });
6979
7203
  return select5({
6980
- message: "How would you like to auto-refresh your setup?",
7204
+ message: "Keep your AI docs & skills in sync as your code evolves?",
6981
7205
  choices
6982
7206
  });
6983
7207
  }
@@ -6997,26 +7221,26 @@ function printSetupSummary(setup) {
6997
7221
  const fileDescriptions = setup.fileDescriptions;
6998
7222
  const deletions = setup.deletions;
6999
7223
  console.log("");
7000
- console.log(chalk9.bold(" Proposed changes:\n"));
7224
+ console.log(chalk10.bold(" Proposed changes:\n"));
7001
7225
  const getDescription = (filePath) => {
7002
7226
  return fileDescriptions?.[filePath];
7003
7227
  };
7004
7228
  if (claude) {
7005
7229
  if (claude.claudeMd) {
7006
- const icon = fs24.existsSync("CLAUDE.md") ? chalk9.yellow("~") : chalk9.green("+");
7230
+ const icon = fs24.existsSync("CLAUDE.md") ? chalk10.yellow("~") : chalk10.green("+");
7007
7231
  const desc = getDescription("CLAUDE.md");
7008
- console.log(` ${icon} ${chalk9.bold("CLAUDE.md")}`);
7009
- if (desc) console.log(chalk9.dim(` ${desc}`));
7232
+ console.log(` ${icon} ${chalk10.bold("CLAUDE.md")}`);
7233
+ if (desc) console.log(chalk10.dim(` ${desc}`));
7010
7234
  console.log("");
7011
7235
  }
7012
7236
  const skills = claude.skills;
7013
7237
  if (Array.isArray(skills) && skills.length > 0) {
7014
7238
  for (const skill of skills) {
7015
7239
  const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
7016
- const icon = fs24.existsSync(skillPath) ? chalk9.yellow("~") : chalk9.green("+");
7240
+ const icon = fs24.existsSync(skillPath) ? chalk10.yellow("~") : chalk10.green("+");
7017
7241
  const desc = getDescription(skillPath);
7018
- console.log(` ${icon} ${chalk9.bold(skillPath)}`);
7019
- console.log(chalk9.dim(` ${desc || skill.description || skill.name}`));
7242
+ console.log(` ${icon} ${chalk10.bold(skillPath)}`);
7243
+ console.log(chalk10.dim(` ${desc || skill.description || skill.name}`));
7020
7244
  console.log("");
7021
7245
  }
7022
7246
  }
@@ -7024,40 +7248,40 @@ function printSetupSummary(setup) {
7024
7248
  const codex = setup.codex;
7025
7249
  if (codex) {
7026
7250
  if (codex.agentsMd) {
7027
- const icon = fs24.existsSync("AGENTS.md") ? chalk9.yellow("~") : chalk9.green("+");
7251
+ const icon = fs24.existsSync("AGENTS.md") ? chalk10.yellow("~") : chalk10.green("+");
7028
7252
  const desc = getDescription("AGENTS.md");
7029
- console.log(` ${icon} ${chalk9.bold("AGENTS.md")}`);
7030
- if (desc) console.log(chalk9.dim(` ${desc}`));
7253
+ console.log(` ${icon} ${chalk10.bold("AGENTS.md")}`);
7254
+ if (desc) console.log(chalk10.dim(` ${desc}`));
7031
7255
  console.log("");
7032
7256
  }
7033
7257
  const codexSkills = codex.skills;
7034
7258
  if (Array.isArray(codexSkills) && codexSkills.length > 0) {
7035
7259
  for (const skill of codexSkills) {
7036
7260
  const skillPath = `.agents/skills/${skill.name}/SKILL.md`;
7037
- const icon = fs24.existsSync(skillPath) ? chalk9.yellow("~") : chalk9.green("+");
7261
+ const icon = fs24.existsSync(skillPath) ? chalk10.yellow("~") : chalk10.green("+");
7038
7262
  const desc = getDescription(skillPath);
7039
- console.log(` ${icon} ${chalk9.bold(skillPath)}`);
7040
- console.log(chalk9.dim(` ${desc || skill.description || skill.name}`));
7263
+ console.log(` ${icon} ${chalk10.bold(skillPath)}`);
7264
+ console.log(chalk10.dim(` ${desc || skill.description || skill.name}`));
7041
7265
  console.log("");
7042
7266
  }
7043
7267
  }
7044
7268
  }
7045
7269
  if (cursor) {
7046
7270
  if (cursor.cursorrules) {
7047
- const icon = fs24.existsSync(".cursorrules") ? chalk9.yellow("~") : chalk9.green("+");
7271
+ const icon = fs24.existsSync(".cursorrules") ? chalk10.yellow("~") : chalk10.green("+");
7048
7272
  const desc = getDescription(".cursorrules");
7049
- console.log(` ${icon} ${chalk9.bold(".cursorrules")}`);
7050
- if (desc) console.log(chalk9.dim(` ${desc}`));
7273
+ console.log(` ${icon} ${chalk10.bold(".cursorrules")}`);
7274
+ if (desc) console.log(chalk10.dim(` ${desc}`));
7051
7275
  console.log("");
7052
7276
  }
7053
7277
  const cursorSkills = cursor.skills;
7054
7278
  if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
7055
7279
  for (const skill of cursorSkills) {
7056
7280
  const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
7057
- const icon = fs24.existsSync(skillPath) ? chalk9.yellow("~") : chalk9.green("+");
7281
+ const icon = fs24.existsSync(skillPath) ? chalk10.yellow("~") : chalk10.green("+");
7058
7282
  const desc = getDescription(skillPath);
7059
- console.log(` ${icon} ${chalk9.bold(skillPath)}`);
7060
- console.log(chalk9.dim(` ${desc || skill.description || skill.name}`));
7283
+ console.log(` ${icon} ${chalk10.bold(skillPath)}`);
7284
+ console.log(chalk10.dim(` ${desc || skill.description || skill.name}`));
7061
7285
  console.log("");
7062
7286
  }
7063
7287
  }
@@ -7065,14 +7289,14 @@ function printSetupSummary(setup) {
7065
7289
  if (Array.isArray(rules) && rules.length > 0) {
7066
7290
  for (const rule of rules) {
7067
7291
  const rulePath = `.cursor/rules/${rule.filename}`;
7068
- const icon = fs24.existsSync(rulePath) ? chalk9.yellow("~") : chalk9.green("+");
7292
+ const icon = fs24.existsSync(rulePath) ? chalk10.yellow("~") : chalk10.green("+");
7069
7293
  const desc = getDescription(rulePath);
7070
- console.log(` ${icon} ${chalk9.bold(rulePath)}`);
7294
+ console.log(` ${icon} ${chalk10.bold(rulePath)}`);
7071
7295
  if (desc) {
7072
- console.log(chalk9.dim(` ${desc}`));
7296
+ console.log(chalk10.dim(` ${desc}`));
7073
7297
  } else {
7074
7298
  const firstLine = rule.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#"))[0];
7075
- if (firstLine) console.log(chalk9.dim(` ${firstLine.trim().slice(0, 80)}`));
7299
+ if (firstLine) console.log(chalk10.dim(` ${firstLine.trim().slice(0, 80)}`));
7076
7300
  }
7077
7301
  console.log("");
7078
7302
  }
@@ -7080,12 +7304,12 @@ function printSetupSummary(setup) {
7080
7304
  }
7081
7305
  if (Array.isArray(deletions) && deletions.length > 0) {
7082
7306
  for (const del of deletions) {
7083
- console.log(` ${chalk9.red("-")} ${chalk9.bold(del.filePath)}`);
7084
- console.log(chalk9.dim(` ${del.reason}`));
7307
+ console.log(` ${chalk10.red("-")} ${chalk10.bold(del.filePath)}`);
7308
+ console.log(chalk10.dim(` ${del.reason}`));
7085
7309
  console.log("");
7086
7310
  }
7087
7311
  }
7088
- console.log(` ${chalk9.green("+")} ${chalk9.dim("new")} ${chalk9.yellow("~")} ${chalk9.dim("modified")} ${chalk9.red("-")} ${chalk9.dim("removed")}`);
7312
+ console.log(` ${chalk10.green("+")} ${chalk10.dim("new")} ${chalk10.yellow("~")} ${chalk10.dim("modified")} ${chalk10.red("-")} ${chalk10.dim("removed")}`);
7089
7313
  console.log("");
7090
7314
  }
7091
7315
  function derivePermissions(fingerprint) {
@@ -7145,20 +7369,20 @@ function ensurePermissions(fingerprint) {
7145
7369
  function displayTokenUsage() {
7146
7370
  const summary = getUsageSummary();
7147
7371
  if (summary.length === 0) {
7148
- console.log(chalk9.dim(" Token tracking not available for this provider.\n"));
7372
+ console.log(chalk10.dim(" Token tracking not available for this provider.\n"));
7149
7373
  return;
7150
7374
  }
7151
- console.log(chalk9.bold(" Token usage:\n"));
7375
+ console.log(chalk10.bold(" Token usage:\n"));
7152
7376
  let totalIn = 0;
7153
7377
  let totalOut = 0;
7154
7378
  for (const m of summary) {
7155
7379
  totalIn += m.inputTokens;
7156
7380
  totalOut += m.outputTokens;
7157
- const cacheInfo = m.cacheReadTokens > 0 || m.cacheWriteTokens > 0 ? chalk9.dim(` (cache: ${m.cacheReadTokens.toLocaleString()} read, ${m.cacheWriteTokens.toLocaleString()} write)`) : "";
7158
- console.log(` ${chalk9.dim(m.model)}: ${m.inputTokens.toLocaleString()} in / ${m.outputTokens.toLocaleString()} out (${m.calls} call${m.calls === 1 ? "" : "s"})${cacheInfo}`);
7381
+ const cacheInfo = m.cacheReadTokens > 0 || m.cacheWriteTokens > 0 ? chalk10.dim(` (cache: ${m.cacheReadTokens.toLocaleString()} read, ${m.cacheWriteTokens.toLocaleString()} write)`) : "";
7382
+ console.log(` ${chalk10.dim(m.model)}: ${m.inputTokens.toLocaleString()} in / ${m.outputTokens.toLocaleString()} out (${m.calls} call${m.calls === 1 ? "" : "s"})${cacheInfo}`);
7159
7383
  }
7160
7384
  if (summary.length > 1) {
7161
- console.log(` ${chalk9.dim("Total")}: ${totalIn.toLocaleString()} in / ${totalOut.toLocaleString()} out`);
7385
+ console.log(` ${chalk10.dim("Total")}: ${totalIn.toLocaleString()} in / ${totalOut.toLocaleString()} out`);
7162
7386
  }
7163
7387
  console.log("");
7164
7388
  }
@@ -7179,14 +7403,14 @@ function writeErrorLog(config, rawOutput, error, stopReason) {
7179
7403
  lines.push("## Raw LLM Output", "```", rawOutput || "(empty)", "```");
7180
7404
  fs24.mkdirSync(path19.join(process.cwd(), ".caliber"), { recursive: true });
7181
7405
  fs24.writeFileSync(logPath, lines.join("\n"));
7182
- console.log(chalk9.dim(`
7406
+ console.log(chalk10.dim(`
7183
7407
  Error log written to .caliber/error-log.md`));
7184
7408
  } catch {
7185
7409
  }
7186
7410
  }
7187
7411
 
7188
7412
  // src/commands/undo.ts
7189
- import chalk10 from "chalk";
7413
+ import chalk11 from "chalk";
7190
7414
  import ora3 from "ora";
7191
7415
  function undoCommand() {
7192
7416
  const spinner = ora3("Reverting setup...").start();
@@ -7199,26 +7423,26 @@ function undoCommand() {
7199
7423
  trackUndoExecuted();
7200
7424
  spinner.succeed("Setup reverted successfully.\n");
7201
7425
  if (restored.length > 0) {
7202
- console.log(chalk10.cyan(" Restored from backup:"));
7426
+ console.log(chalk11.cyan(" Restored from backup:"));
7203
7427
  for (const file of restored) {
7204
- console.log(` ${chalk10.green("\u21A9")} ${file}`);
7428
+ console.log(` ${chalk11.green("\u21A9")} ${file}`);
7205
7429
  }
7206
7430
  }
7207
7431
  if (removed.length > 0) {
7208
- console.log(chalk10.cyan(" Removed:"));
7432
+ console.log(chalk11.cyan(" Removed:"));
7209
7433
  for (const file of removed) {
7210
- console.log(` ${chalk10.red("\u2717")} ${file}`);
7434
+ console.log(` ${chalk11.red("\u2717")} ${file}`);
7211
7435
  }
7212
7436
  }
7213
7437
  console.log("");
7214
7438
  } catch (err) {
7215
- spinner.fail(chalk10.red(err instanceof Error ? err.message : "Undo failed"));
7439
+ spinner.fail(chalk11.red(err instanceof Error ? err.message : "Undo failed"));
7216
7440
  throw new Error("__exit__");
7217
7441
  }
7218
7442
  }
7219
7443
 
7220
7444
  // src/commands/status.ts
7221
- import chalk11 from "chalk";
7445
+ import chalk12 from "chalk";
7222
7446
  import fs25 from "fs";
7223
7447
  init_config();
7224
7448
  async function statusCommand(options) {
@@ -7233,40 +7457,40 @@ async function statusCommand(options) {
7233
7457
  }, null, 2));
7234
7458
  return;
7235
7459
  }
7236
- console.log(chalk11.bold("\nCaliber Status\n"));
7460
+ console.log(chalk12.bold("\nCaliber Status\n"));
7237
7461
  if (config) {
7238
- console.log(` LLM: ${chalk11.green(config.provider)} (${config.model})`);
7462
+ console.log(` LLM: ${chalk12.green(config.provider)} (${config.model})`);
7239
7463
  } else {
7240
- console.log(` LLM: ${chalk11.yellow("Not configured")} \u2014 run ${chalk11.hex("#83D1EB")("caliber config")}`);
7464
+ console.log(` LLM: ${chalk12.yellow("Not configured")} \u2014 run ${chalk12.hex("#83D1EB")("caliber config")}`);
7241
7465
  }
7242
7466
  if (!manifest) {
7243
- console.log(` Setup: ${chalk11.dim("No setup applied")}`);
7244
- console.log(chalk11.dim("\n Run ") + chalk11.hex("#83D1EB")("caliber init") + chalk11.dim(" to get started.\n"));
7467
+ console.log(` Setup: ${chalk12.dim("No setup applied")}`);
7468
+ console.log(chalk12.dim("\n Run ") + chalk12.hex("#83D1EB")("caliber init") + chalk12.dim(" to get started.\n"));
7245
7469
  return;
7246
7470
  }
7247
- console.log(` Files managed: ${chalk11.cyan(manifest.entries.length.toString())}`);
7471
+ console.log(` Files managed: ${chalk12.cyan(manifest.entries.length.toString())}`);
7248
7472
  for (const entry of manifest.entries) {
7249
7473
  const exists = fs25.existsSync(entry.path);
7250
- const icon = exists ? chalk11.green("\u2713") : chalk11.red("\u2717");
7474
+ const icon = exists ? chalk12.green("\u2713") : chalk12.red("\u2717");
7251
7475
  console.log(` ${icon} ${entry.path} (${entry.action})`);
7252
7476
  }
7253
7477
  console.log("");
7254
7478
  }
7255
7479
 
7256
7480
  // src/commands/regenerate.ts
7257
- import chalk12 from "chalk";
7481
+ import chalk13 from "chalk";
7258
7482
  import ora4 from "ora";
7259
7483
  import select6 from "@inquirer/select";
7260
7484
  init_config();
7261
7485
  async function regenerateCommand(options) {
7262
7486
  const config = loadConfig();
7263
7487
  if (!config) {
7264
- console.log(chalk12.red("No LLM provider configured. Run ") + chalk12.hex("#83D1EB")("caliber config") + chalk12.red(" first."));
7488
+ console.log(chalk13.red("No LLM provider configured. Run ") + chalk13.hex("#83D1EB")("caliber config") + chalk13.red(" first."));
7265
7489
  throw new Error("__exit__");
7266
7490
  }
7267
7491
  const manifest = readManifest();
7268
7492
  if (!manifest) {
7269
- console.log(chalk12.yellow("No existing setup found. Run ") + chalk12.hex("#83D1EB")("caliber init") + chalk12.yellow(" first."));
7493
+ console.log(chalk13.yellow("No existing setup found. Run ") + chalk13.hex("#83D1EB")("caliber init") + chalk13.yellow(" first."));
7270
7494
  throw new Error("__exit__");
7271
7495
  }
7272
7496
  const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
@@ -7277,7 +7501,7 @@ async function regenerateCommand(options) {
7277
7501
  const baselineScore = computeLocalScore(process.cwd(), targetAgent);
7278
7502
  displayScoreSummary(baselineScore);
7279
7503
  if (baselineScore.score === 100) {
7280
- console.log(chalk12.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
7504
+ console.log(chalk13.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
7281
7505
  return;
7282
7506
  }
7283
7507
  const genSpinner = ora4("Regenerating setup...").start();
@@ -7318,18 +7542,18 @@ async function regenerateCommand(options) {
7318
7542
  const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
7319
7543
  const staged = stageFiles(setupFiles, process.cwd());
7320
7544
  const totalChanges = staged.newFiles + staged.modifiedFiles;
7321
- console.log(chalk12.dim(`
7322
- ${chalk12.green(`${staged.newFiles} new`)} / ${chalk12.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
7545
+ console.log(chalk13.dim(`
7546
+ ${chalk13.green(`${staged.newFiles} new`)} / ${chalk13.yellow(`${staged.modifiedFiles} modified`)} file${totalChanges !== 1 ? "s" : ""}
7323
7547
  `));
7324
7548
  if (totalChanges === 0) {
7325
- console.log(chalk12.dim(" No changes needed \u2014 your configs are already up to date.\n"));
7549
+ console.log(chalk13.dim(" No changes needed \u2014 your configs are already up to date.\n"));
7326
7550
  cleanupStaging();
7327
7551
  return;
7328
7552
  }
7329
7553
  if (options.dryRun) {
7330
- console.log(chalk12.yellow("[Dry run] Would write:"));
7554
+ console.log(chalk13.yellow("[Dry run] Would write:"));
7331
7555
  for (const f of staged.stagedFiles) {
7332
- console.log(` ${f.isNew ? chalk12.green("+") : chalk12.yellow("~")} ${f.relativePath}`);
7556
+ console.log(` ${f.isNew ? chalk13.green("+") : chalk13.yellow("~")} ${f.relativePath}`);
7333
7557
  }
7334
7558
  cleanupStaging();
7335
7559
  return;
@@ -7348,7 +7572,7 @@ async function regenerateCommand(options) {
7348
7572
  });
7349
7573
  cleanupStaging();
7350
7574
  if (action === "decline") {
7351
- console.log(chalk12.dim("Regeneration cancelled. No files were modified."));
7575
+ console.log(chalk13.dim("Regeneration cancelled. No files were modified."));
7352
7576
  return;
7353
7577
  }
7354
7578
  const writeSpinner = ora4("Writing config files...").start();
@@ -7356,20 +7580,20 @@ async function regenerateCommand(options) {
7356
7580
  const result = writeSetup(generatedSetup);
7357
7581
  writeSpinner.succeed("Config files written");
7358
7582
  for (const file of result.written) {
7359
- console.log(` ${chalk12.green("\u2713")} ${file}`);
7583
+ console.log(` ${chalk13.green("\u2713")} ${file}`);
7360
7584
  }
7361
7585
  if (result.deleted.length > 0) {
7362
7586
  for (const file of result.deleted) {
7363
- console.log(` ${chalk12.red("\u2717")} ${file}`);
7587
+ console.log(` ${chalk13.red("\u2717")} ${file}`);
7364
7588
  }
7365
7589
  }
7366
7590
  if (result.backupDir) {
7367
- console.log(chalk12.dim(`
7591
+ console.log(chalk13.dim(`
7368
7592
  Backups saved to ${result.backupDir}`));
7369
7593
  }
7370
7594
  } catch (err) {
7371
7595
  writeSpinner.fail("Failed to write files");
7372
- console.error(chalk12.red(err instanceof Error ? err.message : "Unknown error"));
7596
+ console.error(chalk13.red(err instanceof Error ? err.message : "Unknown error"));
7373
7597
  throw new Error("__exit__");
7374
7598
  }
7375
7599
  const sha = getCurrentHeadSha();
@@ -7381,25 +7605,25 @@ async function regenerateCommand(options) {
7381
7605
  const afterScore = computeLocalScore(process.cwd(), targetAgent);
7382
7606
  if (afterScore.score < baselineScore.score) {
7383
7607
  console.log("");
7384
- console.log(chalk12.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
7608
+ console.log(chalk13.yellow(` Score would drop from ${baselineScore.score} to ${afterScore.score} \u2014 reverting changes.`));
7385
7609
  try {
7386
7610
  const { restored, removed } = undoSetup();
7387
7611
  if (restored.length > 0 || removed.length > 0) {
7388
- console.log(chalk12.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
7612
+ console.log(chalk13.dim(` Reverted ${restored.length + removed.length} file${restored.length + removed.length === 1 ? "" : "s"} from backup.`));
7389
7613
  }
7390
7614
  } catch {
7391
7615
  }
7392
- console.log(chalk12.dim(" Run ") + chalk12.hex("#83D1EB")("caliber init --force") + chalk12.dim(" to override.\n"));
7616
+ console.log(chalk13.dim(" Run ") + chalk13.hex("#83D1EB")("caliber init --force") + chalk13.dim(" to override.\n"));
7393
7617
  return;
7394
7618
  }
7395
7619
  displayScoreDelta(baselineScore, afterScore);
7396
7620
  trackRegenerateCompleted(action, Date.now());
7397
- console.log(chalk12.bold.green(" Regeneration complete!"));
7398
- console.log(chalk12.dim(" Run ") + chalk12.hex("#83D1EB")("caliber undo") + chalk12.dim(" to revert changes.\n"));
7621
+ console.log(chalk13.bold.green(" Regeneration complete!"));
7622
+ console.log(chalk13.dim(" Run ") + chalk13.hex("#83D1EB")("caliber undo") + chalk13.dim(" to revert changes.\n"));
7399
7623
  }
7400
7624
 
7401
7625
  // src/commands/score.ts
7402
- import chalk13 from "chalk";
7626
+ import chalk14 from "chalk";
7403
7627
  async function scoreCommand(options) {
7404
7628
  const dir = process.cwd();
7405
7629
  const target = options.agent ?? readState()?.targetAgent;
@@ -7414,14 +7638,14 @@ async function scoreCommand(options) {
7414
7638
  return;
7415
7639
  }
7416
7640
  displayScore(result);
7417
- const separator = chalk13.gray(" " + "\u2500".repeat(53));
7641
+ const separator = chalk14.gray(" " + "\u2500".repeat(53));
7418
7642
  console.log(separator);
7419
7643
  if (result.score < 40) {
7420
- console.log(chalk13.gray(" Run ") + chalk13.hex("#83D1EB")("caliber init") + chalk13.gray(" to generate a complete, optimized setup."));
7644
+ console.log(chalk14.gray(" Run ") + chalk14.hex("#83D1EB")("caliber init") + chalk14.gray(" to generate a complete, optimized setup."));
7421
7645
  } else if (result.score < 70) {
7422
- console.log(chalk13.gray(" Run ") + chalk13.hex("#83D1EB")("caliber init") + chalk13.gray(" to improve your setup."));
7646
+ console.log(chalk14.gray(" Run ") + chalk14.hex("#83D1EB")("caliber init") + chalk14.gray(" to improve your setup."));
7423
7647
  } else {
7424
- console.log(chalk13.green(" Looking good!") + chalk13.gray(" Run ") + chalk13.hex("#83D1EB")("caliber regenerate") + chalk13.gray(" to rebuild from scratch."));
7648
+ console.log(chalk14.green(" Looking good!") + chalk14.gray(" Run ") + chalk14.hex("#83D1EB")("caliber regenerate") + chalk14.gray(" to rebuild from scratch."));
7425
7649
  }
7426
7650
  console.log("");
7427
7651
  }
@@ -7429,7 +7653,7 @@ async function scoreCommand(options) {
7429
7653
  // src/commands/refresh.ts
7430
7654
  import fs29 from "fs";
7431
7655
  import path23 from "path";
7432
- import chalk14 from "chalk";
7656
+ import chalk15 from "chalk";
7433
7657
  import ora5 from "ora";
7434
7658
 
7435
7659
  // src/lib/git-diff.ts
@@ -7772,7 +7996,7 @@ function discoverGitRepos(parentDir) {
7772
7996
  }
7773
7997
  async function refreshSingleRepo(repoDir, options) {
7774
7998
  const quiet = !!options.quiet;
7775
- const prefix = options.label ? `${chalk14.bold(options.label)} ` : "";
7999
+ const prefix = options.label ? `${chalk15.bold(options.label)} ` : "";
7776
8000
  const state = readState();
7777
8001
  const lastSha = state?.lastRefreshSha ?? null;
7778
8002
  const diff = collectDiff(lastSha);
@@ -7781,7 +8005,7 @@ async function refreshSingleRepo(repoDir, options) {
7781
8005
  if (currentSha) {
7782
8006
  writeState({ lastRefreshSha: currentSha, lastRefreshTimestamp: (/* @__PURE__ */ new Date()).toISOString() });
7783
8007
  }
7784
- log2(quiet, chalk14.dim(`${prefix}No changes since last refresh.`));
8008
+ log2(quiet, chalk15.dim(`${prefix}No changes since last refresh.`));
7785
8009
  return;
7786
8010
  }
7787
8011
  const spinner = quiet ? null : ora5(`${prefix}Analyzing changes...`).start();
@@ -7815,10 +8039,10 @@ async function refreshSingleRepo(repoDir, options) {
7815
8039
  if (options.dryRun) {
7816
8040
  spinner?.info(`${prefix}Dry run \u2014 would update:`);
7817
8041
  for (const doc of response.docsUpdated) {
7818
- console.log(` ${chalk14.yellow("~")} ${doc}`);
8042
+ console.log(` ${chalk15.yellow("~")} ${doc}`);
7819
8043
  }
7820
8044
  if (response.changesSummary) {
7821
- console.log(chalk14.dim(`
8045
+ console.log(chalk15.dim(`
7822
8046
  ${response.changesSummary}`));
7823
8047
  }
7824
8048
  return;
@@ -7827,10 +8051,10 @@ async function refreshSingleRepo(repoDir, options) {
7827
8051
  trackRefreshCompleted(written.length, Date.now());
7828
8052
  spinner?.succeed(`${prefix}Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
7829
8053
  for (const file of written) {
7830
- log2(quiet, ` ${chalk14.green("\u2713")} ${file}`);
8054
+ log2(quiet, ` ${chalk15.green("\u2713")} ${file}`);
7831
8055
  }
7832
8056
  if (response.changesSummary) {
7833
- log2(quiet, chalk14.dim(`
8057
+ log2(quiet, chalk15.dim(`
7834
8058
  ${response.changesSummary}`));
7835
8059
  }
7836
8060
  if (currentSha) {
@@ -7847,7 +8071,7 @@ async function refreshCommand(options) {
7847
8071
  const config = loadConfig();
7848
8072
  if (!config) {
7849
8073
  if (quiet) return;
7850
- console.log(chalk14.red("No LLM provider configured. Run ") + chalk14.hex("#83D1EB")("caliber config") + chalk14.red(" (e.g. choose Cursor) or set an API key."));
8074
+ console.log(chalk15.red("No LLM provider configured. Run ") + chalk15.hex("#83D1EB")("caliber config") + chalk15.red(" (e.g. choose Cursor) or set an API key."));
7851
8075
  throw new Error("__exit__");
7852
8076
  }
7853
8077
  await validateModel({ fast: true });
@@ -7858,10 +8082,10 @@ async function refreshCommand(options) {
7858
8082
  const repos = discoverGitRepos(process.cwd());
7859
8083
  if (repos.length === 0) {
7860
8084
  if (quiet) return;
7861
- console.log(chalk14.red("Not inside a git repository and no git repos found in child directories."));
8085
+ console.log(chalk15.red("Not inside a git repository and no git repos found in child directories."));
7862
8086
  throw new Error("__exit__");
7863
8087
  }
7864
- log2(quiet, chalk14.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
8088
+ log2(quiet, chalk15.dim(`Found ${repos.length} git repo${repos.length === 1 ? "" : "s"}
7865
8089
  `));
7866
8090
  const originalDir = process.cwd();
7867
8091
  for (const repo of repos) {
@@ -7871,7 +8095,7 @@ async function refreshCommand(options) {
7871
8095
  await refreshSingleRepo(repo, { ...options, label: repoName });
7872
8096
  } catch (err) {
7873
8097
  if (err instanceof Error && err.message === "__exit__") continue;
7874
- log2(quiet, chalk14.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
8098
+ log2(quiet, chalk15.yellow(`${repoName}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`));
7875
8099
  }
7876
8100
  }
7877
8101
  process.chdir(originalDir);
@@ -7879,13 +8103,13 @@ async function refreshCommand(options) {
7879
8103
  if (err instanceof Error && err.message === "__exit__") throw err;
7880
8104
  if (quiet) return;
7881
8105
  const msg = err instanceof Error ? err.message : "Unknown error";
7882
- console.log(chalk14.red(`Refresh failed: ${msg}`));
8106
+ console.log(chalk15.red(`Refresh failed: ${msg}`));
7883
8107
  throw new Error("__exit__");
7884
8108
  }
7885
8109
  }
7886
8110
 
7887
8111
  // src/commands/hooks.ts
7888
- import chalk15 from "chalk";
8112
+ import chalk16 from "chalk";
7889
8113
  var HOOKS = [
7890
8114
  {
7891
8115
  id: "session-end",
@@ -7905,13 +8129,13 @@ var HOOKS = [
7905
8129
  }
7906
8130
  ];
7907
8131
  function printStatus() {
7908
- console.log(chalk15.bold("\n Hooks\n"));
8132
+ console.log(chalk16.bold("\n Hooks\n"));
7909
8133
  for (const hook of HOOKS) {
7910
8134
  const installed = hook.isInstalled();
7911
- const icon = installed ? chalk15.green("\u2713") : chalk15.dim("\u2717");
7912
- const state = installed ? chalk15.green("enabled") : chalk15.dim("disabled");
8135
+ const icon = installed ? chalk16.green("\u2713") : chalk16.dim("\u2717");
8136
+ const state = installed ? chalk16.green("enabled") : chalk16.dim("disabled");
7913
8137
  console.log(` ${icon} ${hook.label.padEnd(26)} ${state}`);
7914
- console.log(chalk15.dim(` ${hook.description}`));
8138
+ console.log(chalk16.dim(` ${hook.description}`));
7915
8139
  }
7916
8140
  console.log("");
7917
8141
  }
@@ -7920,9 +8144,9 @@ async function hooksCommand(options) {
7920
8144
  for (const hook of HOOKS) {
7921
8145
  const result = hook.install();
7922
8146
  if (result.alreadyInstalled) {
7923
- console.log(chalk15.dim(` ${hook.label} already enabled.`));
8147
+ console.log(chalk16.dim(` ${hook.label} already enabled.`));
7924
8148
  } else {
7925
- console.log(chalk15.green(" \u2713") + ` ${hook.label} enabled`);
8149
+ console.log(chalk16.green(" \u2713") + ` ${hook.label} enabled`);
7926
8150
  }
7927
8151
  }
7928
8152
  return;
@@ -7931,9 +8155,9 @@ async function hooksCommand(options) {
7931
8155
  for (const hook of HOOKS) {
7932
8156
  const result = hook.remove();
7933
8157
  if (result.notFound) {
7934
- console.log(chalk15.dim(` ${hook.label} already disabled.`));
8158
+ console.log(chalk16.dim(` ${hook.label} already disabled.`));
7935
8159
  } else {
7936
- console.log(chalk15.green(" \u2713") + ` ${hook.label} removed`);
8160
+ console.log(chalk16.green(" \u2713") + ` ${hook.label} removed`);
7937
8161
  }
7938
8162
  }
7939
8163
  return;
@@ -7948,18 +8172,18 @@ async function hooksCommand(options) {
7948
8172
  const states = HOOKS.map((h) => h.isInstalled());
7949
8173
  function render() {
7950
8174
  const lines = [];
7951
- lines.push(chalk15.bold(" Hooks"));
8175
+ lines.push(chalk16.bold(" Hooks"));
7952
8176
  lines.push("");
7953
8177
  for (let i = 0; i < HOOKS.length; i++) {
7954
8178
  const hook = HOOKS[i];
7955
8179
  const enabled = states[i];
7956
- const toggle = enabled ? chalk15.green("[on] ") : chalk15.dim("[off]");
7957
- const ptr = i === cursor ? chalk15.cyan(">") : " ";
8180
+ const toggle = enabled ? chalk16.green("[on] ") : chalk16.dim("[off]");
8181
+ const ptr = i === cursor ? chalk16.cyan(">") : " ";
7958
8182
  lines.push(` ${ptr} ${toggle} ${hook.label}`);
7959
- lines.push(chalk15.dim(` ${hook.description}`));
8183
+ lines.push(chalk16.dim(` ${hook.description}`));
7960
8184
  }
7961
8185
  lines.push("");
7962
- lines.push(chalk15.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
8186
+ lines.push(chalk16.dim(" \u2191\u2193 navigate \u23B5 toggle a all on n all off \u23CE apply q cancel"));
7963
8187
  return lines.join("\n");
7964
8188
  }
7965
8189
  function draw(initial) {
@@ -7990,16 +8214,16 @@ async function hooksCommand(options) {
7990
8214
  const wantEnabled = states[i];
7991
8215
  if (wantEnabled && !wasInstalled) {
7992
8216
  hook.install();
7993
- console.log(chalk15.green(" \u2713") + ` ${hook.label} enabled`);
8217
+ console.log(chalk16.green(" \u2713") + ` ${hook.label} enabled`);
7994
8218
  changed++;
7995
8219
  } else if (!wantEnabled && wasInstalled) {
7996
8220
  hook.remove();
7997
- console.log(chalk15.green(" \u2713") + ` ${hook.label} disabled`);
8221
+ console.log(chalk16.green(" \u2713") + ` ${hook.label} disabled`);
7998
8222
  changed++;
7999
8223
  }
8000
8224
  }
8001
8225
  if (changed === 0) {
8002
- console.log(chalk15.dim(" No changes."));
8226
+ console.log(chalk16.dim(" No changes."));
8003
8227
  }
8004
8228
  console.log("");
8005
8229
  }
@@ -8035,7 +8259,7 @@ async function hooksCommand(options) {
8035
8259
  case "\x1B":
8036
8260
  case "":
8037
8261
  cleanup();
8038
- console.log(chalk15.dim("\n Cancelled.\n"));
8262
+ console.log(chalk16.dim("\n Cancelled.\n"));
8039
8263
  resolve2();
8040
8264
  break;
8041
8265
  }
@@ -8046,51 +8270,51 @@ async function hooksCommand(options) {
8046
8270
 
8047
8271
  // src/commands/config.ts
8048
8272
  init_config();
8049
- import chalk16 from "chalk";
8273
+ import chalk17 from "chalk";
8050
8274
  async function configCommand() {
8051
8275
  const existing = loadConfig();
8052
8276
  if (existing) {
8053
8277
  const displayModel = getDisplayModel(existing);
8054
8278
  const fastModel = getFastModel();
8055
- console.log(chalk16.bold("\nCurrent Configuration\n"));
8056
- console.log(` Provider: ${chalk16.cyan(existing.provider)}`);
8057
- console.log(` Model: ${chalk16.cyan(displayModel)}`);
8279
+ console.log(chalk17.bold("\nCurrent Configuration\n"));
8280
+ console.log(` Provider: ${chalk17.cyan(existing.provider)}`);
8281
+ console.log(` Model: ${chalk17.cyan(displayModel)}`);
8058
8282
  if (fastModel) {
8059
- console.log(` Scan: ${chalk16.cyan(fastModel)}`);
8283
+ console.log(` Scan: ${chalk17.cyan(fastModel)}`);
8060
8284
  }
8061
8285
  if (existing.apiKey) {
8062
8286
  const masked = existing.apiKey.slice(0, 8) + "..." + existing.apiKey.slice(-4);
8063
- console.log(` API Key: ${chalk16.dim(masked)}`);
8287
+ console.log(` API Key: ${chalk17.dim(masked)}`);
8064
8288
  }
8065
8289
  if (existing.provider === "cursor") {
8066
- console.log(` Seat: ${chalk16.dim("Cursor (agent acp)")}`);
8290
+ console.log(` Seat: ${chalk17.dim("Cursor (agent acp)")}`);
8067
8291
  }
8068
8292
  if (existing.provider === "claude-cli") {
8069
- console.log(` Seat: ${chalk16.dim("Claude Code (claude -p)")}`);
8293
+ console.log(` Seat: ${chalk17.dim("Claude Code (claude -p)")}`);
8070
8294
  }
8071
8295
  if (existing.baseUrl) {
8072
- console.log(` Base URL: ${chalk16.dim(existing.baseUrl)}`);
8296
+ console.log(` Base URL: ${chalk17.dim(existing.baseUrl)}`);
8073
8297
  }
8074
8298
  if (existing.vertexProjectId) {
8075
- console.log(` Vertex Project: ${chalk16.dim(existing.vertexProjectId)}`);
8076
- console.log(` Vertex Region: ${chalk16.dim(existing.vertexRegion || "us-east5")}`);
8299
+ console.log(` Vertex Project: ${chalk17.dim(existing.vertexProjectId)}`);
8300
+ console.log(` Vertex Region: ${chalk17.dim(existing.vertexRegion || "us-east5")}`);
8077
8301
  }
8078
- console.log(` Source: ${chalk16.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())}`);
8302
+ console.log(` Source: ${chalk17.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())}`);
8079
8303
  console.log("");
8080
8304
  }
8081
8305
  await runInteractiveProviderSetup();
8082
8306
  const updated = loadConfig();
8083
8307
  if (updated) trackConfigProviderSet(updated.provider);
8084
- console.log(chalk16.green("\n\u2713 Configuration saved"));
8085
- console.log(chalk16.dim(` ${getConfigFilePath()}
8308
+ console.log(chalk17.green("\n\u2713 Configuration saved"));
8309
+ console.log(chalk17.dim(` ${getConfigFilePath()}
8086
8310
  `));
8087
- console.log(chalk16.dim(" You can also set environment variables instead:"));
8088
- console.log(chalk16.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
8311
+ console.log(chalk17.dim(" You can also set environment variables instead:"));
8312
+ console.log(chalk17.dim(" ANTHROPIC_API_KEY, OPENAI_API_KEY, VERTEX_PROJECT_ID, CALIBER_USE_CURSOR_SEAT=1, or CALIBER_USE_CLAUDE_CLI=1\n"));
8089
8313
  }
8090
8314
 
8091
8315
  // src/commands/learn.ts
8092
8316
  import fs31 from "fs";
8093
- import chalk17 from "chalk";
8317
+ import chalk18 from "chalk";
8094
8318
 
8095
8319
  // src/learner/stdin.ts
8096
8320
  var STDIN_TIMEOUT_MS = 5e3;
@@ -8406,26 +8630,26 @@ async function learnFinalizeCommand(options) {
8406
8630
  if (!options?.force) {
8407
8631
  const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
8408
8632
  if (isCaliberRunning2()) {
8409
- console.log(chalk17.dim("caliber: skipping finalize \u2014 another caliber process is running"));
8633
+ console.log(chalk18.dim("caliber: skipping finalize \u2014 another caliber process is running"));
8410
8634
  return;
8411
8635
  }
8412
8636
  }
8413
8637
  if (!acquireFinalizeLock()) {
8414
- console.log(chalk17.dim("caliber: skipping finalize \u2014 another finalize is in progress"));
8638
+ console.log(chalk18.dim("caliber: skipping finalize \u2014 another finalize is in progress"));
8415
8639
  return;
8416
8640
  }
8417
8641
  let analyzed = false;
8418
8642
  try {
8419
8643
  const config = loadConfig();
8420
8644
  if (!config) {
8421
- console.log(chalk17.yellow("caliber: no LLM provider configured \u2014 run `caliber config` first"));
8645
+ console.log(chalk18.yellow("caliber: no LLM provider configured \u2014 run `caliber config` first"));
8422
8646
  clearSession();
8423
8647
  resetState();
8424
8648
  return;
8425
8649
  }
8426
8650
  const events = readAllEvents();
8427
8651
  if (events.length < MIN_EVENTS_FOR_ANALYSIS) {
8428
- console.log(chalk17.dim(`caliber: ${events.length}/${MIN_EVENTS_FOR_ANALYSIS} events recorded \u2014 need more before analysis`));
8652
+ console.log(chalk18.dim(`caliber: ${events.length}/${MIN_EVENTS_FOR_ANALYSIS} events recorded \u2014 need more before analysis`));
8429
8653
  return;
8430
8654
  }
8431
8655
  await validateModel({ fast: true });
@@ -8446,15 +8670,15 @@ async function learnFinalizeCommand(options) {
8446
8670
  skills: response.skills
8447
8671
  });
8448
8672
  if (result.newItemCount > 0) {
8449
- console.log(chalk17.dim(`caliber: learned ${result.newItemCount} new pattern${result.newItemCount === 1 ? "" : "s"}`));
8673
+ console.log(chalk18.dim(`caliber: learned ${result.newItemCount} new pattern${result.newItemCount === 1 ? "" : "s"}`));
8450
8674
  for (const item of result.newItems) {
8451
- console.log(chalk17.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
8675
+ console.log(chalk18.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
8452
8676
  }
8453
8677
  }
8454
8678
  }
8455
8679
  } catch (err) {
8456
8680
  if (options?.force) {
8457
- console.error(chalk17.red("caliber: finalize failed \u2014"), err instanceof Error ? err.message : err);
8681
+ console.error(chalk18.red("caliber: finalize failed \u2014"), err instanceof Error ? err.message : err);
8458
8682
  }
8459
8683
  } finally {
8460
8684
  if (analyzed) {
@@ -8469,45 +8693,45 @@ async function learnInstallCommand() {
8469
8693
  if (fs31.existsSync(".claude")) {
8470
8694
  const r = installLearningHooks();
8471
8695
  if (r.installed) {
8472
- console.log(chalk17.green("\u2713") + " Claude Code learning hooks installed");
8696
+ console.log(chalk18.green("\u2713") + " Claude Code learning hooks installed");
8473
8697
  anyInstalled = true;
8474
8698
  } else if (r.alreadyInstalled) {
8475
- console.log(chalk17.dim(" Claude Code hooks already installed"));
8699
+ console.log(chalk18.dim(" Claude Code hooks already installed"));
8476
8700
  }
8477
8701
  }
8478
8702
  if (fs31.existsSync(".cursor")) {
8479
8703
  const r = installCursorLearningHooks();
8480
8704
  if (r.installed) {
8481
- console.log(chalk17.green("\u2713") + " Cursor learning hooks installed");
8705
+ console.log(chalk18.green("\u2713") + " Cursor learning hooks installed");
8482
8706
  anyInstalled = true;
8483
8707
  } else if (r.alreadyInstalled) {
8484
- console.log(chalk17.dim(" Cursor hooks already installed"));
8708
+ console.log(chalk18.dim(" Cursor hooks already installed"));
8485
8709
  }
8486
8710
  }
8487
8711
  if (!fs31.existsSync(".claude") && !fs31.existsSync(".cursor")) {
8488
- console.log(chalk17.yellow("No .claude/ or .cursor/ directory found."));
8489
- console.log(chalk17.dim(" Run `caliber init` first, or create the directory manually."));
8712
+ console.log(chalk18.yellow("No .claude/ or .cursor/ directory found."));
8713
+ console.log(chalk18.dim(" Run `caliber init` first, or create the directory manually."));
8490
8714
  return;
8491
8715
  }
8492
8716
  if (anyInstalled) {
8493
- console.log(chalk17.dim(` Tool usage will be recorded and learnings extracted after \u2265${MIN_EVENTS_FOR_ANALYSIS} events.`));
8494
- console.log(chalk17.dim(" Learnings written to CALIBER_LEARNINGS.md."));
8717
+ console.log(chalk18.dim(` Tool usage will be recorded and learnings extracted after \u2265${MIN_EVENTS_FOR_ANALYSIS} events.`));
8718
+ console.log(chalk18.dim(" Learnings written to CALIBER_LEARNINGS.md."));
8495
8719
  }
8496
8720
  }
8497
8721
  async function learnRemoveCommand() {
8498
8722
  let anyRemoved = false;
8499
8723
  const r1 = removeLearningHooks();
8500
8724
  if (r1.removed) {
8501
- console.log(chalk17.green("\u2713") + " Claude Code learning hooks removed");
8725
+ console.log(chalk18.green("\u2713") + " Claude Code learning hooks removed");
8502
8726
  anyRemoved = true;
8503
8727
  }
8504
8728
  const r2 = removeCursorLearningHooks();
8505
8729
  if (r2.removed) {
8506
- console.log(chalk17.green("\u2713") + " Cursor learning hooks removed");
8730
+ console.log(chalk18.green("\u2713") + " Cursor learning hooks removed");
8507
8731
  anyRemoved = true;
8508
8732
  }
8509
8733
  if (!anyRemoved) {
8510
- console.log(chalk17.dim("No learning hooks found."));
8734
+ console.log(chalk18.dim("No learning hooks found."));
8511
8735
  }
8512
8736
  }
8513
8737
  async function learnStatusCommand() {
@@ -8515,34 +8739,34 @@ async function learnStatusCommand() {
8515
8739
  const cursorInstalled = areCursorLearningHooksInstalled();
8516
8740
  const state = readState2();
8517
8741
  const eventCount = getEventCount();
8518
- console.log(chalk17.bold("Session Learning Status"));
8742
+ console.log(chalk18.bold("Session Learning Status"));
8519
8743
  console.log();
8520
8744
  if (claudeInstalled) {
8521
- console.log(chalk17.green("\u2713") + " Claude Code hooks " + chalk17.green("installed"));
8745
+ console.log(chalk18.green("\u2713") + " Claude Code hooks " + chalk18.green("installed"));
8522
8746
  } else {
8523
- console.log(chalk17.dim("\u2717") + " Claude Code hooks " + chalk17.dim("not installed"));
8747
+ console.log(chalk18.dim("\u2717") + " Claude Code hooks " + chalk18.dim("not installed"));
8524
8748
  }
8525
8749
  if (cursorInstalled) {
8526
- console.log(chalk17.green("\u2713") + " Cursor hooks " + chalk17.green("installed"));
8750
+ console.log(chalk18.green("\u2713") + " Cursor hooks " + chalk18.green("installed"));
8527
8751
  } else {
8528
- console.log(chalk17.dim("\u2717") + " Cursor hooks " + chalk17.dim("not installed"));
8752
+ console.log(chalk18.dim("\u2717") + " Cursor hooks " + chalk18.dim("not installed"));
8529
8753
  }
8530
8754
  if (!claudeInstalled && !cursorInstalled) {
8531
- console.log(chalk17.dim(" Run `caliber learn install` to enable session learning."));
8755
+ console.log(chalk18.dim(" Run `caliber learn install` to enable session learning."));
8532
8756
  }
8533
8757
  console.log();
8534
- console.log(`Events recorded: ${chalk17.cyan(String(eventCount))}`);
8535
- console.log(`Threshold for analysis: ${chalk17.cyan(String(MIN_EVENTS_FOR_ANALYSIS))}`);
8758
+ console.log(`Events recorded: ${chalk18.cyan(String(eventCount))}`);
8759
+ console.log(`Threshold for analysis: ${chalk18.cyan(String(MIN_EVENTS_FOR_ANALYSIS))}`);
8536
8760
  if (state.lastAnalysisTimestamp) {
8537
- console.log(`Last analysis: ${chalk17.cyan(state.lastAnalysisTimestamp)}`);
8761
+ console.log(`Last analysis: ${chalk18.cyan(state.lastAnalysisTimestamp)}`);
8538
8762
  } else {
8539
- console.log(`Last analysis: ${chalk17.dim("none")}`);
8763
+ console.log(`Last analysis: ${chalk18.dim("none")}`);
8540
8764
  }
8541
8765
  const learnedSection = readLearnedSection();
8542
8766
  if (learnedSection) {
8543
8767
  const lineCount = learnedSection.split("\n").filter(Boolean).length;
8544
8768
  console.log(`
8545
- Learned items in CALIBER_LEARNINGS.md: ${chalk17.cyan(String(lineCount))}`);
8769
+ Learned items in CALIBER_LEARNINGS.md: ${chalk18.cyan(String(lineCount))}`);
8546
8770
  }
8547
8771
  }
8548
8772
 
@@ -8627,7 +8851,7 @@ import fs33 from "fs";
8627
8851
  import path26 from "path";
8628
8852
  import { fileURLToPath as fileURLToPath2 } from "url";
8629
8853
  import { execSync as execSync14 } from "child_process";
8630
- import chalk18 from "chalk";
8854
+ import chalk19 from "chalk";
8631
8855
  import ora6 from "ora";
8632
8856
  import confirm2 from "@inquirer/confirm";
8633
8857
  var __dirname_vc = path26.dirname(fileURLToPath2(import.meta.url));
@@ -8661,17 +8885,17 @@ async function checkForUpdates() {
8661
8885
  const isInteractive = process.stdin.isTTY === true;
8662
8886
  if (!isInteractive) {
8663
8887
  console.log(
8664
- chalk18.yellow(
8888
+ chalk19.yellow(
8665
8889
  `
8666
8890
  Update available: ${current} -> ${latest}
8667
- Run ${chalk18.bold("npm install -g @rely-ai/caliber")} to upgrade.
8891
+ Run ${chalk19.bold("npm install -g @rely-ai/caliber")} to upgrade.
8668
8892
  `
8669
8893
  )
8670
8894
  );
8671
8895
  return;
8672
8896
  }
8673
8897
  console.log(
8674
- chalk18.yellow(`
8898
+ chalk19.yellow(`
8675
8899
  Update available: ${current} -> ${latest}`)
8676
8900
  );
8677
8901
  const shouldUpdate = await confirm2({ message: "Would you like to update now? (Y/n)", default: true });
@@ -8689,13 +8913,13 @@ Update available: ${current} -> ${latest}`)
8689
8913
  const installed = getInstalledVersion();
8690
8914
  if (installed !== latest) {
8691
8915
  spinner.fail(`Update incomplete \u2014 got ${installed ?? "unknown"}, expected ${latest}`);
8692
- console.log(chalk18.yellow(`Run ${chalk18.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually.
8916
+ console.log(chalk19.yellow(`Run ${chalk19.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually.
8693
8917
  `));
8694
8918
  return;
8695
8919
  }
8696
- spinner.succeed(chalk18.green(`Updated to ${latest}`));
8920
+ spinner.succeed(chalk19.green(`Updated to ${latest}`));
8697
8921
  const args = process.argv.slice(2);
8698
- console.log(chalk18.dim(`
8922
+ console.log(chalk19.dim(`
8699
8923
  Restarting: caliber ${args.join(" ")}
8700
8924
  `));
8701
8925
  execSync14(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
@@ -8708,11 +8932,11 @@ Restarting: caliber ${args.join(" ")}
8708
8932
  if (err instanceof Error) {
8709
8933
  const stderr = err.stderr;
8710
8934
  const errMsg = stderr ? String(stderr).trim().split("\n").pop() : err.message.split("\n")[0];
8711
- if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk18.dim(` ${errMsg}`));
8935
+ if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk19.dim(` ${errMsg}`));
8712
8936
  }
8713
8937
  console.log(
8714
- chalk18.yellow(
8715
- `Run ${chalk18.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually to upgrade.
8938
+ chalk19.yellow(
8939
+ `Run ${chalk19.bold(`npm install -g @rely-ai/caliber@${latest}`)} manually to upgrade.
8716
8940
  `
8717
8941
  )
8718
8942
  );