caveat-cli 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -16095,7 +16095,11 @@ function resolvePaths(caveatHome, knowledgeRepo, userHome) {
16095
16095
  knowledgeRepo: resolved,
16096
16096
  dbPath: join5(caveatHome, "index", "caveat.db"),
16097
16097
  entriesDir: join5(resolved, "entries"),
16098
- communityDir: join5(resolved, "community")
16098
+ // community/ lives at caveatHome level, NOT inside knowledgeRepo. Community
16099
+ // clones are external knowledge caches — not semantically "owned" by the
16100
+ // user — and they embed their own .git dirs which would otherwise nest
16101
+ // inside the user's git-tracked knowledge repo.
16102
+ communityDir: join5(caveatHome, "community")
16099
16103
  };
16100
16104
  }
16101
16105
 
@@ -21253,16 +21257,16 @@ async function pushEntry(opts) {
21253
21257
  const stagingDir = forkStagingDir(opts.caveatHome);
21254
21258
  ensureStagingClone(stagingDir, ghUser, sharedName, sharedOwner);
21255
21259
  const branch = `caveat-push-${owned.id}-${Date.now().toString(36)}`;
21256
- run("git", ["checkout", "-b", branch], { cwd: stagingDir });
21260
+ runOrThrow("git", ["checkout", "-b", branch], { cwd: stagingDir });
21257
21261
  const destPath = join7(stagingDir, "entries", owned.relPath);
21258
21262
  mkdirSync3(dirname4(destPath), { recursive: true });
21259
21263
  copyFileSync(owned.absPath, destPath);
21260
- run("git", ["add", join7("entries", owned.relPath)], { cwd: stagingDir });
21264
+ runOrThrow("git", ["add", join7("entries", owned.relPath)], { cwd: stagingDir });
21261
21265
  const isUpdate = upstreamAlreadyHas(stagingDir, "entries/" + owned.relPath);
21262
21266
  const verb = isUpdate ? "update" : "add";
21263
21267
  const commitMsg = `${verb}: ${owned.title}`;
21264
- run("git", ["commit", "-m", commitMsg], { cwd: stagingDir });
21265
- run("git", ["push", "--set-upstream", "origin", branch], { cwd: stagingDir });
21268
+ runOrThrow("git", ["commit", "-m", commitMsg], { cwd: stagingDir });
21269
+ runOrThrow("git", ["push", "--set-upstream", "origin", branch], { cwd: stagingDir });
21266
21270
  const prTitle = `${verb}: ${owned.title}`;
21267
21271
  const prBody = [
21268
21272
  `Contribution of caveat \`${owned.id}\` via \`caveat push\`.`,
@@ -21272,7 +21276,7 @@ async function pushEntry(opts) {
21272
21276
  "",
21273
21277
  "Merged PRs will appear in subscribers' repos on their next `caveat pull`."
21274
21278
  ].join("\n");
21275
- const pr = spawnSync(
21279
+ const pr = runCapture(
21276
21280
  "gh",
21277
21281
  [
21278
21282
  "pr",
@@ -21288,16 +21292,15 @@ async function pushEntry(opts) {
21288
21292
  "--body",
21289
21293
  prBody
21290
21294
  ],
21291
- { cwd: stagingDir, encoding: "utf-8", shell: true }
21295
+ { cwd: stagingDir }
21292
21296
  );
21293
21297
  if (pr.status !== 0) {
21294
21298
  return {
21295
21299
  status: "failed",
21296
- detail: (typeof pr.stderr === "string" ? pr.stderr : String(pr.stderr ?? "")).trim() || "gh pr create failed"
21300
+ detail: (pr.stderr || "gh pr create failed").trim()
21297
21301
  };
21298
21302
  }
21299
- const prUrl = (typeof pr.stdout === "string" ? pr.stdout : String(pr.stdout ?? "")).trim();
21300
- return { status: "ok", prUrl };
21303
+ return { status: "ok", prUrl: pr.stdout.trim() };
21301
21304
  } catch (err) {
21302
21305
  return {
21303
21306
  status: "failed",
@@ -21305,21 +21308,41 @@ async function pushEntry(opts) {
21305
21308
  };
21306
21309
  }
21307
21310
  }
21311
+ function shellQuote(s) {
21312
+ if (!/[\s&|<>^()"`$!*?\[\]{}\\]/.test(s)) return s;
21313
+ return `"${s.replace(/"/g, '""')}"`;
21314
+ }
21315
+ function runCapture(command, args, opts = {}) {
21316
+ const line = [command, ...args].map(shellQuote).join(" ");
21317
+ const r2 = spawnSync(line, {
21318
+ encoding: "utf-8",
21319
+ cwd: opts.cwd,
21320
+ shell: true
21321
+ });
21322
+ return {
21323
+ status: r2.status,
21324
+ stdout: typeof r2.stdout === "string" ? r2.stdout : "",
21325
+ stderr: typeof r2.stderr === "string" ? r2.stderr : ""
21326
+ };
21327
+ }
21328
+ function runOrThrow(command, args, opts = {}) {
21329
+ const r2 = runCapture(command, args, opts);
21330
+ if (r2.status !== 0) {
21331
+ throw new Error(
21332
+ `${command} ${args.join(" ")} failed: ${(r2.stderr || r2.stdout || "unknown").trim()}`
21333
+ );
21334
+ }
21335
+ }
21308
21336
  function checkGhAvailable() {
21309
- const r2 = spawnSync("gh", ["--version"], { encoding: "utf-8", shell: true });
21310
- return r2.status === 0;
21337
+ return runCapture("gh", ["--version"]).status === 0;
21311
21338
  }
21312
21339
  function checkGhAuthed() {
21313
- const r2 = spawnSync("gh", ["auth", "status"], { encoding: "utf-8", shell: true });
21314
- return r2.status === 0;
21340
+ return runCapture("gh", ["auth", "status"]).status === 0;
21315
21341
  }
21316
21342
  function resolveGhUser() {
21317
- const r2 = spawnSync("gh", ["api", "user", "--jq", ".login"], {
21318
- encoding: "utf-8",
21319
- shell: true
21320
- });
21343
+ const r2 = runCapture("gh", ["api", "user", "--jq", ".login"]);
21321
21344
  if (r2.status !== 0) return void 0;
21322
- return typeof r2.stdout === "string" ? r2.stdout.trim() : "";
21345
+ return r2.stdout.trim() || void 0;
21323
21346
  }
21324
21347
  function parseOwnerRepo(url) {
21325
21348
  const m = /^https:\/\/github\.com\/([^/]+)\/([^/]+?)(\.git)?\/?$/.exec(url);
@@ -21351,44 +21374,28 @@ function forkStagingDir(caveatHome) {
21351
21374
  return join7(caveatHome, "push-fork");
21352
21375
  }
21353
21376
  function ensureFork(owner, repo) {
21354
- spawnSync(
21355
- "gh",
21356
- ["repo", "fork", `${owner}/${repo}`, "--clone=false", "--remote=false"],
21357
- { encoding: "utf-8", shell: true }
21358
- );
21377
+ runCapture("gh", ["repo", "fork", `${owner}/${repo}`, "--clone=false", "--remote=false"]);
21359
21378
  }
21360
21379
  function ensureStagingClone(stagingDir, ghUser, sharedName, upstreamOwner) {
21361
21380
  if (!existsSync7(stagingDir)) {
21362
21381
  mkdirSync3(dirname4(stagingDir), { recursive: true });
21363
21382
  const forkUrl = `https://github.com/${ghUser}/${sharedName}.git`;
21364
- run("git", ["clone", "--depth", "30", forkUrl, stagingDir]);
21365
- run(
21383
+ runOrThrow("git", ["clone", "--depth", "30", forkUrl, stagingDir]);
21384
+ runOrThrow(
21366
21385
  "git",
21367
21386
  ["remote", "add", "upstream", `https://github.com/${upstreamOwner}/${sharedName}.git`],
21368
21387
  { cwd: stagingDir }
21369
21388
  );
21370
21389
  } else {
21371
- run("git", ["checkout", "main"], { cwd: stagingDir });
21372
- run("git", ["fetch", "upstream", "main"], { cwd: stagingDir });
21373
- run("git", ["reset", "--hard", "upstream/main"], { cwd: stagingDir });
21374
- run("git", ["push", "origin", "main", "--force-with-lease"], { cwd: stagingDir });
21390
+ runOrThrow("git", ["checkout", "main"], { cwd: stagingDir });
21391
+ runOrThrow("git", ["fetch", "upstream", "main"], { cwd: stagingDir });
21392
+ runOrThrow("git", ["reset", "--hard", "upstream/main"], { cwd: stagingDir });
21393
+ runOrThrow("git", ["push", "origin", "main", "--force-with-lease"], { cwd: stagingDir });
21375
21394
  }
21376
21395
  }
21377
21396
  function upstreamAlreadyHas(stagingDir, relFromRoot) {
21378
21397
  return existsSync7(join7(stagingDir, relFromRoot));
21379
21398
  }
21380
- function run(command, args, opts = {}) {
21381
- const r2 = spawnSync(command, args, {
21382
- encoding: "utf-8",
21383
- cwd: opts.cwd,
21384
- shell: true
21385
- });
21386
- if (r2.status !== 0) {
21387
- const stderr = typeof r2.stderr === "string" ? r2.stderr : String(r2.stderr ?? "");
21388
- const stdout = typeof r2.stdout === "string" ? r2.stdout : String(r2.stdout ?? "");
21389
- throw new Error(`${command} ${args.join(" ")} failed: ${(stderr || stdout || "unknown").trim()}`);
21390
- }
21391
- }
21392
21399
 
21393
21400
  // ../../packages/core/dist/pullShared.js
21394
21401
  import { existsSync as existsSync8, readdirSync as readdirSync5 } from "node:fs";
@@ -21435,6 +21442,21 @@ function buildContext(logger, overrides = {}) {
21435
21442
  return { caveatHome, userHome, userConfigPath, config: config3, paths, logger };
21436
21443
  }
21437
21444
 
21445
+ // src/version.ts
21446
+ import { readFileSync as readFileSync6 } from "node:fs";
21447
+ import { dirname as dirname5, join as join10 } from "node:path";
21448
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
21449
+ function resolveVersion() {
21450
+ try {
21451
+ const here2 = dirname5(fileURLToPath3(import.meta.url));
21452
+ const pkg = JSON.parse(readFileSync6(join10(here2, "..", "package.json"), "utf-8"));
21453
+ return typeof pkg.version === "string" ? pkg.version : "0.0.0";
21454
+ } catch {
21455
+ return "0.0.0";
21456
+ }
21457
+ }
21458
+ var CAVEAT_VERSION = resolveVersion();
21459
+
21438
21460
  // src/logger.ts
21439
21461
  var stdoutLogger = {
21440
21462
  info: (m) => process.stdout.write(`[caveat] ${m}
@@ -21446,13 +21468,13 @@ var stdoutLogger = {
21446
21468
  };
21447
21469
 
21448
21470
  // src/commands/init.ts
21449
- import { existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync6, writeFileSync as writeFileSync5 } from "node:fs";
21450
- import { join as join11 } from "node:path";
21471
+ import { existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync6, renameSync, rmdirSync, writeFileSync as writeFileSync5 } from "node:fs";
21472
+ import { join as join12 } from "node:path";
21451
21473
 
21452
21474
  // src/claudeInstall.ts
21453
21475
  import { spawnSync as spawnSync2 } from "node:child_process";
21454
- import { copyFileSync as copyFileSync2, existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
21455
- import { dirname as dirname5, join as join10 } from "node:path";
21476
+ import { copyFileSync as copyFileSync2, existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
21477
+ import { dirname as dirname6, join as join11 } from "node:path";
21456
21478
  var EVENT_USER_PROMPT_SUBMIT = "UserPromptSubmit";
21457
21479
  var EVENT_STOP = "Stop";
21458
21480
  function quote(p2) {
@@ -21487,10 +21509,10 @@ function removeHook(settings, event, command) {
21487
21509
  }
21488
21510
  function readSettings(path) {
21489
21511
  if (!existsSync9(path)) return {};
21490
- return JSON.parse(readFileSync6(path, "utf-8"));
21512
+ return JSON.parse(readFileSync7(path, "utf-8"));
21491
21513
  }
21492
21514
  function writeSettings(path, settings) {
21493
- const dir = dirname5(path);
21515
+ const dir = dirname6(path);
21494
21516
  if (!existsSync9(dir)) mkdirSync4(dir, { recursive: true });
21495
21517
  let backupPath = "";
21496
21518
  if (existsSync9(path)) {
@@ -21501,11 +21523,11 @@ function writeSettings(path, settings) {
21501
21523
  return backupPath;
21502
21524
  }
21503
21525
  var CLAUDE_BIN = "claude";
21504
- function shellQuote(s) {
21526
+ function shellQuote2(s) {
21505
21527
  return /[\s&|<>^()]/.test(s) ? `"${s}"` : s;
21506
21528
  }
21507
21529
  function runClaude(args) {
21508
- const line = [CLAUDE_BIN, ...args].map(shellQuote).join(" ");
21530
+ const line = [CLAUDE_BIN, ...args].map(shellQuote2).join(" ");
21509
21531
  return spawnSync2(line, { shell: true, encoding: "utf-8" });
21510
21532
  }
21511
21533
  function registerMcp(nodePath, cliScriptPath, dryRun, logger) {
@@ -21556,7 +21578,7 @@ function unregisterMcp(dryRun, logger) {
21556
21578
  return { action: "skipped", detail: "not registered or removal failed" };
21557
21579
  }
21558
21580
  function installClaudeIntegration(opts) {
21559
- const settingsPath = join10(opts.claudeDir, "settings.json");
21581
+ const settingsPath = join11(opts.claudeDir, "settings.json");
21560
21582
  const settings = readSettings(settingsPath);
21561
21583
  const usCmd = hookCommand(opts.nodePath, opts.cliScriptPath, "user-prompt-submit");
21562
21584
  const stopCmd = hookCommand(opts.nodePath, opts.cliScriptPath, "stop");
@@ -21575,7 +21597,7 @@ function installClaudeIntegration(opts) {
21575
21597
  return { mcp, hooks: { userPromptSubmit, stop }, backupPath };
21576
21598
  }
21577
21599
  function uninstallClaudeIntegration(opts) {
21578
- const settingsPath = join10(opts.claudeDir, "settings.json");
21600
+ const settingsPath = join11(opts.claudeDir, "settings.json");
21579
21601
  const settings = readSettings(settingsPath);
21580
21602
  const usCmd = hookCommand(opts.nodePath, opts.cliScriptPath, "user-prompt-submit");
21581
21603
  const stopCmd = hookCommand(opts.nodePath, opts.cliScriptPath, "stop");
@@ -21605,11 +21627,6 @@ var KNOWLEDGE_GITIGNORE = [
21605
21627
  "",
21606
21628
  "# Obsidian per-user config: workspace layout, theme, plugin state, cache.",
21607
21629
  ".obsidian/",
21608
- "",
21609
- "# community/ is a local cache of shallow-cloned third-party caveat repos",
21610
- "# (populated by `caveat community add`). Each contains its own .git and is not",
21611
- "# part of this repo's tracked knowledge.",
21612
- "community/",
21613
21630
  ""
21614
21631
  ].join("\n");
21615
21632
  async function runInit(ctx, opts = { skipClaude: false, skipShared: false, dryRun: false }) {
@@ -21622,7 +21639,8 @@ async function runInit(ctx, opts = { skipClaude: false, skipShared: false, dryRu
21622
21639
  } else {
21623
21640
  ctx.logger.info(`knowledge repo: ${ctx.paths.knowledgeRepo}`);
21624
21641
  }
21625
- const gitignorePath = join11(ctx.paths.knowledgeRepo, ".gitignore");
21642
+ migrateLegacyCommunityDir(ctx);
21643
+ const gitignorePath = join12(ctx.paths.knowledgeRepo, ".gitignore");
21626
21644
  if (!existsSync10(gitignorePath)) {
21627
21645
  writeFileSync5(gitignorePath, KNOWLEDGE_GITIGNORE, "utf-8");
21628
21646
  ctx.logger.info(`.gitignore created: ${gitignorePath}`);
@@ -21650,7 +21668,7 @@ async function runInit(ctx, opts = { skipClaude: false, skipShared: false, dryRu
21650
21668
  return;
21651
21669
  }
21652
21670
  const result = installClaudeIntegration({
21653
- claudeDir: join11(ctx.userHome, ".claude"),
21671
+ claudeDir: join12(ctx.userHome, ".claude"),
21654
21672
  cliScriptPath,
21655
21673
  nodePath: process.execPath,
21656
21674
  dryRun: opts.dryRun,
@@ -21658,6 +21676,28 @@ async function runInit(ctx, opts = { skipClaude: false, skipShared: false, dryRu
21658
21676
  });
21659
21677
  reportInstallResult(ctx, result, opts.dryRun);
21660
21678
  }
21679
+ function migrateLegacyCommunityDir(ctx) {
21680
+ const legacy = join12(ctx.paths.knowledgeRepo, "community");
21681
+ const current = ctx.paths.communityDir;
21682
+ if (legacy === current) return;
21683
+ if (!existsSync10(legacy)) return;
21684
+ if (existsSync10(current)) {
21685
+ ctx.logger.warn(
21686
+ `legacy community dir still exists at ${legacy} \u2014 remove manually (new location in use)`
21687
+ );
21688
+ return;
21689
+ }
21690
+ mkdirSync5(current, { recursive: true });
21691
+ for (const entry of readdirSync6(legacy, { withFileTypes: true })) {
21692
+ if (!entry.isDirectory()) continue;
21693
+ renameSync(join12(legacy, entry.name), join12(current, entry.name));
21694
+ }
21695
+ try {
21696
+ rmdirSync(legacy);
21697
+ } catch {
21698
+ }
21699
+ ctx.logger.info(`migrated legacy community/ \u2192 ${current}`);
21700
+ }
21661
21701
  async function subscribeSharedRepo(ctx, db) {
21662
21702
  const url = ctx.config.sharedRepo;
21663
21703
  const validation = validateCommunityUrl(url);
@@ -21668,7 +21708,7 @@ async function subscribeSharedRepo(ctx, db) {
21668
21708
  return;
21669
21709
  }
21670
21710
  const handle = validation.handle;
21671
- const target = join11(ctx.paths.communityDir, handle);
21711
+ const target = join12(ctx.paths.communityDir, handle);
21672
21712
  if (!existsSync10(target)) {
21673
21713
  if (!existsSync10(ctx.paths.communityDir)) {
21674
21714
  mkdirSync5(ctx.paths.communityDir, { recursive: true });
@@ -21697,7 +21737,7 @@ async function subscribeSharedRepo(ctx, db) {
21697
21737
  for (const entry of readdirSync6(ctx.paths.communityDir, { withFileTypes: true })) {
21698
21738
  if (!entry.isDirectory()) continue;
21699
21739
  const source = `community/${entry.name}`;
21700
- const root = join11(ctx.paths.communityDir, entry.name, "entries");
21740
+ const root = join12(ctx.paths.communityDir, entry.name, "entries");
21701
21741
  if (!existsSync10(root)) continue;
21702
21742
  const result = scanSource({ db, source, entriesRoot: root });
21703
21743
  ctx.logger.info(`indexed ${source}: +${result.added}`);
@@ -21711,7 +21751,7 @@ function runUninstall(ctx, opts) {
21711
21751
  process.exit(1);
21712
21752
  }
21713
21753
  const result = uninstallClaudeIntegration({
21714
- claudeDir: join11(ctx.userHome, ".claude"),
21754
+ claudeDir: join12(ctx.userHome, ".claude"),
21715
21755
  cliScriptPath,
21716
21756
  nodePath: process.execPath,
21717
21757
  dryRun: opts.dryRun,
@@ -21749,9 +21789,9 @@ function reportInstallResult(ctx, result, dryRun) {
21749
21789
 
21750
21790
  // src/commands/indexCmd.ts
21751
21791
  import { existsSync as existsSync11, readdirSync as readdirSync7, mkdirSync as mkdirSync6 } from "node:fs";
21752
- import { dirname as dirname6, join as join12 } from "node:path";
21792
+ import { dirname as dirname7, join as join13 } from "node:path";
21753
21793
  function runIndex(ctx, opts) {
21754
- const dbDir = dirname6(ctx.paths.dbPath);
21794
+ const dbDir = dirname7(ctx.paths.dbPath);
21755
21795
  if (!existsSync11(dbDir)) mkdirSync6(dbDir, { recursive: true });
21756
21796
  const db = openDb({ path: ctx.paths.dbPath, logger: ctx.logger });
21757
21797
  try {
@@ -21769,7 +21809,7 @@ function runIndex(ctx, opts) {
21769
21809
  for (const entry of readdirSync7(ctx.paths.communityDir, { withFileTypes: true })) {
21770
21810
  if (!entry.isDirectory()) continue;
21771
21811
  const source = `community/${entry.name}`;
21772
- const root = join12(ctx.paths.communityDir, entry.name, "entries");
21812
+ const root = join13(ctx.paths.communityDir, entry.name, "entries");
21773
21813
  if (!existsSync11(root)) continue;
21774
21814
  const result = scanSource({ db, source, entriesRoot: root });
21775
21815
  ctx.logger.info(`${source}: +${result.added} ~${result.updated} -${result.deleted}`);
@@ -22544,11 +22584,11 @@ var serve = (options2, listeningListener) => {
22544
22584
 
22545
22585
  // ../web/dist/context.js
22546
22586
  import { homedir as homedir2 } from "node:os";
22547
- import { join as join13 } from "node:path";
22587
+ import { join as join14 } from "node:path";
22548
22588
  function buildWebContext(overrides = {}) {
22549
22589
  const userHome = overrides.userHome ?? homedir2();
22550
22590
  const caveatHome = overrides.caveatHome ?? findCaveatHome(userHome);
22551
- const userConfigPath = join13(userHome, ".caveatrc.json");
22591
+ const userConfigPath = join14(userHome, ".caveatrc.json");
22552
22592
  const logger = overrides.logger ?? stderrLogger;
22553
22593
  const config3 = loadConfig(userConfigPath);
22554
22594
  const paths = resolvePaths(caveatHome, config3.knowledgeRepo, userHome);
@@ -30276,13 +30316,13 @@ function createDetailRoute(ctx) {
30276
30316
 
30277
30317
  // ../web/dist/routes/community.js
30278
30318
  import { existsSync as existsSync12, readdirSync as readdirSync8, statSync as statSync4 } from "node:fs";
30279
- import { join as join14 } from "node:path";
30319
+ import { join as join15 } from "node:path";
30280
30320
  function listCommunity(communityDir, db) {
30281
30321
  if (!existsSync12(communityDir)) return [];
30282
30322
  const handles = [];
30283
30323
  for (const entry of readdirSync8(communityDir, { withFileTypes: true })) {
30284
30324
  if (!entry.isDirectory()) continue;
30285
- const handlePath = join14(communityDir, entry.name);
30325
+ const handlePath = join15(communityDir, entry.name);
30286
30326
  const countRow = db.prepare("SELECT COUNT(*) AS n FROM entries WHERE source = ?").get(`community/${entry.name}`);
30287
30327
  handles.push({
30288
30328
  handle: entry.name,
@@ -44580,11 +44620,11 @@ var StdioServerTransport = class {
44580
44620
 
44581
44621
  // ../mcp/dist/context.js
44582
44622
  import { homedir as homedir3 } from "node:os";
44583
- import { join as join15 } from "node:path";
44623
+ import { join as join16 } from "node:path";
44584
44624
  function buildMcpContext(overrides = {}) {
44585
44625
  const userHome = overrides.userHome ?? homedir3();
44586
44626
  const caveatHome = overrides.caveatHome ?? findCaveatHome(userHome);
44587
- const userConfigPath = join15(userHome, ".caveatrc.json");
44627
+ const userConfigPath = join16(userHome, ".caveatrc.json");
44588
44628
  const logger = overrides.logger ?? stderrLogger;
44589
44629
  const config3 = loadConfig(userConfigPath);
44590
44630
  const paths = resolvePaths(caveatHome, config3.knowledgeRepo, userHome);
@@ -45022,7 +45062,7 @@ function runCommunityList(ctx) {
45022
45062
 
45023
45063
  // src/index.ts
45024
45064
  var program = new Command();
45025
- program.name("caveat").description("External spec gotcha knowledge base CLI").version("0.6.0");
45065
+ program.name("caveat").description("External spec gotcha knowledge base CLI").version(CAVEAT_VERSION);
45026
45066
  program.command("init").description(
45027
45067
  "Initialize ~/.caveatrc.json, ~/.caveat/, subscribe to the shared community DB, and register Claude Code integration"
45028
45068
  ).option("--skip-claude", "skip Claude Code MCP + hook registration", false).option("--skip-shared", "skip subscribing to the shared community DB", false).option("--dry-run", "show planned changes without writing", false).action(async (opts) => {