@rely-ai/caliber 1.26.0 → 1.27.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 +363 -377
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -1,8 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
4
  var __esm = (fn, res) => function __init() {
7
5
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
6
  };
@@ -10,54 +8,6 @@ var __export = (target, all) => {
10
8
  for (var name in all)
11
9
  __defProp(target, name, { get: all[name], enumerable: true });
12
10
  };
13
- var __copyProps = (to, from, except, desc) => {
14
- if (from && typeof from === "object" || typeof from === "function") {
15
- for (let key of __getOwnPropNames(from))
16
- if (!__hasOwnProp.call(to, key) && key !== except)
17
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
- }
19
- return to;
20
- };
21
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
-
23
- // src/constants.ts
24
- var constants_exports = {};
25
- __export(constants_exports, {
26
- AUTH_DIR: () => AUTH_DIR,
27
- BACKUPS_DIR: () => BACKUPS_DIR,
28
- CALIBER_DIR: () => CALIBER_DIR,
29
- LEARNING_DIR: () => LEARNING_DIR,
30
- LEARNING_FINALIZE_LOG: () => LEARNING_FINALIZE_LOG,
31
- LEARNING_LAST_ERROR_FILE: () => LEARNING_LAST_ERROR_FILE,
32
- LEARNING_MAX_EVENTS: () => LEARNING_MAX_EVENTS,
33
- LEARNING_ROI_FILE: () => LEARNING_ROI_FILE,
34
- LEARNING_SESSION_FILE: () => LEARNING_SESSION_FILE,
35
- LEARNING_STATE_FILE: () => LEARNING_STATE_FILE,
36
- MANIFEST_FILE: () => MANIFEST_FILE,
37
- MIN_SESSIONS_FOR_COMPARISON: () => MIN_SESSIONS_FOR_COMPARISON,
38
- PERSONAL_LEARNINGS_FILE: () => PERSONAL_LEARNINGS_FILE
39
- });
40
- import path2 from "path";
41
- import os from "os";
42
- var AUTH_DIR, CALIBER_DIR, MANIFEST_FILE, BACKUPS_DIR, LEARNING_DIR, LEARNING_SESSION_FILE, LEARNING_STATE_FILE, LEARNING_MAX_EVENTS, LEARNING_ROI_FILE, PERSONAL_LEARNINGS_FILE, LEARNING_FINALIZE_LOG, LEARNING_LAST_ERROR_FILE, MIN_SESSIONS_FOR_COMPARISON;
43
- var init_constants = __esm({
44
- "src/constants.ts"() {
45
- "use strict";
46
- AUTH_DIR = path2.join(os.homedir(), ".caliber");
47
- CALIBER_DIR = ".caliber";
48
- MANIFEST_FILE = path2.join(CALIBER_DIR, "manifest.json");
49
- BACKUPS_DIR = path2.join(CALIBER_DIR, "backups");
50
- LEARNING_DIR = path2.join(CALIBER_DIR, "learning");
51
- LEARNING_SESSION_FILE = "current-session.jsonl";
52
- LEARNING_STATE_FILE = "state.json";
53
- LEARNING_MAX_EVENTS = 500;
54
- LEARNING_ROI_FILE = "roi-stats.json";
55
- PERSONAL_LEARNINGS_FILE = path2.join(AUTH_DIR, "personal-learnings.md");
56
- LEARNING_FINALIZE_LOG = "finalize.log";
57
- LEARNING_LAST_ERROR_FILE = "last-error.json";
58
- MIN_SESSIONS_FOR_COMPARISON = 3;
59
- }
60
- });
61
11
 
62
12
  // src/llm/config.ts
63
13
  var config_exports = {};
@@ -230,7 +180,7 @@ __export(resolve_caliber_exports, {
230
180
  isCaliberCommand: () => isCaliberCommand,
231
181
  resolveCaliber: () => resolveCaliber
232
182
  });
233
- import fs19 from "fs";
183
+ import fs20 from "fs";
234
184
  import { execSync as execSync6 } from "child_process";
235
185
  function resolveCaliber() {
236
186
  if (_resolved) return _resolved;
@@ -252,7 +202,7 @@ function resolveCaliber() {
252
202
  } catch {
253
203
  }
254
204
  const binPath = process.argv[1];
255
- if (binPath && fs19.existsSync(binPath)) {
205
+ if (binPath && fs20.existsSync(binPath)) {
256
206
  _resolved = binPath;
257
207
  return _resolved;
258
208
  }
@@ -278,7 +228,7 @@ var init_resolve_caliber = __esm({
278
228
  import { execSync as execSync12, spawn as spawn3 } from "child_process";
279
229
  import fs26 from "fs";
280
230
  import path22 from "path";
281
- import os5 from "os";
231
+ import os6 from "os";
282
232
  function getEmptyFilePath(proposedPath) {
283
233
  fs26.mkdirSync(DIFF_TEMP_DIR, { recursive: true });
284
234
  const tempPath = path22.join(DIFF_TEMP_DIR, path22.basename(proposedPath));
@@ -322,7 +272,7 @@ var init_editor = __esm({
322
272
  "src/utils/editor.ts"() {
323
273
  "use strict";
324
274
  IS_WINDOWS3 = process.platform === "win32";
325
- DIFF_TEMP_DIR = path22.join(os5.tmpdir(), "caliber-diff");
275
+ DIFF_TEMP_DIR = path22.join(os6.tmpdir(), "caliber-diff");
326
276
  }
327
277
  });
328
278
 
@@ -549,7 +499,7 @@ __export(lock_exports, {
549
499
  });
550
500
  import fs36 from "fs";
551
501
  import path28 from "path";
552
- import os7 from "os";
502
+ import os8 from "os";
553
503
  function isCaliberRunning() {
554
504
  try {
555
505
  if (!fs36.existsSync(LOCK_FILE)) return false;
@@ -582,7 +532,7 @@ var LOCK_FILE, STALE_MS;
582
532
  var init_lock = __esm({
583
533
  "src/lib/lock.ts"() {
584
534
  "use strict";
585
- LOCK_FILE = path28.join(os7.tmpdir(), ".caliber.lock");
535
+ LOCK_FILE = path28.join(os8.tmpdir(), ".caliber.lock");
586
536
  STALE_MS = 10 * 60 * 1e3;
587
537
  }
588
538
  });
@@ -708,9 +658,27 @@ function scan(base, rel, depth, maxDepth, result) {
708
658
  }
709
659
 
710
660
  // src/fingerprint/existing-config.ts
711
- init_constants();
712
661
  import fs2 from "fs";
713
662
  import path3 from "path";
663
+
664
+ // src/constants.ts
665
+ import path2 from "path";
666
+ import os from "os";
667
+ var AUTH_DIR = path2.join(os.homedir(), ".caliber");
668
+ var CALIBER_DIR = ".caliber";
669
+ var MANIFEST_FILE = path2.join(CALIBER_DIR, "manifest.json");
670
+ var BACKUPS_DIR = path2.join(CALIBER_DIR, "backups");
671
+ var LEARNING_DIR = path2.join(CALIBER_DIR, "learning");
672
+ var LEARNING_SESSION_FILE = "current-session.jsonl";
673
+ var LEARNING_STATE_FILE = "state.json";
674
+ var LEARNING_MAX_EVENTS = 500;
675
+ var LEARNING_ROI_FILE = "roi-stats.json";
676
+ var PERSONAL_LEARNINGS_FILE = path2.join(AUTH_DIR, "personal-learnings.md");
677
+ var LEARNING_FINALIZE_LOG = "finalize.log";
678
+ var LEARNING_LAST_ERROR_FILE = "last-error.json";
679
+ var MIN_SESSIONS_FOR_COMPARISON = 3;
680
+
681
+ // src/fingerprint/existing-config.ts
714
682
  function readExistingConfigs(dir) {
715
683
  const configs = {};
716
684
  const readmeMdPath = path3.join(dir, "README.md");
@@ -2945,9 +2913,180 @@ async function enrichWithLLM(fingerprint) {
2945
2913
  }
2946
2914
  }
2947
2915
 
2948
- // src/fingerprint/sources.ts
2916
+ // src/scanner/index.ts
2949
2917
  import fs8 from "fs";
2950
2918
  import path8 from "path";
2919
+ import crypto2 from "crypto";
2920
+ import os4 from "os";
2921
+ function detectPlatforms() {
2922
+ const home = os4.homedir();
2923
+ return {
2924
+ claude: fs8.existsSync(path8.join(home, ".claude")),
2925
+ cursor: fs8.existsSync(getCursorConfigDir()),
2926
+ codex: fs8.existsSync(path8.join(home, ".codex"))
2927
+ };
2928
+ }
2929
+ function scanLocalState(dir) {
2930
+ const items = [];
2931
+ const claudeMdPath = path8.join(dir, "CLAUDE.md");
2932
+ if (fs8.existsSync(claudeMdPath)) {
2933
+ items.push({
2934
+ type: "rule",
2935
+ platform: "claude",
2936
+ name: "CLAUDE.md",
2937
+ contentHash: hashFile(claudeMdPath),
2938
+ path: claudeMdPath
2939
+ });
2940
+ }
2941
+ const skillsDir = path8.join(dir, ".claude", "skills");
2942
+ if (fs8.existsSync(skillsDir)) {
2943
+ for (const file of fs8.readdirSync(skillsDir).filter((f) => f.endsWith(".md"))) {
2944
+ const filePath = path8.join(skillsDir, file);
2945
+ items.push({
2946
+ type: "skill",
2947
+ platform: "claude",
2948
+ name: file,
2949
+ contentHash: hashFile(filePath),
2950
+ path: filePath
2951
+ });
2952
+ }
2953
+ }
2954
+ const mcpJsonPath = path8.join(dir, ".mcp.json");
2955
+ if (fs8.existsSync(mcpJsonPath)) {
2956
+ try {
2957
+ const mcpJson = JSON.parse(fs8.readFileSync(mcpJsonPath, "utf-8"));
2958
+ if (mcpJson.mcpServers) {
2959
+ for (const name of Object.keys(mcpJson.mcpServers)) {
2960
+ items.push({
2961
+ type: "mcp",
2962
+ platform: "claude",
2963
+ name,
2964
+ contentHash: hashJson(mcpJson.mcpServers[name]),
2965
+ path: mcpJsonPath
2966
+ });
2967
+ }
2968
+ }
2969
+ } catch (error) {
2970
+ warnScanSkip(".mcp.json", error);
2971
+ }
2972
+ }
2973
+ const agentsMdPath = path8.join(dir, "AGENTS.md");
2974
+ if (fs8.existsSync(agentsMdPath)) {
2975
+ items.push({
2976
+ type: "rule",
2977
+ platform: "codex",
2978
+ name: "AGENTS.md",
2979
+ contentHash: hashFile(agentsMdPath),
2980
+ path: agentsMdPath
2981
+ });
2982
+ }
2983
+ const codexSkillsDir = path8.join(dir, ".agents", "skills");
2984
+ if (fs8.existsSync(codexSkillsDir)) {
2985
+ try {
2986
+ for (const name of fs8.readdirSync(codexSkillsDir)) {
2987
+ const skillFile = path8.join(codexSkillsDir, name, "SKILL.md");
2988
+ if (fs8.existsSync(skillFile)) {
2989
+ items.push({
2990
+ type: "skill",
2991
+ platform: "codex",
2992
+ name: `${name}/SKILL.md`,
2993
+ contentHash: hashFile(skillFile),
2994
+ path: skillFile
2995
+ });
2996
+ }
2997
+ }
2998
+ } catch (error) {
2999
+ warnScanSkip(".agents/skills", error);
3000
+ }
3001
+ }
3002
+ const cursorrulesPath = path8.join(dir, ".cursorrules");
3003
+ if (fs8.existsSync(cursorrulesPath)) {
3004
+ items.push({
3005
+ type: "rule",
3006
+ platform: "cursor",
3007
+ name: ".cursorrules",
3008
+ contentHash: hashFile(cursorrulesPath),
3009
+ path: cursorrulesPath
3010
+ });
3011
+ }
3012
+ const cursorRulesDir = path8.join(dir, ".cursor", "rules");
3013
+ if (fs8.existsSync(cursorRulesDir)) {
3014
+ for (const file of fs8.readdirSync(cursorRulesDir).filter((f) => f.endsWith(".mdc"))) {
3015
+ const filePath = path8.join(cursorRulesDir, file);
3016
+ items.push({
3017
+ type: "rule",
3018
+ platform: "cursor",
3019
+ name: file,
3020
+ contentHash: hashFile(filePath),
3021
+ path: filePath
3022
+ });
3023
+ }
3024
+ }
3025
+ const cursorSkillsDir = path8.join(dir, ".cursor", "skills");
3026
+ if (fs8.existsSync(cursorSkillsDir)) {
3027
+ try {
3028
+ for (const name of fs8.readdirSync(cursorSkillsDir)) {
3029
+ const skillFile = path8.join(cursorSkillsDir, name, "SKILL.md");
3030
+ if (fs8.existsSync(skillFile)) {
3031
+ items.push({
3032
+ type: "skill",
3033
+ platform: "cursor",
3034
+ name: `${name}/SKILL.md`,
3035
+ contentHash: hashFile(skillFile),
3036
+ path: skillFile
3037
+ });
3038
+ }
3039
+ }
3040
+ } catch (error) {
3041
+ warnScanSkip(".cursor/skills", error);
3042
+ }
3043
+ }
3044
+ const cursorMcpPath = path8.join(dir, ".cursor", "mcp.json");
3045
+ if (fs8.existsSync(cursorMcpPath)) {
3046
+ try {
3047
+ const mcpJson = JSON.parse(fs8.readFileSync(cursorMcpPath, "utf-8"));
3048
+ if (mcpJson.mcpServers) {
3049
+ for (const name of Object.keys(mcpJson.mcpServers)) {
3050
+ items.push({
3051
+ type: "mcp",
3052
+ platform: "cursor",
3053
+ name,
3054
+ contentHash: hashJson(mcpJson.mcpServers[name]),
3055
+ path: cursorMcpPath
3056
+ });
3057
+ }
3058
+ }
3059
+ } catch (error) {
3060
+ warnScanSkip(".cursor/mcp.json", error);
3061
+ }
3062
+ }
3063
+ return items;
3064
+ }
3065
+ function hashFile(filePath) {
3066
+ const text = fs8.readFileSync(filePath, "utf-8");
3067
+ return crypto2.createHash("sha256").update(JSON.stringify({ text })).digest("hex");
3068
+ }
3069
+ function hashJson(obj) {
3070
+ return crypto2.createHash("sha256").update(JSON.stringify(obj)).digest("hex");
3071
+ }
3072
+ function warnScanSkip(target, error) {
3073
+ const message = error instanceof Error ? error.message : String(error);
3074
+ console.warn(`Warning: ${target} scan skipped (${message})`);
3075
+ }
3076
+ function getCursorConfigDir() {
3077
+ const home = os4.homedir();
3078
+ if (process.platform === "darwin") {
3079
+ return path8.join(home, "Library", "Application Support", "Cursor");
3080
+ }
3081
+ if (process.platform === "win32") {
3082
+ return path8.join(home, "AppData", "Roaming", "Cursor");
3083
+ }
3084
+ return path8.join(home, ".config", "Cursor");
3085
+ }
3086
+
3087
+ // src/fingerprint/sources.ts
3088
+ import fs9 from "fs";
3089
+ import path9 from "path";
2951
3090
 
2952
3091
  // src/scoring/utils.ts
2953
3092
  import { existsSync as existsSync2, readFileSync, readdirSync } from "fs";
@@ -3226,7 +3365,7 @@ var SOURCE_CONTENT_LIMIT = 2e3;
3226
3365
  var README_CONTENT_LIMIT = 1e3;
3227
3366
  var ORIGIN_PRIORITY = { cli: 0, config: 1, workspace: 2 };
3228
3367
  function loadSourcesConfig(dir) {
3229
- const configPath = path8.join(dir, ".caliber", "sources.json");
3368
+ const configPath = path9.join(dir, ".caliber", "sources.json");
3230
3369
  const content = readFileOrNull(configPath);
3231
3370
  if (!content) return [];
3232
3371
  try {
@@ -3244,29 +3383,29 @@ function loadSourcesConfig(dir) {
3244
3383
  }
3245
3384
  }
3246
3385
  function writeSourcesConfig(dir, sources2) {
3247
- const configDir = path8.join(dir, ".caliber");
3248
- if (!fs8.existsSync(configDir)) {
3249
- fs8.mkdirSync(configDir, { recursive: true });
3386
+ const configDir = path9.join(dir, ".caliber");
3387
+ if (!fs9.existsSync(configDir)) {
3388
+ fs9.mkdirSync(configDir, { recursive: true });
3250
3389
  }
3251
- const configPath = path8.join(configDir, "sources.json");
3252
- fs8.writeFileSync(configPath, JSON.stringify({ sources: sources2 }, null, 2) + "\n", "utf-8");
3390
+ const configPath = path9.join(configDir, "sources.json");
3391
+ fs9.writeFileSync(configPath, JSON.stringify({ sources: sources2 }, null, 2) + "\n", "utf-8");
3253
3392
  }
3254
3393
  function detectSourceType(absPath) {
3255
3394
  try {
3256
- return fs8.statSync(absPath).isDirectory() ? "repo" : "file";
3395
+ return fs9.statSync(absPath).isDirectory() ? "repo" : "file";
3257
3396
  } catch {
3258
3397
  return "file";
3259
3398
  }
3260
3399
  }
3261
3400
  function isInsideDir(childPath, parentDir) {
3262
- const relative2 = path8.relative(parentDir, childPath);
3263
- return !relative2.startsWith("..") && !path8.isAbsolute(relative2);
3401
+ const relative2 = path9.relative(parentDir, childPath);
3402
+ return !relative2.startsWith("..") && !path9.isAbsolute(relative2);
3264
3403
  }
3265
3404
  function resolveAllSources(dir, cliSources, workspaces) {
3266
3405
  const seen = /* @__PURE__ */ new Map();
3267
- const projectRoot = path8.resolve(dir);
3406
+ const projectRoot = path9.resolve(dir);
3268
3407
  for (const src of cliSources) {
3269
- const absPath = path8.resolve(dir, src);
3408
+ const absPath = path9.resolve(dir, src);
3270
3409
  if (seen.has(absPath)) continue;
3271
3410
  const type = detectSourceType(absPath);
3272
3411
  seen.set(absPath, {
@@ -3279,12 +3418,12 @@ function resolveAllSources(dir, cliSources, workspaces) {
3279
3418
  for (const cfg of configSources) {
3280
3419
  if (cfg.type === "url") continue;
3281
3420
  if (!cfg.path) continue;
3282
- const absPath = path8.resolve(dir, cfg.path);
3421
+ const absPath = path9.resolve(dir, cfg.path);
3283
3422
  if (seen.has(absPath)) continue;
3284
3423
  seen.set(absPath, { absPath, config: cfg, origin: "config" });
3285
3424
  }
3286
3425
  for (const ws of workspaces) {
3287
- const absPath = path8.resolve(dir, ws);
3426
+ const absPath = path9.resolve(dir, ws);
3288
3427
  if (seen.has(absPath)) continue;
3289
3428
  if (!isInsideDir(absPath, projectRoot)) continue;
3290
3429
  seen.set(absPath, {
@@ -3297,7 +3436,7 @@ function resolveAllSources(dir, cliSources, workspaces) {
3297
3436
  for (const [absPath, resolved] of seen) {
3298
3437
  let stat;
3299
3438
  try {
3300
- stat = fs8.statSync(absPath);
3439
+ stat = fs9.statSync(absPath);
3301
3440
  } catch {
3302
3441
  console.warn(`Source ${resolved.config.path || absPath} not found, skipping`);
3303
3442
  continue;
@@ -3326,13 +3465,13 @@ function collectSourceSummary(resolved, projectDir) {
3326
3465
  if (config.type === "file") {
3327
3466
  return collectFileSummary(resolved, projectDir);
3328
3467
  }
3329
- const summaryPath = path8.join(absPath, ".caliber", "summary.json");
3468
+ const summaryPath = path9.join(absPath, ".caliber", "summary.json");
3330
3469
  const summaryContent = readFileOrNull(summaryPath);
3331
3470
  if (summaryContent) {
3332
3471
  try {
3333
3472
  const published = JSON.parse(summaryContent);
3334
3473
  return {
3335
- name: published.name || path8.basename(absPath),
3474
+ name: published.name || path9.basename(absPath),
3336
3475
  type: "repo",
3337
3476
  role: config.role || published.role || "related-repo",
3338
3477
  description: config.description || published.description || "",
@@ -3352,18 +3491,18 @@ function collectRepoSummary(resolved, projectDir) {
3352
3491
  let topLevelDirs;
3353
3492
  let keyFiles;
3354
3493
  try {
3355
- const entries = fs8.readdirSync(absPath, { withFileTypes: true });
3494
+ const entries = fs9.readdirSync(absPath, { withFileTypes: true });
3356
3495
  topLevelDirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules").map((e) => e.name).slice(0, 20);
3357
3496
  keyFiles = entries.filter((e) => e.isFile() && !e.name.startsWith(".")).map((e) => e.name).slice(0, 15);
3358
3497
  } catch {
3359
3498
  }
3360
- const claudeMdContent = readFileOrNull(path8.join(absPath, "CLAUDE.md"));
3499
+ const claudeMdContent = readFileOrNull(path9.join(absPath, "CLAUDE.md"));
3361
3500
  const existingClaudeMd = claudeMdContent ? claudeMdContent.slice(0, SOURCE_CONTENT_LIMIT) : void 0;
3362
- const readmeContent = readFileOrNull(path8.join(absPath, "README.md"));
3501
+ const readmeContent = readFileOrNull(path9.join(absPath, "README.md"));
3363
3502
  const readmeExcerpt = readmeContent ? readmeContent.slice(0, README_CONTENT_LIMIT) : void 0;
3364
3503
  const gitRemoteUrl = getGitRemoteUrl(absPath);
3365
3504
  return {
3366
- name: packageName || path8.basename(absPath),
3505
+ name: packageName || path9.basename(absPath),
3367
3506
  type: "repo",
3368
3507
  role: config.role || "related-repo",
3369
3508
  description: config.description || "",
@@ -3380,7 +3519,7 @@ function collectFileSummary(resolved, projectDir) {
3380
3519
  const { config, origin, absPath } = resolved;
3381
3520
  const content = readFileOrNull(absPath);
3382
3521
  return {
3383
- name: path8.basename(absPath),
3522
+ name: path9.basename(absPath),
3384
3523
  type: "file",
3385
3524
  role: config.role || "reference-doc",
3386
3525
  description: config.description || content?.slice(0, 100).split("\n")[0] || "",
@@ -4019,11 +4158,11 @@ ${f.content}
4019
4158
  }
4020
4159
 
4021
4160
  // src/writers/index.ts
4022
- import fs16 from "fs";
4161
+ import fs17 from "fs";
4023
4162
 
4024
4163
  // src/writers/claude/index.ts
4025
- import fs9 from "fs";
4026
- import path9 from "path";
4164
+ import fs10 from "fs";
4165
+ import path10 from "path";
4027
4166
 
4028
4167
  // src/writers/pre-commit-block.ts
4029
4168
  var BLOCK_START = "<!-- caliber:managed:pre-commit -->";
@@ -4089,13 +4228,13 @@ function getCursorLearningsRule() {
4089
4228
  // src/writers/claude/index.ts
4090
4229
  function writeClaudeConfig(config) {
4091
4230
  const written = [];
4092
- fs9.writeFileSync("CLAUDE.md", appendLearningsBlock(appendPreCommitBlock(config.claudeMd)));
4231
+ fs10.writeFileSync("CLAUDE.md", appendLearningsBlock(appendPreCommitBlock(config.claudeMd)));
4093
4232
  written.push("CLAUDE.md");
4094
4233
  if (config.skills?.length) {
4095
4234
  for (const skill of config.skills) {
4096
- const skillDir = path9.join(".claude", "skills", skill.name);
4097
- if (!fs9.existsSync(skillDir)) fs9.mkdirSync(skillDir, { recursive: true });
4098
- const skillPath = path9.join(skillDir, "SKILL.md");
4235
+ const skillDir = path10.join(".claude", "skills", skill.name);
4236
+ if (!fs10.existsSync(skillDir)) fs10.mkdirSync(skillDir, { recursive: true });
4237
+ const skillPath = path10.join(skillDir, "SKILL.md");
4099
4238
  const frontmatter = [
4100
4239
  "---",
4101
4240
  `name: ${skill.name}`,
@@ -4103,50 +4242,50 @@ function writeClaudeConfig(config) {
4103
4242
  "---",
4104
4243
  ""
4105
4244
  ].join("\n");
4106
- fs9.writeFileSync(skillPath, frontmatter + skill.content);
4245
+ fs10.writeFileSync(skillPath, frontmatter + skill.content);
4107
4246
  written.push(skillPath);
4108
4247
  }
4109
4248
  }
4110
4249
  if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {
4111
4250
  let existingServers = {};
4112
4251
  try {
4113
- if (fs9.existsSync(".mcp.json")) {
4114
- const existing = JSON.parse(fs9.readFileSync(".mcp.json", "utf-8"));
4252
+ if (fs10.existsSync(".mcp.json")) {
4253
+ const existing = JSON.parse(fs10.readFileSync(".mcp.json", "utf-8"));
4115
4254
  if (existing.mcpServers) existingServers = existing.mcpServers;
4116
4255
  }
4117
4256
  } catch {
4118
4257
  }
4119
4258
  const mergedServers = { ...existingServers, ...config.mcpServers };
4120
- fs9.writeFileSync(".mcp.json", JSON.stringify({ mcpServers: mergedServers }, null, 2));
4259
+ fs10.writeFileSync(".mcp.json", JSON.stringify({ mcpServers: mergedServers }, null, 2));
4121
4260
  written.push(".mcp.json");
4122
4261
  }
4123
4262
  return written;
4124
4263
  }
4125
4264
 
4126
4265
  // src/writers/cursor/index.ts
4127
- import fs10 from "fs";
4128
- import path10 from "path";
4266
+ import fs11 from "fs";
4267
+ import path11 from "path";
4129
4268
  function writeCursorConfig(config) {
4130
4269
  const written = [];
4131
4270
  if (config.cursorrules) {
4132
- fs10.writeFileSync(".cursorrules", config.cursorrules);
4271
+ fs11.writeFileSync(".cursorrules", config.cursorrules);
4133
4272
  written.push(".cursorrules");
4134
4273
  }
4135
4274
  const preCommitRule = getCursorPreCommitRule();
4136
4275
  const learningsRule = getCursorLearningsRule();
4137
4276
  const allRules = [...config.rules || [], preCommitRule, learningsRule];
4138
- const rulesDir = path10.join(".cursor", "rules");
4139
- if (!fs10.existsSync(rulesDir)) fs10.mkdirSync(rulesDir, { recursive: true });
4277
+ const rulesDir = path11.join(".cursor", "rules");
4278
+ if (!fs11.existsSync(rulesDir)) fs11.mkdirSync(rulesDir, { recursive: true });
4140
4279
  for (const rule of allRules) {
4141
- const rulePath = path10.join(rulesDir, rule.filename);
4142
- fs10.writeFileSync(rulePath, rule.content);
4280
+ const rulePath = path11.join(rulesDir, rule.filename);
4281
+ fs11.writeFileSync(rulePath, rule.content);
4143
4282
  written.push(rulePath);
4144
4283
  }
4145
4284
  if (config.skills?.length) {
4146
4285
  for (const skill of config.skills) {
4147
- const skillDir = path10.join(".cursor", "skills", skill.name);
4148
- if (!fs10.existsSync(skillDir)) fs10.mkdirSync(skillDir, { recursive: true });
4149
- const skillPath = path10.join(skillDir, "SKILL.md");
4286
+ const skillDir = path11.join(".cursor", "skills", skill.name);
4287
+ if (!fs11.existsSync(skillDir)) fs11.mkdirSync(skillDir, { recursive: true });
4288
+ const skillPath = path11.join(skillDir, "SKILL.md");
4150
4289
  const frontmatter = [
4151
4290
  "---",
4152
4291
  `name: ${skill.name}`,
@@ -4154,41 +4293,41 @@ function writeCursorConfig(config) {
4154
4293
  "---",
4155
4294
  ""
4156
4295
  ].join("\n");
4157
- fs10.writeFileSync(skillPath, frontmatter + skill.content);
4296
+ fs11.writeFileSync(skillPath, frontmatter + skill.content);
4158
4297
  written.push(skillPath);
4159
4298
  }
4160
4299
  }
4161
4300
  if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {
4162
4301
  const cursorDir = ".cursor";
4163
- if (!fs10.existsSync(cursorDir)) fs10.mkdirSync(cursorDir, { recursive: true });
4164
- const mcpPath = path10.join(cursorDir, "mcp.json");
4302
+ if (!fs11.existsSync(cursorDir)) fs11.mkdirSync(cursorDir, { recursive: true });
4303
+ const mcpPath = path11.join(cursorDir, "mcp.json");
4165
4304
  let existingServers = {};
4166
4305
  try {
4167
- if (fs10.existsSync(mcpPath)) {
4168
- const existing = JSON.parse(fs10.readFileSync(mcpPath, "utf-8"));
4306
+ if (fs11.existsSync(mcpPath)) {
4307
+ const existing = JSON.parse(fs11.readFileSync(mcpPath, "utf-8"));
4169
4308
  if (existing.mcpServers) existingServers = existing.mcpServers;
4170
4309
  }
4171
4310
  } catch {
4172
4311
  }
4173
4312
  const mergedServers = { ...existingServers, ...config.mcpServers };
4174
- fs10.writeFileSync(mcpPath, JSON.stringify({ mcpServers: mergedServers }, null, 2));
4313
+ fs11.writeFileSync(mcpPath, JSON.stringify({ mcpServers: mergedServers }, null, 2));
4175
4314
  written.push(mcpPath);
4176
4315
  }
4177
4316
  return written;
4178
4317
  }
4179
4318
 
4180
4319
  // src/writers/codex/index.ts
4181
- import fs11 from "fs";
4182
- import path11 from "path";
4320
+ import fs12 from "fs";
4321
+ import path12 from "path";
4183
4322
  function writeCodexConfig(config) {
4184
4323
  const written = [];
4185
- fs11.writeFileSync("AGENTS.md", appendLearningsBlock(appendPreCommitBlock(config.agentsMd)));
4324
+ fs12.writeFileSync("AGENTS.md", appendLearningsBlock(appendPreCommitBlock(config.agentsMd)));
4186
4325
  written.push("AGENTS.md");
4187
4326
  if (config.skills?.length) {
4188
4327
  for (const skill of config.skills) {
4189
- const skillDir = path11.join(".agents", "skills", skill.name);
4190
- if (!fs11.existsSync(skillDir)) fs11.mkdirSync(skillDir, { recursive: true });
4191
- const skillPath = path11.join(skillDir, "SKILL.md");
4328
+ const skillDir = path12.join(".agents", "skills", skill.name);
4329
+ if (!fs12.existsSync(skillDir)) fs12.mkdirSync(skillDir, { recursive: true });
4330
+ const skillPath = path12.join(skillDir, "SKILL.md");
4192
4331
  const frontmatter = [
4193
4332
  "---",
4194
4333
  `name: ${skill.name}`,
@@ -4196,7 +4335,7 @@ function writeCodexConfig(config) {
4196
4335
  "---",
4197
4336
  ""
4198
4337
  ].join("\n");
4199
- fs11.writeFileSync(skillPath, frontmatter + skill.content);
4338
+ fs12.writeFileSync(skillPath, frontmatter + skill.content);
4200
4339
  written.push(skillPath);
4201
4340
  }
4202
4341
  }
@@ -4204,20 +4343,20 @@ function writeCodexConfig(config) {
4204
4343
  }
4205
4344
 
4206
4345
  // src/writers/github-copilot/index.ts
4207
- import fs12 from "fs";
4208
- import path12 from "path";
4346
+ import fs13 from "fs";
4347
+ import path13 from "path";
4209
4348
  function writeGithubCopilotConfig(config) {
4210
4349
  const written = [];
4211
4350
  if (config.instructions) {
4212
- fs12.mkdirSync(".github", { recursive: true });
4213
- fs12.writeFileSync(path12.join(".github", "copilot-instructions.md"), appendLearningsBlock(appendPreCommitBlock(config.instructions)));
4351
+ fs13.mkdirSync(".github", { recursive: true });
4352
+ fs13.writeFileSync(path13.join(".github", "copilot-instructions.md"), appendLearningsBlock(appendPreCommitBlock(config.instructions)));
4214
4353
  written.push(".github/copilot-instructions.md");
4215
4354
  }
4216
4355
  if (config.instructionFiles?.length) {
4217
- const instructionsDir = path12.join(".github", "instructions");
4218
- fs12.mkdirSync(instructionsDir, { recursive: true });
4356
+ const instructionsDir = path13.join(".github", "instructions");
4357
+ fs13.mkdirSync(instructionsDir, { recursive: true });
4219
4358
  for (const file of config.instructionFiles) {
4220
- fs12.writeFileSync(path12.join(instructionsDir, file.filename), file.content);
4359
+ fs13.writeFileSync(path13.join(instructionsDir, file.filename), file.content);
4221
4360
  written.push(`.github/instructions/${file.filename}`);
4222
4361
  }
4223
4362
  }
@@ -4225,37 +4364,36 @@ function writeGithubCopilotConfig(config) {
4225
4364
  }
4226
4365
 
4227
4366
  // src/writers/backup.ts
4228
- init_constants();
4229
- import fs13 from "fs";
4230
- import path13 from "path";
4367
+ import fs14 from "fs";
4368
+ import path14 from "path";
4231
4369
  function createBackup(files) {
4232
4370
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4233
- const backupDir = path13.join(BACKUPS_DIR, timestamp);
4371
+ const backupDir = path14.join(BACKUPS_DIR, timestamp);
4234
4372
  for (const file of files) {
4235
- if (!fs13.existsSync(file)) continue;
4236
- const dest = path13.join(backupDir, file);
4237
- const destDir = path13.dirname(dest);
4238
- if (!fs13.existsSync(destDir)) {
4239
- fs13.mkdirSync(destDir, { recursive: true });
4373
+ if (!fs14.existsSync(file)) continue;
4374
+ const dest = path14.join(backupDir, file);
4375
+ const destDir = path14.dirname(dest);
4376
+ if (!fs14.existsSync(destDir)) {
4377
+ fs14.mkdirSync(destDir, { recursive: true });
4240
4378
  }
4241
- fs13.copyFileSync(file, dest);
4379
+ fs14.copyFileSync(file, dest);
4242
4380
  }
4243
4381
  return backupDir;
4244
4382
  }
4245
4383
  function restoreBackup(backupDir, file) {
4246
- const backupFile = path13.join(backupDir, file);
4247
- if (!fs13.existsSync(backupFile)) return false;
4248
- const destDir = path13.dirname(file);
4249
- if (!fs13.existsSync(destDir)) {
4250
- fs13.mkdirSync(destDir, { recursive: true });
4384
+ const backupFile = path14.join(backupDir, file);
4385
+ if (!fs14.existsSync(backupFile)) return false;
4386
+ const destDir = path14.dirname(file);
4387
+ if (!fs14.existsSync(destDir)) {
4388
+ fs14.mkdirSync(destDir, { recursive: true });
4251
4389
  }
4252
- fs13.copyFileSync(backupFile, file);
4390
+ fs14.copyFileSync(backupFile, file);
4253
4391
  return true;
4254
4392
  }
4255
4393
 
4256
4394
  // src/lib/builtin-skills.ts
4257
- import fs14 from "fs";
4258
- import path14 from "path";
4395
+ import fs15 from "fs";
4396
+ import path15 from "path";
4259
4397
  function buildSkillContent(skill) {
4260
4398
  const frontmatter = `---
4261
4399
  name: ${skill.name}
@@ -4381,19 +4519,19 @@ User: "never use any in TypeScript, use unknown instead"
4381
4519
  };
4382
4520
  var BUILTIN_SKILLS = [FIND_SKILLS_SKILL, SAVE_LEARNING_SKILL];
4383
4521
  var PLATFORM_CONFIGS = [
4384
- { platformDir: ".claude", skillsDir: path14.join(".claude", "skills") },
4385
- { platformDir: ".cursor", skillsDir: path14.join(".cursor", "skills") },
4386
- { platformDir: ".agents", skillsDir: path14.join(".agents", "skills") }
4522
+ { platformDir: ".claude", skillsDir: path15.join(".claude", "skills") },
4523
+ { platformDir: ".cursor", skillsDir: path15.join(".cursor", "skills") },
4524
+ { platformDir: ".agents", skillsDir: path15.join(".agents", "skills") }
4387
4525
  ];
4388
4526
  function ensureBuiltinSkills() {
4389
4527
  const written = [];
4390
4528
  for (const { platformDir, skillsDir } of PLATFORM_CONFIGS) {
4391
- if (!fs14.existsSync(platformDir)) continue;
4529
+ if (!fs15.existsSync(platformDir)) continue;
4392
4530
  for (const skill of BUILTIN_SKILLS) {
4393
- const skillPath = path14.join(skillsDir, skill.name, "SKILL.md");
4394
- if (fs14.existsSync(skillPath)) continue;
4395
- fs14.mkdirSync(path14.dirname(skillPath), { recursive: true });
4396
- fs14.writeFileSync(skillPath, buildSkillContent(skill));
4531
+ const skillPath = path15.join(skillsDir, skill.name, "SKILL.md");
4532
+ if (fs15.existsSync(skillPath)) continue;
4533
+ fs15.mkdirSync(path15.dirname(skillPath), { recursive: true });
4534
+ fs15.writeFileSync(skillPath, buildSkillContent(skill));
4397
4535
  written.push(skillPath);
4398
4536
  }
4399
4537
  }
@@ -4401,34 +4539,33 @@ function ensureBuiltinSkills() {
4401
4539
  }
4402
4540
 
4403
4541
  // src/writers/manifest.ts
4404
- init_constants();
4405
- import fs15 from "fs";
4406
- import crypto2 from "crypto";
4542
+ import fs16 from "fs";
4543
+ import crypto3 from "crypto";
4407
4544
  function readManifest() {
4408
4545
  try {
4409
- if (!fs15.existsSync(MANIFEST_FILE)) return null;
4410
- return JSON.parse(fs15.readFileSync(MANIFEST_FILE, "utf-8"));
4546
+ if (!fs16.existsSync(MANIFEST_FILE)) return null;
4547
+ return JSON.parse(fs16.readFileSync(MANIFEST_FILE, "utf-8"));
4411
4548
  } catch {
4412
4549
  return null;
4413
4550
  }
4414
4551
  }
4415
4552
  function writeManifest(manifest) {
4416
- if (!fs15.existsSync(CALIBER_DIR)) {
4417
- fs15.mkdirSync(CALIBER_DIR, { recursive: true });
4553
+ if (!fs16.existsSync(CALIBER_DIR)) {
4554
+ fs16.mkdirSync(CALIBER_DIR, { recursive: true });
4418
4555
  }
4419
- fs15.writeFileSync(MANIFEST_FILE, JSON.stringify(manifest, null, 2));
4556
+ fs16.writeFileSync(MANIFEST_FILE, JSON.stringify(manifest, null, 2));
4420
4557
  }
4421
4558
  function fileChecksum(filePath) {
4422
- const content = fs15.readFileSync(filePath);
4423
- return crypto2.createHash("sha256").update(content).digest("hex");
4559
+ const content = fs16.readFileSync(filePath);
4560
+ return crypto3.createHash("sha256").update(content).digest("hex");
4424
4561
  }
4425
4562
 
4426
4563
  // src/writers/index.ts
4427
4564
  function writeSetup(setup) {
4428
4565
  const filesToWrite = getFilesToWrite(setup);
4429
- const filesToDelete = (setup.deletions || []).map((d) => d.filePath).filter((f) => fs16.existsSync(f));
4566
+ const filesToDelete = (setup.deletions || []).map((d) => d.filePath).filter((f) => fs17.existsSync(f));
4430
4567
  const existingFiles = [
4431
- ...filesToWrite.filter((f) => fs16.existsSync(f)),
4568
+ ...filesToWrite.filter((f) => fs17.existsSync(f)),
4432
4569
  ...filesToDelete
4433
4570
  ];
4434
4571
  const backupDir = existingFiles.length > 0 ? createBackup(existingFiles) : void 0;
@@ -4447,7 +4584,7 @@ function writeSetup(setup) {
4447
4584
  }
4448
4585
  const deleted = [];
4449
4586
  for (const filePath of filesToDelete) {
4450
- fs16.unlinkSync(filePath);
4587
+ fs17.unlinkSync(filePath);
4451
4588
  deleted.push(filePath);
4452
4589
  }
4453
4590
  written.push(...ensureBuiltinSkills());
@@ -4478,8 +4615,8 @@ function undoSetup() {
4478
4615
  const removed = [];
4479
4616
  for (const entry of manifest.entries) {
4480
4617
  if (entry.action === "created") {
4481
- if (fs16.existsSync(entry.path)) {
4482
- fs16.unlinkSync(entry.path);
4618
+ if (fs17.existsSync(entry.path)) {
4619
+ fs17.unlinkSync(entry.path);
4483
4620
  removed.push(entry.path);
4484
4621
  }
4485
4622
  } else if ((entry.action === "modified" || entry.action === "deleted") && manifest.backupDir) {
@@ -4488,9 +4625,8 @@ function undoSetup() {
4488
4625
  }
4489
4626
  }
4490
4627
  }
4491
- const { MANIFEST_FILE: MANIFEST_FILE2 } = (init_constants(), __toCommonJS(constants_exports));
4492
- if (fs16.existsSync(MANIFEST_FILE2)) {
4493
- fs16.unlinkSync(MANIFEST_FILE2);
4628
+ if (fs17.existsSync(MANIFEST_FILE)) {
4629
+ fs17.unlinkSync(MANIFEST_FILE);
4494
4630
  }
4495
4631
  return { restored, removed };
4496
4632
  }
@@ -4501,7 +4637,7 @@ function getFilesToWrite(setup) {
4501
4637
  if (setup.claude.mcpServers) files.push(".mcp.json");
4502
4638
  if (setup.claude.skills) {
4503
4639
  for (const s of setup.claude.skills) {
4504
- files.push(`.claude/skills/${s.name.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}.md`);
4640
+ files.push(`.claude/skills/${s.name.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}/SKILL.md`);
4505
4641
  }
4506
4642
  }
4507
4643
  }
@@ -4531,23 +4667,22 @@ function getFilesToWrite(setup) {
4531
4667
  }
4532
4668
  function ensureGitignore() {
4533
4669
  const gitignorePath = ".gitignore";
4534
- if (fs16.existsSync(gitignorePath)) {
4535
- const content = fs16.readFileSync(gitignorePath, "utf-8");
4670
+ if (fs17.existsSync(gitignorePath)) {
4671
+ const content = fs17.readFileSync(gitignorePath, "utf-8");
4536
4672
  if (!content.includes(".caliber/")) {
4537
- fs16.appendFileSync(gitignorePath, "\n# Caliber local state\n.caliber/\n");
4673
+ fs17.appendFileSync(gitignorePath, "\n# Caliber local state\n.caliber/\n");
4538
4674
  }
4539
4675
  } else {
4540
- fs16.writeFileSync(gitignorePath, "# Caliber local state\n.caliber/\n");
4676
+ fs17.writeFileSync(gitignorePath, "# Caliber local state\n.caliber/\n");
4541
4677
  }
4542
4678
  }
4543
4679
 
4544
4680
  // src/writers/staging.ts
4545
- init_constants();
4546
- import fs17 from "fs";
4547
- import path15 from "path";
4548
- var STAGED_DIR = path15.join(CALIBER_DIR, "staged");
4549
- var PROPOSED_DIR = path15.join(STAGED_DIR, "proposed");
4550
- var CURRENT_DIR = path15.join(STAGED_DIR, "current");
4681
+ import fs18 from "fs";
4682
+ import path16 from "path";
4683
+ var STAGED_DIR = path16.join(CALIBER_DIR, "staged");
4684
+ var PROPOSED_DIR = path16.join(STAGED_DIR, "proposed");
4685
+ var CURRENT_DIR = path16.join(STAGED_DIR, "current");
4551
4686
  function normalizeContent(content) {
4552
4687
  return content.split("\n").map((line) => line.trimEnd()).join("\n").replace(/\n{3,}/g, "\n\n").trim();
4553
4688
  }
@@ -4557,20 +4692,20 @@ function stageFiles(files, projectDir) {
4557
4692
  let modifiedFiles = 0;
4558
4693
  const stagedFiles = [];
4559
4694
  for (const file of files) {
4560
- const originalPath = path15.join(projectDir, file.path);
4561
- if (fs17.existsSync(originalPath)) {
4562
- const existing = fs17.readFileSync(originalPath, "utf-8");
4695
+ const originalPath = path16.join(projectDir, file.path);
4696
+ if (fs18.existsSync(originalPath)) {
4697
+ const existing = fs18.readFileSync(originalPath, "utf-8");
4563
4698
  if (normalizeContent(existing) === normalizeContent(file.content)) {
4564
4699
  continue;
4565
4700
  }
4566
4701
  }
4567
- const proposedPath = path15.join(PROPOSED_DIR, file.path);
4568
- fs17.mkdirSync(path15.dirname(proposedPath), { recursive: true });
4569
- fs17.writeFileSync(proposedPath, file.content);
4570
- if (fs17.existsSync(originalPath)) {
4571
- const currentPath = path15.join(CURRENT_DIR, file.path);
4572
- fs17.mkdirSync(path15.dirname(currentPath), { recursive: true });
4573
- fs17.copyFileSync(originalPath, currentPath);
4702
+ const proposedPath = path16.join(PROPOSED_DIR, file.path);
4703
+ fs18.mkdirSync(path16.dirname(proposedPath), { recursive: true });
4704
+ fs18.writeFileSync(proposedPath, file.content);
4705
+ if (fs18.existsSync(originalPath)) {
4706
+ const currentPath = path16.join(CURRENT_DIR, file.path);
4707
+ fs18.mkdirSync(path16.dirname(currentPath), { recursive: true });
4708
+ fs18.copyFileSync(originalPath, currentPath);
4574
4709
  modifiedFiles++;
4575
4710
  stagedFiles.push({ relativePath: file.path, proposedPath, currentPath, originalPath, isNew: false });
4576
4711
  } else {
@@ -4581,13 +4716,13 @@ function stageFiles(files, projectDir) {
4581
4716
  return { newFiles, modifiedFiles, stagedFiles };
4582
4717
  }
4583
4718
  function cleanupStaging() {
4584
- if (fs17.existsSync(STAGED_DIR)) {
4585
- fs17.rmSync(STAGED_DIR, { recursive: true, force: true });
4719
+ if (fs18.existsSync(STAGED_DIR)) {
4720
+ fs18.rmSync(STAGED_DIR, { recursive: true, force: true });
4586
4721
  }
4587
4722
  }
4588
4723
 
4589
4724
  // src/commands/setup-files.ts
4590
- import fs18 from "fs";
4725
+ import fs19 from "fs";
4591
4726
  function collectSetupFiles(setup, targetAgent) {
4592
4727
  const files = [];
4593
4728
  const claude = setup.claude;
@@ -4646,7 +4781,7 @@ function collectSetupFiles(setup, targetAgent) {
4646
4781
  }
4647
4782
  }
4648
4783
  const codexTargeted = targetAgent ? targetAgent.includes("codex") : false;
4649
- if (codexTargeted && !fs18.existsSync("AGENTS.md") && !(codex && codex.agentsMd)) {
4784
+ if (codexTargeted && !fs19.existsSync("AGENTS.md") && !(codex && codex.agentsMd)) {
4650
4785
  const agentRefs = [];
4651
4786
  if (claude) agentRefs.push("See `CLAUDE.md` for Claude Code configuration.");
4652
4787
  if (cursor) agentRefs.push("See `.cursor/rules/` for Cursor rules.");
@@ -4664,9 +4799,9 @@ ${agentRefs.join(" ")}
4664
4799
 
4665
4800
  // src/lib/learning-hooks.ts
4666
4801
  init_resolve_caliber();
4667
- import fs20 from "fs";
4668
- import path16 from "path";
4669
- var SETTINGS_PATH = path16.join(".claude", "settings.json");
4802
+ import fs21 from "fs";
4803
+ import path17 from "path";
4804
+ var SETTINGS_PATH = path17.join(".claude", "settings.json");
4670
4805
  var HOOK_TAILS = [
4671
4806
  { event: "PostToolUse", tail: "learn observe", description: "Caliber: recording tool usage for session learning" },
4672
4807
  { event: "PostToolUseFailure", tail: "learn observe --failure", description: "Caliber: recording tool failure for session learning" },
@@ -4683,17 +4818,17 @@ function getHookConfigs() {
4683
4818
  }));
4684
4819
  }
4685
4820
  function readSettings() {
4686
- if (!fs20.existsSync(SETTINGS_PATH)) return {};
4821
+ if (!fs21.existsSync(SETTINGS_PATH)) return {};
4687
4822
  try {
4688
- return JSON.parse(fs20.readFileSync(SETTINGS_PATH, "utf-8"));
4823
+ return JSON.parse(fs21.readFileSync(SETTINGS_PATH, "utf-8"));
4689
4824
  } catch {
4690
4825
  return {};
4691
4826
  }
4692
4827
  }
4693
4828
  function writeSettings(settings) {
4694
- const dir = path16.dirname(SETTINGS_PATH);
4695
- if (!fs20.existsSync(dir)) fs20.mkdirSync(dir, { recursive: true });
4696
- fs20.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
4829
+ const dir = path17.dirname(SETTINGS_PATH);
4830
+ if (!fs21.existsSync(dir)) fs21.mkdirSync(dir, { recursive: true });
4831
+ fs21.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
4697
4832
  }
4698
4833
  function hasLearningHook(matchers, tail) {
4699
4834
  return matchers.some((entry) => entry.hooks?.some((h) => isCaliberCommand(h.command, tail)));
@@ -4727,7 +4862,7 @@ function installLearningHooks() {
4727
4862
  writeSettings(settings);
4728
4863
  return { installed: true, alreadyInstalled: false };
4729
4864
  }
4730
- var CURSOR_HOOKS_PATH = path16.join(".cursor", "hooks.json");
4865
+ var CURSOR_HOOKS_PATH = path17.join(".cursor", "hooks.json");
4731
4866
  var CURSOR_HOOK_EVENTS = [
4732
4867
  { event: "postToolUse", tail: "learn observe" },
4733
4868
  { event: "postToolUseFailure", tail: "learn observe --failure" },
@@ -4735,17 +4870,17 @@ var CURSOR_HOOK_EVENTS = [
4735
4870
  { event: "sessionEnd", tail: "learn finalize --auto" }
4736
4871
  ];
4737
4872
  function readCursorHooks() {
4738
- if (!fs20.existsSync(CURSOR_HOOKS_PATH)) return { version: 1, hooks: {} };
4873
+ if (!fs21.existsSync(CURSOR_HOOKS_PATH)) return { version: 1, hooks: {} };
4739
4874
  try {
4740
- return JSON.parse(fs20.readFileSync(CURSOR_HOOKS_PATH, "utf-8"));
4875
+ return JSON.parse(fs21.readFileSync(CURSOR_HOOKS_PATH, "utf-8"));
4741
4876
  } catch {
4742
4877
  return { version: 1, hooks: {} };
4743
4878
  }
4744
4879
  }
4745
4880
  function writeCursorHooks(config) {
4746
- const dir = path16.dirname(CURSOR_HOOKS_PATH);
4747
- if (!fs20.existsSync(dir)) fs20.mkdirSync(dir, { recursive: true });
4748
- fs20.writeFileSync(CURSOR_HOOKS_PATH, JSON.stringify(config, null, 2));
4881
+ const dir = path17.dirname(CURSOR_HOOKS_PATH);
4882
+ if (!fs21.existsSync(dir)) fs21.mkdirSync(dir, { recursive: true });
4883
+ fs21.writeFileSync(CURSOR_HOOKS_PATH, JSON.stringify(config, null, 2));
4749
4884
  }
4750
4885
  function hasCursorHook(entries, tail) {
4751
4886
  return entries.some((e) => isCaliberCommand(e.command, tail));
@@ -4814,11 +4949,10 @@ function removeLearningHooks() {
4814
4949
  }
4815
4950
 
4816
4951
  // src/lib/state.ts
4817
- init_constants();
4818
- import fs21 from "fs";
4819
- import path17 from "path";
4952
+ import fs22 from "fs";
4953
+ import path18 from "path";
4820
4954
  import { execSync as execSync7 } from "child_process";
4821
- var STATE_FILE = path17.join(CALIBER_DIR, ".caliber-state.json");
4955
+ var STATE_FILE = path18.join(CALIBER_DIR, ".caliber-state.json");
4822
4956
  function normalizeTargetAgent(value) {
4823
4957
  if (Array.isArray(value)) return value;
4824
4958
  if (typeof value === "string") {
@@ -4829,8 +4963,8 @@ function normalizeTargetAgent(value) {
4829
4963
  }
4830
4964
  function readState() {
4831
4965
  try {
4832
- if (!fs21.existsSync(STATE_FILE)) return null;
4833
- const raw = JSON.parse(fs21.readFileSync(STATE_FILE, "utf-8"));
4966
+ if (!fs22.existsSync(STATE_FILE)) return null;
4967
+ const raw = JSON.parse(fs22.readFileSync(STATE_FILE, "utf-8"));
4834
4968
  if (raw.targetAgent) raw.targetAgent = normalizeTargetAgent(raw.targetAgent);
4835
4969
  return raw;
4836
4970
  } catch {
@@ -4838,10 +4972,10 @@ function readState() {
4838
4972
  }
4839
4973
  }
4840
4974
  function writeState(state) {
4841
- if (!fs21.existsSync(CALIBER_DIR)) {
4842
- fs21.mkdirSync(CALIBER_DIR, { recursive: true });
4975
+ if (!fs22.existsSync(CALIBER_DIR)) {
4976
+ fs22.mkdirSync(CALIBER_DIR, { recursive: true });
4843
4977
  }
4844
- fs21.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
4978
+ fs22.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
4845
4979
  }
4846
4980
  function getCurrentHeadSha() {
4847
4981
  try {
@@ -5899,23 +6033,22 @@ function checkSources(dir) {
5899
6033
  }
5900
6034
 
5901
6035
  // src/scoring/dismissed.ts
5902
- init_constants();
5903
- import fs22 from "fs";
5904
- import path18 from "path";
5905
- var DISMISSED_FILE = path18.join(CALIBER_DIR, "dismissed-checks.json");
6036
+ import fs23 from "fs";
6037
+ import path19 from "path";
6038
+ var DISMISSED_FILE = path19.join(CALIBER_DIR, "dismissed-checks.json");
5906
6039
  function readDismissedChecks() {
5907
6040
  try {
5908
- if (!fs22.existsSync(DISMISSED_FILE)) return [];
5909
- return JSON.parse(fs22.readFileSync(DISMISSED_FILE, "utf-8"));
6041
+ if (!fs23.existsSync(DISMISSED_FILE)) return [];
6042
+ return JSON.parse(fs23.readFileSync(DISMISSED_FILE, "utf-8"));
5910
6043
  } catch {
5911
6044
  return [];
5912
6045
  }
5913
6046
  }
5914
6047
  function writeDismissedChecks(checks) {
5915
- if (!fs22.existsSync(CALIBER_DIR)) {
5916
- fs22.mkdirSync(CALIBER_DIR, { recursive: true });
6048
+ if (!fs23.existsSync(CALIBER_DIR)) {
6049
+ fs23.mkdirSync(CALIBER_DIR, { recursive: true });
5917
6050
  }
5918
- fs22.writeFileSync(DISMISSED_FILE, JSON.stringify(checks, null, 2) + "\n");
6051
+ fs23.writeFileSync(DISMISSED_FILE, JSON.stringify(checks, null, 2) + "\n");
5919
6052
  }
5920
6053
  function getDismissedIds() {
5921
6054
  return new Set(readDismissedChecks().map((c) => c.id));
@@ -6161,152 +6294,6 @@ import ora from "ora";
6161
6294
  import select3 from "@inquirer/select";
6162
6295
  import { mkdirSync, readFileSync as readFileSync4, readdirSync as readdirSync4, existsSync as existsSync8, writeFileSync } from "fs";
6163
6296
  import { join as join10, dirname as dirname2 } from "path";
6164
-
6165
- // src/scanner/index.ts
6166
- import fs23 from "fs";
6167
- import path19 from "path";
6168
- import crypto3 from "crypto";
6169
- function scanLocalState(dir) {
6170
- const items = [];
6171
- const claudeMdPath = path19.join(dir, "CLAUDE.md");
6172
- if (fs23.existsSync(claudeMdPath)) {
6173
- items.push({
6174
- type: "rule",
6175
- platform: "claude",
6176
- name: "CLAUDE.md",
6177
- contentHash: hashFile(claudeMdPath),
6178
- path: claudeMdPath
6179
- });
6180
- }
6181
- const skillsDir = path19.join(dir, ".claude", "skills");
6182
- if (fs23.existsSync(skillsDir)) {
6183
- for (const file of fs23.readdirSync(skillsDir).filter((f) => f.endsWith(".md"))) {
6184
- const filePath = path19.join(skillsDir, file);
6185
- items.push({
6186
- type: "skill",
6187
- platform: "claude",
6188
- name: file,
6189
- contentHash: hashFile(filePath),
6190
- path: filePath
6191
- });
6192
- }
6193
- }
6194
- const mcpJsonPath = path19.join(dir, ".mcp.json");
6195
- if (fs23.existsSync(mcpJsonPath)) {
6196
- try {
6197
- const mcpJson = JSON.parse(fs23.readFileSync(mcpJsonPath, "utf-8"));
6198
- if (mcpJson.mcpServers) {
6199
- for (const name of Object.keys(mcpJson.mcpServers)) {
6200
- items.push({
6201
- type: "mcp",
6202
- platform: "claude",
6203
- name,
6204
- contentHash: hashJson(mcpJson.mcpServers[name]),
6205
- path: mcpJsonPath
6206
- });
6207
- }
6208
- }
6209
- } catch {
6210
- }
6211
- }
6212
- const agentsMdPath = path19.join(dir, "AGENTS.md");
6213
- if (fs23.existsSync(agentsMdPath)) {
6214
- items.push({
6215
- type: "rule",
6216
- platform: "codex",
6217
- name: "AGENTS.md",
6218
- contentHash: hashFile(agentsMdPath),
6219
- path: agentsMdPath
6220
- });
6221
- }
6222
- const codexSkillsDir = path19.join(dir, ".agents", "skills");
6223
- if (fs23.existsSync(codexSkillsDir)) {
6224
- try {
6225
- for (const name of fs23.readdirSync(codexSkillsDir)) {
6226
- const skillFile = path19.join(codexSkillsDir, name, "SKILL.md");
6227
- if (fs23.existsSync(skillFile)) {
6228
- items.push({
6229
- type: "skill",
6230
- platform: "codex",
6231
- name: `${name}/SKILL.md`,
6232
- contentHash: hashFile(skillFile),
6233
- path: skillFile
6234
- });
6235
- }
6236
- }
6237
- } catch {
6238
- }
6239
- }
6240
- const cursorrulesPath = path19.join(dir, ".cursorrules");
6241
- if (fs23.existsSync(cursorrulesPath)) {
6242
- items.push({
6243
- type: "rule",
6244
- platform: "cursor",
6245
- name: ".cursorrules",
6246
- contentHash: hashFile(cursorrulesPath),
6247
- path: cursorrulesPath
6248
- });
6249
- }
6250
- const cursorRulesDir = path19.join(dir, ".cursor", "rules");
6251
- if (fs23.existsSync(cursorRulesDir)) {
6252
- for (const file of fs23.readdirSync(cursorRulesDir).filter((f) => f.endsWith(".mdc"))) {
6253
- const filePath = path19.join(cursorRulesDir, file);
6254
- items.push({
6255
- type: "rule",
6256
- platform: "cursor",
6257
- name: file,
6258
- contentHash: hashFile(filePath),
6259
- path: filePath
6260
- });
6261
- }
6262
- }
6263
- const cursorSkillsDir = path19.join(dir, ".cursor", "skills");
6264
- if (fs23.existsSync(cursorSkillsDir)) {
6265
- try {
6266
- for (const name of fs23.readdirSync(cursorSkillsDir)) {
6267
- const skillFile = path19.join(cursorSkillsDir, name, "SKILL.md");
6268
- if (fs23.existsSync(skillFile)) {
6269
- items.push({
6270
- type: "skill",
6271
- platform: "cursor",
6272
- name: `${name}/SKILL.md`,
6273
- contentHash: hashFile(skillFile),
6274
- path: skillFile
6275
- });
6276
- }
6277
- }
6278
- } catch {
6279
- }
6280
- }
6281
- const cursorMcpPath = path19.join(dir, ".cursor", "mcp.json");
6282
- if (fs23.existsSync(cursorMcpPath)) {
6283
- try {
6284
- const mcpJson = JSON.parse(fs23.readFileSync(cursorMcpPath, "utf-8"));
6285
- if (mcpJson.mcpServers) {
6286
- for (const name of Object.keys(mcpJson.mcpServers)) {
6287
- items.push({
6288
- type: "mcp",
6289
- platform: "cursor",
6290
- name,
6291
- contentHash: hashJson(mcpJson.mcpServers[name]),
6292
- path: cursorMcpPath
6293
- });
6294
- }
6295
- }
6296
- } catch {
6297
- }
6298
- }
6299
- return items;
6300
- }
6301
- function hashFile(filePath) {
6302
- const text = fs23.readFileSync(filePath, "utf-8");
6303
- return crypto3.createHash("sha256").update(JSON.stringify({ text })).digest("hex");
6304
- }
6305
- function hashJson(obj) {
6306
- return crypto3.createHash("sha256").update(JSON.stringify(obj)).digest("hex");
6307
- }
6308
-
6309
- // src/commands/recommend.ts
6310
6297
  init_config();
6311
6298
 
6312
6299
  // src/telemetry/index.ts
@@ -6316,10 +6303,10 @@ import chalk5 from "chalk";
6316
6303
  // src/telemetry/config.ts
6317
6304
  import fs24 from "fs";
6318
6305
  import path20 from "path";
6319
- import os4 from "os";
6306
+ import os5 from "os";
6320
6307
  import crypto4 from "crypto";
6321
6308
  import { execSync as execSync11 } from "child_process";
6322
- var CONFIG_DIR2 = path20.join(os4.homedir(), ".caliber");
6309
+ var CONFIG_DIR2 = path20.join(os5.homedir(), ".caliber");
6323
6310
  var CONFIG_FILE2 = path20.join(CONFIG_DIR2, "config.json");
6324
6311
  var runtimeDisabled = false;
6325
6312
  function readConfig() {
@@ -8599,6 +8586,11 @@ async function initCommand(options) {
8599
8586
  } else {
8600
8587
  console.log(brand.bold("\n CALIBER") + chalk14.dim(" \u2014 regenerating config\n"));
8601
8588
  }
8589
+ const platforms = detectPlatforms();
8590
+ if (!platforms.claude && !platforms.cursor && !platforms.codex) {
8591
+ console.log(chalk14.yellow(" \u26A0 No supported AI platforms detected (Claude, Cursor, Codex)."));
8592
+ console.log(chalk14.yellow(" Caliber will still generate config files, but they won't be auto-installed.\n"));
8593
+ }
8602
8594
  const report = options.debugReport ? new DebugReport() : null;
8603
8595
  console.log(title.bold(" Step 1/4 \u2014 Setup\n"));
8604
8596
  let config = loadConfig();
@@ -9334,7 +9326,7 @@ async function regenerateCommand(options) {
9334
9326
 
9335
9327
  // src/commands/score.ts
9336
9328
  import fs33 from "fs";
9337
- import os6 from "os";
9329
+ import os7 from "os";
9338
9330
  import path25 from "path";
9339
9331
  import { execFileSync } from "child_process";
9340
9332
  import chalk18 from "chalk";
@@ -9342,7 +9334,7 @@ var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".cursorrules", "CALIBER_LEARNINGS
9342
9334
  var CONFIG_DIRS = [".claude", ".cursor"];
9343
9335
  function scoreBaseRef(ref, target) {
9344
9336
  if (!/^[\w.\-\/~^@{}]+$/.test(ref)) return null;
9345
- const tmpDir = fs33.mkdtempSync(path25.join(os6.tmpdir(), "caliber-compare-"));
9337
+ const tmpDir = fs33.mkdtempSync(path25.join(os7.tmpdir(), "caliber-compare-"));
9346
9338
  try {
9347
9339
  for (const file of CONFIG_FILES) {
9348
9340
  try {
@@ -9658,7 +9650,6 @@ function isSimilarLearning(a, b) {
9658
9650
  }
9659
9651
 
9660
9652
  // src/learner/writer.ts
9661
- init_constants();
9662
9653
  var LEARNINGS_FILE = "CALIBER_LEARNINGS.md";
9663
9654
  var LEARNINGS_HEADER = `# Caliber Learnings
9664
9655
 
@@ -10354,7 +10345,6 @@ function readStdin() {
10354
10345
  }
10355
10346
 
10356
10347
  // src/learner/storage.ts
10357
- init_constants();
10358
10348
  import fs40 from "fs";
10359
10349
  import path31 from "path";
10360
10350
  var MAX_RESPONSE_LENGTH = 2e3;
@@ -10529,7 +10519,6 @@ function sanitizeSecrets(text) {
10529
10519
  }
10530
10520
 
10531
10521
  // src/lib/notifications.ts
10532
- init_constants();
10533
10522
  import fs41 from "fs";
10534
10523
  import path32 from "path";
10535
10524
  import chalk22 from "chalk";
@@ -10698,7 +10687,6 @@ function calculateSessionWaste(events) {
10698
10687
  init_config();
10699
10688
 
10700
10689
  // src/learner/roi.ts
10701
- init_constants();
10702
10690
  import fs42 from "fs";
10703
10691
  import path33 from "path";
10704
10692
  var DEFAULT_TOTALS = {
@@ -10935,7 +10923,6 @@ function findStaleLearnings(stats, minSessions = DEFAULT_MIN_SESSIONS) {
10935
10923
  }
10936
10924
 
10937
10925
  // src/commands/learn.ts
10938
- init_constants();
10939
10926
  var MIN_EVENTS_FOR_ANALYSIS = 25;
10940
10927
  var MIN_EVENTS_AUTO = 10;
10941
10928
  var AUTO_SETTLE_MS = 200;
@@ -11428,7 +11415,6 @@ async function learnAddCommand(content, options) {
11428
11415
 
11429
11416
  // src/commands/insights.ts
11430
11417
  import chalk24 from "chalk";
11431
- init_constants();
11432
11418
  var MIN_SESSIONS_FULL = 20;
11433
11419
  function buildInsightsData(stats) {
11434
11420
  const t = stats.totals;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rely-ai/caliber",
3
- "version": "1.26.0",
3
+ "version": "1.27.0",
4
4
  "description": "Analyze your codebase and generate optimized AI agent configs (CLAUDE.md, .cursorrules, skills) — no API key needed",
5
5
  "type": "module",
6
6
  "bin": {