ctxloom-pro 1.7.1 → 1.7.3

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/README.md CHANGED
@@ -69,7 +69,7 @@ The full first-run flow is **one install + one trial + one init per project.** E
69
69
  npm install -g ctxloom-pro
70
70
  ```
71
71
 
72
- > **For local trial / dev use the unpinned command above is fine.** For unattended CI usage, pin to the exact version (`ctxloom-pro@1.7.1`) so future CLI releases don't silently desync your agent-spec coverage — see the workflow example below.
72
+ > **For local trial / dev use the unpinned command above is fine.** For unattended CI usage, pin to the exact version (`ctxloom-pro@1.7.3`) so future CLI releases don't silently desync your agent-spec coverage — see the workflow example below.
73
73
 
74
74
  ### 2 — Start your free trial (once per email)
75
75
 
@@ -383,7 +383,7 @@ jobs:
383
383
  # Exact pin (not `@^1`) so future CLI releases that add/remove MCP
384
384
  # tools don't silently desync your reviewer-agent specs. Bump on
385
385
  # every release; see CHANGELOG.md for the live version table.
386
- - run: npm install -g ctxloom-pro@1.7.1
386
+ - run: npm install -g ctxloom-pro@1.7.3
387
387
  - run: ctxloom index
388
388
  - run: ctxloom rules check --json
389
389
  ```
@@ -2909,6 +2909,26 @@ var CallGraphIndex = class _CallGraphIndex {
2909
2909
  var TS_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue"]);
2910
2910
  var PY_EXTENSIONS = /* @__PURE__ */ new Set([".py", ".ipynb"]);
2911
2911
  var AST_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".py", ".go", ".rs", ".java", ".cs", ".rb", ".kt", ".kts", ".swift", ".ipynb", ".php", ".dart"]);
2912
+ var CTXLOOM_VERSION = "1.7.3".length > 0 ? "1.7.3" : "dev";
2913
+ var SNAPSHOT_SCHEMA_VERSION = 2;
2914
+ function compareCtxloomVersions(snapshotVer, currentVer) {
2915
+ if (snapshotVer === currentVer) return "same";
2916
+ if (snapshotVer === "dev") return "unknown";
2917
+ if (currentVer === "dev") return "older";
2918
+ const parse = (v) => {
2919
+ const parts = v.split(".").map((s) => Number.parseInt(s, 10));
2920
+ if (parts.length < 3 || parts.some((n) => !Number.isFinite(n))) return null;
2921
+ return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
2922
+ };
2923
+ const a = parse(snapshotVer);
2924
+ const b = parse(currentVer);
2925
+ if (!a || !b) return "unknown";
2926
+ for (let i = 0; i < 3; i++) {
2927
+ if (a[i] < b[i]) return "older";
2928
+ if (a[i] > b[i]) return "newer";
2929
+ }
2930
+ return "same";
2931
+ }
2912
2932
  var DependencyGraph = class {
2913
2933
  /** file → set of files it imports (forward edges) */
2914
2934
  forwardEdges = /* @__PURE__ */ new Map();
@@ -3399,7 +3419,12 @@ var DependencyGraph = class {
3399
3419
  fs7.mkdirSync(this.snapshotDir, { recursive: true });
3400
3420
  }
3401
3421
  const data = {
3402
- version: 1,
3422
+ version: SNAPSHOT_SCHEMA_VERSION,
3423
+ // Build-time ctxloom version. The loader uses this to invalidate
3424
+ // snapshots written by an older binary (e.g. one that pre-dated
3425
+ // absolute Python import resolution) so users don't get stuck with
3426
+ // an empty graph after `npm i -g ctxloom-pro@latest`.
3427
+ ctxloomVersion: CTXLOOM_VERSION,
3403
3428
  builtAt: Date.now(),
3404
3429
  fileCount: this.forwardEdges.size,
3405
3430
  forwardEdges: Object.fromEntries(
@@ -3425,6 +3450,7 @@ var DependencyGraph = class {
3425
3450
  if (!data || typeof data !== "object") return false;
3426
3451
  const d = data;
3427
3452
  if (typeof d["version"] !== "number") return false;
3453
+ if (d["ctxloomVersion"] !== void 0 && typeof d["ctxloomVersion"] !== "string") return false;
3428
3454
  if (!d["forwardEdges"] || typeof d["forwardEdges"] !== "object") return false;
3429
3455
  if (!d["reverseEdges"] || typeof d["reverseEdges"] !== "object") return false;
3430
3456
  for (const v of Object.values(d["forwardEdges"])) {
@@ -3445,6 +3471,27 @@ var DependencyGraph = class {
3445
3471
  return false;
3446
3472
  }
3447
3473
  const data = raw;
3474
+ const snapshotVer = data.ctxloomVersion;
3475
+ if (snapshotVer === void 0) {
3476
+ logger.info("Graph snapshot has no ctxloomVersion (legacy v1), rebuilding under current ctxloom", {
3477
+ current: CTXLOOM_VERSION
3478
+ });
3479
+ return false;
3480
+ }
3481
+ const cmp = compareCtxloomVersions(snapshotVer, CTXLOOM_VERSION);
3482
+ if (cmp === "older") {
3483
+ logger.info("Graph snapshot from older ctxloom, rebuilding", {
3484
+ snapshot: snapshotVer,
3485
+ current: CTXLOOM_VERSION
3486
+ });
3487
+ return false;
3488
+ }
3489
+ if (cmp === "newer") {
3490
+ logger.warn("Graph snapshot from newer ctxloom than installed binary; reusing but watch for shape drift", {
3491
+ snapshot: snapshotVer,
3492
+ current: CTXLOOM_VERSION
3493
+ });
3494
+ }
3448
3495
  if (currentFileCount !== void 0 && data.fileCount !== void 0) {
3449
3496
  if (data.fileCount !== currentFileCount) {
3450
3497
  logger.info("Graph snapshot stale, rebuilding", { prev: data.fileCount, curr: currentFileCount });
@@ -12094,7 +12141,7 @@ function resolveTelemetryLevel() {
12094
12141
  }
12095
12142
  var TELEMETRY_LEVEL = resolveTelemetryLevel();
12096
12143
  var TELEMETRY_DISABLED = TELEMETRY_LEVEL === "off";
12097
- var CTXLOOM_VERSION = "1.7.1".length > 0 ? "1.7.1" : "dev";
12144
+ var CTXLOOM_VERSION2 = "1.7.3".length > 0 ? "1.7.3" : "dev";
12098
12145
  var POSTHOG_HOST = "https://eu.i.posthog.com";
12099
12146
  var POSTHOG_KEY = process.env["POSTHOG_API_KEY"] ?? (true ? "phc_CiDkmFLcZ2K6uCpcoSUQLmFrnnUvsyXGhSxopX5TVKE6" : "");
12100
12147
  var SENTRY_DSN = process.env["SENTRY_DSN"] ?? (true ? "https://81c94a0f04a8e242dee493ac1e17f733@o4508531702497280.ingest.de.sentry.io/4511256875368528" : "");
@@ -12135,7 +12182,7 @@ async function sendPostHog(event, distinctId, props) {
12135
12182
  event,
12136
12183
  properties: {
12137
12184
  $lib: "ctxloom-cli",
12138
- release: CTXLOOM_VERSION,
12185
+ release: CTXLOOM_VERSION2,
12139
12186
  ...props
12140
12187
  }
12141
12188
  }),
@@ -12155,7 +12202,7 @@ async function sendAlias(newId, oldAlias) {
12155
12202
  event: "$create_alias",
12156
12203
  properties: {
12157
12204
  $lib: "ctxloom-cli",
12158
- release: CTXLOOM_VERSION,
12205
+ release: CTXLOOM_VERSION2,
12159
12206
  alias: oldAlias
12160
12207
  }
12161
12208
  }),
@@ -12198,7 +12245,7 @@ async function sendSentry(err, context) {
12198
12245
  ]
12199
12246
  },
12200
12247
  extra: context,
12201
- tags: { runtime: "node", component: "cli-license", release: CTXLOOM_VERSION }
12248
+ tags: { runtime: "node", component: "cli-license", release: CTXLOOM_VERSION2 }
12202
12249
  }),
12203
12250
  signal: AbortSignal.timeout(4e3)
12204
12251
  });
@@ -12335,12 +12382,17 @@ those instead of guessing.
12335
12382
  | \`ctx_architecture_overview\` | High-level codebase map |
12336
12383
  | \`ctx_refactor_preview\` / \`ctx_apply_refactor\` | Plan a rename |
12337
12384
 
12338
- ### Hooks keep the graph fresh
12339
-
12340
- \`ctxloom init\` installed a PostToolUse hook on \`Write|Edit\` that
12341
- runs \`ctxloom update --incremental --quiet\` \u2014 so the graph is
12342
- always up to date when you query it. No "did the index update yet?"
12343
- guessing.`;
12385
+ ### How the graph stays fresh
12386
+
12387
+ The ctxloom MCP server's built-in \`FileWatcher\` (chokidar with 200ms
12388
+ debounce) keeps the graph + vectors in sync in real time as you edit
12389
+ files \u2014 no manual reindex needed. A belt-and-suspenders PostToolUse
12390
+ hook (\`ctxloom update --incremental --quiet\`) is also installed; in
12391
+ v1.7.3+ it's a no-op that exits cleanly. In earlier versions the
12392
+ \`update\` subcommand silently didn't exist, which made the hook spawn
12393
+ orphan MCP servers and accumulate LanceDB fragments \u2014 if you ever see
12394
+ \`ctx_search\` stalling for minutes, run \`ctxloom vectors-cleanup\`
12395
+ to fix.`;
12344
12396
  var SESSION_START_HEADER = `#!/usr/bin/env bash
12345
12397
  # ctxloom \u2014 agent-harness session-start hook
12346
12398
  # Generated by \`ctxloom init\`. Re-run \`ctxloom init\` to update.
@@ -2705,6 +2705,26 @@ var CallGraphIndex = class _CallGraphIndex {
2705
2705
  var TS_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue"]);
2706
2706
  var PY_EXTENSIONS = /* @__PURE__ */ new Set([".py", ".ipynb"]);
2707
2707
  var AST_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".py", ".go", ".rs", ".java", ".cs", ".rb", ".kt", ".kts", ".swift", ".ipynb", ".php", ".dart"]);
2708
+ var CTXLOOM_VERSION = "1.7.3".length > 0 ? "1.7.3" : "dev";
2709
+ var SNAPSHOT_SCHEMA_VERSION = 2;
2710
+ function compareCtxloomVersions(snapshotVer, currentVer) {
2711
+ if (snapshotVer === currentVer) return "same";
2712
+ if (snapshotVer === "dev") return "unknown";
2713
+ if (currentVer === "dev") return "older";
2714
+ const parse = (v) => {
2715
+ const parts = v.split(".").map((s) => Number.parseInt(s, 10));
2716
+ if (parts.length < 3 || parts.some((n) => !Number.isFinite(n))) return null;
2717
+ return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
2718
+ };
2719
+ const a = parse(snapshotVer);
2720
+ const b = parse(currentVer);
2721
+ if (!a || !b) return "unknown";
2722
+ for (let i = 0; i < 3; i++) {
2723
+ if (a[i] < b[i]) return "older";
2724
+ if (a[i] > b[i]) return "newer";
2725
+ }
2726
+ return "same";
2727
+ }
2708
2728
  var DependencyGraph = class {
2709
2729
  /** file → set of files it imports (forward edges) */
2710
2730
  forwardEdges = /* @__PURE__ */ new Map();
@@ -3195,7 +3215,12 @@ var DependencyGraph = class {
3195
3215
  fs6.mkdirSync(this.snapshotDir, { recursive: true });
3196
3216
  }
3197
3217
  const data = {
3198
- version: 1,
3218
+ version: SNAPSHOT_SCHEMA_VERSION,
3219
+ // Build-time ctxloom version. The loader uses this to invalidate
3220
+ // snapshots written by an older binary (e.g. one that pre-dated
3221
+ // absolute Python import resolution) so users don't get stuck with
3222
+ // an empty graph after `npm i -g ctxloom-pro@latest`.
3223
+ ctxloomVersion: CTXLOOM_VERSION,
3199
3224
  builtAt: Date.now(),
3200
3225
  fileCount: this.forwardEdges.size,
3201
3226
  forwardEdges: Object.fromEntries(
@@ -3221,6 +3246,7 @@ var DependencyGraph = class {
3221
3246
  if (!data || typeof data !== "object") return false;
3222
3247
  const d = data;
3223
3248
  if (typeof d["version"] !== "number") return false;
3249
+ if (d["ctxloomVersion"] !== void 0 && typeof d["ctxloomVersion"] !== "string") return false;
3224
3250
  if (!d["forwardEdges"] || typeof d["forwardEdges"] !== "object") return false;
3225
3251
  if (!d["reverseEdges"] || typeof d["reverseEdges"] !== "object") return false;
3226
3252
  for (const v of Object.values(d["forwardEdges"])) {
@@ -3241,6 +3267,27 @@ var DependencyGraph = class {
3241
3267
  return false;
3242
3268
  }
3243
3269
  const data = raw;
3270
+ const snapshotVer = data.ctxloomVersion;
3271
+ if (snapshotVer === void 0) {
3272
+ logger.info("Graph snapshot has no ctxloomVersion (legacy v1), rebuilding under current ctxloom", {
3273
+ current: CTXLOOM_VERSION
3274
+ });
3275
+ return false;
3276
+ }
3277
+ const cmp = compareCtxloomVersions(snapshotVer, CTXLOOM_VERSION);
3278
+ if (cmp === "older") {
3279
+ logger.info("Graph snapshot from older ctxloom, rebuilding", {
3280
+ snapshot: snapshotVer,
3281
+ current: CTXLOOM_VERSION
3282
+ });
3283
+ return false;
3284
+ }
3285
+ if (cmp === "newer") {
3286
+ logger.warn("Graph snapshot from newer ctxloom than installed binary; reusing but watch for shape drift", {
3287
+ snapshot: snapshotVer,
3288
+ current: CTXLOOM_VERSION
3289
+ });
3290
+ }
3244
3291
  if (currentFileCount !== void 0 && data.fileCount !== void 0) {
3245
3292
  if (data.fileCount !== currentFileCount) {
3246
3293
  logger.info("Graph snapshot stale, rebuilding", { prev: data.fileCount, curr: currentFileCount });
@@ -10912,7 +10959,7 @@ var TELEMETRY_DISABLED = TELEMETRY_LEVEL === "off";
10912
10959
  function getTelemetryLevel() {
10913
10960
  return TELEMETRY_LEVEL;
10914
10961
  }
10915
- var CTXLOOM_VERSION = "1.7.1".length > 0 ? "1.7.1" : "dev";
10962
+ var CTXLOOM_VERSION2 = "1.7.3".length > 0 ? "1.7.3" : "dev";
10916
10963
  var POSTHOG_HOST = "https://eu.i.posthog.com";
10917
10964
  var POSTHOG_KEY = process.env["POSTHOG_API_KEY"] ?? (true ? "phc_CiDkmFLcZ2K6uCpcoSUQLmFrnnUvsyXGhSxopX5TVKE6" : "");
10918
10965
  var SENTRY_DSN = process.env["SENTRY_DSN"] ?? (true ? "https://81c94a0f04a8e242dee493ac1e17f733@o4508531702497280.ingest.de.sentry.io/4511256875368528" : "");
@@ -10953,7 +11000,7 @@ async function sendPostHog(event, distinctId, props) {
10953
11000
  event,
10954
11001
  properties: {
10955
11002
  $lib: "ctxloom-cli",
10956
- release: CTXLOOM_VERSION,
11003
+ release: CTXLOOM_VERSION2,
10957
11004
  ...props
10958
11005
  }
10959
11006
  }),
@@ -10973,7 +11020,7 @@ async function sendAlias(newId, oldAlias) {
10973
11020
  event: "$create_alias",
10974
11021
  properties: {
10975
11022
  $lib: "ctxloom-cli",
10976
- release: CTXLOOM_VERSION,
11023
+ release: CTXLOOM_VERSION2,
10977
11024
  alias: oldAlias
10978
11025
  }
10979
11026
  }),
@@ -11016,7 +11063,7 @@ async function sendSentry(err, context) {
11016
11063
  ]
11017
11064
  },
11018
11065
  extra: context,
11019
- tags: { runtime: "node", component: "cli-license", release: CTXLOOM_VERSION }
11066
+ tags: { runtime: "node", component: "cli-license", release: CTXLOOM_VERSION2 }
11020
11067
  }),
11021
11068
  signal: AbortSignal.timeout(4e3)
11022
11069
  });
@@ -11623,12 +11670,17 @@ those instead of guessing.
11623
11670
  | \`ctx_architecture_overview\` | High-level codebase map |
11624
11671
  | \`ctx_refactor_preview\` / \`ctx_apply_refactor\` | Plan a rename |
11625
11672
 
11626
- ### Hooks keep the graph fresh
11627
-
11628
- \`ctxloom init\` installed a PostToolUse hook on \`Write|Edit\` that
11629
- runs \`ctxloom update --incremental --quiet\` \u2014 so the graph is
11630
- always up to date when you query it. No "did the index update yet?"
11631
- guessing.`;
11673
+ ### How the graph stays fresh
11674
+
11675
+ The ctxloom MCP server's built-in \`FileWatcher\` (chokidar with 200ms
11676
+ debounce) keeps the graph + vectors in sync in real time as you edit
11677
+ files \u2014 no manual reindex needed. A belt-and-suspenders PostToolUse
11678
+ hook (\`ctxloom update --incremental --quiet\`) is also installed; in
11679
+ v1.7.3+ it's a no-op that exits cleanly. In earlier versions the
11680
+ \`update\` subcommand silently didn't exist, which made the hook spawn
11681
+ orphan MCP servers and accumulate LanceDB fragments \u2014 if you ever see
11682
+ \`ctx_search\` stalling for minutes, run \`ctxloom vectors-cleanup\`
11683
+ to fix.`;
11632
11684
  var SESSION_START_HEADER = `#!/usr/bin/env bash
11633
11685
  # ctxloom \u2014 agent-harness session-start hook
11634
11686
  # Generated by \`ctxloom init\`. Re-run \`ctxloom init\` to update.
@@ -12588,4 +12640,4 @@ export {
12588
12640
  skillFilePath,
12589
12641
  installHarness
12590
12642
  };
12591
- //# sourceMappingURL=chunk-6W4DFPP2.js.map
12643
+ //# sourceMappingURL=chunk-KQ5CQLIA.js.map
package/dist/index.js CHANGED
@@ -47,7 +47,7 @@ import {
47
47
  validateDefaultRoot,
48
48
  wrapWithIndexingEnvelope,
49
49
  writeCODEOWNERS
50
- } from "./chunk-6W4DFPP2.js";
50
+ } from "./chunk-KQ5CQLIA.js";
51
51
  import {
52
52
  addCtxloomToConfig,
53
53
  detectInstalledClients
@@ -56,6 +56,7 @@ import {
56
56
  VectorStore
57
57
  } from "./chunk-7S2ELKNU.js";
58
58
  import {
59
+ collectFiles,
59
60
  generateEmbedding,
60
61
  indexDirectory
61
62
  } from "./chunk-6FGTNOCP.js";
@@ -435,6 +436,33 @@ async function startServer(opts = {}) {
435
436
  }
436
437
  } catch {
437
438
  }
439
+ if (PROJECT_ROOT) {
440
+ try {
441
+ const fragCounts = inspectVectorsDb(PROJECT_ROOT);
442
+ const fragTotal = fragCounts.txn + fragCounts.manifest + fragCounts.lance;
443
+ if (fragTotal > 500) {
444
+ const sourceFileCount = collectFiles(PROJECT_ROOT).length;
445
+ const FRAGMENT_RATIO_THRESHOLD = 50;
446
+ if (sourceFileCount > 0 && fragTotal > sourceFileCount * FRAGMENT_RATIO_THRESHOLD) {
447
+ const mb = (fragCounts.totalBytes / 1024 / 1024).toFixed(0);
448
+ logger.warn(
449
+ "LanceDB fragment count is pathological \u2014 MCP tools may stall for minutes on first call. Run `ctxloom vectors-cleanup` (close other ctxloom MCP servers first) to fix.",
450
+ {
451
+ sourceFiles: sourceFileCount,
452
+ fragments: fragTotal,
453
+ ratio: Math.round(fragTotal / sourceFileCount),
454
+ ratioThreshold: FRAGMENT_RATIO_THRESHOLD,
455
+ sizeMB: Number(mb),
456
+ txn: fragCounts.txn,
457
+ manifest: fragCounts.manifest,
458
+ lance: fragCounts.lance
459
+ }
460
+ );
461
+ }
462
+ }
463
+ } catch {
464
+ }
465
+ }
438
466
  if (!ctx.noDefaultMode) {
439
467
  Promise.all([ctx.getGraph(), generateEmbedding("warmup")]).then(async ([graph]) => {
440
468
  logger.info("Ready", { edges: graph.edgeCount() });
@@ -631,7 +659,7 @@ jobs:
631
659
  with:
632
660
  fetch-depth: 0 # required: pr-bot reads git history for co-change overlay
633
661
 
634
- - uses: kodiii/ctxloom/apps/pr-bot@${ref}
662
+ - uses: kodiii/ctxloom-pr-bot@${ref}
635
663
  `;
636
664
  }
637
665
  function installPrBotWorkflow(opts = {}) {
@@ -1039,7 +1067,7 @@ try {
1039
1067
  } catch {
1040
1068
  }
1041
1069
  var args = process.argv.slice(2);
1042
- var ctxloomVersion = "1.7.1".length > 0 ? "1.7.1" : "dev";
1070
+ var ctxloomVersion = "1.7.3".length > 0 ? "1.7.3" : "dev";
1043
1071
  if (args.includes("--version") || args.includes("-v")) {
1044
1072
  process.stdout.write(`ctxloom ${ctxloomVersion}
1045
1073
  `);
@@ -1107,12 +1135,34 @@ function buildActivityFromOverlay(store) {
1107
1135
  lastCommitTimestamp
1108
1136
  }));
1109
1137
  }
1110
- var LICENSE_GATE_BYPASS_COMMANDS = /* @__PURE__ */ new Set(["trial", "activate", "deactivate", "status", "budget-stats", "--help"]);
1138
+ var LICENSE_GATE_BYPASS_COMMANDS = /* @__PURE__ */ new Set(["trial", "activate", "deactivate", "status", "budget-stats", "--help", "update"]);
1139
+ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
1140
+ "trial",
1141
+ "activate",
1142
+ "deactivate",
1143
+ "status",
1144
+ "init",
1145
+ "index",
1146
+ "setup",
1147
+ "install-pr-bot",
1148
+ "register",
1149
+ "repos",
1150
+ "grammars",
1151
+ "vectors-cleanup",
1152
+ "budget-stats",
1153
+ "dashboard",
1154
+ "review-suggest",
1155
+ "authors-sync",
1156
+ "rules",
1157
+ "update",
1158
+ "--help",
1159
+ "-h"
1160
+ ]);
1111
1161
  async function checkLicense() {
1112
1162
  if (command !== void 0 && LICENSE_GATE_BYPASS_COMMANDS.has(command)) return;
1113
1163
  const ciKey = process.env["CTXLOOM_LICENSE_KEY"];
1114
1164
  if (ciKey) {
1115
- const { ApiClient } = await import("./src-FQQOURSD.js");
1165
+ const { ApiClient } = await import("./src-Y4TTG5HV.js");
1116
1166
  const client = new ApiClient(process.env["CTXLOOM_API_BASE"]);
1117
1167
  try {
1118
1168
  const result = await client.validate(ciKey, "ci-ephemeral");
@@ -1339,8 +1389,23 @@ async function main() {
1339
1389
  if (command !== void 0 && shouldEmitInstallCompleted()) {
1340
1390
  track("install_completed", { command });
1341
1391
  }
1392
+ if (command !== void 0 && !KNOWN_COMMANDS.has(command)) {
1393
+ process.stderr.write(
1394
+ `${error(`Unknown command: ${style.bold(String(command))}`)}
1395
+
1396
+ Run ${style.highlight("ctxloom --help")} for the list of available commands.
1397
+ To start the MCP server, run ${style.highlight("ctxloom")} with no arguments.
1398
+
1399
+ `
1400
+ );
1401
+ process.exit(1);
1402
+ }
1342
1403
  await checkLicense();
1343
1404
  switch (command) {
1405
+ case void 0: {
1406
+ await startServer({ withGit, gitWindowDays });
1407
+ break;
1408
+ }
1344
1409
  case "trial": {
1345
1410
  await runTrial();
1346
1411
  break;
@@ -1447,7 +1512,7 @@ async function main() {
1447
1512
  process.stdout.write(success(`Created ${result.path}`));
1448
1513
  process.stdout.write(` ${style.dim(`Default branch: ${result.defaultBranch}`)}
1449
1514
  `);
1450
- process.stdout.write(` ${style.dim(`Pinned to: kodiii/ctxloom/apps/pr-bot@${ref}`)}
1515
+ process.stdout.write(` ${style.dim(`Pinned to: kodiii/ctxloom-pr-bot@${ref}`)}
1451
1516
 
1452
1517
  `);
1453
1518
  process.stdout.write(
@@ -1490,7 +1555,7 @@ async function main() {
1490
1555
  }
1491
1556
  if (!skipHarness) {
1492
1557
  process.stdout.write("\n");
1493
- const { installHarness } = await import("./src-FQQOURSD.js");
1558
+ const { installHarness } = await import("./src-Y4TTG5HV.js");
1494
1559
  const h = installHarness({ cwd: initRoot, dryRun, force, extraHosts });
1495
1560
  const harnessFiles = [
1496
1561
  h.claudeMd,
@@ -1553,7 +1618,7 @@ async function main() {
1553
1618
  process.exit(1);
1554
1619
  }
1555
1620
  if (alias !== void 0) {
1556
- const { validateAlias } = await import("./src-FQQOURSD.js");
1621
+ const { validateAlias } = await import("./src-Y4TTG5HV.js");
1557
1622
  const v = validateAlias(alias);
1558
1623
  if (!v.ok) {
1559
1624
  console.error(`[ctxloom] Invalid alias: ${v.reason}`);
@@ -1912,7 +1977,7 @@ Suggested reviewers for ${files.length} file(s):`);
1912
1977
  process.stderr.write("[ctxloom] --limit must be a non-negative integer (0 for unlimited)\n");
1913
1978
  process.exit(2);
1914
1979
  }
1915
- const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-FQQOURSD.js");
1980
+ const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-Y4TTG5HV.js");
1916
1981
  let config;
1917
1982
  try {
1918
1983
  config = await loadRulesConfig(root);
@@ -1936,7 +2001,7 @@ Suggested reviewers for ${files.length} file(s):`);
1936
2001
  }
1937
2002
  let graph;
1938
2003
  if (useSnapshot) {
1939
- const { DependencyGraph: DG } = await import("./src-FQQOURSD.js");
2004
+ const { DependencyGraph: DG } = await import("./src-Y4TTG5HV.js");
1940
2005
  graph = new DG();
1941
2006
  const loaded = await graph.loadSnapshotOnly(root);
1942
2007
  if (!loaded) {
@@ -1945,7 +2010,7 @@ Suggested reviewers for ${files.length} file(s):`);
1945
2010
  }
1946
2011
  } else {
1947
2012
  process.stderr.write("[ctxloom] Building dependency graph...\n");
1948
- const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-FQQOURSD.js");
2013
+ const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-Y4TTG5HV.js");
1949
2014
  let parser;
1950
2015
  try {
1951
2016
  parser = new ASTParser2();
@@ -2062,10 +2127,23 @@ Tools Exposed:
2062
2127
  `);
2063
2128
  break;
2064
2129
  }
2065
- default: {
2066
- await startServer({ withGit, gitWindowDays });
2130
+ case "update": {
2131
+ const isQuiet = args.includes("--quiet");
2132
+ if (!isQuiet) {
2133
+ process.stdout.write(
2134
+ `${success("ctxloom update: no-op (MCP server FileWatcher handles incremental updates)")}
2135
+ `
2136
+ );
2137
+ }
2067
2138
  break;
2068
2139
  }
2140
+ default: {
2141
+ process.stderr.write(
2142
+ `${error(`Internal error: unhandled command '${String(command)}' reached switch default. This indicates KNOWN_COMMANDS and the switch are out of sync.`)}
2143
+ `
2144
+ );
2145
+ process.exit(1);
2146
+ }
2069
2147
  }
2070
2148
  }
2071
2149
  main().catch((err) => {
@@ -132,7 +132,7 @@ import {
132
132
  wrapBlock,
133
133
  wrapWithIndexingEnvelope,
134
134
  writeCODEOWNERS
135
- } from "./chunk-6W4DFPP2.js";
135
+ } from "./chunk-KQ5CQLIA.js";
136
136
  import {
137
137
  VectorStore
138
138
  } from "./chunk-7S2ELKNU.js";
@@ -300,4 +300,4 @@ export {
300
300
  wrapWithIndexingEnvelope,
301
301
  writeCODEOWNERS
302
302
  };
303
- //# sourceMappingURL=src-FQQOURSD.js.map
303
+ //# sourceMappingURL=src-Y4TTG5HV.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctxloom-pro",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "ctxloom — The Universal Code Context Engine. A local-first MCP server providing intelligent code context via hybrid Vector + AST + Graph search with Skeletonization (92% token reduction).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",