@rely-ai/caliber 1.41.3 → 1.42.0

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 +673 -467
  2. package/package.json +2 -1
package/dist/bin.js CHANGED
@@ -169,19 +169,44 @@ import fs6 from "fs";
169
169
  import { execSync as execSync4 } from "child_process";
170
170
  function resolveCaliber() {
171
171
  if (_resolved) return _resolved;
172
+ const whichCmd = process.platform === "win32" ? "where caliber" : "which caliber";
173
+ const whichNpxCmd = process.platform === "win32" ? "where npx" : "which npx";
172
174
  const isNpx = process.argv[1]?.includes("_npx") || process.env.npm_execpath?.includes("npx");
173
175
  if (isNpx) {
176
+ try {
177
+ const out = execSync4(whichCmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
178
+ const caliberPath = out.split("\n")[0].trim();
179
+ if (caliberPath) {
180
+ _resolved = caliberPath;
181
+ return _resolved;
182
+ }
183
+ } catch {
184
+ }
185
+ try {
186
+ const out = execSync4(whichNpxCmd, {
187
+ encoding: "utf-8",
188
+ stdio: ["pipe", "pipe", "pipe"]
189
+ }).trim();
190
+ const npxPath = out.split("\n")[0].trim();
191
+ if (npxPath) {
192
+ _resolved = `${npxPath} --yes @rely-ai/caliber`;
193
+ return _resolved;
194
+ }
195
+ } catch {
196
+ }
174
197
  _resolved = "npx --yes @rely-ai/caliber";
175
198
  return _resolved;
176
199
  }
177
200
  try {
178
- const whichCmd = process.platform === "win32" ? "where caliber" : "which caliber";
179
- execSync4(whichCmd, {
201
+ const out = execSync4(whichCmd, {
180
202
  encoding: "utf-8",
181
203
  stdio: ["pipe", "pipe", "pipe"]
182
- });
183
- _resolved = "caliber";
184
- return _resolved;
204
+ }).trim();
205
+ const caliberPath = out.split("\n")[0].trim();
206
+ if (caliberPath) {
207
+ _resolved = caliberPath;
208
+ return _resolved;
209
+ }
185
210
  } catch {
186
211
  }
187
212
  const binPath = process.argv[1];
@@ -193,7 +218,8 @@ function resolveCaliber() {
193
218
  return _resolved;
194
219
  }
195
220
  function isNpxResolution() {
196
- return resolveCaliber().startsWith("npx ");
221
+ const r = resolveCaliber();
222
+ return r === "npx --yes @rely-ai/caliber" || r.endsWith("/npx --yes @rely-ai/caliber");
197
223
  }
198
224
  function resetResolvedCaliber() {
199
225
  _resolved = null;
@@ -203,6 +229,8 @@ function isCaliberCommand(command, subcommandTail) {
203
229
  if (command.endsWith(`/caliber ${subcommandTail}`)) return true;
204
230
  if (command === `npx --yes @rely-ai/caliber ${subcommandTail}`) return true;
205
231
  if (command === `npx @rely-ai/caliber ${subcommandTail}`) return true;
232
+ if (command.endsWith(`/npx --yes @rely-ai/caliber ${subcommandTail}`)) return true;
233
+ if (command.endsWith(`/npx @rely-ai/caliber ${subcommandTail}`)) return true;
206
234
  return false;
207
235
  }
208
236
  var _resolved;
@@ -445,7 +473,7 @@ __export(builtin_skills_exports, {
445
473
  buildSkillContent: () => buildSkillContent,
446
474
  ensureBuiltinSkills: () => ensureBuiltinSkills
447
475
  });
448
- import fs16 from "fs";
476
+ import fs17 from "fs";
449
477
  import path16 from "path";
450
478
  function buildSkillContent(skill) {
451
479
  const frontmatter = `---
@@ -779,11 +807,11 @@ From now on, every commit keeps all your agent configs in sync automatically.
779
807
  function ensureBuiltinSkills() {
780
808
  const written = [];
781
809
  for (const { platformDir, skillsDir } of PLATFORM_CONFIGS) {
782
- if (!fs16.existsSync(platformDir)) continue;
810
+ if (!fs17.existsSync(platformDir)) continue;
783
811
  for (const skill of BUILTIN_SKILLS) {
784
812
  const skillPath = path16.join(skillsDir, skill.name, "SKILL.md");
785
- fs16.mkdirSync(path16.dirname(skillPath), { recursive: true });
786
- fs16.writeFileSync(skillPath, buildSkillContent(skill));
813
+ fs17.mkdirSync(path16.dirname(skillPath), { recursive: true });
814
+ fs17.writeFileSync(skillPath, buildSkillContent(skill));
787
815
  written.push(skillPath);
788
816
  }
789
817
  }
@@ -828,13 +856,13 @@ var init_builtin_skills = __esm({
828
856
 
829
857
  // src/utils/editor.ts
830
858
  import { execSync as execSync14, spawn as spawn3 } from "child_process";
831
- import fs28 from "fs";
859
+ import fs29 from "fs";
832
860
  import path25 from "path";
833
861
  import os6 from "os";
834
862
  function getEmptyFilePath(proposedPath) {
835
- fs28.mkdirSync(DIFF_TEMP_DIR, { recursive: true });
863
+ fs29.mkdirSync(DIFF_TEMP_DIR, { recursive: true });
836
864
  const tempPath = path25.join(DIFF_TEMP_DIR, path25.basename(proposedPath));
837
- fs28.writeFileSync(tempPath, "");
865
+ fs29.writeFileSync(tempPath, "");
838
866
  return tempPath;
839
867
  }
840
868
  function commandExists(cmd) {
@@ -886,10 +914,11 @@ __export(review_exports, {
886
914
  promptWantsReview: () => promptWantsReview
887
915
  });
888
916
  import chalk10 from "chalk";
889
- import fs29 from "fs";
917
+ import fs30 from "fs";
890
918
  import select4 from "@inquirer/select";
891
919
  import { createTwoFilesPatch } from "diff";
892
920
  async function promptWantsReview() {
921
+ if (!process.stdin.isTTY) return false;
893
922
  return select4({
894
923
  message: "Would you like to review the diffs before deciding?",
895
924
  choices: [
@@ -901,6 +930,7 @@ async function promptWantsReview() {
901
930
  async function promptReviewMethod() {
902
931
  const available = detectAvailableEditors();
903
932
  if (available.length === 1) return "terminal";
933
+ if (!process.stdin.isTTY) return "terminal";
904
934
  const choices = available.map((method) => {
905
935
  switch (method) {
906
936
  case "cursor":
@@ -915,16 +945,19 @@ async function promptReviewMethod() {
915
945
  }
916
946
  async function openReview(method, stagedFiles) {
917
947
  if (method === "cursor" || method === "vscode") {
918
- openDiffsInEditor(method, stagedFiles.map((f) => ({
919
- originalPath: f.originalPath,
920
- proposedPath: f.proposedPath
921
- })));
948
+ openDiffsInEditor(
949
+ method,
950
+ stagedFiles.map((f) => ({
951
+ originalPath: f.originalPath,
952
+ proposedPath: f.proposedPath
953
+ }))
954
+ );
922
955
  console.log(chalk10.dim(" Diffs opened in your editor.\n"));
923
956
  return;
924
957
  }
925
958
  const fileInfos = stagedFiles.map((file) => {
926
- const proposed = fs29.readFileSync(file.proposedPath, "utf-8");
927
- const current = file.currentPath ? fs29.readFileSync(file.currentPath, "utf-8") : "";
959
+ const proposed = fs30.readFileSync(file.proposedPath, "utf-8");
960
+ const current = file.currentPath ? fs30.readFileSync(file.currentPath, "utf-8") : "";
928
961
  const patch = createTwoFilesPatch(
929
962
  file.isNew ? "/dev/null" : file.relativePath,
930
963
  file.relativePath,
@@ -1099,7 +1132,7 @@ __export(lock_exports, {
1099
1132
  isCaliberRunning: () => isCaliberRunning,
1100
1133
  releaseLock: () => releaseLock
1101
1134
  });
1102
- import fs40 from "fs";
1135
+ import fs41 from "fs";
1103
1136
  import path33 from "path";
1104
1137
  import os8 from "os";
1105
1138
  import crypto5 from "crypto";
@@ -1115,8 +1148,8 @@ function getLockFile() {
1115
1148
  function isCaliberRunning() {
1116
1149
  try {
1117
1150
  const lockFile = buildLockPath();
1118
- if (!fs40.existsSync(lockFile)) return false;
1119
- const raw = fs40.readFileSync(lockFile, "utf-8").trim();
1151
+ if (!fs41.existsSync(lockFile)) return false;
1152
+ const raw = fs41.readFileSync(lockFile, "utf-8").trim();
1120
1153
  const { pid, ts } = JSON.parse(raw);
1121
1154
  if (pid === process.pid) return false;
1122
1155
  if (Date.now() - ts > STALE_MS) return false;
@@ -1132,14 +1165,14 @@ function isCaliberRunning() {
1132
1165
  }
1133
1166
  function acquireLock() {
1134
1167
  try {
1135
- fs40.writeFileSync(getLockFile(), JSON.stringify({ pid: process.pid, ts: Date.now() }));
1168
+ fs41.writeFileSync(getLockFile(), JSON.stringify({ pid: process.pid, ts: Date.now() }));
1136
1169
  } catch {
1137
1170
  }
1138
1171
  }
1139
1172
  function releaseLock() {
1140
1173
  try {
1141
1174
  const lockFile = getLockFile();
1142
- if (fs40.existsSync(lockFile)) fs40.unlinkSync(lockFile);
1175
+ if (fs41.existsSync(lockFile)) fs41.unlinkSync(lockFile);
1143
1176
  } catch {
1144
1177
  }
1145
1178
  }
@@ -1154,17 +1187,17 @@ var init_lock = __esm({
1154
1187
 
1155
1188
  // src/cli.ts
1156
1189
  import { Command } from "commander";
1157
- import fs51 from "fs";
1190
+ import fs52 from "fs";
1158
1191
  import path42 from "path";
1159
1192
  import { fileURLToPath } from "url";
1160
1193
 
1161
1194
  // src/commands/init.ts
1162
1195
  import path28 from "path";
1163
1196
  import chalk14 from "chalk";
1164
- import fs34 from "fs";
1197
+ import fs35 from "fs";
1165
1198
 
1166
1199
  // src/fingerprint/index.ts
1167
- import fs8 from "fs";
1200
+ import fs9 from "fs";
1168
1201
  import path8 from "path";
1169
1202
 
1170
1203
  // src/fingerprint/git.ts
@@ -2358,7 +2391,7 @@ var OpenAICompatProvider = class {
2358
2391
  };
2359
2392
 
2360
2393
  // src/llm/cursor-acp.ts
2361
- import { spawn, execSync as execSync5 } from "child_process";
2394
+ import { spawn, execSync as execSync5, execFileSync } from "child_process";
2362
2395
  import os3 from "os";
2363
2396
 
2364
2397
  // src/llm/seat-based-errors.ts
@@ -2430,8 +2463,23 @@ function estimateTokens(text) {
2430
2463
  }
2431
2464
 
2432
2465
  // src/llm/cursor-acp.ts
2433
- var AGENT_BIN = "agent";
2434
2466
  var IS_WINDOWS = process.platform === "win32";
2467
+ var _agentBin = null;
2468
+ function resolveAgentBin() {
2469
+ if (_agentBin !== null) return _agentBin;
2470
+ try {
2471
+ const whichCmd = IS_WINDOWS ? "where agent" : "which agent";
2472
+ const out = execSync5(whichCmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
2473
+ const p = out.split("\n")[0].trim();
2474
+ if (p) {
2475
+ _agentBin = p;
2476
+ return _agentBin;
2477
+ }
2478
+ } catch {
2479
+ }
2480
+ _agentBin = "agent";
2481
+ return _agentBin;
2482
+ }
2435
2483
  var DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
2436
2484
  var SIGKILL_DELAY_MS = 5e3;
2437
2485
  var STDERR_MAX_BYTES = 10 * 1024;
@@ -2489,7 +2537,7 @@ var CursorAcpProvider = class {
2489
2537
  const targetModel = model || this.defaultModel;
2490
2538
  if (this.warmProcess && !this.warmProcess.killed && this.warmModel === targetModel) return;
2491
2539
  const args = this.buildArgs(targetModel, false);
2492
- this.warmProcess = spawn(AGENT_BIN, args, {
2540
+ this.warmProcess = spawn(resolveAgentBin(), args, {
2493
2541
  stdio: ["pipe", "pipe", "pipe"],
2494
2542
  env: { ...process.env, ...this.cursorApiKey && { CURSOR_API_KEY: this.cursorApiKey } },
2495
2543
  ...IS_WINDOWS && { shell: true }
@@ -2536,7 +2584,7 @@ var CursorAcpProvider = class {
2536
2584
  return { child: warm, stderrChunks: stderrChunks2 };
2537
2585
  }
2538
2586
  const args = this.buildArgs(model, streaming);
2539
- const child = spawn(AGENT_BIN, args, {
2587
+ const child = spawn(resolveAgentBin(), args, {
2540
2588
  stdio: ["pipe", "pipe", "pipe"],
2541
2589
  env: { ...process.env, ...this.cursorApiKey && { CURSOR_API_KEY: this.cursorApiKey } },
2542
2590
  ...IS_WINDOWS && { shell: true }
@@ -2710,9 +2758,9 @@ var CursorAcpProvider = class {
2710
2758
  }
2711
2759
  };
2712
2760
  function isCursorAgentAvailable() {
2761
+ if (resolveAgentBin() !== "agent") return true;
2713
2762
  try {
2714
- const cmd = IS_WINDOWS ? `where ${AGENT_BIN}` : `which ${AGENT_BIN}`;
2715
- execSync5(cmd, { stdio: "ignore" });
2763
+ execSync5(IS_WINDOWS ? "where agent" : "which agent", { stdio: "ignore" });
2716
2764
  return true;
2717
2765
  } catch {
2718
2766
  return false;
@@ -2720,7 +2768,7 @@ function isCursorAgentAvailable() {
2720
2768
  }
2721
2769
  function isCursorLoggedIn() {
2722
2770
  try {
2723
- const result = execSync5(`${AGENT_BIN} status`, {
2771
+ const result = execFileSync(resolveAgentBin(), ["status"], {
2724
2772
  input: "",
2725
2773
  stdio: ["pipe", "pipe", "pipe"],
2726
2774
  timeout: 5e3
@@ -2732,18 +2780,56 @@ function isCursorLoggedIn() {
2732
2780
  }
2733
2781
 
2734
2782
  // src/llm/claude-cli.ts
2735
- import { spawn as spawn2, execSync as execSync6 } from "child_process";
2736
- var CLAUDE_CLI_BIN = "claude";
2783
+ import fs7 from "fs";
2784
+ import { spawn as spawn2, execSync as execSync6, execFileSync as execFileSync2 } from "child_process";
2737
2785
  var DEFAULT_TIMEOUT_MS2 = 10 * 60 * 1e3;
2738
2786
  var IS_WINDOWS2 = process.platform === "win32";
2787
+ function candidateClaudePaths() {
2788
+ if (IS_WINDOWS2) return [];
2789
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
2790
+ return [
2791
+ `${home}/.local/bin/claude`,
2792
+ // Claude Code default installer path
2793
+ "/usr/local/bin/claude",
2794
+ // Homebrew / manual install
2795
+ "/opt/homebrew/bin/claude"
2796
+ // Apple Silicon Homebrew
2797
+ ].filter(Boolean);
2798
+ }
2799
+ var _claudeBin = null;
2800
+ function resolveClaudeBin() {
2801
+ if (_claudeBin !== null) return _claudeBin;
2802
+ try {
2803
+ const whichCmd = IS_WINDOWS2 ? "where claude" : "which claude";
2804
+ const out = execSync6(whichCmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
2805
+ const p = out.split("\n")[0].trim();
2806
+ if (p) {
2807
+ _claudeBin = p;
2808
+ return _claudeBin;
2809
+ }
2810
+ } catch {
2811
+ }
2812
+ for (const candidate of candidateClaudePaths()) {
2813
+ try {
2814
+ fs7.accessSync(candidate, fs7.constants.X_OK);
2815
+ _claudeBin = candidate;
2816
+ return _claudeBin;
2817
+ } catch {
2818
+ }
2819
+ }
2820
+ _claudeBin = "claude";
2821
+ return _claudeBin;
2822
+ }
2739
2823
  function spawnClaude(args) {
2740
- const env = { ...process.env, CLAUDE_CODE_SIMPLE: "1" };
2741
- return IS_WINDOWS2 ? spawn2([CLAUDE_CLI_BIN, ...args].join(" "), {
2824
+ const bin = resolveClaudeBin();
2825
+ const { CLAUDE_CODE_SIMPLE: _stripped, ...parentEnv } = process.env;
2826
+ const env = parentEnv;
2827
+ return IS_WINDOWS2 ? spawn2([bin, ...args].join(" "), {
2742
2828
  cwd: process.cwd(),
2743
2829
  stdio: ["pipe", "pipe", "pipe"],
2744
2830
  env,
2745
2831
  shell: true
2746
- }) : spawn2(CLAUDE_CLI_BIN, args, {
2832
+ }) : spawn2(bin, args, {
2747
2833
  cwd: process.cwd(),
2748
2834
  stdio: ["pipe", "pipe", "pipe"],
2749
2835
  env
@@ -2818,8 +2904,8 @@ var ClaudeCliProvider = class {
2818
2904
  callbacks.onEnd({ stopReason: "end_turn" });
2819
2905
  } else {
2820
2906
  const stderr = Buffer.concat(stderrChunks).toString("utf-8").trim();
2821
- const friendly = parseSeatBasedError(stderr, code);
2822
2907
  const stdout = Buffer.concat(chunks).toString("utf-8").trim();
2908
+ const friendly = parseSeatBasedError(stderr || stdout, code);
2823
2909
  const base = signal ? `Claude CLI killed (${signal})` : code != null ? `Claude CLI exited with code ${code}` : "Claude CLI exited";
2824
2910
  const detail = friendly || stderr || (stdout ? stdout.slice(0, 200) : "");
2825
2911
  callbacks.onError(new Error(detail ? `${base}. ${detail}` : base));
@@ -2879,7 +2965,7 @@ var ClaudeCliProvider = class {
2879
2965
  resolve3(stdout);
2880
2966
  } else {
2881
2967
  const stderr = Buffer.concat(stderrChunks).toString("utf-8").trim();
2882
- const friendly = parseSeatBasedError(stderr, code);
2968
+ const friendly = parseSeatBasedError(stderr || stdout, code);
2883
2969
  const base = signal ? `Claude CLI killed (${signal})` : code != null ? `Claude CLI exited with code ${code}` : "Claude CLI exited";
2884
2970
  const detail = friendly || stderr || (stdout ? stdout.slice(0, 200) : "");
2885
2971
  reject(new Error(detail ? `${base}. ${detail}` : base));
@@ -2889,9 +2975,9 @@ var ClaudeCliProvider = class {
2889
2975
  }
2890
2976
  };
2891
2977
  function isClaudeCliAvailable() {
2978
+ if (resolveClaudeBin() !== "claude") return true;
2892
2979
  try {
2893
- const cmd = process.platform === "win32" ? `where ${CLAUDE_CLI_BIN}` : `which ${CLAUDE_CLI_BIN}`;
2894
- execSync6(cmd, { stdio: "ignore" });
2980
+ execSync6(IS_WINDOWS2 ? "where claude" : "which claude", { stdio: "ignore" });
2895
2981
  return true;
2896
2982
  } catch {
2897
2983
  return false;
@@ -2901,7 +2987,7 @@ var cachedLoggedIn = null;
2901
2987
  function isClaudeCliLoggedIn() {
2902
2988
  if (cachedLoggedIn !== null) return cachedLoggedIn;
2903
2989
  try {
2904
- const result = execSync6(`${CLAUDE_CLI_BIN} auth status`, {
2990
+ const result = execFileSync2(resolveClaudeBin(), ["auth", "status"], {
2905
2991
  input: "",
2906
2992
  stdio: ["pipe", "pipe", "pipe"],
2907
2993
  timeout: 5e3
@@ -3720,7 +3806,7 @@ async function detectProjectStack(fileTree, suffixCounts) {
3720
3806
  init_config();
3721
3807
 
3722
3808
  // src/fingerprint/cache.ts
3723
- import fs7 from "fs";
3809
+ import fs8 from "fs";
3724
3810
  import path7 from "path";
3725
3811
  import crypto from "crypto";
3726
3812
  import { execSync as execSync7 } from "child_process";
@@ -3765,8 +3851,8 @@ function computeTreeSignature(fileTree, dir) {
3765
3851
  function loadFingerprintCache(dir, fileTree) {
3766
3852
  const cachePath = getCachePath(dir);
3767
3853
  try {
3768
- if (!fs7.existsSync(cachePath)) return null;
3769
- const raw = fs7.readFileSync(cachePath, "utf-8");
3854
+ if (!fs8.existsSync(cachePath)) return null;
3855
+ const raw = fs8.readFileSync(cachePath, "utf-8");
3770
3856
  const cache = JSON.parse(raw);
3771
3857
  if (cache.version !== CACHE_VERSION) return null;
3772
3858
  const currentHead = getGitHead(dir);
@@ -3788,8 +3874,8 @@ function saveFingerprintCache(dir, fileTree, codeAnalysis, languages, frameworks
3788
3874
  const cachePath = getCachePath(dir);
3789
3875
  try {
3790
3876
  const cacheDir = path7.dirname(cachePath);
3791
- if (!fs7.existsSync(cacheDir)) {
3792
- fs7.mkdirSync(cacheDir, { recursive: true });
3877
+ if (!fs8.existsSync(cacheDir)) {
3878
+ fs8.mkdirSync(cacheDir, { recursive: true });
3793
3879
  }
3794
3880
  const cache = {
3795
3881
  version: CACHE_VERSION,
@@ -3801,15 +3887,15 @@ function saveFingerprintCache(dir, fileTree, codeAnalysis, languages, frameworks
3801
3887
  tools,
3802
3888
  workspaces
3803
3889
  };
3804
- fs7.writeFileSync(cachePath, JSON.stringify(cache), "utf-8");
3890
+ fs8.writeFileSync(cachePath, JSON.stringify(cache), "utf-8");
3805
3891
  } catch {
3806
3892
  }
3807
3893
  }
3808
3894
  function getDetectedWorkspaces(dir) {
3809
3895
  const cachePath = getCachePath(dir);
3810
3896
  try {
3811
- if (!fs7.existsSync(cachePath)) return [];
3812
- const raw = fs7.readFileSync(cachePath, "utf-8");
3897
+ if (!fs8.existsSync(cachePath)) return [];
3898
+ const raw = fs8.readFileSync(cachePath, "utf-8");
3813
3899
  const cache = JSON.parse(raw);
3814
3900
  return cache.workspaces ?? [];
3815
3901
  } catch {
@@ -3862,8 +3948,8 @@ async function collectFingerprint(dir) {
3862
3948
  function readPackageName(dir) {
3863
3949
  try {
3864
3950
  const pkgPath = path8.join(dir, "package.json");
3865
- if (!fs8.existsSync(pkgPath)) return void 0;
3866
- const pkg3 = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
3951
+ if (!fs9.existsSync(pkgPath)) return void 0;
3952
+ const pkg3 = JSON.parse(fs9.readFileSync(pkgPath, "utf-8"));
3867
3953
  return pkg3.name;
3868
3954
  } catch {
3869
3955
  return void 0;
@@ -3893,23 +3979,23 @@ async function enrichWithLLM(fingerprint) {
3893
3979
  }
3894
3980
 
3895
3981
  // src/scanner/index.ts
3896
- import fs9 from "fs";
3982
+ import fs10 from "fs";
3897
3983
  import path9 from "path";
3898
3984
  import crypto2 from "crypto";
3899
3985
  import os4 from "os";
3900
3986
  function detectPlatforms() {
3901
3987
  const home = os4.homedir();
3902
3988
  return {
3903
- claude: fs9.existsSync(path9.join(home, ".claude")),
3904
- cursor: fs9.existsSync(getCursorConfigDir()),
3905
- codex: fs9.existsSync(path9.join(home, ".codex")),
3906
- opencode: fs9.existsSync(path9.join(home, ".config", "opencode"))
3989
+ claude: fs10.existsSync(path9.join(home, ".claude")),
3990
+ cursor: fs10.existsSync(getCursorConfigDir()),
3991
+ codex: fs10.existsSync(path9.join(home, ".codex")),
3992
+ opencode: fs10.existsSync(path9.join(home, ".config", "opencode"))
3907
3993
  };
3908
3994
  }
3909
3995
  function scanLocalState(dir) {
3910
3996
  const items = [];
3911
3997
  const claudeMdPath = path9.join(dir, "CLAUDE.md");
3912
- if (fs9.existsSync(claudeMdPath)) {
3998
+ if (fs10.existsSync(claudeMdPath)) {
3913
3999
  items.push({
3914
4000
  type: "rule",
3915
4001
  platform: "claude",
@@ -3919,8 +4005,8 @@ function scanLocalState(dir) {
3919
4005
  });
3920
4006
  }
3921
4007
  const skillsDir = path9.join(dir, ".claude", "skills");
3922
- if (fs9.existsSync(skillsDir)) {
3923
- for (const file of fs9.readdirSync(skillsDir).filter((f) => f.endsWith(".md"))) {
4008
+ if (fs10.existsSync(skillsDir)) {
4009
+ for (const file of fs10.readdirSync(skillsDir).filter((f) => f.endsWith(".md"))) {
3924
4010
  const filePath = path9.join(skillsDir, file);
3925
4011
  items.push({
3926
4012
  type: "skill",
@@ -3932,9 +4018,9 @@ function scanLocalState(dir) {
3932
4018
  }
3933
4019
  }
3934
4020
  const mcpJsonPath = path9.join(dir, ".mcp.json");
3935
- if (fs9.existsSync(mcpJsonPath)) {
4021
+ if (fs10.existsSync(mcpJsonPath)) {
3936
4022
  try {
3937
- const mcpJson = JSON.parse(fs9.readFileSync(mcpJsonPath, "utf-8"));
4023
+ const mcpJson = JSON.parse(fs10.readFileSync(mcpJsonPath, "utf-8"));
3938
4024
  if (mcpJson.mcpServers) {
3939
4025
  for (const name of Object.keys(mcpJson.mcpServers)) {
3940
4026
  items.push({
@@ -3951,7 +4037,7 @@ function scanLocalState(dir) {
3951
4037
  }
3952
4038
  }
3953
4039
  const agentsMdPath = path9.join(dir, "AGENTS.md");
3954
- if (fs9.existsSync(agentsMdPath)) {
4040
+ if (fs10.existsSync(agentsMdPath)) {
3955
4041
  items.push({
3956
4042
  type: "rule",
3957
4043
  platform: "codex",
@@ -3961,11 +4047,11 @@ function scanLocalState(dir) {
3961
4047
  });
3962
4048
  }
3963
4049
  const codexSkillsDir = path9.join(dir, ".agents", "skills");
3964
- if (fs9.existsSync(codexSkillsDir)) {
4050
+ if (fs10.existsSync(codexSkillsDir)) {
3965
4051
  try {
3966
- for (const name of fs9.readdirSync(codexSkillsDir)) {
4052
+ for (const name of fs10.readdirSync(codexSkillsDir)) {
3967
4053
  const skillFile = path9.join(codexSkillsDir, name, "SKILL.md");
3968
- if (fs9.existsSync(skillFile)) {
4054
+ if (fs10.existsSync(skillFile)) {
3969
4055
  items.push({
3970
4056
  type: "skill",
3971
4057
  platform: "codex",
@@ -3980,11 +4066,11 @@ function scanLocalState(dir) {
3980
4066
  }
3981
4067
  }
3982
4068
  const opencodeSkillsDir = path9.join(dir, ".opencode", "skills");
3983
- if (fs9.existsSync(opencodeSkillsDir)) {
4069
+ if (fs10.existsSync(opencodeSkillsDir)) {
3984
4070
  try {
3985
- for (const name of fs9.readdirSync(opencodeSkillsDir)) {
4071
+ for (const name of fs10.readdirSync(opencodeSkillsDir)) {
3986
4072
  const skillFile = path9.join(opencodeSkillsDir, name, "SKILL.md");
3987
- if (fs9.existsSync(skillFile)) {
4073
+ if (fs10.existsSync(skillFile)) {
3988
4074
  items.push({
3989
4075
  type: "skill",
3990
4076
  platform: "opencode",
@@ -3999,7 +4085,7 @@ function scanLocalState(dir) {
3999
4085
  }
4000
4086
  }
4001
4087
  const cursorrulesPath = path9.join(dir, ".cursorrules");
4002
- if (fs9.existsSync(cursorrulesPath)) {
4088
+ if (fs10.existsSync(cursorrulesPath)) {
4003
4089
  items.push({
4004
4090
  type: "rule",
4005
4091
  platform: "cursor",
@@ -4009,8 +4095,8 @@ function scanLocalState(dir) {
4009
4095
  });
4010
4096
  }
4011
4097
  const cursorRulesDir = path9.join(dir, ".cursor", "rules");
4012
- if (fs9.existsSync(cursorRulesDir)) {
4013
- for (const file of fs9.readdirSync(cursorRulesDir).filter((f) => f.endsWith(".mdc"))) {
4098
+ if (fs10.existsSync(cursorRulesDir)) {
4099
+ for (const file of fs10.readdirSync(cursorRulesDir).filter((f) => f.endsWith(".mdc"))) {
4014
4100
  const filePath = path9.join(cursorRulesDir, file);
4015
4101
  items.push({
4016
4102
  type: "rule",
@@ -4022,11 +4108,11 @@ function scanLocalState(dir) {
4022
4108
  }
4023
4109
  }
4024
4110
  const cursorSkillsDir = path9.join(dir, ".cursor", "skills");
4025
- if (fs9.existsSync(cursorSkillsDir)) {
4111
+ if (fs10.existsSync(cursorSkillsDir)) {
4026
4112
  try {
4027
- for (const name of fs9.readdirSync(cursorSkillsDir)) {
4113
+ for (const name of fs10.readdirSync(cursorSkillsDir)) {
4028
4114
  const skillFile = path9.join(cursorSkillsDir, name, "SKILL.md");
4029
- if (fs9.existsSync(skillFile)) {
4115
+ if (fs10.existsSync(skillFile)) {
4030
4116
  items.push({
4031
4117
  type: "skill",
4032
4118
  platform: "cursor",
@@ -4041,9 +4127,9 @@ function scanLocalState(dir) {
4041
4127
  }
4042
4128
  }
4043
4129
  const cursorMcpPath = path9.join(dir, ".cursor", "mcp.json");
4044
- if (fs9.existsSync(cursorMcpPath)) {
4130
+ if (fs10.existsSync(cursorMcpPath)) {
4045
4131
  try {
4046
- const mcpJson = JSON.parse(fs9.readFileSync(cursorMcpPath, "utf-8"));
4132
+ const mcpJson = JSON.parse(fs10.readFileSync(cursorMcpPath, "utf-8"));
4047
4133
  if (mcpJson.mcpServers) {
4048
4134
  for (const name of Object.keys(mcpJson.mcpServers)) {
4049
4135
  items.push({
@@ -4062,7 +4148,7 @@ function scanLocalState(dir) {
4062
4148
  return items;
4063
4149
  }
4064
4150
  function hashFile(filePath) {
4065
- const text = fs9.readFileSync(filePath, "utf-8");
4151
+ const text = fs10.readFileSync(filePath, "utf-8");
4066
4152
  return crypto2.createHash("sha256").update(JSON.stringify({ text })).digest("hex");
4067
4153
  }
4068
4154
  function hashJson(obj) {
@@ -4085,7 +4171,7 @@ function getCursorConfigDir() {
4085
4171
 
4086
4172
  // src/lib/hooks.ts
4087
4173
  init_resolve_caliber();
4088
- import fs10 from "fs";
4174
+ import fs11 from "fs";
4089
4175
  import path10 from "path";
4090
4176
  import { execSync as execSync8 } from "child_process";
4091
4177
  var SETTINGS_PATH = path10.join(".claude", "settings.json");
@@ -4095,17 +4181,17 @@ function getHookCommand() {
4095
4181
  return `${resolveCaliber()} ${REFRESH_TAIL}`;
4096
4182
  }
4097
4183
  function readSettings() {
4098
- if (!fs10.existsSync(SETTINGS_PATH)) return {};
4184
+ if (!fs11.existsSync(SETTINGS_PATH)) return {};
4099
4185
  try {
4100
- return JSON.parse(fs10.readFileSync(SETTINGS_PATH, "utf-8"));
4186
+ return JSON.parse(fs11.readFileSync(SETTINGS_PATH, "utf-8"));
4101
4187
  } catch {
4102
4188
  return {};
4103
4189
  }
4104
4190
  }
4105
4191
  function writeSettings(settings) {
4106
4192
  const dir = path10.dirname(SETTINGS_PATH);
4107
- if (!fs10.existsSync(dir)) fs10.mkdirSync(dir, { recursive: true });
4108
- fs10.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
4193
+ if (!fs11.existsSync(dir)) fs11.mkdirSync(dir, { recursive: true });
4194
+ fs11.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
4109
4195
  }
4110
4196
  function findHookIndex(sessionEnd) {
4111
4197
  return sessionEnd.findIndex(
@@ -4153,7 +4239,8 @@ function removeHook() {
4153
4239
  return { removed: true, notFound: false };
4154
4240
  }
4155
4241
  function createScriptHook(config) {
4156
- const { eventName, scriptPath, scriptContent, description } = config;
4242
+ const { eventName, scriptPath, description } = config;
4243
+ const getContent = () => typeof config.scriptContent === "function" ? config.scriptContent() : config.scriptContent;
4157
4244
  const hasHook = (matchers) => matchers.some((entry) => entry.hooks?.some((h) => h.description === description));
4158
4245
  function isInstalled() {
4159
4246
  const settings = readSettings();
@@ -4168,9 +4255,9 @@ function createScriptHook(config) {
4168
4255
  return { installed: false, alreadyInstalled: true };
4169
4256
  }
4170
4257
  const scriptDir = path10.dirname(scriptPath);
4171
- if (!fs10.existsSync(scriptDir)) fs10.mkdirSync(scriptDir, { recursive: true });
4172
- fs10.writeFileSync(scriptPath, scriptContent);
4173
- fs10.chmodSync(scriptPath, 493);
4258
+ if (!fs11.existsSync(scriptDir)) fs11.mkdirSync(scriptDir, { recursive: true });
4259
+ fs11.writeFileSync(scriptPath, getContent());
4260
+ fs11.chmodSync(scriptPath, 493);
4174
4261
  if (!Array.isArray(settings.hooks[eventName])) {
4175
4262
  settings.hooks[eventName] = [];
4176
4263
  }
@@ -4194,7 +4281,7 @@ function createScriptHook(config) {
4194
4281
  if (settings.hooks && Object.keys(settings.hooks).length === 0) delete settings.hooks;
4195
4282
  writeSettings(settings);
4196
4283
  try {
4197
- fs10.unlinkSync(scriptPath);
4284
+ fs11.unlinkSync(scriptPath);
4198
4285
  } catch {
4199
4286
  }
4200
4287
  return { removed: true, notFound: false };
@@ -4221,7 +4308,9 @@ var stopHook = createScriptHook({
4221
4308
  });
4222
4309
  var installStopHook = stopHook.install;
4223
4310
  var removeStopHook = stopHook.remove;
4224
- var FRESHNESS_SCRIPT = `#!/bin/sh
4311
+ function getFreshnessScript() {
4312
+ const bin = resolveCaliber();
4313
+ return `#!/bin/sh
4225
4314
  STATE_FILE=".caliber/.caliber-state.json"
4226
4315
  [ ! -f "$STATE_FILE" ] && exit 0
4227
4316
  LAST_SHA=$(grep -o '"lastRefreshSha":"[^"]*"' "$STATE_FILE" 2>/dev/null | cut -d'"' -f4)
@@ -4230,13 +4319,14 @@ CURRENT_SHA=$(git rev-parse HEAD 2>/dev/null)
4230
4319
  [ "$LAST_SHA" = "$CURRENT_SHA" ] && exit 0
4231
4320
  COMMITS_BEHIND=$(git rev-list --count "$LAST_SHA".."$CURRENT_SHA" 2>/dev/null || echo 0)
4232
4321
  if [ "$COMMITS_BEHIND" -gt 15 ]; then
4233
- printf '{"systemMessage":"Caliber: agent configs are %s commits behind. Run caliber refresh to sync."}' "$COMMITS_BEHIND"
4322
+ printf '{"systemMessage":"Caliber: agent configs are %s commits behind. Run ${bin} refresh to sync."}' "$COMMITS_BEHIND"
4234
4323
  fi
4235
4324
  `;
4325
+ }
4236
4326
  var sessionStartHook = createScriptHook({
4237
4327
  eventName: "SessionStart",
4238
4328
  scriptPath: path10.join(".claude", "hooks", "caliber-session-freshness.sh"),
4239
- scriptContent: FRESHNESS_SCRIPT,
4329
+ scriptContent: getFreshnessScript,
4240
4330
  description: "Caliber: check config freshness on session start"
4241
4331
  });
4242
4332
  var isSessionStartHookInstalled = sessionStartHook.isInstalled;
@@ -4245,7 +4335,7 @@ var removeSessionStartHook = sessionStartHook.remove;
4245
4335
  var notificationHook = createScriptHook({
4246
4336
  eventName: "Notification",
4247
4337
  scriptPath: path10.join(".claude", "hooks", "caliber-freshness-notify.sh"),
4248
- scriptContent: FRESHNESS_SCRIPT,
4338
+ scriptContent: getFreshnessScript,
4249
4339
  description: "Caliber: warn when agent configs are stale"
4250
4340
  });
4251
4341
  var isNotificationHookInstalled = notificationHook.isInstalled;
@@ -4254,10 +4344,28 @@ var removeNotificationHook = notificationHook.remove;
4254
4344
  var PRECOMMIT_START = "# caliber:pre-commit:start";
4255
4345
  var PRECOMMIT_END = "# caliber:pre-commit:end";
4256
4346
  function getPrecommitBlock() {
4257
- const bin = resolveCaliber();
4347
+ const cmd = resolveCaliber();
4258
4348
  const npx = isNpxResolution();
4259
- const guard = npx ? "command -v npx >/dev/null 2>&1" : `[ -x "${bin}" ] || command -v "${bin}" >/dev/null 2>&1`;
4260
- const invoke = npx ? bin : `"${bin}"`;
4349
+ let guard;
4350
+ let invoke;
4351
+ if (npx) {
4352
+ const npxBin = cmd.split(" ")[0];
4353
+ if (npxBin.startsWith("/")) {
4354
+ guard = `[ -x "${npxBin}" ]`;
4355
+ const npxArgs = cmd.slice(npxBin.length);
4356
+ invoke = `"${npxBin}"${npxArgs}`;
4357
+ } else {
4358
+ guard = "command -v npx >/dev/null 2>&1";
4359
+ invoke = cmd;
4360
+ }
4361
+ } else {
4362
+ if (cmd.startsWith("/")) {
4363
+ guard = `[ -x "${cmd}" ]`;
4364
+ } else {
4365
+ guard = `[ -x "${cmd}" ] || command -v "${cmd}" >/dev/null 2>&1`;
4366
+ }
4367
+ invoke = `"${cmd}"`;
4368
+ }
4261
4369
  return `${PRECOMMIT_START}
4262
4370
  if ${guard}; then
4263
4371
  mkdir -p .caliber
@@ -4285,8 +4393,8 @@ function getPreCommitPath() {
4285
4393
  }
4286
4394
  function isPreCommitHookInstalled() {
4287
4395
  const hookPath = getPreCommitPath();
4288
- if (!hookPath || !fs10.existsSync(hookPath)) return false;
4289
- const content = fs10.readFileSync(hookPath, "utf-8");
4396
+ if (!hookPath || !fs11.existsSync(hookPath)) return false;
4397
+ const content = fs11.readFileSync(hookPath, "utf-8");
4290
4398
  return content.includes(PRECOMMIT_START);
4291
4399
  }
4292
4400
  function installPreCommitHook() {
@@ -4296,45 +4404,45 @@ function installPreCommitHook() {
4296
4404
  const hookPath = getPreCommitPath();
4297
4405
  if (!hookPath) return { installed: false, alreadyInstalled: false };
4298
4406
  const hooksDir = path10.dirname(hookPath);
4299
- if (!fs10.existsSync(hooksDir)) fs10.mkdirSync(hooksDir, { recursive: true });
4407
+ if (!fs11.existsSync(hooksDir)) fs11.mkdirSync(hooksDir, { recursive: true });
4300
4408
  let content = "";
4301
- if (fs10.existsSync(hookPath)) {
4302
- content = fs10.readFileSync(hookPath, "utf-8");
4409
+ if (fs11.existsSync(hookPath)) {
4410
+ content = fs11.readFileSync(hookPath, "utf-8");
4303
4411
  if (!content.endsWith("\n")) content += "\n";
4304
4412
  content += "\n" + getPrecommitBlock() + "\n";
4305
4413
  } else {
4306
4414
  content = "#!/bin/sh\n\n" + getPrecommitBlock() + "\n";
4307
4415
  }
4308
- fs10.writeFileSync(hookPath, content);
4309
- fs10.chmodSync(hookPath, 493);
4416
+ fs11.writeFileSync(hookPath, content);
4417
+ fs11.chmodSync(hookPath, 493);
4310
4418
  return { installed: true, alreadyInstalled: false };
4311
4419
  }
4312
4420
  function removePreCommitHook() {
4313
4421
  const hookPath = getPreCommitPath();
4314
- if (!hookPath || !fs10.existsSync(hookPath)) {
4422
+ if (!hookPath || !fs11.existsSync(hookPath)) {
4315
4423
  return { removed: false, notFound: true };
4316
4424
  }
4317
- let content = fs10.readFileSync(hookPath, "utf-8");
4425
+ let content = fs11.readFileSync(hookPath, "utf-8");
4318
4426
  if (!content.includes(PRECOMMIT_START)) {
4319
4427
  return { removed: false, notFound: true };
4320
4428
  }
4321
4429
  const regex = new RegExp(`\\n?${PRECOMMIT_START}[\\s\\S]*?${PRECOMMIT_END}\\n?`);
4322
4430
  content = content.replace(regex, "\n");
4323
4431
  if (content.trim() === "#!/bin/sh" || content.trim() === "") {
4324
- fs10.unlinkSync(hookPath);
4432
+ fs11.unlinkSync(hookPath);
4325
4433
  } else {
4326
- fs10.writeFileSync(hookPath, content);
4434
+ fs11.writeFileSync(hookPath, content);
4327
4435
  }
4328
4436
  return { removed: true, notFound: false };
4329
4437
  }
4330
4438
 
4331
4439
  // src/fingerprint/sources.ts
4332
- import fs11 from "fs";
4440
+ import fs12 from "fs";
4333
4441
  import path11 from "path";
4334
4442
 
4335
4443
  // src/scoring/utils.ts
4336
4444
  import { existsSync as existsSync2, readFileSync, readdirSync } from "fs";
4337
- import { execFileSync } from "child_process";
4445
+ import { execFileSync as execFileSync3 } from "child_process";
4338
4446
  import { join, relative } from "path";
4339
4447
  function readFileOrNull(filePath) {
4340
4448
  try {
@@ -4384,7 +4492,7 @@ var IGNORED_FILES = /* @__PURE__ */ new Set([
4384
4492
  ]);
4385
4493
  function isGitRepo2(dir) {
4386
4494
  try {
4387
- execFileSync("git", ["rev-parse", "--git-dir"], {
4495
+ execFileSync3("git", ["rev-parse", "--git-dir"], {
4388
4496
  cwd: dir,
4389
4497
  encoding: "utf-8",
4390
4498
  stdio: ["pipe", "pipe", "pipe"]
@@ -4397,7 +4505,7 @@ function isGitRepo2(dir) {
4397
4505
  function checkGitIgnored(dir, paths) {
4398
4506
  if (paths.length === 0) return /* @__PURE__ */ new Set();
4399
4507
  try {
4400
- const result = execFileSync("git", ["check-ignore", ...paths], {
4508
+ const result = execFileSync3("git", ["check-ignore", ...paths], {
4401
4509
  cwd: dir,
4402
4510
  encoding: "utf-8",
4403
4511
  stdio: ["pipe", "pipe", "pipe"]
@@ -4678,15 +4786,15 @@ function loadSourcesConfig(dir) {
4678
4786
  }
4679
4787
  function writeSourcesConfig(dir, sources2) {
4680
4788
  const configDir = path11.join(dir, ".caliber");
4681
- if (!fs11.existsSync(configDir)) {
4682
- fs11.mkdirSync(configDir, { recursive: true });
4789
+ if (!fs12.existsSync(configDir)) {
4790
+ fs12.mkdirSync(configDir, { recursive: true });
4683
4791
  }
4684
4792
  const configPath = path11.join(configDir, "sources.json");
4685
- fs11.writeFileSync(configPath, JSON.stringify({ sources: sources2 }, null, 2) + "\n", "utf-8");
4793
+ fs12.writeFileSync(configPath, JSON.stringify({ sources: sources2 }, null, 2) + "\n", "utf-8");
4686
4794
  }
4687
4795
  function detectSourceType(absPath) {
4688
4796
  try {
4689
- return fs11.statSync(absPath).isDirectory() ? "repo" : "file";
4797
+ return fs12.statSync(absPath).isDirectory() ? "repo" : "file";
4690
4798
  } catch {
4691
4799
  return "file";
4692
4800
  }
@@ -4730,7 +4838,7 @@ function resolveAllSources(dir, cliSources, workspaces) {
4730
4838
  for (const [absPath, resolved] of seen) {
4731
4839
  let stat;
4732
4840
  try {
4733
- stat = fs11.statSync(absPath);
4841
+ stat = fs12.statSync(absPath);
4734
4842
  } catch {
4735
4843
  console.warn(`Source ${resolved.config.path || absPath} not found, skipping`);
4736
4844
  continue;
@@ -4785,7 +4893,7 @@ function collectRepoSummary(resolved, _projectDir) {
4785
4893
  let topLevelDirs;
4786
4894
  let keyFiles;
4787
4895
  try {
4788
- const entries = fs11.readdirSync(absPath, { withFileTypes: true });
4896
+ const entries = fs12.readdirSync(absPath, { withFileTypes: true });
4789
4897
  topLevelDirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules").map((e) => e.name).slice(0, 20);
4790
4898
  keyFiles = entries.filter((e) => e.isFile() && !e.name.startsWith(".")).map((e) => e.name).slice(0, 15);
4791
4899
  } catch {
@@ -5646,32 +5754,32 @@ ${f.content}
5646
5754
  }
5647
5755
 
5648
5756
  // src/writers/index.ts
5649
- import fs20 from "fs";
5757
+ import fs21 from "fs";
5650
5758
 
5651
5759
  // src/writers/claude/index.ts
5652
5760
  init_pre_commit_block();
5653
- import fs12 from "fs";
5761
+ import fs13 from "fs";
5654
5762
  import path12 from "path";
5655
5763
  function writeClaudeConfig(config) {
5656
5764
  const written = [];
5657
- fs12.writeFileSync(
5765
+ fs13.writeFileSync(
5658
5766
  "CLAUDE.md",
5659
5767
  appendSyncBlock(appendLearningsBlock(appendPreCommitBlock(config.claudeMd)))
5660
5768
  );
5661
5769
  written.push("CLAUDE.md");
5662
5770
  if (config.rules?.length) {
5663
5771
  const rulesDir = path12.join(".claude", "rules");
5664
- if (!fs12.existsSync(rulesDir)) fs12.mkdirSync(rulesDir, { recursive: true });
5772
+ if (!fs13.existsSync(rulesDir)) fs13.mkdirSync(rulesDir, { recursive: true });
5665
5773
  for (const rule of config.rules) {
5666
5774
  const rulePath = path12.join(rulesDir, rule.filename);
5667
- fs12.writeFileSync(rulePath, rule.content);
5775
+ fs13.writeFileSync(rulePath, rule.content);
5668
5776
  written.push(rulePath);
5669
5777
  }
5670
5778
  }
5671
5779
  if (config.skills?.length) {
5672
5780
  for (const skill of config.skills) {
5673
5781
  const skillDir = path12.join(".claude", "skills", skill.name);
5674
- if (!fs12.existsSync(skillDir)) fs12.mkdirSync(skillDir, { recursive: true });
5782
+ if (!fs13.existsSync(skillDir)) fs13.mkdirSync(skillDir, { recursive: true });
5675
5783
  const skillPath = path12.join(skillDir, "SKILL.md");
5676
5784
  const frontmatterLines = ["---", `name: ${skill.name}`, `description: ${skill.description}`];
5677
5785
  if (skill.paths?.length) {
@@ -5682,21 +5790,21 @@ function writeClaudeConfig(config) {
5682
5790
  }
5683
5791
  frontmatterLines.push("---", "");
5684
5792
  const frontmatter = frontmatterLines.join("\n");
5685
- fs12.writeFileSync(skillPath, frontmatter + skill.content);
5793
+ fs13.writeFileSync(skillPath, frontmatter + skill.content);
5686
5794
  written.push(skillPath);
5687
5795
  }
5688
5796
  }
5689
5797
  if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {
5690
5798
  let existingServers = {};
5691
5799
  try {
5692
- if (fs12.existsSync(".mcp.json")) {
5693
- const existing = JSON.parse(fs12.readFileSync(".mcp.json", "utf-8"));
5800
+ if (fs13.existsSync(".mcp.json")) {
5801
+ const existing = JSON.parse(fs13.readFileSync(".mcp.json", "utf-8"));
5694
5802
  if (existing.mcpServers) existingServers = existing.mcpServers;
5695
5803
  }
5696
5804
  } catch {
5697
5805
  }
5698
5806
  const mergedServers = { ...existingServers, ...config.mcpServers };
5699
- fs12.writeFileSync(".mcp.json", JSON.stringify({ mcpServers: mergedServers }, null, 2));
5807
+ fs13.writeFileSync(".mcp.json", JSON.stringify({ mcpServers: mergedServers }, null, 2));
5700
5808
  written.push(".mcp.json");
5701
5809
  }
5702
5810
  return written;
@@ -5704,12 +5812,12 @@ function writeClaudeConfig(config) {
5704
5812
 
5705
5813
  // src/writers/cursor/index.ts
5706
5814
  init_pre_commit_block();
5707
- import fs13 from "fs";
5815
+ import fs14 from "fs";
5708
5816
  import path13 from "path";
5709
5817
  function writeCursorConfig(config) {
5710
5818
  const written = [];
5711
5819
  if (config.cursorrules) {
5712
- fs13.writeFileSync(".cursorrules", config.cursorrules);
5820
+ fs14.writeFileSync(".cursorrules", config.cursorrules);
5713
5821
  written.push(".cursorrules");
5714
5822
  }
5715
5823
  const preCommitRule = getCursorPreCommitRule();
@@ -5717,16 +5825,16 @@ function writeCursorConfig(config) {
5717
5825
  const syncRule = getCursorSyncRule();
5718
5826
  const allRules = [...config.rules || [], preCommitRule, learningsRule, syncRule];
5719
5827
  const rulesDir = path13.join(".cursor", "rules");
5720
- if (!fs13.existsSync(rulesDir)) fs13.mkdirSync(rulesDir, { recursive: true });
5828
+ if (!fs14.existsSync(rulesDir)) fs14.mkdirSync(rulesDir, { recursive: true });
5721
5829
  for (const rule of allRules) {
5722
5830
  const rulePath = path13.join(rulesDir, rule.filename);
5723
- fs13.writeFileSync(rulePath, rule.content);
5831
+ fs14.writeFileSync(rulePath, rule.content);
5724
5832
  written.push(rulePath);
5725
5833
  }
5726
5834
  if (config.skills?.length) {
5727
5835
  for (const skill of config.skills) {
5728
5836
  const skillDir = path13.join(".cursor", "skills", skill.name);
5729
- if (!fs13.existsSync(skillDir)) fs13.mkdirSync(skillDir, { recursive: true });
5837
+ if (!fs14.existsSync(skillDir)) fs14.mkdirSync(skillDir, { recursive: true });
5730
5838
  const skillPath = path13.join(skillDir, "SKILL.md");
5731
5839
  const frontmatter = [
5732
5840
  "---",
@@ -5735,24 +5843,24 @@ function writeCursorConfig(config) {
5735
5843
  "---",
5736
5844
  ""
5737
5845
  ].join("\n");
5738
- fs13.writeFileSync(skillPath, frontmatter + skill.content);
5846
+ fs14.writeFileSync(skillPath, frontmatter + skill.content);
5739
5847
  written.push(skillPath);
5740
5848
  }
5741
5849
  }
5742
5850
  if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {
5743
5851
  const cursorDir = ".cursor";
5744
- if (!fs13.existsSync(cursorDir)) fs13.mkdirSync(cursorDir, { recursive: true });
5852
+ if (!fs14.existsSync(cursorDir)) fs14.mkdirSync(cursorDir, { recursive: true });
5745
5853
  const mcpPath = path13.join(cursorDir, "mcp.json");
5746
5854
  let existingServers = {};
5747
5855
  try {
5748
- if (fs13.existsSync(mcpPath)) {
5749
- const existing = JSON.parse(fs13.readFileSync(mcpPath, "utf-8"));
5856
+ if (fs14.existsSync(mcpPath)) {
5857
+ const existing = JSON.parse(fs14.readFileSync(mcpPath, "utf-8"));
5750
5858
  if (existing.mcpServers) existingServers = existing.mcpServers;
5751
5859
  }
5752
5860
  } catch {
5753
5861
  }
5754
5862
  const mergedServers = { ...existingServers, ...config.mcpServers };
5755
- fs13.writeFileSync(mcpPath, JSON.stringify({ mcpServers: mergedServers }, null, 2));
5863
+ fs14.writeFileSync(mcpPath, JSON.stringify({ mcpServers: mergedServers }, null, 2));
5756
5864
  written.push(mcpPath);
5757
5865
  }
5758
5866
  return written;
@@ -5760,11 +5868,11 @@ function writeCursorConfig(config) {
5760
5868
 
5761
5869
  // src/writers/codex/index.ts
5762
5870
  init_pre_commit_block();
5763
- import fs14 from "fs";
5871
+ import fs15 from "fs";
5764
5872
  import path14 from "path";
5765
5873
  function writeCodexConfig(config) {
5766
5874
  const written = [];
5767
- fs14.writeFileSync(
5875
+ fs15.writeFileSync(
5768
5876
  "AGENTS.md",
5769
5877
  appendLearningsBlock(appendPreCommitBlock(config.agentsMd, "codex"))
5770
5878
  );
@@ -5772,7 +5880,7 @@ function writeCodexConfig(config) {
5772
5880
  if (config.skills?.length) {
5773
5881
  for (const skill of config.skills) {
5774
5882
  const skillDir = path14.join(".agents", "skills", skill.name);
5775
- if (!fs14.existsSync(skillDir)) fs14.mkdirSync(skillDir, { recursive: true });
5883
+ if (!fs15.existsSync(skillDir)) fs15.mkdirSync(skillDir, { recursive: true });
5776
5884
  const skillPath = path14.join(skillDir, "SKILL.md");
5777
5885
  const frontmatter = [
5778
5886
  "---",
@@ -5781,7 +5889,7 @@ function writeCodexConfig(config) {
5781
5889
  "---",
5782
5890
  ""
5783
5891
  ].join("\n");
5784
- fs14.writeFileSync(skillPath, frontmatter + skill.content);
5892
+ fs15.writeFileSync(skillPath, frontmatter + skill.content);
5785
5893
  written.push(skillPath);
5786
5894
  }
5787
5895
  }
@@ -5790,13 +5898,13 @@ function writeCodexConfig(config) {
5790
5898
 
5791
5899
  // src/writers/github-copilot/index.ts
5792
5900
  init_pre_commit_block();
5793
- import fs15 from "fs";
5901
+ import fs16 from "fs";
5794
5902
  import path15 from "path";
5795
5903
  function writeGithubCopilotConfig(config) {
5796
5904
  const written = [];
5797
5905
  if (config.instructions) {
5798
- fs15.mkdirSync(".github", { recursive: true });
5799
- fs15.writeFileSync(
5906
+ fs16.mkdirSync(".github", { recursive: true });
5907
+ fs16.writeFileSync(
5800
5908
  path15.join(".github", "copilot-instructions.md"),
5801
5909
  appendSyncBlock(appendLearningsBlock(appendPreCommitBlock(config.instructions, "copilot")))
5802
5910
  );
@@ -5804,9 +5912,9 @@ function writeGithubCopilotConfig(config) {
5804
5912
  }
5805
5913
  if (config.instructionFiles?.length) {
5806
5914
  const instructionsDir = path15.join(".github", "instructions");
5807
- fs15.mkdirSync(instructionsDir, { recursive: true });
5915
+ fs16.mkdirSync(instructionsDir, { recursive: true });
5808
5916
  for (const file of config.instructionFiles) {
5809
- fs15.writeFileSync(path15.join(instructionsDir, file.filename), file.content);
5917
+ fs16.writeFileSync(path15.join(instructionsDir, file.filename), file.content);
5810
5918
  written.push(`.github/instructions/${file.filename}`);
5811
5919
  }
5812
5920
  }
@@ -5816,12 +5924,12 @@ function writeGithubCopilotConfig(config) {
5816
5924
  // src/writers/opencode/index.ts
5817
5925
  init_pre_commit_block();
5818
5926
  init_builtin_skills();
5819
- import fs17 from "fs";
5927
+ import fs18 from "fs";
5820
5928
  import path17 from "path";
5821
5929
  function writeOpencodeConfig(config, agentsMdAlreadyWritten = false) {
5822
5930
  const written = [];
5823
5931
  if (!agentsMdAlreadyWritten) {
5824
- fs17.writeFileSync(
5932
+ fs18.writeFileSync(
5825
5933
  "AGENTS.md",
5826
5934
  appendLearningsBlock(appendPreCommitBlock(config.agentsMd, "codex"))
5827
5935
  );
@@ -5830,9 +5938,9 @@ function writeOpencodeConfig(config, agentsMdAlreadyWritten = false) {
5830
5938
  if (config.skills?.length) {
5831
5939
  for (const skill of config.skills) {
5832
5940
  const skillDir = path17.join(".opencode", "skills", skill.name);
5833
- if (!fs17.existsSync(skillDir)) fs17.mkdirSync(skillDir, { recursive: true });
5941
+ if (!fs18.existsSync(skillDir)) fs18.mkdirSync(skillDir, { recursive: true });
5834
5942
  const skillPath = path17.join(skillDir, "SKILL.md");
5835
- fs17.writeFileSync(skillPath, buildSkillContent(skill));
5943
+ fs18.writeFileSync(skillPath, buildSkillContent(skill));
5836
5944
  written.push(skillPath);
5837
5945
  }
5838
5946
  }
@@ -5840,30 +5948,30 @@ function writeOpencodeConfig(config, agentsMdAlreadyWritten = false) {
5840
5948
  }
5841
5949
 
5842
5950
  // src/writers/backup.ts
5843
- import fs18 from "fs";
5951
+ import fs19 from "fs";
5844
5952
  import path18 from "path";
5845
5953
  function createBackup(files) {
5846
5954
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
5847
5955
  const backupDir = path18.join(BACKUPS_DIR, timestamp);
5848
5956
  for (const file of files) {
5849
- if (!fs18.existsSync(file)) continue;
5957
+ if (!fs19.existsSync(file)) continue;
5850
5958
  const dest = path18.join(backupDir, file);
5851
5959
  const destDir = path18.dirname(dest);
5852
- if (!fs18.existsSync(destDir)) {
5853
- fs18.mkdirSync(destDir, { recursive: true });
5960
+ if (!fs19.existsSync(destDir)) {
5961
+ fs19.mkdirSync(destDir, { recursive: true });
5854
5962
  }
5855
- fs18.copyFileSync(file, dest);
5963
+ fs19.copyFileSync(file, dest);
5856
5964
  }
5857
5965
  return backupDir;
5858
5966
  }
5859
5967
  function restoreBackup(backupDir, file) {
5860
5968
  const backupFile = path18.join(backupDir, file);
5861
- if (!fs18.existsSync(backupFile)) return false;
5969
+ if (!fs19.existsSync(backupFile)) return false;
5862
5970
  const destDir = path18.dirname(file);
5863
- if (!fs18.existsSync(destDir)) {
5864
- fs18.mkdirSync(destDir, { recursive: true });
5971
+ if (!fs19.existsSync(destDir)) {
5972
+ fs19.mkdirSync(destDir, { recursive: true });
5865
5973
  }
5866
- fs18.copyFileSync(backupFile, file);
5974
+ fs19.copyFileSync(backupFile, file);
5867
5975
  return true;
5868
5976
  }
5869
5977
 
@@ -5871,32 +5979,32 @@ function restoreBackup(backupDir, file) {
5871
5979
  init_builtin_skills();
5872
5980
 
5873
5981
  // src/writers/manifest.ts
5874
- import fs19 from "fs";
5982
+ import fs20 from "fs";
5875
5983
  import crypto3 from "crypto";
5876
5984
  function readManifest() {
5877
5985
  try {
5878
- if (!fs19.existsSync(MANIFEST_FILE)) return null;
5879
- return JSON.parse(fs19.readFileSync(MANIFEST_FILE, "utf-8"));
5986
+ if (!fs20.existsSync(MANIFEST_FILE)) return null;
5987
+ return JSON.parse(fs20.readFileSync(MANIFEST_FILE, "utf-8"));
5880
5988
  } catch {
5881
5989
  return null;
5882
5990
  }
5883
5991
  }
5884
5992
  function writeManifest(manifest) {
5885
- if (!fs19.existsSync(CALIBER_DIR)) {
5886
- fs19.mkdirSync(CALIBER_DIR, { recursive: true });
5993
+ if (!fs20.existsSync(CALIBER_DIR)) {
5994
+ fs20.mkdirSync(CALIBER_DIR, { recursive: true });
5887
5995
  }
5888
- fs19.writeFileSync(MANIFEST_FILE, JSON.stringify(manifest, null, 2));
5996
+ fs20.writeFileSync(MANIFEST_FILE, JSON.stringify(manifest, null, 2));
5889
5997
  }
5890
5998
  function fileChecksum(filePath) {
5891
- const content = fs19.readFileSync(filePath);
5999
+ const content = fs20.readFileSync(filePath);
5892
6000
  return crypto3.createHash("sha256").update(content).digest("hex");
5893
6001
  }
5894
6002
 
5895
6003
  // src/writers/index.ts
5896
6004
  function writeSetup(setup) {
5897
6005
  const filesToWrite = getFilesToWrite(setup);
5898
- const filesToDelete = (setup.deletions || []).map((d) => d.filePath).filter((f) => fs20.existsSync(f));
5899
- const existingFiles = [...filesToWrite.filter((f) => fs20.existsSync(f)), ...filesToDelete];
6006
+ const filesToDelete = (setup.deletions || []).map((d) => d.filePath).filter((f) => fs21.existsSync(f));
6007
+ const existingFiles = [...filesToWrite.filter((f) => fs21.existsSync(f)), ...filesToDelete];
5900
6008
  const backupDir = existingFiles.length > 0 ? createBackup(existingFiles) : void 0;
5901
6009
  const written = [];
5902
6010
  if (setup.targetAgent.includes("claude") && setup.claude) {
@@ -5917,7 +6025,7 @@ function writeSetup(setup) {
5917
6025
  }
5918
6026
  const deleted = [];
5919
6027
  for (const filePath of filesToDelete) {
5920
- fs20.unlinkSync(filePath);
6028
+ fs21.unlinkSync(filePath);
5921
6029
  deleted.push(filePath);
5922
6030
  }
5923
6031
  written.push(...ensureBuiltinSkills());
@@ -5948,8 +6056,8 @@ function undoSetup() {
5948
6056
  const removed = [];
5949
6057
  for (const entry of manifest.entries) {
5950
6058
  if (entry.action === "created") {
5951
- if (fs20.existsSync(entry.path)) {
5952
- fs20.unlinkSync(entry.path);
6059
+ if (fs21.existsSync(entry.path)) {
6060
+ fs21.unlinkSync(entry.path);
5953
6061
  removed.push(entry.path);
5954
6062
  }
5955
6063
  } else if ((entry.action === "modified" || entry.action === "deleted") && manifest.backupDir) {
@@ -5958,8 +6066,8 @@ function undoSetup() {
5958
6066
  }
5959
6067
  }
5960
6068
  }
5961
- if (fs20.existsSync(MANIFEST_FILE)) {
5962
- fs20.unlinkSync(MANIFEST_FILE);
6069
+ if (fs21.existsSync(MANIFEST_FILE)) {
6070
+ fs21.unlinkSync(MANIFEST_FILE);
5963
6071
  }
5964
6072
  return { restored, removed };
5965
6073
  }
@@ -6012,18 +6120,18 @@ function getFilesToWrite(setup) {
6012
6120
  }
6013
6121
  function ensureGitignore() {
6014
6122
  const gitignorePath = ".gitignore";
6015
- if (fs20.existsSync(gitignorePath)) {
6016
- const content = fs20.readFileSync(gitignorePath, "utf-8");
6123
+ if (fs21.existsSync(gitignorePath)) {
6124
+ const content = fs21.readFileSync(gitignorePath, "utf-8");
6017
6125
  if (!content.includes(".caliber/")) {
6018
- fs20.appendFileSync(gitignorePath, "\n# Caliber local state\n.caliber/\n");
6126
+ fs21.appendFileSync(gitignorePath, "\n# Caliber local state\n.caliber/\n");
6019
6127
  }
6020
6128
  } else {
6021
- fs20.writeFileSync(gitignorePath, "# Caliber local state\n.caliber/\n");
6129
+ fs21.writeFileSync(gitignorePath, "# Caliber local state\n.caliber/\n");
6022
6130
  }
6023
6131
  }
6024
6132
 
6025
6133
  // src/writers/staging.ts
6026
- import fs21 from "fs";
6134
+ import fs22 from "fs";
6027
6135
  import path19 from "path";
6028
6136
  var STAGED_DIR = path19.join(CALIBER_DIR, "staged");
6029
6137
  var PROPOSED_DIR = path19.join(STAGED_DIR, "proposed");
@@ -6039,19 +6147,19 @@ function stageFiles(files, projectDir) {
6039
6147
  for (const file of files) {
6040
6148
  assertPathWithinDir(file.path, projectDir);
6041
6149
  const originalPath = path19.join(projectDir, file.path);
6042
- if (fs21.existsSync(originalPath)) {
6043
- const existing = fs21.readFileSync(originalPath, "utf-8");
6150
+ if (fs22.existsSync(originalPath)) {
6151
+ const existing = fs22.readFileSync(originalPath, "utf-8");
6044
6152
  if (normalizeContent(existing) === normalizeContent(file.content)) {
6045
6153
  continue;
6046
6154
  }
6047
6155
  }
6048
6156
  const proposedPath = path19.join(PROPOSED_DIR, file.path);
6049
- fs21.mkdirSync(path19.dirname(proposedPath), { recursive: true });
6050
- fs21.writeFileSync(proposedPath, file.content);
6051
- if (fs21.existsSync(originalPath)) {
6157
+ fs22.mkdirSync(path19.dirname(proposedPath), { recursive: true });
6158
+ fs22.writeFileSync(proposedPath, file.content);
6159
+ if (fs22.existsSync(originalPath)) {
6052
6160
  const currentPath = path19.join(CURRENT_DIR, file.path);
6053
- fs21.mkdirSync(path19.dirname(currentPath), { recursive: true });
6054
- fs21.copyFileSync(originalPath, currentPath);
6161
+ fs22.mkdirSync(path19.dirname(currentPath), { recursive: true });
6162
+ fs22.copyFileSync(originalPath, currentPath);
6055
6163
  modifiedFiles++;
6056
6164
  stagedFiles.push({
6057
6165
  relativePath: file.path,
@@ -6068,14 +6176,14 @@ function stageFiles(files, projectDir) {
6068
6176
  return { newFiles, modifiedFiles, stagedFiles };
6069
6177
  }
6070
6178
  function cleanupStaging() {
6071
- if (fs21.existsSync(STAGED_DIR)) {
6072
- fs21.rmSync(STAGED_DIR, { recursive: true, force: true });
6179
+ if (fs22.existsSync(STAGED_DIR)) {
6180
+ fs22.rmSync(STAGED_DIR, { recursive: true, force: true });
6073
6181
  }
6074
6182
  }
6075
6183
 
6076
6184
  // src/commands/setup-files.ts
6077
6185
  init_builtin_skills();
6078
- import fs22 from "fs";
6186
+ import fs23 from "fs";
6079
6187
  function collectSetupFiles(setup, targetAgent) {
6080
6188
  const files = [];
6081
6189
  const claude = setup.claude;
@@ -6182,7 +6290,7 @@ function collectSetupFiles(setup, targetAgent) {
6182
6290
  }
6183
6291
  const codexTargeted = targetAgent ? targetAgent.includes("codex") : false;
6184
6292
  const opencodeTargeted = targetAgent ? targetAgent.includes("opencode") : false;
6185
- if ((codexTargeted || opencodeTargeted) && !fs22.existsSync("AGENTS.md") && !(codex && codex.agentsMd) && !(opencode && opencode.agentsMd)) {
6293
+ if ((codexTargeted || opencodeTargeted) && !fs23.existsSync("AGENTS.md") && !(codex && codex.agentsMd) && !(opencode && opencode.agentsMd)) {
6186
6294
  const agentRefs = [];
6187
6295
  if (claude) agentRefs.push("See `CLAUDE.md` for Claude Code configuration.");
6188
6296
  if (cursor) agentRefs.push("See `.cursor/rules/` for Cursor rules.");
@@ -6201,7 +6309,7 @@ ${agentRefs.join(" ")}
6201
6309
 
6202
6310
  // src/lib/learning-hooks.ts
6203
6311
  init_resolve_caliber();
6204
- import fs23 from "fs";
6312
+ import fs24 from "fs";
6205
6313
  import path20 from "path";
6206
6314
  var SETTINGS_PATH2 = path20.join(".claude", "settings.json");
6207
6315
  var HOOK_TAILS = [
@@ -6220,17 +6328,17 @@ function getHookConfigs() {
6220
6328
  }));
6221
6329
  }
6222
6330
  function readSettings2() {
6223
- if (!fs23.existsSync(SETTINGS_PATH2)) return {};
6331
+ if (!fs24.existsSync(SETTINGS_PATH2)) return {};
6224
6332
  try {
6225
- return JSON.parse(fs23.readFileSync(SETTINGS_PATH2, "utf-8"));
6333
+ return JSON.parse(fs24.readFileSync(SETTINGS_PATH2, "utf-8"));
6226
6334
  } catch {
6227
6335
  return {};
6228
6336
  }
6229
6337
  }
6230
6338
  function writeSettings2(settings) {
6231
6339
  const dir = path20.dirname(SETTINGS_PATH2);
6232
- if (!fs23.existsSync(dir)) fs23.mkdirSync(dir, { recursive: true });
6233
- fs23.writeFileSync(SETTINGS_PATH2, JSON.stringify(settings, null, 2));
6340
+ if (!fs24.existsSync(dir)) fs24.mkdirSync(dir, { recursive: true });
6341
+ fs24.writeFileSync(SETTINGS_PATH2, JSON.stringify(settings, null, 2));
6234
6342
  }
6235
6343
  function hasLearningHook(matchers, tail) {
6236
6344
  return matchers.some((entry) => entry.hooks?.some((h) => isCaliberCommand(h.command, tail)));
@@ -6272,17 +6380,17 @@ var CURSOR_HOOK_EVENTS = [
6272
6380
  { event: "sessionEnd", tail: "learn finalize --auto" }
6273
6381
  ];
6274
6382
  function readCursorHooks() {
6275
- if (!fs23.existsSync(CURSOR_HOOKS_PATH)) return { version: 1, hooks: {} };
6383
+ if (!fs24.existsSync(CURSOR_HOOKS_PATH)) return { version: 1, hooks: {} };
6276
6384
  try {
6277
- return JSON.parse(fs23.readFileSync(CURSOR_HOOKS_PATH, "utf-8"));
6385
+ return JSON.parse(fs24.readFileSync(CURSOR_HOOKS_PATH, "utf-8"));
6278
6386
  } catch {
6279
6387
  return { version: 1, hooks: {} };
6280
6388
  }
6281
6389
  }
6282
6390
  function writeCursorHooks(config) {
6283
6391
  const dir = path20.dirname(CURSOR_HOOKS_PATH);
6284
- if (!fs23.existsSync(dir)) fs23.mkdirSync(dir, { recursive: true });
6285
- fs23.writeFileSync(CURSOR_HOOKS_PATH, JSON.stringify(config, null, 2));
6392
+ if (!fs24.existsSync(dir)) fs24.mkdirSync(dir, { recursive: true });
6393
+ fs24.writeFileSync(CURSOR_HOOKS_PATH, JSON.stringify(config, null, 2));
6286
6394
  }
6287
6395
  function hasCursorHook(entries, tail) {
6288
6396
  return entries.some((e) => isCaliberCommand(e.command, tail));
@@ -6354,7 +6462,7 @@ function removeLearningHooks() {
6354
6462
  init_resolve_caliber();
6355
6463
 
6356
6464
  // src/lib/state.ts
6357
- import fs24 from "fs";
6465
+ import fs25 from "fs";
6358
6466
  import path21 from "path";
6359
6467
  import { execSync as execSync9 } from "child_process";
6360
6468
  var STATE_FILE = path21.join(CALIBER_DIR, ".caliber-state.json");
@@ -6368,8 +6476,8 @@ function normalizeTargetAgent(value) {
6368
6476
  }
6369
6477
  function readState() {
6370
6478
  try {
6371
- if (!fs24.existsSync(STATE_FILE)) return null;
6372
- const raw = JSON.parse(fs24.readFileSync(STATE_FILE, "utf-8"));
6479
+ if (!fs25.existsSync(STATE_FILE)) return null;
6480
+ const raw = JSON.parse(fs25.readFileSync(STATE_FILE, "utf-8"));
6373
6481
  if (raw.targetAgent) raw.targetAgent = normalizeTargetAgent(raw.targetAgent);
6374
6482
  return raw;
6375
6483
  } catch {
@@ -6377,10 +6485,10 @@ function readState() {
6377
6485
  }
6378
6486
  }
6379
6487
  function writeState(state) {
6380
- if (!fs24.existsSync(CALIBER_DIR)) {
6381
- fs24.mkdirSync(CALIBER_DIR, { recursive: true });
6488
+ if (!fs25.existsSync(CALIBER_DIR)) {
6489
+ fs25.mkdirSync(CALIBER_DIR, { recursive: true });
6382
6490
  }
6383
- fs24.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
6491
+ fs25.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
6384
6492
  }
6385
6493
  function getCurrentHeadSha() {
6386
6494
  try {
@@ -6397,6 +6505,7 @@ function getCurrentHeadSha() {
6397
6505
  import chalk2 from "chalk";
6398
6506
  import readline from "readline";
6399
6507
  function promptInput(question) {
6508
+ if (!process.stdin.isTTY) return Promise.resolve("");
6400
6509
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
6401
6510
  return new Promise((resolve3) => {
6402
6511
  rl.question(chalk2.cyan(`${question} `), (answer) => {
@@ -7487,7 +7596,7 @@ function checkSources(dir) {
7487
7596
  }
7488
7597
 
7489
7598
  // src/scoring/dismissed.ts
7490
- import fs25 from "fs";
7599
+ import fs26 from "fs";
7491
7600
  import path22 from "path";
7492
7601
  var DISMISSED_FILE = path22.join(CALIBER_DIR, "dismissed-checks.json");
7493
7602
  function dismissedFilePath(dir) {
@@ -7496,17 +7605,17 @@ function dismissedFilePath(dir) {
7496
7605
  function readDismissedChecks(dir) {
7497
7606
  try {
7498
7607
  const filePath = dismissedFilePath(dir);
7499
- if (!fs25.existsSync(filePath)) return [];
7500
- return JSON.parse(fs25.readFileSync(filePath, "utf-8"));
7608
+ if (!fs26.existsSync(filePath)) return [];
7609
+ return JSON.parse(fs26.readFileSync(filePath, "utf-8"));
7501
7610
  } catch {
7502
7611
  return [];
7503
7612
  }
7504
7613
  }
7505
7614
  function writeDismissedChecks(checks) {
7506
- if (!fs25.existsSync(CALIBER_DIR)) {
7507
- fs25.mkdirSync(CALIBER_DIR, { recursive: true });
7615
+ if (!fs26.existsSync(CALIBER_DIR)) {
7616
+ fs26.mkdirSync(CALIBER_DIR, { recursive: true });
7508
7617
  }
7509
- fs25.writeFileSync(DISMISSED_FILE, JSON.stringify(checks, null, 2) + "\n");
7618
+ fs26.writeFileSync(DISMISSED_FILE, JSON.stringify(checks, null, 2) + "\n");
7510
7619
  }
7511
7620
  function getDismissedIds(dir) {
7512
7621
  return new Set(readDismissedChecks(dir).map((c) => c.id));
@@ -7765,7 +7874,7 @@ import { PostHog } from "posthog-node";
7765
7874
  import chalk5 from "chalk";
7766
7875
 
7767
7876
  // src/telemetry/config.ts
7768
- import fs26 from "fs";
7877
+ import fs27 from "fs";
7769
7878
  import path23 from "path";
7770
7879
  import os5 from "os";
7771
7880
  import crypto4 from "crypto";
@@ -7775,17 +7884,17 @@ var CONFIG_FILE2 = path23.join(CONFIG_DIR2, "config.json");
7775
7884
  var runtimeDisabled = false;
7776
7885
  function readConfig() {
7777
7886
  try {
7778
- if (!fs26.existsSync(CONFIG_FILE2)) return {};
7779
- return JSON.parse(fs26.readFileSync(CONFIG_FILE2, "utf-8"));
7887
+ if (!fs27.existsSync(CONFIG_FILE2)) return {};
7888
+ return JSON.parse(fs27.readFileSync(CONFIG_FILE2, "utf-8"));
7780
7889
  } catch {
7781
7890
  return {};
7782
7891
  }
7783
7892
  }
7784
7893
  function writeConfig(config) {
7785
- if (!fs26.existsSync(CONFIG_DIR2)) {
7786
- fs26.mkdirSync(CONFIG_DIR2, { recursive: true });
7894
+ if (!fs27.existsSync(CONFIG_DIR2)) {
7895
+ fs27.mkdirSync(CONFIG_DIR2, { recursive: true });
7787
7896
  }
7788
- fs26.writeFileSync(CONFIG_FILE2, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
7897
+ fs27.writeFileSync(CONFIG_FILE2, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
7789
7898
  }
7790
7899
  function getMachineId() {
7791
7900
  const config = readConfig();
@@ -8458,6 +8567,10 @@ async function recommendCommand(options) {
8458
8567
  await querySkills(options.query);
8459
8568
  return;
8460
8569
  }
8570
+ if (!process.stdin.isTTY) {
8571
+ console.log(chalk6.dim(" Skills search requires an interactive terminal."));
8572
+ return;
8573
+ }
8461
8574
  const proceed = await select3({
8462
8575
  message: "Search public repos for relevant skills to add to this project?",
8463
8576
  choices: [
@@ -9125,7 +9238,7 @@ async function runScoreRefineWithSpinner(setup, dir, sessionHistory, options) {
9125
9238
  }
9126
9239
 
9127
9240
  // src/lib/debug-report.ts
9128
- import fs27 from "fs";
9241
+ import fs28 from "fs";
9129
9242
  import path24 from "path";
9130
9243
  var DebugReport = class {
9131
9244
  sections = [];
@@ -9196,10 +9309,10 @@ var DebugReport = class {
9196
9309
  lines.push("");
9197
9310
  }
9198
9311
  const dir = path24.dirname(outputPath);
9199
- if (!fs27.existsSync(dir)) {
9200
- fs27.mkdirSync(dir, { recursive: true });
9312
+ if (!fs28.existsSync(dir)) {
9313
+ fs28.mkdirSync(dir, { recursive: true });
9201
9314
  }
9202
- fs27.writeFileSync(outputPath, lines.join("\n"));
9315
+ fs28.writeFileSync(outputPath, lines.join("\n"));
9203
9316
  }
9204
9317
  };
9205
9318
  function formatMs(ms) {
@@ -9600,7 +9713,7 @@ import chalk11 from "chalk";
9600
9713
  import ora3 from "ora";
9601
9714
  import select5 from "@inquirer/select";
9602
9715
  import checkbox from "@inquirer/checkbox";
9603
- import fs30 from "fs";
9716
+ import fs31 from "fs";
9604
9717
 
9605
9718
  // src/ai/refine.ts
9606
9719
  async function refineSetup(currentSetup, message, conversationHistory, callbacks) {
@@ -9776,11 +9889,11 @@ init_config();
9776
9889
  init_review();
9777
9890
  function detectAgents(dir) {
9778
9891
  const agents = [];
9779
- if (fs30.existsSync(`${dir}/.claude`)) agents.push("claude");
9780
- if (fs30.existsSync(`${dir}/.cursor`)) agents.push("cursor");
9781
- if (fs30.existsSync(`${dir}/.agents`) || fs30.existsSync(`${dir}/AGENTS.md`)) agents.push("codex");
9782
- if (fs30.existsSync(`${dir}/.opencode`)) agents.push("opencode");
9783
- if (fs30.existsSync(`${dir}/.github/copilot-instructions.md`)) agents.push("github-copilot");
9892
+ if (fs31.existsSync(`${dir}/.claude`)) agents.push("claude");
9893
+ if (fs31.existsSync(`${dir}/.cursor`)) agents.push("cursor");
9894
+ if (fs31.existsSync(`${dir}/.agents`) || fs31.existsSync(`${dir}/AGENTS.md`)) agents.push("codex");
9895
+ if (fs31.existsSync(`${dir}/.opencode`)) agents.push("opencode");
9896
+ if (fs31.existsSync(`${dir}/.github/copilot-instructions.md`)) agents.push("github-copilot");
9784
9897
  return agents;
9785
9898
  }
9786
9899
  async function promptAgent(detected) {
@@ -9884,7 +9997,7 @@ async function refineLoop(currentSetup, sessionHistory, summarizeSetup2, printSu
9884
9997
 
9885
9998
  // src/commands/init-display.ts
9886
9999
  import chalk12 from "chalk";
9887
- import fs31 from "fs";
10000
+ import fs32 from "fs";
9888
10001
  init_types();
9889
10002
  function formatWhatChanged(setup) {
9890
10003
  const lines = [];
@@ -9892,12 +10005,12 @@ function formatWhatChanged(setup) {
9892
10005
  const codex = setup.codex;
9893
10006
  const cursor = setup.cursor;
9894
10007
  if (claude?.claudeMd) {
9895
- const action = fs31.existsSync("CLAUDE.md") ? "Updated" : "Created";
10008
+ const action = fs32.existsSync("CLAUDE.md") ? "Updated" : "Created";
9896
10009
  lines.push(`${action} CLAUDE.md`);
9897
10010
  }
9898
10011
  const opencode = setup.opencode;
9899
10012
  if (codex?.agentsMd || opencode?.agentsMd) {
9900
- const action = fs31.existsSync("AGENTS.md") ? "Updated" : "Created";
10013
+ const action = fs32.existsSync("AGENTS.md") ? "Updated" : "Created";
9901
10014
  lines.push(`${action} AGENTS.md`);
9902
10015
  }
9903
10016
  const allSkills = [];
@@ -9941,7 +10054,7 @@ function printSetupSummary(setup) {
9941
10054
  };
9942
10055
  if (claude) {
9943
10056
  if (claude.claudeMd) {
9944
- const icon = fs31.existsSync("CLAUDE.md") ? chalk12.yellow("~") : chalk12.green("+");
10057
+ const icon = fs32.existsSync("CLAUDE.md") ? chalk12.yellow("~") : chalk12.green("+");
9945
10058
  const desc = getDescription("CLAUDE.md");
9946
10059
  console.log(` ${icon} ${chalk12.bold("CLAUDE.md")}`);
9947
10060
  if (desc) console.log(chalk12.dim(` ${desc}`));
@@ -9951,7 +10064,7 @@ function printSetupSummary(setup) {
9951
10064
  if (Array.isArray(skills) && skills.length > 0) {
9952
10065
  for (const skill of skills) {
9953
10066
  const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
9954
- const icon = fs31.existsSync(skillPath) ? chalk12.yellow("~") : chalk12.green("+");
10067
+ const icon = fs32.existsSync(skillPath) ? chalk12.yellow("~") : chalk12.green("+");
9955
10068
  const desc = getDescription(skillPath);
9956
10069
  console.log(` ${icon} ${chalk12.bold(skillPath)}`);
9957
10070
  console.log(chalk12.dim(` ${desc || skill.description || skill.name}`));
@@ -9962,7 +10075,7 @@ function printSetupSummary(setup) {
9962
10075
  const codex = setup.codex;
9963
10076
  if (codex) {
9964
10077
  if (codex.agentsMd) {
9965
- const icon = fs31.existsSync("AGENTS.md") ? chalk12.yellow("~") : chalk12.green("+");
10078
+ const icon = fs32.existsSync("AGENTS.md") ? chalk12.yellow("~") : chalk12.green("+");
9966
10079
  const desc = getDescription("AGENTS.md");
9967
10080
  console.log(` ${icon} ${chalk12.bold("AGENTS.md")}`);
9968
10081
  if (desc) console.log(chalk12.dim(` ${desc}`));
@@ -9972,7 +10085,7 @@ function printSetupSummary(setup) {
9972
10085
  if (Array.isArray(codexSkills) && codexSkills.length > 0) {
9973
10086
  for (const skill of codexSkills) {
9974
10087
  const skillPath = `.agents/skills/${skill.name}/SKILL.md`;
9975
- const icon = fs31.existsSync(skillPath) ? chalk12.yellow("~") : chalk12.green("+");
10088
+ const icon = fs32.existsSync(skillPath) ? chalk12.yellow("~") : chalk12.green("+");
9976
10089
  const desc = getDescription(skillPath);
9977
10090
  console.log(` ${icon} ${chalk12.bold(skillPath)}`);
9978
10091
  console.log(chalk12.dim(` ${desc || skill.description || skill.name}`));
@@ -9983,7 +10096,7 @@ function printSetupSummary(setup) {
9983
10096
  const opencode = setup.opencode;
9984
10097
  if (opencode) {
9985
10098
  if (opencode.agentsMd && !codex?.agentsMd) {
9986
- const icon = fs31.existsSync("AGENTS.md") ? chalk12.yellow("~") : chalk12.green("+");
10099
+ const icon = fs32.existsSync("AGENTS.md") ? chalk12.yellow("~") : chalk12.green("+");
9987
10100
  const desc = getDescription("AGENTS.md");
9988
10101
  console.log(` ${icon} ${chalk12.bold("AGENTS.md")} ${chalk12.dim("(OpenCode)")}`);
9989
10102
  if (desc) console.log(chalk12.dim(` ${desc}`));
@@ -9993,7 +10106,7 @@ function printSetupSummary(setup) {
9993
10106
  if (Array.isArray(opencodeSkills) && opencodeSkills.length > 0) {
9994
10107
  for (const skill of opencodeSkills) {
9995
10108
  const skillPath = `.opencode/skills/${skill.name}/SKILL.md`;
9996
- const icon = fs31.existsSync(skillPath) ? chalk12.yellow("~") : chalk12.green("+");
10109
+ const icon = fs32.existsSync(skillPath) ? chalk12.yellow("~") : chalk12.green("+");
9997
10110
  const desc = getDescription(skillPath);
9998
10111
  console.log(` ${icon} ${chalk12.bold(skillPath)}`);
9999
10112
  console.log(chalk12.dim(` ${desc || skill.description || skill.name}`));
@@ -10003,7 +10116,7 @@ function printSetupSummary(setup) {
10003
10116
  }
10004
10117
  if (cursor) {
10005
10118
  if (cursor.cursorrules) {
10006
- const icon = fs31.existsSync(".cursorrules") ? chalk12.yellow("~") : chalk12.green("+");
10119
+ const icon = fs32.existsSync(".cursorrules") ? chalk12.yellow("~") : chalk12.green("+");
10007
10120
  const desc = getDescription(".cursorrules");
10008
10121
  console.log(` ${icon} ${chalk12.bold(".cursorrules")}`);
10009
10122
  if (desc) console.log(chalk12.dim(` ${desc}`));
@@ -10013,7 +10126,7 @@ function printSetupSummary(setup) {
10013
10126
  if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
10014
10127
  for (const skill of cursorSkills) {
10015
10128
  const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
10016
- const icon = fs31.existsSync(skillPath) ? chalk12.yellow("~") : chalk12.green("+");
10129
+ const icon = fs32.existsSync(skillPath) ? chalk12.yellow("~") : chalk12.green("+");
10017
10130
  const desc = getDescription(skillPath);
10018
10131
  console.log(` ${icon} ${chalk12.bold(skillPath)}`);
10019
10132
  console.log(chalk12.dim(` ${desc || skill.description || skill.name}`));
@@ -10024,7 +10137,7 @@ function printSetupSummary(setup) {
10024
10137
  if (Array.isArray(rulesArr) && rulesArr.length > 0) {
10025
10138
  for (const rule of rulesArr) {
10026
10139
  const rulePath = `.cursor/rules/${rule.filename}`;
10027
- const icon = fs31.existsSync(rulePath) ? chalk12.yellow("~") : chalk12.green("+");
10140
+ const icon = fs32.existsSync(rulePath) ? chalk12.yellow("~") : chalk12.green("+");
10028
10141
  const desc = getDescription(rulePath);
10029
10142
  console.log(` ${icon} ${chalk12.bold(rulePath)}`);
10030
10143
  if (desc) {
@@ -10086,12 +10199,12 @@ function displayTokenUsage() {
10086
10199
  // src/commands/init-helpers.ts
10087
10200
  init_config();
10088
10201
  import chalk13 from "chalk";
10089
- import fs32 from "fs";
10202
+ import fs33 from "fs";
10090
10203
  import path26 from "path";
10091
10204
  function isFirstRun(dir) {
10092
10205
  const caliberDir = path26.join(dir, ".caliber");
10093
10206
  try {
10094
- const stat = fs32.statSync(caliberDir);
10207
+ const stat = fs33.statSync(caliberDir);
10095
10208
  return !stat.isDirectory();
10096
10209
  } catch {
10097
10210
  return true;
@@ -10144,8 +10257,8 @@ function ensurePermissions(fingerprint) {
10144
10257
  const settingsPath = ".claude/settings.json";
10145
10258
  let settings = {};
10146
10259
  try {
10147
- if (fs32.existsSync(settingsPath)) {
10148
- settings = JSON.parse(fs32.readFileSync(settingsPath, "utf-8"));
10260
+ if (fs33.existsSync(settingsPath)) {
10261
+ settings = JSON.parse(fs33.readFileSync(settingsPath, "utf-8"));
10149
10262
  }
10150
10263
  } catch {
10151
10264
  }
@@ -10154,8 +10267,8 @@ function ensurePermissions(fingerprint) {
10154
10267
  if (Array.isArray(allow) && allow.length > 0) return;
10155
10268
  permissions.allow = derivePermissions(fingerprint);
10156
10269
  settings.permissions = permissions;
10157
- if (!fs32.existsSync(".claude")) fs32.mkdirSync(".claude", { recursive: true });
10158
- fs32.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
10270
+ if (!fs33.existsSync(".claude")) fs33.mkdirSync(".claude", { recursive: true });
10271
+ fs33.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
10159
10272
  }
10160
10273
  function writeErrorLog(config, rawOutput, error, stopReason) {
10161
10274
  try {
@@ -10184,8 +10297,8 @@ function writeErrorLog(config, rawOutput, error, stopReason) {
10184
10297
  lines.push("```");
10185
10298
  lines.push("", "If timeouts persist, try a different model.");
10186
10299
  }
10187
- fs32.mkdirSync(path26.join(process.cwd(), ".caliber"), { recursive: true });
10188
- fs32.writeFileSync(logPath, lines.join("\n"));
10300
+ fs33.mkdirSync(path26.join(process.cwd(), ".caliber"), { recursive: true });
10301
+ fs33.writeFileSync(logPath, lines.join("\n"));
10189
10302
  console.log(chalk13.dim(`
10190
10303
  Error log written to .caliber/error-log.md`));
10191
10304
  } catch {
@@ -10238,7 +10351,7 @@ ${JSON.stringify(checkList, null, 2)}`,
10238
10351
  }
10239
10352
 
10240
10353
  // src/scoring/history.ts
10241
- import fs33 from "fs";
10354
+ import fs34 from "fs";
10242
10355
  import path27 from "path";
10243
10356
  var HISTORY_FILE = "score-history.jsonl";
10244
10357
  var MAX_ENTRIES = 500;
@@ -10255,14 +10368,14 @@ function recordScore(result, trigger) {
10255
10368
  trigger
10256
10369
  };
10257
10370
  try {
10258
- fs33.mkdirSync(CALIBER_DIR, { recursive: true });
10371
+ fs34.mkdirSync(CALIBER_DIR, { recursive: true });
10259
10372
  const filePath = historyFilePath();
10260
- fs33.appendFileSync(filePath, JSON.stringify(entry) + "\n");
10261
- const stat = fs33.statSync(filePath);
10373
+ fs34.appendFileSync(filePath, JSON.stringify(entry) + "\n");
10374
+ const stat = fs34.statSync(filePath);
10262
10375
  if (stat.size > TRIM_THRESHOLD * 120) {
10263
- const lines = fs33.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
10376
+ const lines = fs34.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
10264
10377
  if (lines.length > MAX_ENTRIES) {
10265
- fs33.writeFileSync(filePath, lines.slice(-MAX_ENTRIES).join("\n") + "\n");
10378
+ fs34.writeFileSync(filePath, lines.slice(-MAX_ENTRIES).join("\n") + "\n");
10266
10379
  }
10267
10380
  }
10268
10381
  } catch {
@@ -10271,7 +10384,7 @@ function recordScore(result, trigger) {
10271
10384
  function readScoreHistory() {
10272
10385
  const filePath = historyFilePath();
10273
10386
  try {
10274
- const content = fs33.readFileSync(filePath, "utf-8");
10387
+ const content = fs34.readFileSync(filePath, "utf-8");
10275
10388
  const entries = [];
10276
10389
  for (const line of content.split("\n")) {
10277
10390
  if (!line) continue;
@@ -10450,12 +10563,12 @@ async function initCommand(options) {
10450
10563
  }
10451
10564
  const { ensureBuiltinSkills: ensureBuiltinSkills2 } = await Promise.resolve().then(() => (init_builtin_skills(), builtin_skills_exports));
10452
10565
  for (const agent of targetAgent) {
10453
- if (agent === "claude" && !fs34.existsSync(".claude"))
10454
- fs34.mkdirSync(".claude", { recursive: true });
10455
- if (agent === "cursor" && !fs34.existsSync(".cursor"))
10456
- fs34.mkdirSync(".cursor", { recursive: true });
10457
- if (agent === "codex" && !fs34.existsSync(".agents"))
10458
- fs34.mkdirSync(".agents", { recursive: true });
10566
+ if (agent === "claude" && !fs35.existsSync(".claude"))
10567
+ fs35.mkdirSync(".claude", { recursive: true });
10568
+ if (agent === "cursor" && !fs35.existsSync(".cursor"))
10569
+ fs35.mkdirSync(".cursor", { recursive: true });
10570
+ if (agent === "codex" && !fs35.existsSync(".agents"))
10571
+ fs35.mkdirSync(".agents", { recursive: true });
10459
10572
  }
10460
10573
  const skillsWritten = ensureBuiltinSkills2();
10461
10574
  if (skillsWritten.length > 0) {
@@ -10544,7 +10657,7 @@ async function initCommand(options) {
10544
10657
  const claudeMdPath = "CLAUDE.md";
10545
10658
  let claudeContent = "";
10546
10659
  try {
10547
- claudeContent = fs34.readFileSync(claudeMdPath, "utf-8");
10660
+ claudeContent = fs35.readFileSync(claudeMdPath, "utf-8");
10548
10661
  } catch {
10549
10662
  }
10550
10663
  if (!claudeContent) {
@@ -10552,20 +10665,20 @@ async function initCommand(options) {
10552
10665
  `;
10553
10666
  }
10554
10667
  const updatedClaude = appendManagedBlocks2(claudeContent, "claude");
10555
- if (updatedClaude !== claudeContent || !fs34.existsSync(claudeMdPath)) {
10556
- fs34.writeFileSync(claudeMdPath, updatedClaude);
10668
+ if (updatedClaude !== claudeContent || !fs35.existsSync(claudeMdPath)) {
10669
+ fs35.writeFileSync(claudeMdPath, updatedClaude);
10557
10670
  console.log(` ${chalk14.green("\u2713")} CLAUDE.md \u2014 added Caliber sync instructions`);
10558
10671
  }
10559
10672
  if (targetAgent.includes("cursor")) {
10560
10673
  const rulesDir = path28.join(".cursor", "rules");
10561
- if (!fs34.existsSync(rulesDir)) fs34.mkdirSync(rulesDir, { recursive: true });
10674
+ if (!fs35.existsSync(rulesDir)) fs35.mkdirSync(rulesDir, { recursive: true });
10562
10675
  for (const rule of [
10563
10676
  getCursorPreCommitRule2(),
10564
10677
  getCursorLearningsRule2(),
10565
10678
  getCursorSyncRule2(),
10566
10679
  getCursorSetupRule2()
10567
10680
  ]) {
10568
- fs34.writeFileSync(path28.join(rulesDir, rule.filename), rule.content);
10681
+ fs35.writeFileSync(path28.join(rulesDir, rule.filename), rule.content);
10569
10682
  }
10570
10683
  console.log(` ${chalk14.green("\u2713")} Cursor rules \u2014 added Caliber sync rules`);
10571
10684
  }
@@ -10573,17 +10686,17 @@ async function initCommand(options) {
10573
10686
  const copilotPath = path28.join(".github", "copilot-instructions.md");
10574
10687
  let copilotContent = "";
10575
10688
  try {
10576
- copilotContent = fs34.readFileSync(copilotPath, "utf-8");
10689
+ copilotContent = fs35.readFileSync(copilotPath, "utf-8");
10577
10690
  } catch {
10578
10691
  }
10579
10692
  if (!copilotContent) {
10580
- fs34.mkdirSync(".github", { recursive: true });
10693
+ fs35.mkdirSync(".github", { recursive: true });
10581
10694
  copilotContent = `# ${path28.basename(process.cwd())}
10582
10695
  `;
10583
10696
  }
10584
10697
  const updatedCopilot = appendManagedBlocks2(copilotContent, "copilot");
10585
10698
  if (updatedCopilot !== copilotContent) {
10586
- fs34.writeFileSync(copilotPath, updatedCopilot);
10699
+ fs35.writeFileSync(copilotPath, updatedCopilot);
10587
10700
  console.log(` ${chalk14.green("\u2713")} Copilot instructions \u2014 added Caliber sync instructions`);
10588
10701
  }
10589
10702
  }
@@ -10930,7 +11043,7 @@ async function initCommand(options) {
10930
11043
  const { default: ora9 } = await import("ora");
10931
11044
  const writeSpinner = ora9("Writing config files...").start();
10932
11045
  try {
10933
- if (targetAgent.includes("codex") && !fs34.existsSync("AGENTS.md") && !generatedSetup.codex) {
11046
+ if (targetAgent.includes("codex") && !fs35.existsSync("AGENTS.md") && !generatedSetup.codex) {
10934
11047
  const claude = generatedSetup.claude;
10935
11048
  const cursor = generatedSetup.cursor;
10936
11049
  const agentRefs = [];
@@ -11120,7 +11233,7 @@ function undoCommand() {
11120
11233
 
11121
11234
  // src/commands/status.ts
11122
11235
  import chalk16 from "chalk";
11123
- import fs35 from "fs";
11236
+ import fs36 from "fs";
11124
11237
  init_config();
11125
11238
  init_resolve_caliber();
11126
11239
  async function statusCommand(options) {
@@ -11149,7 +11262,7 @@ async function statusCommand(options) {
11149
11262
  }
11150
11263
  console.log(` Files managed: ${chalk16.cyan(manifest.entries.length.toString())}`);
11151
11264
  for (const entry of manifest.entries) {
11152
- const exists = fs35.existsSync(entry.path);
11265
+ const exists = fs36.existsSync(entry.path);
11153
11266
  const icon = exists ? chalk16.green("\u2713") : chalk16.red("\u2717");
11154
11267
  console.log(` ${icon} ${entry.path} (${entry.action})`);
11155
11268
  }
@@ -11306,42 +11419,42 @@ async function regenerateCommand(options) {
11306
11419
  }
11307
11420
 
11308
11421
  // src/commands/score.ts
11309
- import fs36 from "fs";
11422
+ import fs37 from "fs";
11310
11423
  import os7 from "os";
11311
11424
  import path29 from "path";
11312
- import { execFileSync as execFileSync2 } from "child_process";
11425
+ import { execFileSync as execFileSync4 } from "child_process";
11313
11426
  import chalk18 from "chalk";
11314
11427
  init_resolve_caliber();
11315
11428
  var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".cursorrules", "CALIBER_LEARNINGS.md"];
11316
11429
  var CONFIG_DIRS = [".claude", ".cursor"];
11317
11430
  function scoreBaseRef(ref, target) {
11318
11431
  if (!/^[\w.\-/~^@{}]+$/.test(ref)) return null;
11319
- const tmpDir = fs36.mkdtempSync(path29.join(os7.tmpdir(), "caliber-compare-"));
11432
+ const tmpDir = fs37.mkdtempSync(path29.join(os7.tmpdir(), "caliber-compare-"));
11320
11433
  try {
11321
11434
  for (const file of CONFIG_FILES) {
11322
11435
  try {
11323
- const content = execFileSync2("git", ["show", `${ref}:${file}`], {
11436
+ const content = execFileSync4("git", ["show", `${ref}:${file}`], {
11324
11437
  encoding: "utf-8",
11325
11438
  stdio: ["pipe", "pipe", "pipe"]
11326
11439
  });
11327
- fs36.writeFileSync(path29.join(tmpDir, file), content);
11440
+ fs37.writeFileSync(path29.join(tmpDir, file), content);
11328
11441
  } catch {
11329
11442
  }
11330
11443
  }
11331
11444
  for (const dir of CONFIG_DIRS) {
11332
11445
  try {
11333
- const files = execFileSync2("git", ["ls-tree", "-r", "--name-only", ref, `${dir}/`], {
11446
+ const files = execFileSync4("git", ["ls-tree", "-r", "--name-only", ref, `${dir}/`], {
11334
11447
  encoding: "utf-8",
11335
11448
  stdio: ["pipe", "pipe", "pipe"]
11336
11449
  }).trim().split("\n").filter(Boolean);
11337
11450
  for (const file of files) {
11338
11451
  const filePath = path29.join(tmpDir, file);
11339
- fs36.mkdirSync(path29.dirname(filePath), { recursive: true });
11340
- const content = execFileSync2("git", ["show", `${ref}:${file}`], {
11452
+ fs37.mkdirSync(path29.dirname(filePath), { recursive: true });
11453
+ const content = execFileSync4("git", ["show", `${ref}:${file}`], {
11341
11454
  encoding: "utf-8",
11342
11455
  stdio: ["pipe", "pipe", "pipe"]
11343
11456
  });
11344
- fs36.writeFileSync(filePath, content);
11457
+ fs37.writeFileSync(filePath, content);
11345
11458
  }
11346
11459
  } catch {
11347
11460
  }
@@ -11351,7 +11464,7 @@ function scoreBaseRef(ref, target) {
11351
11464
  } catch {
11352
11465
  return null;
11353
11466
  } finally {
11354
- fs36.rmSync(tmpDir, { recursive: true, force: true });
11467
+ fs37.rmSync(tmpDir, { recursive: true, force: true });
11355
11468
  }
11356
11469
  }
11357
11470
  async function scoreCommand(options) {
@@ -11444,10 +11557,11 @@ async function scoreCommand(options) {
11444
11557
  }
11445
11558
 
11446
11559
  // src/commands/refresh.ts
11447
- import fs41 from "fs";
11560
+ import fs42 from "fs";
11448
11561
  import path34 from "path";
11449
11562
  import chalk19 from "chalk";
11450
11563
  import ora6 from "ora";
11564
+ import pLimit from "p-limit";
11451
11565
 
11452
11566
  // src/lib/git-diff.ts
11453
11567
  import { execSync as execSync15 } from "child_process";
@@ -11560,13 +11674,13 @@ function scopeDiffToDir(diff, dir, allConfigDirs) {
11560
11674
 
11561
11675
  // src/writers/refresh.ts
11562
11676
  init_pre_commit_block();
11563
- import fs37 from "fs";
11677
+ import fs38 from "fs";
11564
11678
  import path30 from "path";
11565
11679
  function writeFileGroup(groupDir, files) {
11566
- fs37.mkdirSync(groupDir, { recursive: true });
11680
+ fs38.mkdirSync(groupDir, { recursive: true });
11567
11681
  return files.map((file) => {
11568
11682
  const filePath = path30.join(groupDir, file.filename);
11569
- fs37.writeFileSync(filePath, file.content);
11683
+ fs38.writeFileSync(filePath, file.content);
11570
11684
  return filePath.replace(/\\/g, "/");
11571
11685
  });
11572
11686
  }
@@ -11575,18 +11689,18 @@ function writeRefreshDocs(docs, dir = ".") {
11575
11689
  const p = (relPath) => (dir === "." ? relPath : path30.join(dir, relPath)).replace(/\\/g, "/");
11576
11690
  const ensureParent = (filePath) => {
11577
11691
  const parent = path30.dirname(filePath);
11578
- if (parent !== "." && !fs37.existsSync(parent)) fs37.mkdirSync(parent, { recursive: true });
11692
+ if (parent !== "." && !fs38.existsSync(parent)) fs38.mkdirSync(parent, { recursive: true });
11579
11693
  };
11580
11694
  if (docs.agentsMd) {
11581
11695
  const filePath = p("AGENTS.md");
11582
11696
  ensureParent(filePath);
11583
- fs37.writeFileSync(filePath, appendManagedBlocks(docs.agentsMd, "codex"));
11697
+ fs38.writeFileSync(filePath, appendManagedBlocks(docs.agentsMd, "codex"));
11584
11698
  written.push(filePath);
11585
11699
  }
11586
11700
  if (docs.claudeMd) {
11587
11701
  const filePath = p("CLAUDE.md");
11588
11702
  ensureParent(filePath);
11589
- fs37.writeFileSync(filePath, appendManagedBlocks(docs.claudeMd));
11703
+ fs38.writeFileSync(filePath, appendManagedBlocks(docs.claudeMd));
11590
11704
  written.push(filePath);
11591
11705
  }
11592
11706
  if (docs.claudeRules) {
@@ -11595,13 +11709,13 @@ function writeRefreshDocs(docs, dir = ".") {
11595
11709
  if (docs.readmeMd) {
11596
11710
  const filePath = p("README.md");
11597
11711
  ensureParent(filePath);
11598
- fs37.writeFileSync(filePath, docs.readmeMd);
11712
+ fs38.writeFileSync(filePath, docs.readmeMd);
11599
11713
  written.push(filePath);
11600
11714
  }
11601
11715
  if (docs.cursorrules) {
11602
11716
  const filePath = p(".cursorrules");
11603
11717
  ensureParent(filePath);
11604
- fs37.writeFileSync(filePath, docs.cursorrules);
11718
+ fs38.writeFileSync(filePath, docs.cursorrules);
11605
11719
  written.push(filePath);
11606
11720
  }
11607
11721
  if (docs.cursorRules) {
@@ -11610,7 +11724,7 @@ function writeRefreshDocs(docs, dir = ".") {
11610
11724
  if (docs.copilotInstructions) {
11611
11725
  const filePath = p(path30.join(".github", "copilot-instructions.md"));
11612
11726
  ensureParent(filePath);
11613
- fs37.writeFileSync(filePath, appendManagedBlocks(docs.copilotInstructions, "copilot"));
11727
+ fs38.writeFileSync(filePath, appendManagedBlocks(docs.copilotInstructions, "copilot"));
11614
11728
  written.push(filePath);
11615
11729
  }
11616
11730
  if (docs.copilotInstructionFiles) {
@@ -11752,7 +11866,7 @@ Changed files: ${diff.changedFiles.join(", ")}`);
11752
11866
  }
11753
11867
 
11754
11868
  // src/learner/writer.ts
11755
- import fs38 from "fs";
11869
+ import fs39 from "fs";
11756
11870
  import path31 from "path";
11757
11871
 
11758
11872
  // src/learner/utils.ts
@@ -11870,8 +11984,8 @@ function deduplicateLearnedItems(existing, incoming) {
11870
11984
  }
11871
11985
  function writeLearnedSectionTo(filePath, header, existing, incoming, mode) {
11872
11986
  const { merged, newCount, newItems } = deduplicateLearnedItems(existing, incoming);
11873
- fs38.writeFileSync(filePath, header + merged + "\n");
11874
- if (mode) fs38.chmodSync(filePath, mode);
11987
+ fs39.writeFileSync(filePath, header + merged + "\n");
11988
+ if (mode) fs39.chmodSync(filePath, mode);
11875
11989
  return { newCount, newItems };
11876
11990
  }
11877
11991
  function writeLearnedSection(content) {
@@ -11879,11 +11993,11 @@ function writeLearnedSection(content) {
11879
11993
  }
11880
11994
  function writeLearnedSkill(skill) {
11881
11995
  const skillDir = path31.join(".claude", "skills", skill.name);
11882
- if (!fs38.existsSync(skillDir)) fs38.mkdirSync(skillDir, { recursive: true });
11996
+ if (!fs39.existsSync(skillDir)) fs39.mkdirSync(skillDir, { recursive: true });
11883
11997
  const skillPath = path31.join(skillDir, "SKILL.md");
11884
- if (!skill.isNew && fs38.existsSync(skillPath)) {
11885
- const existing = fs38.readFileSync(skillPath, "utf-8");
11886
- fs38.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
11998
+ if (!skill.isNew && fs39.existsSync(skillPath)) {
11999
+ const existing = fs39.readFileSync(skillPath, "utf-8");
12000
+ fs39.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
11887
12001
  } else {
11888
12002
  const frontmatter = [
11889
12003
  "---",
@@ -11892,12 +12006,12 @@ function writeLearnedSkill(skill) {
11892
12006
  "---",
11893
12007
  ""
11894
12008
  ].join("\n");
11895
- fs38.writeFileSync(skillPath, frontmatter + skill.content);
12009
+ fs39.writeFileSync(skillPath, frontmatter + skill.content);
11896
12010
  }
11897
12011
  return skillPath;
11898
12012
  }
11899
12013
  function writePersonalLearnedSection(content) {
11900
- if (!fs38.existsSync(AUTH_DIR)) fs38.mkdirSync(AUTH_DIR, { recursive: true });
12014
+ if (!fs39.existsSync(AUTH_DIR)) fs39.mkdirSync(AUTH_DIR, { recursive: true });
11901
12015
  return writeLearnedSectionTo(PERSONAL_LEARNINGS_FILE, PERSONAL_LEARNINGS_HEADER, readPersonalLearnings(), content, 384);
11902
12016
  }
11903
12017
  function addLearning(bullet, scope = "project") {
@@ -11910,38 +12024,38 @@ function addLearning(bullet, scope = "project") {
11910
12024
  return { file: LEARNINGS_FILE, added: result.newCount > 0 };
11911
12025
  }
11912
12026
  function readPersonalLearnings() {
11913
- if (!fs38.existsSync(PERSONAL_LEARNINGS_FILE)) return null;
11914
- const content = fs38.readFileSync(PERSONAL_LEARNINGS_FILE, "utf-8");
12027
+ if (!fs39.existsSync(PERSONAL_LEARNINGS_FILE)) return null;
12028
+ const content = fs39.readFileSync(PERSONAL_LEARNINGS_FILE, "utf-8");
11915
12029
  const bullets = content.split("\n").filter((l) => l.startsWith("- ")).join("\n");
11916
12030
  return bullets || null;
11917
12031
  }
11918
12032
  function readLearnedSection() {
11919
- if (fs38.existsSync(LEARNINGS_FILE)) {
11920
- const content2 = fs38.readFileSync(LEARNINGS_FILE, "utf-8");
12033
+ if (fs39.existsSync(LEARNINGS_FILE)) {
12034
+ const content2 = fs39.readFileSync(LEARNINGS_FILE, "utf-8");
11921
12035
  const bullets = content2.split("\n").filter((l) => l.startsWith("- ")).join("\n");
11922
12036
  return bullets || null;
11923
12037
  }
11924
12038
  const claudeMdPath = "CLAUDE.md";
11925
- if (!fs38.existsSync(claudeMdPath)) return null;
11926
- const content = fs38.readFileSync(claudeMdPath, "utf-8");
12039
+ if (!fs39.existsSync(claudeMdPath)) return null;
12040
+ const content = fs39.readFileSync(claudeMdPath, "utf-8");
11927
12041
  const startIdx = content.indexOf(LEARNED_START);
11928
12042
  const endIdx = content.indexOf(LEARNED_END);
11929
12043
  if (startIdx === -1 || endIdx === -1) return null;
11930
12044
  return content.slice(startIdx + LEARNED_START.length, endIdx).trim() || null;
11931
12045
  }
11932
12046
  function migrateInlineLearnings() {
11933
- if (fs38.existsSync(LEARNINGS_FILE)) return false;
12047
+ if (fs39.existsSync(LEARNINGS_FILE)) return false;
11934
12048
  const claudeMdPath = "CLAUDE.md";
11935
- if (!fs38.existsSync(claudeMdPath)) return false;
11936
- const content = fs38.readFileSync(claudeMdPath, "utf-8");
12049
+ if (!fs39.existsSync(claudeMdPath)) return false;
12050
+ const content = fs39.readFileSync(claudeMdPath, "utf-8");
11937
12051
  const startIdx = content.indexOf(LEARNED_START);
11938
12052
  const endIdx = content.indexOf(LEARNED_END);
11939
12053
  if (startIdx === -1 || endIdx === -1) return false;
11940
12054
  const section = content.slice(startIdx + LEARNED_START.length, endIdx).trim();
11941
12055
  if (!section) return false;
11942
- fs38.writeFileSync(LEARNINGS_FILE, LEARNINGS_HEADER + section + "\n");
12056
+ fs39.writeFileSync(LEARNINGS_FILE, LEARNINGS_HEADER + section + "\n");
11943
12057
  const cleaned = content.slice(0, startIdx) + content.slice(endIdx + LEARNED_END.length);
11944
- fs38.writeFileSync(claudeMdPath, cleaned.replace(/\n{3,}/g, "\n\n").trim() + "\n");
12058
+ fs39.writeFileSync(claudeMdPath, cleaned.replace(/\n{3,}/g, "\n\n").trim() + "\n");
11945
12059
  return true;
11946
12060
  }
11947
12061
 
@@ -11951,7 +12065,7 @@ init_resolve_caliber();
11951
12065
  init_builtin_skills();
11952
12066
 
11953
12067
  // src/lib/config-discovery.ts
11954
- import fs39 from "fs";
12068
+ import fs40 from "fs";
11955
12069
  import path32 from "path";
11956
12070
  var CONFIG_FILE_MARKERS = [
11957
12071
  "CLAUDE.md",
@@ -11978,11 +12092,11 @@ var IGNORE_DIRS3 = /* @__PURE__ */ new Set([
11978
12092
  var MAX_DEPTH = 4;
11979
12093
  function hasConfigFiles(dir) {
11980
12094
  for (const marker of CONFIG_FILE_MARKERS) {
11981
- if (fs39.existsSync(path32.join(dir, marker))) return true;
12095
+ if (fs40.existsSync(path32.join(dir, marker))) return true;
11982
12096
  }
11983
12097
  for (const marker of CONFIG_DIR_MARKERS) {
11984
12098
  const markerPath = path32.join(dir, marker);
11985
- if (fs39.existsSync(markerPath) && fs39.statSync(markerPath).isDirectory()) return true;
12099
+ if (fs40.existsSync(markerPath) && fs40.statSync(markerPath).isDirectory()) return true;
11986
12100
  }
11987
12101
  return false;
11988
12102
  }
@@ -11999,7 +12113,7 @@ function walkForConfigs(baseDir, currentDir, depth, result) {
11999
12113
  if (depth >= MAX_DEPTH) return;
12000
12114
  let entries;
12001
12115
  try {
12002
- entries = fs39.readdirSync(currentDir, { withFileTypes: true });
12116
+ entries = fs40.readdirSync(currentDir, { withFileTypes: true });
12003
12117
  } catch {
12004
12118
  return;
12005
12119
  }
@@ -12018,8 +12132,8 @@ function walkForConfigs(baseDir, currentDir, depth, result) {
12018
12132
  // src/commands/refresh.ts
12019
12133
  function writeRefreshError(error) {
12020
12134
  try {
12021
- if (!fs41.existsSync(CALIBER_DIR)) fs41.mkdirSync(CALIBER_DIR, { recursive: true });
12022
- fs41.writeFileSync(
12135
+ if (!fs42.existsSync(CALIBER_DIR)) fs42.mkdirSync(CALIBER_DIR, { recursive: true });
12136
+ fs42.writeFileSync(
12023
12137
  REFRESH_LAST_ERROR_FILE,
12024
12138
  JSON.stringify(
12025
12139
  {
@@ -12038,15 +12152,15 @@ function writeRefreshError(error) {
12038
12152
  }
12039
12153
  function readRefreshError() {
12040
12154
  try {
12041
- if (!fs41.existsSync(REFRESH_LAST_ERROR_FILE)) return null;
12042
- return JSON.parse(fs41.readFileSync(REFRESH_LAST_ERROR_FILE, "utf-8"));
12155
+ if (!fs42.existsSync(REFRESH_LAST_ERROR_FILE)) return null;
12156
+ return JSON.parse(fs42.readFileSync(REFRESH_LAST_ERROR_FILE, "utf-8"));
12043
12157
  } catch {
12044
12158
  return null;
12045
12159
  }
12046
12160
  }
12047
12161
  function clearRefreshError() {
12048
12162
  try {
12049
- if (fs41.existsSync(REFRESH_LAST_ERROR_FILE)) fs41.unlinkSync(REFRESH_LAST_ERROR_FILE);
12163
+ if (fs42.existsSync(REFRESH_LAST_ERROR_FILE)) fs42.unlinkSync(REFRESH_LAST_ERROR_FILE);
12050
12164
  } catch {
12051
12165
  }
12052
12166
  }
@@ -12066,11 +12180,11 @@ function log2(quiet, ...args) {
12066
12180
  function discoverGitRepos(parentDir) {
12067
12181
  const repos = [];
12068
12182
  try {
12069
- const entries = fs41.readdirSync(parentDir, { withFileTypes: true });
12183
+ const entries = fs42.readdirSync(parentDir, { withFileTypes: true });
12070
12184
  for (const entry of entries) {
12071
12185
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
12072
12186
  const childPath = path34.join(parentDir, entry.name);
12073
- if (fs41.existsSync(path34.join(childPath, ".git"))) {
12187
+ if (fs42.existsSync(path34.join(childPath, ".git"))) {
12074
12188
  repos.push(childPath);
12075
12189
  }
12076
12190
  }
@@ -12101,12 +12215,15 @@ function collectFilesToWrite(updatedDocs, dir = ".") {
12101
12215
  return files;
12102
12216
  }
12103
12217
  var REFRESH_COOLDOWN_MS = 3e4;
12218
+ var PARALLEL_DIR_CONCURRENCY = 4;
12104
12219
  async function refreshDir(repoDir, dir, diff, options) {
12105
12220
  const quiet = !!options.quiet;
12221
+ const suppress = !!options.suppressSpinner;
12222
+ const effectiveQuiet = quiet || suppress;
12106
12223
  const prefix = options.label ? `${chalk19.bold(options.label)} ` : "";
12107
12224
  const absDir = dir === "." ? repoDir : path34.resolve(repoDir, dir);
12108
12225
  const scope = dir === "." ? void 0 : dir;
12109
- const spinner = quiet ? null : ora6(`${prefix}Analyzing changes...`).start();
12226
+ const spinner = effectiveQuiet ? null : ora6(`${prefix}Analyzing changes...`).start();
12110
12227
  const learnedSection = readLearnedSection();
12111
12228
  const fingerprint = await collectFingerprint(absDir);
12112
12229
  const existingDocs = fingerprint.existingConfigs;
@@ -12155,7 +12272,7 @@ async function refreshDir(repoDir, dir, diff, options) {
12155
12272
  }
12156
12273
  if (!response.docsUpdated || response.docsUpdated.length === 0) {
12157
12274
  spinner?.succeed(`${prefix}No doc updates needed`);
12158
- return { written: [] };
12275
+ return { written: [], fileChanges: [], syncedAgents: [], changesSummary: null };
12159
12276
  }
12160
12277
  if (options.dryRun) {
12161
12278
  spinner?.info(`${prefix}Dry run \u2014 would update:`);
@@ -12166,14 +12283,14 @@ async function refreshDir(repoDir, dir, diff, options) {
12166
12283
  console.log(chalk19.dim(`
12167
12284
  ${response.changesSummary}`));
12168
12285
  }
12169
- return { written: [] };
12286
+ return { written: [], fileChanges: [], syncedAgents: [], changesSummary: null };
12170
12287
  }
12171
12288
  const allFilesToWrite = collectFilesToWrite(response.updatedDocs, dir);
12172
12289
  const preRefreshContents = /* @__PURE__ */ new Map();
12173
12290
  for (const filePath of allFilesToWrite) {
12174
12291
  const fullPath = path34.resolve(repoDir, filePath);
12175
12292
  try {
12176
- preRefreshContents.set(filePath, fs41.readFileSync(fullPath, "utf-8"));
12293
+ preRefreshContents.set(filePath, fs42.readFileSync(fullPath, "utf-8"));
12177
12294
  } catch {
12178
12295
  preRefreshContents.set(filePath, null);
12179
12296
  }
@@ -12192,43 +12309,47 @@ async function refreshDir(repoDir, dir, diff, options) {
12192
12309
  const fullPath = path34.resolve(repoDir, filePath);
12193
12310
  if (content === null) {
12194
12311
  try {
12195
- fs41.unlinkSync(fullPath);
12312
+ fs42.unlinkSync(fullPath);
12196
12313
  } catch {
12197
12314
  }
12198
12315
  } else {
12199
- fs41.writeFileSync(fullPath, content);
12316
+ fs42.writeFileSync(fullPath, content);
12200
12317
  }
12201
12318
  }
12202
12319
  spinner?.warn(
12203
12320
  `${prefix}Refresh reverted \u2014 score would drop from ${preScore.score} to ${postScore.score}`
12204
12321
  );
12205
- log2(quiet, chalk19.dim(` Config quality gate prevented a regression. No files were changed.`));
12206
- return { written: [] };
12322
+ log2(
12323
+ effectiveQuiet,
12324
+ chalk19.dim(` Config quality gate prevented a regression. No files were changed.`)
12325
+ );
12326
+ return { written: [], fileChanges: [], syncedAgents: [], changesSummary: null };
12207
12327
  }
12208
12328
  recordScore(postScore, "refresh");
12209
12329
  }
12210
12330
  spinner?.succeed(`${prefix}Updated ${written.length} doc${written.length === 1 ? "" : "s"}`);
12211
- const fileChangesMap = new Map(
12212
- (response.fileChanges || []).map((fc) => [
12213
- fc.file,
12214
- fc.description
12215
- ])
12216
- );
12217
- for (const file of written) {
12218
- const desc = fileChangesMap.get(file);
12219
- const suffix = desc ? chalk19.dim(` \u2014 ${desc}`) : "";
12220
- log2(quiet, ` ${chalk19.green("\u2713")} ${file}${suffix}`);
12221
- }
12222
- const agents = detectSyncedAgents(written);
12223
- if (agents.length > 1) {
12224
- log2(quiet, chalk19.cyan(`
12225
- ${agents.length} agent formats in sync (${agents.join(", ")})`));
12226
- }
12227
- if (response.changesSummary) {
12228
- log2(quiet, chalk19.dim(`
12331
+ const fileChanges = response.fileChanges || [];
12332
+ const fileChangesMap = new Map(fileChanges.map((fc) => [fc.file, fc.description]));
12333
+ const syncedAgents = detectSyncedAgents(written);
12334
+ if (!suppress) {
12335
+ for (const file of written) {
12336
+ const desc = fileChangesMap.get(file);
12337
+ const suffix = desc ? chalk19.dim(` \u2014 ${desc}`) : "";
12338
+ log2(effectiveQuiet, ` ${chalk19.green("\u2713")} ${file}${suffix}`);
12339
+ }
12340
+ if (syncedAgents.length > 1) {
12341
+ log2(
12342
+ effectiveQuiet,
12343
+ chalk19.cyan(`
12344
+ ${syncedAgents.length} agent formats in sync (${syncedAgents.join(", ")})`)
12345
+ );
12346
+ }
12347
+ if (response.changesSummary) {
12348
+ log2(effectiveQuiet, chalk19.dim(`
12229
12349
  ${response.changesSummary}`));
12350
+ }
12230
12351
  }
12231
- return { written };
12352
+ return { written, fileChanges, syncedAgents, changesSummary: response.changesSummary };
12232
12353
  }
12233
12354
  async function refreshSingleRepo(repoDir, options) {
12234
12355
  const quiet = !!options.quiet;
@@ -12260,21 +12381,57 @@ async function refreshSingleRepo(repoDir, options) {
12260
12381
  } else {
12261
12382
  log2(quiet, chalk19.dim(`${prefix}Found configs in ${configDirs.length} directories
12262
12383
  `));
12384
+ const dirsWithChanges = configDirs.map((dir) => ({ dir, scopedDiff: scopeDiffToDir(diff, dir, configDirs) })).filter(({ scopedDiff }) => scopedDiff.hasChanges);
12385
+ const parallelSpinner = quiet ? null : ora6(
12386
+ `${prefix}Refreshing ${dirsWithChanges.length} director${dirsWithChanges.length === 1 ? "y" : "ies"}...`
12387
+ ).start();
12388
+ const limit = pLimit(PARALLEL_DIR_CONCURRENCY);
12389
+ const results = await Promise.allSettled(
12390
+ dirsWithChanges.map(({ dir, scopedDiff }) => {
12391
+ const dirLabel = dir === "." ? "root" : dir;
12392
+ return limit(
12393
+ () => refreshDir(repoDir, dir, scopedDiff, {
12394
+ ...options,
12395
+ suppressSpinner: true,
12396
+ label: dirLabel
12397
+ })
12398
+ );
12399
+ })
12400
+ );
12401
+ parallelSpinner?.stop();
12263
12402
  let hadFailure = false;
12264
- for (const dir of configDirs) {
12265
- const scopedDiff = scopeDiffToDir(diff, dir, configDirs);
12266
- if (!scopedDiff.hasChanges) continue;
12403
+ for (const [i, result] of results.entries()) {
12404
+ const { dir } = dirsWithChanges[i];
12267
12405
  const dirLabel = dir === "." ? "root" : dir;
12268
- try {
12269
- await refreshDir(repoDir, dir, scopedDiff, { ...options, label: dirLabel });
12270
- } catch (err) {
12406
+ if (result.status === "rejected") {
12271
12407
  hadFailure = true;
12272
12408
  log2(
12273
12409
  quiet,
12274
12410
  chalk19.yellow(
12275
- ` ${dirLabel}: refresh failed \u2014 ${err instanceof Error ? err.message : "unknown error"}`
12411
+ ` ${dirLabel}: refresh failed \u2014 ${result.reason instanceof Error ? result.reason.message : "unknown error"}`
12276
12412
  )
12277
12413
  );
12414
+ } else {
12415
+ const { written, fileChanges, syncedAgents, changesSummary } = result.value;
12416
+ const fileChangesMap = new Map(fileChanges.map((fc) => [fc.file, fc.description]));
12417
+ for (const file of written) {
12418
+ const desc = fileChangesMap.get(file);
12419
+ const suffix = desc ? chalk19.dim(` \u2014 ${desc}`) : "";
12420
+ log2(quiet, ` ${chalk19.green("\u2713")} ${dirLabel}/${file}${suffix}`);
12421
+ }
12422
+ if (syncedAgents.length > 1) {
12423
+ log2(
12424
+ quiet,
12425
+ chalk19.cyan(
12426
+ `
12427
+ ${syncedAgents.length} agent formats in sync (${syncedAgents.join(", ")})`
12428
+ )
12429
+ );
12430
+ }
12431
+ if (changesSummary) {
12432
+ log2(quiet, chalk19.dim(`
12433
+ ${changesSummary}`));
12434
+ }
12278
12435
  }
12279
12436
  }
12280
12437
  if (hadFailure) {
@@ -12366,7 +12523,7 @@ async function refreshCommand(options) {
12366
12523
 
12367
12524
  // src/commands/hooks.ts
12368
12525
  import chalk20 from "chalk";
12369
- import fs42 from "fs";
12526
+ import fs43 from "fs";
12370
12527
  var HOOKS = [
12371
12528
  {
12372
12529
  id: "session-end",
@@ -12430,11 +12587,11 @@ async function hooksCommand(options) {
12430
12587
  console.log(chalk20.green(" \u2713") + ` ${hook.label} enabled`);
12431
12588
  }
12432
12589
  }
12433
- if (fs42.existsSync(".claude")) {
12590
+ if (fs43.existsSync(".claude")) {
12434
12591
  const r = installLearningHooks();
12435
12592
  if (r.installed) console.log(chalk20.green(" \u2713") + " Claude Code learning hooks enabled");
12436
12593
  }
12437
- if (fs42.existsSync(".cursor")) {
12594
+ if (fs43.existsSync(".cursor")) {
12438
12595
  const r = installCursorLearningHooks();
12439
12596
  if (r.installed) console.log(chalk20.green(" \u2713") + " Cursor learning hooks enabled");
12440
12597
  }
@@ -12602,7 +12759,7 @@ async function configCommand() {
12602
12759
  }
12603
12760
 
12604
12761
  // src/commands/learn.ts
12605
- import fs46 from "fs";
12762
+ import fs47 from "fs";
12606
12763
  import path38 from "path";
12607
12764
  import chalk23 from "chalk";
12608
12765
 
@@ -12634,7 +12791,7 @@ function readStdin() {
12634
12791
  }
12635
12792
 
12636
12793
  // src/learner/storage.ts
12637
- import fs43 from "fs";
12794
+ import fs44 from "fs";
12638
12795
  import path35 from "path";
12639
12796
  var MAX_RESPONSE_LENGTH = 2e3;
12640
12797
  var MAX_PROMPT_LENGTH = 2e3;
@@ -12646,8 +12803,8 @@ var DEFAULT_STATE = {
12646
12803
  lastAnalysisEventCount: 0
12647
12804
  };
12648
12805
  function ensureLearningDir() {
12649
- if (!fs43.existsSync(getLearningDir())) {
12650
- fs43.mkdirSync(getLearningDir(), { recursive: true });
12806
+ if (!fs44.existsSync(getLearningDir())) {
12807
+ fs44.mkdirSync(getLearningDir(), { recursive: true });
12651
12808
  }
12652
12809
  }
12653
12810
  function sessionFilePath() {
@@ -12663,9 +12820,9 @@ function truncateResponse(response) {
12663
12820
  }
12664
12821
  function trimSessionFileIfNeeded(filePath) {
12665
12822
  try {
12666
- const stat = fs43.statSync(filePath);
12823
+ const stat = fs44.statSync(filePath);
12667
12824
  if (stat.size > MAX_SESSION_FILE_BYTES) {
12668
- fs43.writeFileSync(filePath, "");
12825
+ fs44.writeFileSync(filePath, "");
12669
12826
  resetState();
12670
12827
  return;
12671
12828
  }
@@ -12674,10 +12831,10 @@ function trimSessionFileIfNeeded(filePath) {
12674
12831
  }
12675
12832
  const state = readState2();
12676
12833
  if (state.eventCount + 1 > LEARNING_MAX_EVENTS) {
12677
- const lines = fs43.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
12834
+ const lines = fs44.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
12678
12835
  if (lines.length > LEARNING_MAX_EVENTS) {
12679
12836
  const kept = lines.slice(lines.length - LEARNING_MAX_EVENTS);
12680
- fs43.writeFileSync(filePath, kept.join("\n") + "\n");
12837
+ fs44.writeFileSync(filePath, kept.join("\n") + "\n");
12681
12838
  }
12682
12839
  }
12683
12840
  }
@@ -12685,7 +12842,7 @@ function appendEvent(event) {
12685
12842
  ensureLearningDir();
12686
12843
  const truncated = { ...event, tool_response: truncateResponse(event.tool_response) };
12687
12844
  const filePath = sessionFilePath();
12688
- fs43.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
12845
+ fs44.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
12689
12846
  trimSessionFileIfNeeded(filePath);
12690
12847
  }
12691
12848
  function appendPromptEvent(event) {
@@ -12695,22 +12852,22 @@ function appendPromptEvent(event) {
12695
12852
  prompt_content: event.prompt_content.length > MAX_PROMPT_LENGTH ? event.prompt_content.slice(0, MAX_PROMPT_LENGTH) : event.prompt_content
12696
12853
  };
12697
12854
  const filePath = sessionFilePath();
12698
- fs43.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
12855
+ fs44.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
12699
12856
  trimSessionFileIfNeeded(filePath);
12700
12857
  }
12701
12858
  function readAllEvents() {
12702
12859
  const filePath = sessionFilePath();
12703
12860
  try {
12704
- const stat = fs43.statSync(filePath);
12861
+ const stat = fs44.statSync(filePath);
12705
12862
  if (stat.size > MAX_SESSION_FILE_BYTES) {
12706
- fs43.writeFileSync(filePath, "");
12863
+ fs44.writeFileSync(filePath, "");
12707
12864
  resetState();
12708
12865
  return [];
12709
12866
  }
12710
12867
  } catch {
12711
12868
  return [];
12712
12869
  }
12713
- const lines = fs43.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
12870
+ const lines = fs44.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
12714
12871
  const events = [];
12715
12872
  for (const line of lines) {
12716
12873
  try {
@@ -12723,33 +12880,33 @@ function readAllEvents() {
12723
12880
  function getEventCount() {
12724
12881
  const filePath = sessionFilePath();
12725
12882
  try {
12726
- const stat = fs43.statSync(filePath);
12883
+ const stat = fs44.statSync(filePath);
12727
12884
  if (stat.size > MAX_SESSION_FILE_BYTES) return 0;
12728
12885
  } catch {
12729
12886
  return 0;
12730
12887
  }
12731
- const content = fs43.readFileSync(filePath, "utf-8");
12888
+ const content = fs44.readFileSync(filePath, "utf-8");
12732
12889
  return content.split("\n").filter(Boolean).length;
12733
12890
  }
12734
12891
  function clearSession() {
12735
12892
  const filePath = sessionFilePath();
12736
12893
  try {
12737
- fs43.writeFileSync(filePath, "");
12894
+ fs44.writeFileSync(filePath, "");
12738
12895
  } catch {
12739
12896
  }
12740
12897
  }
12741
12898
  function readState2() {
12742
12899
  const filePath = stateFilePath();
12743
- if (!fs43.existsSync(filePath)) return { ...DEFAULT_STATE };
12900
+ if (!fs44.existsSync(filePath)) return { ...DEFAULT_STATE };
12744
12901
  try {
12745
- return JSON.parse(fs43.readFileSync(filePath, "utf-8"));
12902
+ return JSON.parse(fs44.readFileSync(filePath, "utf-8"));
12746
12903
  } catch {
12747
12904
  return { ...DEFAULT_STATE };
12748
12905
  }
12749
12906
  }
12750
12907
  function writeState2(state) {
12751
12908
  ensureLearningDir();
12752
- fs43.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
12909
+ fs44.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
12753
12910
  }
12754
12911
  function resetState() {
12755
12912
  writeState2({ ...DEFAULT_STATE });
@@ -12762,11 +12919,11 @@ function lockFilePath() {
12762
12919
  function acquireFinalizeLock() {
12763
12920
  ensureLearningDir();
12764
12921
  const lockPath = lockFilePath();
12765
- if (fs43.existsSync(lockPath)) {
12922
+ if (fs44.existsSync(lockPath)) {
12766
12923
  try {
12767
- const stat = fs43.statSync(lockPath);
12924
+ const stat = fs44.statSync(lockPath);
12768
12925
  if (Date.now() - stat.mtimeMs < LOCK_STALE_MS) {
12769
- const pid = parseInt(fs43.readFileSync(lockPath, "utf-8").trim(), 10);
12926
+ const pid = parseInt(fs44.readFileSync(lockPath, "utf-8").trim(), 10);
12770
12927
  if (!isNaN(pid) && isProcessAlive(pid)) {
12771
12928
  return false;
12772
12929
  }
@@ -12774,12 +12931,12 @@ function acquireFinalizeLock() {
12774
12931
  } catch {
12775
12932
  }
12776
12933
  try {
12777
- fs43.unlinkSync(lockPath);
12934
+ fs44.unlinkSync(lockPath);
12778
12935
  } catch {
12779
12936
  }
12780
12937
  }
12781
12938
  try {
12782
- fs43.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
12939
+ fs44.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
12783
12940
  return true;
12784
12941
  } catch {
12785
12942
  return false;
@@ -12796,13 +12953,13 @@ function isProcessAlive(pid) {
12796
12953
  function releaseFinalizeLock() {
12797
12954
  const lockPath = lockFilePath();
12798
12955
  try {
12799
- if (fs43.existsSync(lockPath)) fs43.unlinkSync(lockPath);
12956
+ if (fs44.existsSync(lockPath)) fs44.unlinkSync(lockPath);
12800
12957
  } catch {
12801
12958
  }
12802
12959
  }
12803
12960
 
12804
12961
  // src/lib/notifications.ts
12805
- import fs44 from "fs";
12962
+ import fs45 from "fs";
12806
12963
  import path36 from "path";
12807
12964
  import chalk22 from "chalk";
12808
12965
  function notificationFilePath() {
@@ -12811,15 +12968,15 @@ function notificationFilePath() {
12811
12968
  function writeFinalizeSummary(summary) {
12812
12969
  try {
12813
12970
  ensureLearningDir();
12814
- fs44.writeFileSync(notificationFilePath(), JSON.stringify(summary, null, 2));
12971
+ fs45.writeFileSync(notificationFilePath(), JSON.stringify(summary, null, 2));
12815
12972
  } catch {
12816
12973
  }
12817
12974
  }
12818
12975
  function checkPendingNotifications() {
12819
12976
  try {
12820
- if (!fs44.existsSync(notificationFilePath())) return;
12821
- const raw = fs44.readFileSync(notificationFilePath(), "utf-8");
12822
- fs44.unlinkSync(notificationFilePath());
12977
+ if (!fs45.existsSync(notificationFilePath())) return;
12978
+ const raw = fs45.readFileSync(notificationFilePath(), "utf-8");
12979
+ fs45.unlinkSync(notificationFilePath());
12823
12980
  const summary = JSON.parse(raw);
12824
12981
  if (!summary.newItemCount || summary.newItemCount === 0) return;
12825
12982
  const wasteLabel = summary.wasteTokens > 0 ? ` (~${summary.wasteTokens.toLocaleString()} wasted tokens captured)` : "";
@@ -12835,7 +12992,7 @@ function checkPendingNotifications() {
12835
12992
  console.log("");
12836
12993
  } catch {
12837
12994
  try {
12838
- fs44.unlinkSync(notificationFilePath());
12995
+ fs45.unlinkSync(notificationFilePath());
12839
12996
  } catch {
12840
12997
  }
12841
12998
  }
@@ -12987,7 +13144,7 @@ function calculateSessionWaste(events) {
12987
13144
  init_config();
12988
13145
 
12989
13146
  // src/learner/roi.ts
12990
- import fs45 from "fs";
13147
+ import fs46 from "fs";
12991
13148
  import path37 from "path";
12992
13149
  var DEFAULT_TOTALS = {
12993
13150
  totalWasteTokens: 0,
@@ -13006,15 +13163,15 @@ function roiFilePath() {
13006
13163
  }
13007
13164
  function readROIStats() {
13008
13165
  const filePath = roiFilePath();
13009
- if (!fs45.existsSync(filePath)) {
13166
+ if (!fs46.existsSync(filePath)) {
13010
13167
  return { learnings: [], sessions: [], totals: { ...DEFAULT_TOTALS } };
13011
13168
  }
13012
13169
  try {
13013
- return JSON.parse(fs45.readFileSync(filePath, "utf-8"));
13170
+ return JSON.parse(fs46.readFileSync(filePath, "utf-8"));
13014
13171
  } catch {
13015
13172
  try {
13016
13173
  const corruptPath = filePath + ".corrupt";
13017
- fs45.renameSync(filePath, corruptPath);
13174
+ fs46.renameSync(filePath, corruptPath);
13018
13175
  console.error(`caliber: roi-stats.json was corrupt \u2014 renamed to ${corruptPath}`);
13019
13176
  } catch {
13020
13177
  }
@@ -13023,7 +13180,7 @@ function readROIStats() {
13023
13180
  }
13024
13181
  function writeROIStats(stats) {
13025
13182
  ensureLearningDir();
13026
- fs45.writeFileSync(roiFilePath(), JSON.stringify(stats, null, 2));
13183
+ fs46.writeFileSync(roiFilePath(), JSON.stringify(stats, null, 2));
13027
13184
  }
13028
13185
  function recalculateTotals(stats) {
13029
13186
  const totals = stats.totals;
@@ -13233,20 +13390,27 @@ var INCREMENTAL_INTERVAL = 50;
13233
13390
  function writeFinalizeError(message) {
13234
13391
  try {
13235
13392
  const errorPath = path38.join(getLearningDir(), LEARNING_LAST_ERROR_FILE);
13236
- if (!fs46.existsSync(getLearningDir())) fs46.mkdirSync(getLearningDir(), { recursive: true });
13237
- fs46.writeFileSync(errorPath, JSON.stringify({
13238
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13239
- error: message,
13240
- pid: process.pid
13241
- }, null, 2));
13393
+ if (!fs47.existsSync(getLearningDir())) fs47.mkdirSync(getLearningDir(), { recursive: true });
13394
+ fs47.writeFileSync(
13395
+ errorPath,
13396
+ JSON.stringify(
13397
+ {
13398
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13399
+ error: message,
13400
+ pid: process.pid
13401
+ },
13402
+ null,
13403
+ 2
13404
+ )
13405
+ );
13242
13406
  } catch {
13243
13407
  }
13244
13408
  }
13245
13409
  function readFinalizeError() {
13246
13410
  try {
13247
13411
  const errorPath = path38.join(getLearningDir(), LEARNING_LAST_ERROR_FILE);
13248
- if (!fs46.existsSync(errorPath)) return null;
13249
- return JSON.parse(fs46.readFileSync(errorPath, "utf-8"));
13412
+ if (!fs47.existsSync(errorPath)) return null;
13413
+ return JSON.parse(fs47.readFileSync(errorPath, "utf-8"));
13250
13414
  } catch {
13251
13415
  return null;
13252
13416
  }
@@ -13294,17 +13458,19 @@ async function learnObserveCommand(options) {
13294
13458
  const eventsSinceLastAnalysis = state.eventCount - (state.lastAnalysisEventCount || 0);
13295
13459
  if (eventsSinceLastAnalysis >= INCREMENTAL_INTERVAL) {
13296
13460
  try {
13297
- const { resolveCaliber: resolveCaliber2 } = await Promise.resolve().then(() => (init_resolve_caliber(), resolve_caliber_exports));
13461
+ const { resolveCaliber: resolveCaliber2, isNpxResolution: isNpxResolution2 } = await Promise.resolve().then(() => (init_resolve_caliber(), resolve_caliber_exports));
13298
13462
  const bin = resolveCaliber2();
13299
13463
  const { spawn: spawn4 } = await import("child_process");
13300
13464
  const logPath = path38.join(getLearningDir(), LEARNING_FINALIZE_LOG);
13301
- if (!fs46.existsSync(getLearningDir())) fs46.mkdirSync(getLearningDir(), { recursive: true });
13302
- const logFd = fs46.openSync(logPath, "a");
13303
- spawn4(bin, ["learn", "finalize", "--auto", "--incremental"], {
13465
+ if (!fs47.existsSync(getLearningDir())) fs47.mkdirSync(getLearningDir(), { recursive: true });
13466
+ const logFd = fs47.openSync(logPath, "a");
13467
+ const NPX_SUFFIX = " --yes @rely-ai/caliber";
13468
+ const [exe, binArgs] = isNpxResolution2() ? [bin.slice(0, -NPX_SUFFIX.length) || "npx", ["--yes", "@rely-ai/caliber"]] : [bin, []];
13469
+ spawn4(exe, [...binArgs, "learn", "finalize", "--auto", "--incremental"], {
13304
13470
  detached: true,
13305
13471
  stdio: ["ignore", logFd, logFd]
13306
13472
  }).unref();
13307
- fs46.closeSync(logFd);
13473
+ fs47.closeSync(logFd);
13308
13474
  } catch {
13309
13475
  }
13310
13476
  }
@@ -13317,7 +13483,8 @@ async function learnFinalizeCommand(options) {
13317
13483
  if (!options?.force && !isAuto) {
13318
13484
  const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
13319
13485
  if (isCaliberRunning2()) {
13320
- if (!isAuto) console.log(chalk23.dim("caliber: skipping finalize \u2014 another caliber process is running"));
13486
+ if (!isAuto)
13487
+ console.log(chalk23.dim("caliber: skipping finalize \u2014 another caliber process is running"));
13321
13488
  return;
13322
13489
  }
13323
13490
  }
@@ -13325,7 +13492,8 @@ async function learnFinalizeCommand(options) {
13325
13492
  await new Promise((r) => setTimeout(r, AUTO_SETTLE_MS));
13326
13493
  }
13327
13494
  if (!acquireFinalizeLock()) {
13328
- if (!isAuto) console.log(chalk23.dim("caliber: skipping finalize \u2014 another finalize is in progress"));
13495
+ if (!isAuto)
13496
+ console.log(chalk23.dim("caliber: skipping finalize \u2014 another finalize is in progress"));
13329
13497
  return;
13330
13498
  }
13331
13499
  let analyzed = false;
@@ -13333,7 +13501,11 @@ async function learnFinalizeCommand(options) {
13333
13501
  const config = loadConfig();
13334
13502
  if (!config) {
13335
13503
  if (isAuto) return;
13336
- console.log(chalk23.yellow(`caliber: no LLM provider configured \u2014 run \`${resolveCaliber()} config\` first`));
13504
+ console.log(
13505
+ chalk23.yellow(
13506
+ `caliber: no LLM provider configured \u2014 run \`${resolveCaliber()} config\` first`
13507
+ )
13508
+ );
13337
13509
  clearSession();
13338
13510
  resetState();
13339
13511
  return;
@@ -13341,7 +13513,12 @@ async function learnFinalizeCommand(options) {
13341
13513
  const allEvents = readAllEvents();
13342
13514
  const threshold = isAuto ? MIN_EVENTS_AUTO : MIN_EVENTS_FOR_ANALYSIS;
13343
13515
  if (allEvents.length < threshold) {
13344
- if (!isAuto) console.log(chalk23.dim(`caliber: ${allEvents.length}/${threshold} events recorded \u2014 need more before analysis`));
13516
+ if (!isAuto)
13517
+ console.log(
13518
+ chalk23.dim(
13519
+ `caliber: ${allEvents.length}/${threshold} events recorded \u2014 need more before analysis`
13520
+ )
13521
+ );
13345
13522
  return;
13346
13523
  }
13347
13524
  await validateModel({ fast: true });
@@ -13350,7 +13527,12 @@ async function learnFinalizeCommand(options) {
13350
13527
  const analysisOffset = isIncremental ? state.lastAnalysisEventCount || 0 : 0;
13351
13528
  const events = analysisOffset > 0 ? allEvents.slice(analysisOffset) : allEvents;
13352
13529
  if (events.length < threshold) {
13353
- if (!isAuto) console.log(chalk23.dim(`caliber: ${events.length}/${threshold} new events since last analysis \u2014 need more`));
13530
+ if (!isAuto)
13531
+ console.log(
13532
+ chalk23.dim(
13533
+ `caliber: ${events.length}/${threshold} new events since last analysis \u2014 need more`
13534
+ )
13535
+ );
13354
13536
  return;
13355
13537
  }
13356
13538
  const existingConfigs = readExistingConfigs(process.cwd());
@@ -13386,7 +13568,11 @@ async function learnFinalizeCommand(options) {
13386
13568
  });
13387
13569
  } else {
13388
13570
  const wasteLabel = waste.totalWasteTokens > 0 ? ` (~${waste.totalWasteTokens.toLocaleString()} wasted tokens captured)` : "";
13389
- console.log(chalk23.dim(`caliber: learned ${result.newItemCount} new pattern${result.newItemCount === 1 ? "" : "s"}${wasteLabel}`));
13571
+ console.log(
13572
+ chalk23.dim(
13573
+ `caliber: learned ${result.newItemCount} new pattern${result.newItemCount === 1 ? "" : "s"}${wasteLabel}`
13574
+ )
13575
+ );
13390
13576
  for (const item of result.newItems) {
13391
13577
  console.log(chalk23.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
13392
13578
  }
@@ -13481,12 +13667,20 @@ async function learnFinalizeCommand(options) {
13481
13667
  if (!isIncremental) {
13482
13668
  const staleLearnings = findStaleLearnings(roiStats);
13483
13669
  if (staleLearnings.length > 0 && !isAuto) {
13484
- console.log(chalk23.yellow(`caliber: ${staleLearnings.length} learning${staleLearnings.length === 1 ? "" : "s"} never activated \u2014 run \`${resolveCaliber()} learn list --verbose\` to review`));
13670
+ console.log(
13671
+ chalk23.yellow(
13672
+ `caliber: ${staleLearnings.length} learning${staleLearnings.length === 1 ? "" : "s"} never activated \u2014 run \`${resolveCaliber()} learn list --verbose\` to review`
13673
+ )
13674
+ );
13485
13675
  }
13486
13676
  }
13487
13677
  if (!isAuto && t.estimatedSavingsTokens > 0) {
13488
13678
  const totalLearnings = existingLearnedItems + newLearningsProduced;
13489
- console.log(chalk23.dim(`caliber: ${totalLearnings} learnings active \u2014 est. ~${t.estimatedSavingsTokens.toLocaleString()} tokens saved across ${t.totalSessionsWithLearnings} sessions`));
13679
+ console.log(
13680
+ chalk23.dim(
13681
+ `caliber: ${totalLearnings} learnings active \u2014 est. ~${t.estimatedSavingsTokens.toLocaleString()} tokens saved across ${t.totalSessionsWithLearnings} sessions`
13682
+ )
13683
+ );
13490
13684
  }
13491
13685
  } catch (err) {
13492
13686
  const errorMsg = err instanceof Error ? err.message : String(err);
@@ -13511,7 +13705,7 @@ async function learnFinalizeCommand(options) {
13511
13705
  }
13512
13706
  async function learnInstallCommand() {
13513
13707
  let anyInstalled = false;
13514
- if (fs46.existsSync(".claude")) {
13708
+ if (fs47.existsSync(".claude")) {
13515
13709
  const r = installLearningHooks();
13516
13710
  if (r.installed) {
13517
13711
  console.log(chalk23.green("\u2713") + " Claude Code learning hooks installed");
@@ -13520,7 +13714,7 @@ async function learnInstallCommand() {
13520
13714
  console.log(chalk23.dim(" Claude Code hooks already installed"));
13521
13715
  }
13522
13716
  }
13523
- if (fs46.existsSync(".cursor")) {
13717
+ if (fs47.existsSync(".cursor")) {
13524
13718
  const r = installCursorLearningHooks();
13525
13719
  if (r.installed) {
13526
13720
  console.log(chalk23.green("\u2713") + " Cursor learning hooks installed");
@@ -13529,13 +13723,19 @@ async function learnInstallCommand() {
13529
13723
  console.log(chalk23.dim(" Cursor hooks already installed"));
13530
13724
  }
13531
13725
  }
13532
- if (!fs46.existsSync(".claude") && !fs46.existsSync(".cursor")) {
13726
+ if (!fs47.existsSync(".claude") && !fs47.existsSync(".cursor")) {
13533
13727
  console.log(chalk23.yellow("No .claude/ or .cursor/ directory found."));
13534
- console.log(chalk23.dim(` Run \`${resolveCaliber()} init\` first, or create the directory manually.`));
13728
+ console.log(
13729
+ chalk23.dim(` Run \`${resolveCaliber()} init\` first, or create the directory manually.`)
13730
+ );
13535
13731
  return;
13536
13732
  }
13537
13733
  if (anyInstalled) {
13538
- console.log(chalk23.dim(` Tool usage will be recorded and learnings extracted after \u2265${MIN_EVENTS_FOR_ANALYSIS} events.`));
13734
+ console.log(
13735
+ chalk23.dim(
13736
+ ` Tool usage will be recorded and learnings extracted after \u2265${MIN_EVENTS_FOR_ANALYSIS} events.`
13737
+ )
13738
+ );
13539
13739
  console.log(chalk23.dim(" Learnings written to CALIBER_LEARNINGS.md."));
13540
13740
  }
13541
13741
  }
@@ -13573,7 +13773,9 @@ async function learnStatusCommand() {
13573
13773
  console.log(chalk23.dim("\u2717") + " Cursor hooks " + chalk23.dim("not installed"));
13574
13774
  }
13575
13775
  if (!claudeInstalled && !cursorInstalled) {
13576
- console.log(chalk23.dim(` Run \`${resolveCaliber()} learn install\` to enable session learning.`));
13776
+ console.log(
13777
+ chalk23.dim(` Run \`${resolveCaliber()} learn install\` to enable session learning.`)
13778
+ );
13577
13779
  }
13578
13780
  console.log();
13579
13781
  console.log(`Events recorded: ${chalk23.cyan(String(eventCount))}`);
@@ -13588,7 +13790,7 @@ async function learnStatusCommand() {
13588
13790
  console.log(`Last error: ${chalk23.red(lastError.error)}`);
13589
13791
  console.log(chalk23.dim(` at ${lastError.timestamp}`));
13590
13792
  const logPath = path38.join(getLearningDir(), LEARNING_FINALIZE_LOG);
13591
- if (fs46.existsSync(logPath)) {
13793
+ if (fs47.existsSync(logPath)) {
13592
13794
  console.log(chalk23.dim(` Full log: ${logPath}`));
13593
13795
  }
13594
13796
  }
@@ -13657,7 +13859,11 @@ async function learnListCommand(options) {
13657
13859
  async function learnDeleteCommand(indexStr) {
13658
13860
  const index = parseInt(indexStr, 10);
13659
13861
  if (isNaN(index) || index < 1) {
13660
- console.log(chalk23.red(`Invalid index: "${indexStr}". Use a number from \`${resolveCaliber()} learn list\`.`));
13862
+ console.log(
13863
+ chalk23.red(
13864
+ `Invalid index: "${indexStr}". Use a number from \`${resolveCaliber()} learn list\`.`
13865
+ )
13866
+ );
13661
13867
  return;
13662
13868
  }
13663
13869
  const items = getAllLearnings();
@@ -13668,11 +13874,11 @@ async function learnDeleteCommand(indexStr) {
13668
13874
  }
13669
13875
  const item = items[targetIdx];
13670
13876
  const filePath = item.source === "personal" ? PERSONAL_LEARNINGS_FILE : "CALIBER_LEARNINGS.md";
13671
- if (!fs46.existsSync(filePath)) {
13877
+ if (!fs47.existsSync(filePath)) {
13672
13878
  console.log(chalk23.red("Learnings file not found."));
13673
13879
  return;
13674
13880
  }
13675
- const content = fs46.readFileSync(filePath, "utf-8");
13881
+ const content = fs47.readFileSync(filePath, "utf-8");
13676
13882
  const lines = content.split("\n");
13677
13883
  const bulletsOfSource = items.filter((i) => i.source === item.source);
13678
13884
  const posInFile = bulletsOfSource.indexOf(item);
@@ -13693,9 +13899,9 @@ async function learnDeleteCommand(indexStr) {
13693
13899
  }
13694
13900
  const bulletToRemove = lines[lineToRemove];
13695
13901
  const newLines = lines.filter((_, i) => i !== lineToRemove);
13696
- fs46.writeFileSync(filePath, newLines.join("\n"));
13902
+ fs47.writeFileSync(filePath, newLines.join("\n"));
13697
13903
  if (item.source === "personal") {
13698
- fs46.chmodSync(filePath, 384);
13904
+ fs47.chmodSync(filePath, 384);
13699
13905
  }
13700
13906
  const roiStats = readROIStats();
13701
13907
  const cleanText = bulletToRemove.replace(/^- /, "").replace(/^\*\*\[[^\]]+\]\*\*\s*/, "").trim();
@@ -13868,7 +14074,7 @@ async function insightsCommand(options) {
13868
14074
  }
13869
14075
 
13870
14076
  // src/commands/sources.ts
13871
- import fs47 from "fs";
14077
+ import fs48 from "fs";
13872
14078
  import path39 from "path";
13873
14079
  import chalk25 from "chalk";
13874
14080
  init_resolve_caliber();
@@ -13886,9 +14092,9 @@ async function sourcesListCommand() {
13886
14092
  if (configSources.length > 0) {
13887
14093
  for (const source of configSources) {
13888
14094
  const sourcePath = source.path || source.url || "";
13889
- const exists = source.path ? fs47.existsSync(path39.resolve(dir, source.path)) : false;
14095
+ const exists = source.path ? fs48.existsSync(path39.resolve(dir, source.path)) : false;
13890
14096
  const status = exists ? chalk25.green("reachable") : chalk25.red("not found");
13891
- const hasSummary = source.path && fs47.existsSync(path39.join(path39.resolve(dir, source.path), ".caliber", "summary.json"));
14097
+ const hasSummary = source.path && fs48.existsSync(path39.join(path39.resolve(dir, source.path), ".caliber", "summary.json"));
13892
14098
  console.log(` ${chalk25.bold(source.role || source.type)} ${chalk25.dim(sourcePath)}`);
13893
14099
  console.log(` Type: ${source.type} Status: ${status}${hasSummary ? " " + chalk25.cyan("has summary.json") : ""}`);
13894
14100
  if (source.description) console.log(` ${chalk25.dim(source.description)}`);
@@ -13898,7 +14104,7 @@ async function sourcesListCommand() {
13898
14104
  if (workspaces.length > 0) {
13899
14105
  console.log(chalk25.dim(" Auto-detected workspaces:"));
13900
14106
  for (const ws of workspaces) {
13901
- const exists = fs47.existsSync(path39.resolve(dir, ws));
14107
+ const exists = fs48.existsSync(path39.resolve(dir, ws));
13902
14108
  console.log(` ${exists ? chalk25.green("\u25CF") : chalk25.red("\u25CF")} ${ws}`);
13903
14109
  }
13904
14110
  console.log("");
@@ -13907,7 +14113,7 @@ async function sourcesListCommand() {
13907
14113
  async function sourcesAddCommand(sourcePath) {
13908
14114
  const dir = process.cwd();
13909
14115
  const absPath = path39.resolve(dir, sourcePath);
13910
- if (!fs47.existsSync(absPath)) {
14116
+ if (!fs48.existsSync(absPath)) {
13911
14117
  console.log(chalk25.red(`
13912
14118
  Path not found: ${sourcePath}
13913
14119
  `));
@@ -13970,7 +14176,7 @@ async function sourcesRemoveCommand(name) {
13970
14176
  }
13971
14177
 
13972
14178
  // src/commands/publish.ts
13973
- import fs48 from "fs";
14179
+ import fs49 from "fs";
13974
14180
  import path40 from "path";
13975
14181
  import chalk26 from "chalk";
13976
14182
  import ora7 from "ora";
@@ -14015,11 +14221,11 @@ async function publishCommand() {
14015
14221
  } catch {
14016
14222
  }
14017
14223
  const outputDir = path40.join(dir, ".caliber");
14018
- if (!fs48.existsSync(outputDir)) {
14019
- fs48.mkdirSync(outputDir, { recursive: true });
14224
+ if (!fs49.existsSync(outputDir)) {
14225
+ fs49.mkdirSync(outputDir, { recursive: true });
14020
14226
  }
14021
14227
  const outputPath = path40.join(outputDir, "summary.json");
14022
- fs48.writeFileSync(outputPath, JSON.stringify(summary, null, 2) + "\n", "utf-8");
14228
+ fs49.writeFileSync(outputPath, JSON.stringify(summary, null, 2) + "\n", "utf-8");
14023
14229
  spinner.succeed("Project summary published");
14024
14230
  console.log(` ${chalk26.green("\u2713")} ${path40.relative(dir, outputPath)}`);
14025
14231
  console.log(chalk26.dim("\n Other projects can now reference this repo as a source."));
@@ -14034,7 +14240,7 @@ async function publishCommand() {
14034
14240
 
14035
14241
  // src/commands/bootstrap.ts
14036
14242
  init_builtin_skills();
14037
- import fs49 from "fs";
14243
+ import fs50 from "fs";
14038
14244
  import chalk27 from "chalk";
14039
14245
  var PLATFORM_SKILL_DIRS = {
14040
14246
  claude: ".claude/skills",
@@ -14055,8 +14261,8 @@ async function bootstrapCommand() {
14055
14261
  for (const skill of BUILTIN_SKILLS) {
14056
14262
  const skillDir = `${skillsDir}/${skill.name}`;
14057
14263
  const skillPath = `${skillDir}/SKILL.md`;
14058
- fs49.mkdirSync(skillDir, { recursive: true });
14059
- fs49.writeFileSync(skillPath, buildSkillContent(skill));
14264
+ fs50.mkdirSync(skillDir, { recursive: true });
14265
+ fs50.writeFileSync(skillPath, buildSkillContent(skill));
14060
14266
  written.push(skillPath);
14061
14267
  }
14062
14268
  }
@@ -14073,7 +14279,7 @@ async function bootstrapCommand() {
14073
14279
  }
14074
14280
 
14075
14281
  // src/commands/uninstall.ts
14076
- import fs50 from "fs";
14282
+ import fs51 from "fs";
14077
14283
  import path41 from "path";
14078
14284
  import chalk28 from "chalk";
14079
14285
  import confirm3 from "@inquirer/confirm";
@@ -14090,11 +14296,11 @@ var CURSOR_RULES_DIR = path41.join(".cursor", "rules");
14090
14296
  var CLAUDE_RULES_DIR = path41.join(".claude", "rules");
14091
14297
  function removeCaliberManagedFiles(dir, extension) {
14092
14298
  const removed = [];
14093
- if (!fs50.existsSync(dir)) return removed;
14094
- for (const file of fs50.readdirSync(dir)) {
14299
+ if (!fs51.existsSync(dir)) return removed;
14300
+ for (const file of fs51.readdirSync(dir)) {
14095
14301
  if (file.startsWith(CALIBER_MANAGED_PREFIX) && file.endsWith(extension)) {
14096
14302
  const fullPath = path41.join(dir, file);
14097
- fs50.unlinkSync(fullPath);
14303
+ fs51.unlinkSync(fullPath);
14098
14304
  removed.push(fullPath);
14099
14305
  }
14100
14306
  }
@@ -14103,11 +14309,11 @@ function removeCaliberManagedFiles(dir, extension) {
14103
14309
  function removeBuiltinSkills() {
14104
14310
  const removed = [];
14105
14311
  for (const skillsDir of SKILL_DIRS) {
14106
- if (!fs50.existsSync(skillsDir)) continue;
14312
+ if (!fs51.existsSync(skillsDir)) continue;
14107
14313
  for (const name of BUILTIN_SKILL_NAMES) {
14108
14314
  const skillDir = path41.join(skillsDir, name);
14109
- if (fs50.existsSync(skillDir)) {
14110
- fs50.rmSync(skillDir, { recursive: true });
14315
+ if (fs51.existsSync(skillDir)) {
14316
+ fs51.rmSync(skillDir, { recursive: true });
14111
14317
  removed.push(skillDir);
14112
14318
  }
14113
14319
  }
@@ -14117,15 +14323,15 @@ function removeBuiltinSkills() {
14117
14323
  function stripManagedBlocksFromFiles() {
14118
14324
  const modified = [];
14119
14325
  for (const filePath of MANAGED_DOC_FILES) {
14120
- if (!fs50.existsSync(filePath)) continue;
14121
- const original = fs50.readFileSync(filePath, "utf-8");
14326
+ if (!fs51.existsSync(filePath)) continue;
14327
+ const original = fs51.readFileSync(filePath, "utf-8");
14122
14328
  const stripped = stripManagedBlocks(original);
14123
14329
  if (stripped !== original) {
14124
14330
  const trimmed = stripped.trim();
14125
14331
  if (!trimmed || /^#\s*\S*$/.test(trimmed)) {
14126
- fs50.unlinkSync(filePath);
14332
+ fs51.unlinkSync(filePath);
14127
14333
  } else {
14128
- fs50.writeFileSync(filePath, stripped);
14334
+ fs51.writeFileSync(filePath, stripped);
14129
14335
  }
14130
14336
  modified.push(filePath);
14131
14337
  }
@@ -14133,8 +14339,8 @@ function stripManagedBlocksFromFiles() {
14133
14339
  return modified;
14134
14340
  }
14135
14341
  function removeDirectory(dir) {
14136
- if (!fs50.existsSync(dir)) return false;
14137
- fs50.rmSync(dir, { recursive: true });
14342
+ if (!fs51.existsSync(dir)) return false;
14343
+ fs51.rmSync(dir, { recursive: true });
14138
14344
  return true;
14139
14345
  }
14140
14346
  async function uninstallCommand(options) {
@@ -14206,8 +14412,8 @@ async function uninstallCommand(options) {
14206
14412
  console.log(` ${chalk28.red("\u2717")} ${skill}/`);
14207
14413
  }
14208
14414
  if (removedSkills.length > 0) actions.push("builtin skills");
14209
- if (fs50.existsSync("CALIBER_LEARNINGS.md")) {
14210
- fs50.unlinkSync("CALIBER_LEARNINGS.md");
14415
+ if (fs51.existsSync("CALIBER_LEARNINGS.md")) {
14416
+ fs51.unlinkSync("CALIBER_LEARNINGS.md");
14211
14417
  console.log(` ${chalk28.red("\u2717")} CALIBER_LEARNINGS.md`);
14212
14418
  actions.push("learnings file");
14213
14419
  }
@@ -14221,18 +14427,18 @@ async function uninstallCommand(options) {
14221
14427
  }
14222
14428
  trackUninstallExecuted();
14223
14429
  const configPath = getConfigFilePath();
14224
- if (fs50.existsSync(configPath)) {
14430
+ if (fs51.existsSync(configPath)) {
14225
14431
  console.log("");
14226
14432
  const removeConfig = options.force || await confirm3({
14227
14433
  message: `Remove global config (~/.caliber/config.json)? This affects all projects.`
14228
14434
  });
14229
14435
  if (removeConfig) {
14230
- fs50.unlinkSync(configPath);
14436
+ fs51.unlinkSync(configPath);
14231
14437
  console.log(` ${chalk28.red("\u2717")} ${configPath}`);
14232
14438
  const configDir = path41.dirname(configPath);
14233
14439
  try {
14234
- const remaining = fs50.readdirSync(configDir);
14235
- if (remaining.length === 0) fs50.rmdirSync(configDir);
14440
+ const remaining = fs51.readdirSync(configDir);
14441
+ if (remaining.length === 0) fs51.rmdirSync(configDir);
14236
14442
  } catch {
14237
14443
  }
14238
14444
  }
@@ -14244,7 +14450,7 @@ async function uninstallCommand(options) {
14244
14450
 
14245
14451
  // src/cli.ts
14246
14452
  var __dirname = path42.dirname(fileURLToPath(import.meta.url));
14247
- var pkg = JSON.parse(fs51.readFileSync(path42.resolve(__dirname, "..", "package.json"), "utf-8"));
14453
+ var pkg = JSON.parse(fs52.readFileSync(path42.resolve(__dirname, "..", "package.json"), "utf-8"));
14248
14454
  var program = new Command();
14249
14455
  var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
14250
14456
  program.name(process.env.CALIBER_LOCAL ? "caloc" : "caliber").description("AI context infrastructure for coding agents").version(displayVersion).option("--no-traces", "Disable anonymous telemetry for this run");
@@ -14355,15 +14561,15 @@ learn.command("delete <index>").description("Delete a learning by its index numb
14355
14561
  learn.command("add <content>").description("Add a learning directly (used by agent skills)").option("--personal", "Save as a personal learning instead of project-level").action(tracked("learn:add", learnAddCommand));
14356
14562
 
14357
14563
  // src/utils/version-check.ts
14358
- import fs52 from "fs";
14564
+ import fs53 from "fs";
14359
14565
  import path43 from "path";
14360
14566
  import { fileURLToPath as fileURLToPath2 } from "url";
14361
- import { execSync as execSync16, execFileSync as execFileSync3 } from "child_process";
14567
+ import { execSync as execSync16, execFileSync as execFileSync5 } from "child_process";
14362
14568
  import chalk29 from "chalk";
14363
14569
  import ora8 from "ora";
14364
14570
  import confirm4 from "@inquirer/confirm";
14365
14571
  var __dirname_vc = path43.dirname(fileURLToPath2(import.meta.url));
14366
- var pkg2 = JSON.parse(fs52.readFileSync(path43.resolve(__dirname_vc, "..", "package.json"), "utf-8"));
14572
+ var pkg2 = JSON.parse(fs53.readFileSync(path43.resolve(__dirname_vc, "..", "package.json"), "utf-8"));
14367
14573
  function getChannel(version) {
14368
14574
  const match = version.match(/-(dev|next)\./);
14369
14575
  return match ? match[1] : "latest";
@@ -14391,7 +14597,7 @@ function getInstalledVersion() {
14391
14597
  stdio: ["pipe", "pipe", "pipe"]
14392
14598
  }).trim();
14393
14599
  const pkgPath = path43.join(globalRoot, "@rely-ai", "caliber", "package.json");
14394
- return JSON.parse(fs52.readFileSync(pkgPath, "utf-8")).version;
14600
+ return JSON.parse(fs53.readFileSync(pkgPath, "utf-8")).version;
14395
14601
  } catch {
14396
14602
  return null;
14397
14603
  }
@@ -14439,7 +14645,7 @@ Update available: ${current} -> ${latest}`));
14439
14645
  if (!/^[\w.-]+$/.test(tag)) return;
14440
14646
  const spinner = ora8("Updating caliber...").start();
14441
14647
  try {
14442
- execFileSync3("npm", ["install", "-g", `@rely-ai/caliber@${tag}`], {
14648
+ execFileSync5("npm", ["install", "-g", `@rely-ai/caliber@${tag}`], {
14443
14649
  stdio: "pipe",
14444
14650
  timeout: 12e4,
14445
14651
  env: { ...process.env, npm_config_fund: "false", npm_config_audit: "false" }
@@ -14458,7 +14664,7 @@ Update available: ${current} -> ${latest}`));
14458
14664
  console.log(chalk29.dim(`
14459
14665
  Restarting: caliber ${args.join(" ")}
14460
14666
  `));
14461
- execFileSync3("caliber", args, {
14667
+ execFileSync5("caliber", args, {
14462
14668
  stdio: "inherit",
14463
14669
  env: { ...process.env, CALIBER_SKIP_UPDATE_CHECK: "1" }
14464
14670
  });