clast-ai 0.1.2 → 0.2.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 (290) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/.claude-plugin/plugin.json +11 -9
  3. package/README.md +447 -401
  4. package/bench/ab/onair-concept.json +22 -0
  5. package/bench/ab/onair-deadcode.json +7 -0
  6. package/bench/ab/onair-hard.json +32 -0
  7. package/bench/ab/onair-impact.json +17 -0
  8. package/bench/ab/onair-refactors.json +18 -0
  9. package/bench/ab/onair-survey.json +17 -0
  10. package/bench/ab/onair-tasks.json +20 -0
  11. package/bench/ab/onair.json +52 -0
  12. package/bench/ab/vscode-concept.json +22 -0
  13. package/bench/ab/vscode-hard.json +32 -0
  14. package/bench/ab/vscode-impact.json +17 -0
  15. package/bench/ab/vscode-refactors.json +18 -0
  16. package/bench/ab/vscode-tasks.json +20 -0
  17. package/bench/ab/vscode.json +52 -0
  18. package/bench/ab.mjs +213 -0
  19. package/bench/bench.mjs +98 -0
  20. package/bench/resolution.mjs +75 -0
  21. package/dist/cli.d.ts +2 -0
  22. package/dist/cli.js +257 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/config/defaults.d.ts +12 -2
  25. package/dist/config/defaults.js +38 -31
  26. package/dist/config/defaults.js.map +1 -1
  27. package/dist/config/index.d.ts +1 -1
  28. package/dist/config/index.js +26 -14
  29. package/dist/config/index.js.map +1 -1
  30. package/dist/db/index.d.ts +73 -13
  31. package/dist/db/index.js +481 -39
  32. package/dist/db/index.js.map +1 -1
  33. package/dist/engine.d.ts +15 -0
  34. package/dist/engine.js +28 -0
  35. package/dist/engine.js.map +1 -0
  36. package/dist/indexer/imports.d.ts +6 -0
  37. package/dist/indexer/imports.js +254 -0
  38. package/dist/indexer/imports.js.map +1 -0
  39. package/dist/indexer/index.d.ts +63 -0
  40. package/dist/indexer/index.js +360 -0
  41. package/dist/indexer/index.js.map +1 -0
  42. package/dist/indexer/process.d.ts +22 -0
  43. package/dist/indexer/process.js +42 -0
  44. package/dist/indexer/process.js.map +1 -0
  45. package/dist/indexer/scan.d.ts +43 -0
  46. package/dist/indexer/scan.js +223 -0
  47. package/dist/indexer/scan.js.map +1 -0
  48. package/dist/indexer/worker.d.ts +1 -0
  49. package/dist/indexer/worker.js +23 -0
  50. package/dist/indexer/worker.js.map +1 -0
  51. package/dist/llm/comment-generator.d.ts +17 -19
  52. package/dist/llm/comment-generator.js +46 -80
  53. package/dist/llm/comment-generator.js.map +1 -1
  54. package/dist/llm/index.d.ts +0 -1
  55. package/dist/llm/index.js.map +1 -1
  56. package/dist/llm/prompts.d.ts +0 -1
  57. package/dist/llm/prompts.js +16 -16
  58. package/dist/parser/extractor.d.ts +21 -16
  59. package/dist/parser/extractor.js +700 -228
  60. package/dist/parser/extractor.js.map +1 -1
  61. package/dist/parser/index.d.ts +17 -21
  62. package/dist/parser/index.js +115 -171
  63. package/dist/parser/index.js.map +1 -1
  64. package/dist/parser/langs/c.d.ts +3 -0
  65. package/dist/parser/langs/c.js +879 -0
  66. package/dist/parser/langs/c.js.map +1 -0
  67. package/dist/parser/langs/csharp.d.ts +2 -0
  68. package/dist/parser/langs/csharp.js +548 -0
  69. package/dist/parser/langs/csharp.js.map +1 -0
  70. package/dist/parser/langs/dart.d.ts +2 -0
  71. package/dist/parser/langs/dart.js +893 -0
  72. package/dist/parser/langs/dart.js.map +1 -0
  73. package/dist/parser/langs/go.d.ts +2 -0
  74. package/dist/parser/langs/go.js +455 -0
  75. package/dist/parser/langs/go.js.map +1 -0
  76. package/dist/parser/langs/java.d.ts +2 -0
  77. package/dist/parser/langs/java.js +390 -0
  78. package/dist/parser/langs/java.js.map +1 -0
  79. package/dist/parser/langs/php.d.ts +2 -0
  80. package/dist/parser/langs/php.js +486 -0
  81. package/dist/parser/langs/php.js.map +1 -0
  82. package/dist/parser/langs/python.d.ts +2 -0
  83. package/dist/parser/langs/python.js +216 -0
  84. package/dist/parser/langs/python.js.map +1 -0
  85. package/dist/parser/langs/ruby.d.ts +2 -0
  86. package/dist/parser/langs/ruby.js +602 -0
  87. package/dist/parser/langs/ruby.js.map +1 -0
  88. package/dist/parser/langs/rust.d.ts +2 -0
  89. package/dist/parser/langs/rust.js +931 -0
  90. package/dist/parser/langs/rust.js.map +1 -0
  91. package/dist/parser/langs/swift.d.ts +2 -0
  92. package/dist/parser/langs/swift.js +616 -0
  93. package/dist/parser/langs/swift.js.map +1 -0
  94. package/dist/parser/langs/typescript.d.ts +4 -0
  95. package/dist/parser/langs/typescript.js +535 -0
  96. package/dist/parser/langs/typescript.js.map +1 -0
  97. package/dist/parser/registry.d.ts +16 -0
  98. package/dist/parser/registry.js +87 -0
  99. package/dist/parser/registry.js.map +1 -0
  100. package/dist/parser/returns.d.ts +9 -0
  101. package/dist/parser/returns.js +152 -0
  102. package/dist/parser/returns.js.map +1 -0
  103. package/dist/parser/spec.d.ts +165 -0
  104. package/dist/parser/spec.js +188 -0
  105. package/dist/parser/spec.js.map +1 -0
  106. package/dist/query/arity.d.ts +27 -0
  107. package/dist/query/arity.js +187 -0
  108. package/dist/query/arity.js.map +1 -0
  109. package/dist/query/callgraph.d.ts +113 -0
  110. package/dist/query/callgraph.js +332 -0
  111. package/dist/query/callgraph.js.map +1 -0
  112. package/dist/query/format.d.ts +36 -0
  113. package/dist/query/format.js +136 -0
  114. package/dist/query/format.js.map +1 -0
  115. package/dist/query/hierarchy.d.ts +44 -0
  116. package/dist/query/hierarchy.js +441 -0
  117. package/dist/query/hierarchy.js.map +1 -0
  118. package/dist/query/resolve.d.ts +265 -0
  119. package/dist/query/resolve.js +1957 -0
  120. package/dist/query/resolve.js.map +1 -0
  121. package/dist/query/search.d.ts +35 -0
  122. package/dist/query/search.js +379 -0
  123. package/dist/query/search.js.map +1 -0
  124. package/dist/query/words.d.ts +30 -0
  125. package/dist/query/words.js +201 -0
  126. package/dist/query/words.js.map +1 -0
  127. package/dist/server/index.d.ts +1 -3
  128. package/dist/server/index.js +313 -73
  129. package/dist/server/index.js.map +1 -1
  130. package/dist/tools/context.d.ts +35 -0
  131. package/dist/tools/context.js +79 -0
  132. package/dist/tools/context.js.map +1 -0
  133. package/dist/tools/explore.d.ts +51 -0
  134. package/dist/tools/explore.js +779 -0
  135. package/dist/tools/explore.js.map +1 -0
  136. package/dist/tools/impact.d.ts +21 -0
  137. package/dist/tools/impact.js +743 -0
  138. package/dist/tools/impact.js.map +1 -0
  139. package/dist/tools/search.d.ts +59 -0
  140. package/dist/tools/search.js +843 -0
  141. package/dist/tools/search.js.map +1 -0
  142. package/dist/tools/stats.d.ts +26 -0
  143. package/dist/tools/stats.js +604 -0
  144. package/dist/tools/stats.js.map +1 -0
  145. package/dist/types.d.ts +95 -40
  146. package/dist/types.js +9 -1
  147. package/dist/types.js.map +1 -1
  148. package/dist/version.d.ts +2 -0
  149. package/dist/version.js +3 -0
  150. package/dist/version.js.map +1 -0
  151. package/dist/watcher/index.d.ts +18 -16
  152. package/dist/watcher/index.js +94 -77
  153. package/dist/watcher/index.js.map +1 -1
  154. package/package.json +21 -24
  155. package/plugin/server.mjs +50 -0
  156. package/skills/audit/SKILL.md +37 -0
  157. package/skills/deadcode/SKILL.md +33 -0
  158. package/skills/explore/SKILL.md +54 -0
  159. package/skills/impact/SKILL.md +24 -0
  160. package/skills/status/SKILL.md +11 -0
  161. package/src/cli.ts +256 -0
  162. package/src/config/defaults.ts +50 -32
  163. package/src/config/index.ts +23 -14
  164. package/src/db/index.ts +540 -43
  165. package/src/engine.ts +30 -0
  166. package/src/indexer/imports.ts +241 -0
  167. package/src/indexer/index.ts +369 -0
  168. package/src/indexer/process.ts +63 -0
  169. package/src/indexer/scan.ts +226 -0
  170. package/src/indexer/worker.ts +24 -0
  171. package/src/llm/comment-generator.ts +52 -103
  172. package/src/llm/index.ts +80 -80
  173. package/src/llm/prompts.ts +95 -95
  174. package/src/parser/extractor.ts +643 -256
  175. package/src/parser/index.ts +105 -205
  176. package/src/parser/langs/c.ts +860 -0
  177. package/src/parser/langs/csharp.ts +519 -0
  178. package/src/parser/langs/dart.ts +820 -0
  179. package/src/parser/langs/go.ts +437 -0
  180. package/src/parser/langs/java.ts +361 -0
  181. package/src/parser/langs/php.ts +450 -0
  182. package/src/parser/langs/python.ts +206 -0
  183. package/src/parser/langs/ruby.ts +554 -0
  184. package/src/parser/langs/rust.ts +904 -0
  185. package/src/parser/langs/swift.ts +590 -0
  186. package/src/parser/langs/typescript.ts +499 -0
  187. package/src/parser/registry.ts +88 -0
  188. package/src/parser/returns.ts +137 -0
  189. package/src/parser/spec.ts +309 -0
  190. package/src/query/arity.ts +173 -0
  191. package/src/query/callgraph.ts +473 -0
  192. package/src/query/format.ts +136 -0
  193. package/src/query/hierarchy.ts +447 -0
  194. package/src/query/resolve.ts +1972 -0
  195. package/src/query/search.ts +430 -0
  196. package/src/query/words.ts +183 -0
  197. package/src/server/index.ts +390 -79
  198. package/src/tools/context.ts +82 -0
  199. package/src/tools/explore.ts +860 -0
  200. package/src/tools/impact.ts +748 -0
  201. package/src/tools/search.ts +886 -0
  202. package/src/tools/stats.ts +633 -0
  203. package/src/types.ts +113 -45
  204. package/src/version.ts +2 -0
  205. package/src/watcher/index.ts +82 -88
  206. package/tsconfig.json +7 -4
  207. package/.mcp.json +0 -8
  208. package/commands/clast-status.md +0 -9
  209. package/dist/config/defaults.d.ts.map +0 -1
  210. package/dist/config/index.d.ts.map +0 -1
  211. package/dist/db/index.d.ts.map +0 -1
  212. package/dist/db/queries.d.ts +0 -44
  213. package/dist/db/queries.d.ts.map +0 -1
  214. package/dist/db/queries.js +0 -251
  215. package/dist/db/queries.js.map +0 -1
  216. package/dist/db/schema.d.ts +0 -3
  217. package/dist/db/schema.d.ts.map +0 -1
  218. package/dist/db/schema.js +0 -94
  219. package/dist/db/schema.js.map +0 -1
  220. package/dist/db/types.d.ts +0 -44
  221. package/dist/db/types.d.ts.map +0 -1
  222. package/dist/db/types.js +0 -2
  223. package/dist/db/types.js.map +0 -1
  224. package/dist/llm/comment-generator.d.ts.map +0 -1
  225. package/dist/llm/index.d.ts.map +0 -1
  226. package/dist/llm/prompts.d.ts.map +0 -1
  227. package/dist/parser/call-resolver.d.ts +0 -15
  228. package/dist/parser/call-resolver.d.ts.map +0 -1
  229. package/dist/parser/call-resolver.js +0 -16
  230. package/dist/parser/call-resolver.js.map +0 -1
  231. package/dist/parser/extractor.d.ts.map +0 -1
  232. package/dist/parser/index.d.ts.map +0 -1
  233. package/dist/parser/languages.d.ts +0 -11
  234. package/dist/parser/languages.d.ts.map +0 -1
  235. package/dist/parser/languages.js +0 -74
  236. package/dist/parser/languages.js.map +0 -1
  237. package/dist/server/index.d.ts.map +0 -1
  238. package/dist/server/register-tools.d.ts +0 -7
  239. package/dist/server/register-tools.d.ts.map +0 -1
  240. package/dist/server/register-tools.js +0 -17
  241. package/dist/server/register-tools.js.map +0 -1
  242. package/dist/server/tools/clast-call-graph.d.ts +0 -4
  243. package/dist/server/tools/clast-call-graph.d.ts.map +0 -1
  244. package/dist/server/tools/clast-call-graph.js +0 -70
  245. package/dist/server/tools/clast-call-graph.js.map +0 -1
  246. package/dist/server/tools/clast-comment.d.ts +0 -5
  247. package/dist/server/tools/clast-comment.d.ts.map +0 -1
  248. package/dist/server/tools/clast-comment.js +0 -64
  249. package/dist/server/tools/clast-comment.js.map +0 -1
  250. package/dist/server/tools/clast-file-summary.d.ts +0 -4
  251. package/dist/server/tools/clast-file-summary.d.ts.map +0 -1
  252. package/dist/server/tools/clast-file-summary.js +0 -42
  253. package/dist/server/tools/clast-file-summary.js.map +0 -1
  254. package/dist/server/tools/clast-get-context.d.ts +0 -4
  255. package/dist/server/tools/clast-get-context.d.ts.map +0 -1
  256. package/dist/server/tools/clast-get-context.js +0 -80
  257. package/dist/server/tools/clast-get-context.js.map +0 -1
  258. package/dist/server/tools/clast-reindex.d.ts +0 -5
  259. package/dist/server/tools/clast-reindex.d.ts.map +0 -1
  260. package/dist/server/tools/clast-reindex.js +0 -36
  261. package/dist/server/tools/clast-reindex.js.map +0 -1
  262. package/dist/server/tools/clast-search.d.ts +0 -4
  263. package/dist/server/tools/clast-search.d.ts.map +0 -1
  264. package/dist/server/tools/clast-search.js +0 -29
  265. package/dist/server/tools/clast-search.js.map +0 -1
  266. package/dist/server/tools/clast-status.d.ts +0 -5
  267. package/dist/server/tools/clast-status.d.ts.map +0 -1
  268. package/dist/server/tools/clast-status.js +0 -23
  269. package/dist/server/tools/clast-status.js.map +0 -1
  270. package/dist/types.d.ts.map +0 -1
  271. package/dist/watcher/gitignore.d.ts +0 -9
  272. package/dist/watcher/gitignore.d.ts.map +0 -1
  273. package/dist/watcher/gitignore.js +0 -38
  274. package/dist/watcher/gitignore.js.map +0 -1
  275. package/dist/watcher/index.d.ts.map +0 -1
  276. package/skills/clast-explore/SKILL.md +0 -41
  277. package/src/db/queries.ts +0 -332
  278. package/src/db/schema.ts +0 -106
  279. package/src/db/types.ts +0 -47
  280. package/src/parser/call-resolver.ts +0 -17
  281. package/src/parser/languages.ts +0 -86
  282. package/src/server/register-tools.ts +0 -30
  283. package/src/server/tools/clast-call-graph.ts +0 -82
  284. package/src/server/tools/clast-comment.ts +0 -76
  285. package/src/server/tools/clast-file-summary.ts +0 -59
  286. package/src/server/tools/clast-get-context.ts +0 -97
  287. package/src/server/tools/clast-reindex.ts +0 -52
  288. package/src/server/tools/clast-search.ts +0 -38
  289. package/src/server/tools/clast-status.ts +0 -37
  290. package/src/watcher/gitignore.ts +0 -42
@@ -0,0 +1,98 @@
1
+ // Benchmark: cold index, warm rescan and query latency on real repositories.
2
+ //
3
+ // npm run build
4
+ // node bench/bench.mjs <dir-with-repos> [repo-name ...]
5
+ //
6
+ // Each sub-directory of <dir-with-repos> is treated as one repository. The
7
+ // benchmark uses its own database file (.clast/bench.db) so it never touches
8
+ // a real index. Output is a Markdown table.
9
+
10
+ import { existsSync, readdirSync, rmSync, statSync } from 'node:fs';
11
+ import { join, resolve } from 'node:path';
12
+
13
+ process.env.CLAST_DB_PATH = '.clast/bench.db';
14
+ process.env.UV_THREADPOOL_SIZE ??= '16';
15
+
16
+ const { Clast } = await import('../dist/engine.js');
17
+ const { ToolContext } = await import('../dist/tools/context.js');
18
+ const { search, getContext, callGraph } = await import('../dist/tools/search.js');
19
+ const { overview, references } = await import('../dist/tools/explore.js');
20
+
21
+ const base = resolve(process.argv[2] ?? '.bench/repos');
22
+ const only = new Set(process.argv.slice(3));
23
+ const repos = readdirSync(base).filter(
24
+ name => statSync(join(base, name)).isDirectory() && (only.size === 0 || only.has(name))
25
+ );
26
+
27
+ const ms = n => (n < 10 ? n.toFixed(1) : Math.round(n).toString());
28
+
29
+ async function time(fn) {
30
+ const t = performance.now();
31
+ await fn();
32
+ return performance.now() - t;
33
+ }
34
+
35
+ /** Median of several runs of an async function, in ms. */
36
+ async function median(fn, runs = 5) {
37
+ const samples = [];
38
+ for (let i = 0; i < runs; i++) samples.push(await time(fn));
39
+ samples.sort((a, b) => a - b);
40
+ return samples[Math.floor(samples.length / 2)];
41
+ }
42
+
43
+ const rows = [];
44
+ for (const name of repos) {
45
+ const root = join(base, name);
46
+ for (const suffix of ['', '-wal', '-shm']) rmSync(join(root, '.clast', 'bench.db' + suffix), { force: true });
47
+
48
+ let clast = new Clast(root);
49
+ const cold = await clast.indexer.indexAll();
50
+ const stats = clast.db.stats();
51
+ clast.close();
52
+
53
+ // Warm start: new process state, nothing changed on disk.
54
+ clast = new Clast(root);
55
+ const warm = await clast.indexer.indexAll();
56
+ const ctx = new ToolContext(clast);
57
+
58
+ // Pick a real, well-connected symbol to query: the most called function / method.
59
+ const busiest = clast.db.get(
60
+ `SELECT s.name AS name, s.qname AS qname, COUNT(*) AS n FROM calls c
61
+ JOIN names nm ON nm.id = c.name_id JOIN symbols s ON s.name = nm.name
62
+ WHERE s.kind IN ('function', 'method') AND length(s.name) > 6
63
+ GROUP BY s.name HAVING COUNT(DISTINCT s.id) = 1 ORDER BY n DESC LIMIT 1`
64
+ );
65
+ const target = busiest?.qname ?? 'main';
66
+ const word = busiest?.name ?? 'main';
67
+
68
+ const tSearch = await median(() => search(ctx, { query: word }));
69
+ const tText = await median(() => search(ctx, { query: 'parse config file' }));
70
+ const tSymbol = await median(() => getContext(ctx, { name: target }));
71
+ const tCallers = await median(() => callGraph(ctx, { name: target, direction: 'callers', depth: 2 }));
72
+ const tRefs = await median(() => references(ctx, { name: word }));
73
+ const tOverview = await time(() => overview(ctx, {}));
74
+
75
+ const dbFile = join(root, '.clast', 'bench.db');
76
+ const dbMb = existsSync(dbFile) ? statSync(dbFile).size / 1e6 : 0;
77
+ clast.close();
78
+ for (const suffix of ['', '-wal', '-shm']) rmSync(dbFile + suffix, { force: true });
79
+
80
+ rows.push({
81
+ name, files: stats.files, symbols: stats.symbols, calls: stats.calls,
82
+ cold: cold.durationMs, workers: cold.workers, warm: warm.durationMs, dbMb,
83
+ tSearch, tText, tSymbol, tCallers, tRefs, tOverview, target,
84
+ });
85
+ console.error(`${name}: cold ${cold.durationMs}ms, warm ${warm.durationMs}ms`);
86
+ }
87
+
88
+ rows.sort((a, b) => b.files - a.files);
89
+ console.log('| repo | files | symbols | call edges | cold index | warm rescan | db size | search (name) | search (words) | symbol + callers/callees | callers depth 2 | references | overview |');
90
+ console.log('|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|');
91
+ for (const r of rows) {
92
+ console.log(
93
+ `| ${r.name} | ${r.files} | ${r.symbols} | ${r.calls} | ${(r.cold / 1000).toFixed(1)} s | ${ms(r.warm)} ms | ` +
94
+ `${r.dbMb.toFixed(0)} MB | ${ms(r.tSearch)} ms | ${ms(r.tText)} ms | ${ms(r.tSymbol)} ms | ${ms(r.tCallers)} ms | ` +
95
+ `${ms(r.tRefs)} ms | ${ms(r.tOverview)} ms |`
96
+ );
97
+ }
98
+ console.log(`\nNode ${process.version}, ${process.platform} ${process.arch}. Query times are medians of 5 in-process runs on the most-called function of each repo.`);
@@ -0,0 +1,75 @@
1
+ // Diagnostic: how well does call resolution do on real repositories?
2
+ //
3
+ // npm run build
4
+ // node bench/resolution.mjs <dir-with-repos> [repo-name ...]
5
+ //
6
+ // For a random sample of call sites per repository it reports how the
7
+ // resolver classified them:
8
+ // resolved - linked to one definition with confidence
9
+ // name-only - a candidate was found but could not be confirmed ("?")
10
+ // unknown - a member call on a receiver whose type could not be determined
11
+ // external - no definition in the project (library / runtime / builtin)
12
+
13
+ import { readdirSync, rmSync, statSync } from 'node:fs';
14
+ import { join, resolve } from 'node:path';
15
+
16
+ process.env.CLAST_DB_PATH = '.clast/bench.db';
17
+ process.env.UV_THREADPOOL_SIZE ??= '16';
18
+
19
+ const { Clast } = await import('../dist/engine.js');
20
+ const { Resolver } = await import('../dist/query/resolve.js');
21
+
22
+ const base = resolve(process.argv[2] ?? '.bench/repos');
23
+ const only = new Set(process.argv.slice(3));
24
+ const repos = readdirSync(base).filter(
25
+ name => statSync(join(base, name)).isDirectory() && (only.size === 0 || only.has(name))
26
+ );
27
+ const SAMPLE = 4000;
28
+
29
+ const rows = [];
30
+ for (const name of repos) {
31
+ const root = join(base, name);
32
+ for (const suffix of ['', '-wal', '-shm']) rmSync(join(root, '.clast', 'bench.db' + suffix), { force: true });
33
+ const clast = new Clast(root);
34
+ await clast.indexer.indexAll();
35
+ const db = clast.db;
36
+ const resolver = new Resolver(db);
37
+ const total = db.get(`SELECT COUNT(*) AS n FROM calls`).n;
38
+ const sample = db.all(
39
+ `SELECT c.rowid AS id, n.name, c.file_id, c.caller_id, c.receiver, c.rtype, c.via, c.argc, f.path, f.lang
40
+ FROM calls c JOIN names n ON n.id = c.name_id JOIN files f ON f.id = c.file_id
41
+ WHERE c.rowid IN (SELECT rowid FROM calls ORDER BY random() LIMIT ?)`,
42
+ SAMPLE
43
+ );
44
+ const count = { resolved: 0, nameOnly: 0, unknown: 0, external: 0 };
45
+ const member = { resolved: 0, nameOnly: 0, unknown: 0, external: 0, n: 0 };
46
+ for (const row of sample) {
47
+ const caller = row.caller_id !== null ? db.symbolById(row.caller_id) ?? null : null;
48
+ const site = { fileId: row.file_id, path: row.path, lang: row.lang, receiver: row.receiver, rtype: row.rtype, via: row.via, argc: row.argc, caller };
49
+ const res = resolver.resolve(row.name, site);
50
+ let kind;
51
+ if (res.candidates.length) kind = res.confident ? 'resolved' : 'nameOnly';
52
+ else kind = resolver.isOpaqueReceiver(site) && resolver.candidates(row.name).length ? 'unknown' : 'external';
53
+ count[kind]++;
54
+ if (row.receiver) {
55
+ member[kind]++;
56
+ member.n++;
57
+ }
58
+ }
59
+ clast.close();
60
+ for (const suffix of ['', '-wal', '-shm']) rmSync(join(root, '.clast', 'bench.db' + suffix), { force: true });
61
+ rows.push({ name, total, n: sample.length, count, member });
62
+ console.error(`${name}: done`);
63
+ }
64
+
65
+ const pct = (a, b) => (b ? ((100 * a) / b).toFixed(0) + '%' : '-');
66
+ rows.sort((a, b) => b.total - a.total);
67
+ console.log('| repo | call edges | resolved | name-only "?" | unknown receiver | external | member calls: resolved / unknown |');
68
+ console.log('|---|---:|---:|---:|---:|---:|---:|');
69
+ for (const r of rows) {
70
+ console.log(
71
+ `| ${r.name} | ${r.total} | ${pct(r.count.resolved, r.n)} | ${pct(r.count.nameOnly, r.n)} | ${pct(r.count.unknown, r.n)} | ` +
72
+ `${pct(r.count.external, r.n)} | ${pct(r.member.resolved, r.member.n)} / ${pct(r.member.unknown, r.member.n)} |`
73
+ );
74
+ }
75
+ console.log(`\nSample: up to ${SAMPLE} random call sites per repository. "external" includes calls into libraries and language builtins, which no index of the project alone can resolve.`);
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,257 @@
1
+ #!/usr/bin/env node
2
+ // More I/O threads: the startup scan stats every source file, which is the
3
+ // dominant warm-start cost. Must be set before the first async fs call.
4
+ process.env.UV_THREADPOOL_SIZE ??= '16';
5
+ import { readFileSync } from 'node:fs';
6
+ import { resolve } from 'node:path';
7
+ import { Clast } from './engine.js';
8
+ import { SourceParser } from './parser/index.js';
9
+ import { ToolContext } from './tools/context.js';
10
+ import { callGraph, getContext, hierarchy, search } from './tools/search.js';
11
+ import { changes, fileSummary, grep, overview, references, reindex, status } from './tools/explore.js';
12
+ import { impact, unused } from './tools/impact.js';
13
+ import { stats } from './tools/stats.js';
14
+ import { VERSION } from './version.js';
15
+ const HELP = `clast-ai ${VERSION} - code index for LLM agents
16
+
17
+ usage: clast-ai [command] [args] [--root <dir>]
18
+
19
+ (no command), serve run the MCP server on stdio (what Claude Code launches)
20
+ index [--force] build / update the index
21
+ status index statistics
22
+ overview [path] repository map
23
+ outline <path> file or directory outline
24
+ search <query...> ranked symbol search [--kind k] [--path p] [--lang l] [--limit n]
25
+ symbol <name...> source + callers + callees of a symbol [--path p] [--max-lines n] [--no-body]
26
+ callers <name> who calls it [--depth n] [--limit n] [--within path] [--no-tests|--tests] [--uncertain]
27
+ callees <name> what it calls [--depth n] [--limit n]
28
+ hierarchy <name> supertypes / subtypes / overrides [--depth n] [--limit n] [--within path]
29
+ refs <name> all references to an identifier [--path p] [--limit n]
30
+ grep <pattern> text search with enclosing symbols [--regex] [--path p] [--limit n]
31
+ changes [base] symbols touched by the git diff and their impact
32
+ impact <name> what must change with it, who reaches it, which tests to run [--depth n] [--limit n]
33
+ unused [path] dead code [--kind k] [--lang l] [--limit n] [--no-exported]
34
+ stats [what] [name] exact counts: inventory | symbols | subtypes | calls | text | imports | endpoints | database
35
+ [--kind k] [--on receiver] [--path p] [--lang l] [--group-by g] [--depth n] [--limit n] [--tests]
36
+ parse <file> [--json] debug: show what the extractor produces for a file
37
+ ast <file> debug: dump the tree-sitter syntax tree
38
+
39
+ Query commands refresh the index incrementally first (skip with --no-scan).`;
40
+ const CLI_NAMES = {
41
+ clast_search: 'clast-ai search',
42
+ clast_get_context: 'clast-ai symbol',
43
+ clast_call_graph: 'clast-ai callers / callees',
44
+ clast_references: 'clast-ai refs',
45
+ clast_hierarchy: 'clast-ai hierarchy',
46
+ clast_file_summary: 'clast-ai outline',
47
+ clast_overview: 'clast-ai overview',
48
+ clast_grep: 'clast-ai grep',
49
+ clast_changes: 'clast-ai changes',
50
+ clast_stats: 'clast-ai stats',
51
+ clast_impact: 'clast-ai impact',
52
+ clast_unused: 'clast-ai unused',
53
+ clast_reindex: 'clast-ai index',
54
+ clast_status: 'clast-ai status',
55
+ };
56
+ const BOOLEAN_FLAGS = new Set([
57
+ 'force', 'json', 'regex', 'no-body', 'no-scan', 'no-tests', 'tests', 'uncertain', 'help', 'version', 'all', 'no-exported',
58
+ ]);
59
+ function parseArgs(argv) {
60
+ const positional = [];
61
+ const flags = new Map();
62
+ for (let i = 0; i < argv.length; i++) {
63
+ const a = argv[i];
64
+ if (a.startsWith('--')) {
65
+ const eq = a.indexOf('=');
66
+ if (eq !== -1)
67
+ flags.set(a.slice(2, eq), a.slice(eq + 1));
68
+ else if (BOOLEAN_FLAGS.has(a.slice(2)) || i + 1 >= argv.length)
69
+ flags.set(a.slice(2), true);
70
+ else
71
+ flags.set(a.slice(2), argv[++i]);
72
+ }
73
+ else if (a === '-h')
74
+ flags.set('help', true);
75
+ else
76
+ positional.push(a);
77
+ }
78
+ return { positional, flags };
79
+ }
80
+ async function main() {
81
+ const argv = process.argv.slice(2);
82
+ const cmd = argv[0] && !argv[0].startsWith('-') ? argv[0] : undefined;
83
+ const { positional, flags } = parseArgs(cmd ? argv.slice(1) : argv);
84
+ const str = (k) => {
85
+ const v = flags.get(k);
86
+ return typeof v === 'string' ? v : undefined;
87
+ };
88
+ const num = (k) => {
89
+ const v = str(k);
90
+ return v !== undefined && /^\d+$/.test(v) ? Number(v) : undefined;
91
+ };
92
+ if (flags.has('version'))
93
+ return void console.log(VERSION);
94
+ if (flags.has('help') || cmd === 'help')
95
+ return void console.log(HELP);
96
+ if (cmd === undefined || cmd === 'serve') {
97
+ if (str('root'))
98
+ process.env.CLAST_PROJECT_DIR = resolve(str('root'));
99
+ const { startServer } = await import('./server/index.js');
100
+ await startServer();
101
+ return;
102
+ }
103
+ if (cmd === 'parse' || cmd === 'ast') {
104
+ const file = positional[0];
105
+ if (!file)
106
+ throw new Error(`usage: clast-ai ${cmd} <file>`);
107
+ const source = readFileSync(file, 'utf-8');
108
+ const parser = new SourceParser();
109
+ if (cmd === 'ast')
110
+ return void console.log(await parser.dumpTree(file, source));
111
+ const ex = await parser.extract(file, source);
112
+ if (!ex)
113
+ throw new Error('unsupported file type');
114
+ if (flags.has('json'))
115
+ return void console.log(JSON.stringify(ex, null, 1));
116
+ for (const s of ex.symbols) {
117
+ console.log(`${String(s.startLine).padStart(5)}-${String(s.endLine).padEnd(5)} ${s.kind.padEnd(11)} ${s.qname}` +
118
+ `${s.exported ? ' [exported]' : ''}\n${' '.repeat(12)}sig: ${s.signature}` +
119
+ (s.doc ? `\n${' '.repeat(12)}doc: ${s.doc.split('\n')[0]}` : ''));
120
+ }
121
+ console.log(`\ncalls (${ex.calls.length}):`);
122
+ for (const c of ex.calls) {
123
+ const caller = c.caller >= 0 ? ex.symbols[c.caller].qname : '<file>';
124
+ console.log(` ${caller} -> ${c.receiver ? c.receiver + '.' : ''}${c.name} @${c.line}${c.count > 1 ? ' x' + c.count : ''}`);
125
+ }
126
+ console.log(`\nimports (${ex.imports.length}):`);
127
+ for (const i of ex.imports)
128
+ console.log(` ${i.source} {${i.names.join(', ')}} @${i.line}`);
129
+ console.log(`\nheritage (${ex.heritage.length}):`);
130
+ for (const h of ex.heritage)
131
+ console.log(` ${ex.symbols[h.symbol].qname} ${h.kind} ${h.name}`);
132
+ console.log(`\nidentifiers: ${ex.occ.length} distinct, parse errors: ${ex.hadError}`);
133
+ return;
134
+ }
135
+ const root = resolve(str('root') ?? process.env.CLAST_PROJECT_DIR ?? process.cwd());
136
+ const clast = new Clast(root);
137
+ const ctx = new ToolContext(clast);
138
+ try {
139
+ if (cmd === 'index') {
140
+ const target = positional[0];
141
+ if (target) {
142
+ // Convenience: `clast-ai index <dir>` indexes another directory.
143
+ clast.close();
144
+ const other = new Clast(resolve(target));
145
+ const octx = new ToolContext(other);
146
+ console.log(await reindex(octx, { force: flags.has('force') }));
147
+ other.close();
148
+ return;
149
+ }
150
+ console.log(await reindex(ctx, { force: flags.has('force') }));
151
+ return;
152
+ }
153
+ if (!flags.has('no-scan'))
154
+ await clast.indexer.indexAll();
155
+ const includeTests = flags.has('no-tests') ? false : flags.has('tests') ? true : undefined;
156
+ let out;
157
+ switch (cmd) {
158
+ case 'status':
159
+ out = await status(ctx);
160
+ break;
161
+ case 'overview':
162
+ case 'map':
163
+ out = await overview(ctx, { path: positional[0] });
164
+ break;
165
+ case 'outline':
166
+ case 'file':
167
+ out = await fileSummary(ctx, { path: positional[0] ?? '.', members: flags.has('all') ? 'all' : 'auto' });
168
+ break;
169
+ case 'search':
170
+ out = await search(ctx, {
171
+ query: positional.join(' '), kind: str('kind'), path: str('path'), lang: str('lang'), limit: num('limit'),
172
+ });
173
+ break;
174
+ case 'symbol':
175
+ case 'context':
176
+ out = await getContext(ctx, {
177
+ name: positional, path: str('path'), maxLines: num('max-lines'), includeBody: !flags.has('no-body'),
178
+ });
179
+ break;
180
+ case 'callers':
181
+ case 'callees':
182
+ case 'graph':
183
+ out = await callGraph(ctx, {
184
+ name: positional[0] ?? '', path: str('path'),
185
+ direction: cmd === 'graph' ? 'both' : cmd,
186
+ depth: num('depth'), limit: num('limit'), includeTests, within: str('within'), uncertain: flags.has('uncertain'),
187
+ });
188
+ break;
189
+ case 'hierarchy':
190
+ case 'types':
191
+ out = await hierarchy(ctx, {
192
+ name: positional[0] ?? '', path: str('path'), depth: num('depth'), limit: num('limit'), within: str('within'),
193
+ direction: str('direction'),
194
+ });
195
+ break;
196
+ case 'refs':
197
+ case 'references':
198
+ out = await references(ctx, { name: positional[0] ?? '', path: str('path'), limit: num('limit'), includeTests });
199
+ break;
200
+ case 'grep':
201
+ out = await grep(ctx, {
202
+ pattern: positional.join(' '), regex: flags.has('regex'), path: str('path'), lang: str('lang'),
203
+ limit: num('limit'), includeTests,
204
+ });
205
+ break;
206
+ case 'changes':
207
+ out = await changes(ctx, { base: positional[0] });
208
+ break;
209
+ case 'impact':
210
+ out = await impact(ctx, { name: positional.join(' '), path: str('path'), depth: num('depth'), limit: num('limit') });
211
+ break;
212
+ case 'unused':
213
+ case 'dead':
214
+ out = await unused(ctx, {
215
+ path: positional[0] ?? str('path'), lang: str('lang'), kind: str('kind'), limit: num('limit'),
216
+ exported: flags.has('no-exported') ? false : undefined,
217
+ });
218
+ break;
219
+ case 'stats':
220
+ case 'count': {
221
+ const WHATS = ['inventory', 'symbols', 'subtypes', 'calls', 'text', 'imports', 'endpoints', 'database'];
222
+ const hasWhat = WHATS.includes(positional[0] ?? '');
223
+ out = await stats(ctx, {
224
+ what: hasWhat ? positional[0] : undefined,
225
+ name: (hasWhat ? positional.slice(1) : positional).join(' ') || undefined,
226
+ kind: str('kind'), on: str('on'), path: str('path'), lang: str('lang'),
227
+ groupBy: str('group-by'), depth: num('depth'), limit: num('limit'),
228
+ includeTests: includeTests === true,
229
+ });
230
+ break;
231
+ }
232
+ default:
233
+ console.error(`unknown command: ${cmd}\n\n${HELP}`);
234
+ process.exitCode = 1;
235
+ return;
236
+ }
237
+ // Tool hints name MCP tools; say the same thing in CLI terms here.
238
+ console.log(out
239
+ .replace(/clast_[a-z_]+/g, t => CLI_NAMES[t] ?? t)
240
+ .replace(/\buncertain=true\b/g, '--uncertain')
241
+ .replace(/\bincludeTests=true\b/g, '--tests')
242
+ .replace(/\braise maxLines\b/g, 'raise --max-lines'));
243
+ if (out.startsWith('error:'))
244
+ process.exitCode = 1;
245
+ }
246
+ finally {
247
+ try {
248
+ clast.close();
249
+ }
250
+ catch { /* closed above */ }
251
+ }
252
+ }
253
+ main().catch(err => {
254
+ console.error(err instanceof Error ? err.message : err);
255
+ process.exit(1);
256
+ });
257
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,18 @@
1
1
  export interface ClastConfig {
2
+ /** Language ids to index. Empty = all supported languages. */
2
3
  languages: string[];
4
+ /** Directory / file names (or gitignore-style patterns) to skip. */
3
5
  ignoredPaths: string[];
6
+ /** Honour .gitignore files (root and nested). */
7
+ respectGitignore: boolean;
8
+ /** Index location, relative to the project root unless absolute. */
4
9
  dbPath: string;
10
+ /** Files larger than this many bytes are skipped (generated / vendored blobs). */
11
+ maxFileSize: number;
12
+ /** Safety cap on the number of source files indexed (e.g. when started in a home directory). */
13
+ maxFiles: number;
14
+ /** Parser worker threads for bulk indexing. 0 = auto, 1 = no workers. */
15
+ workers: number;
5
16
  llm: {
6
17
  endpoint: string;
7
18
  model: string;
@@ -13,7 +24,6 @@ export interface ClastConfig {
13
24
  debounceMs: number;
14
25
  enabled: boolean;
15
26
  };
16
- maxBodySize: number;
17
27
  }
28
+ export declare const DEFAULT_IGNORED: string[];
18
29
  export declare const DEFAULT_CONFIG: ClastConfig;
19
- //# sourceMappingURL=defaults.d.ts.map
@@ -1,33 +1,41 @@
1
+ export const DEFAULT_IGNORED = [
2
+ 'node_modules',
3
+ '.git',
4
+ '.hg',
5
+ '.svn',
6
+ 'dist',
7
+ 'build',
8
+ 'out',
9
+ '__pycache__',
10
+ '.venv',
11
+ 'venv',
12
+ '.clast',
13
+ 'vendor',
14
+ 'target',
15
+ '.next',
16
+ '.nuxt',
17
+ 'coverage',
18
+ '.idea',
19
+ '.vscode-test',
20
+ '.gradle',
21
+ '.tox',
22
+ '.mypy_cache',
23
+ '.pytest_cache',
24
+ 'bower_components',
25
+ 'Pods',
26
+ '*.min.js',
27
+ '*.min.css',
28
+ '*.bundle.js',
29
+ '*.d.ts.map',
30
+ ];
1
31
  export const DEFAULT_CONFIG = {
2
- languages: [
3
- 'typescript',
4
- 'javascript',
5
- 'python',
6
- 'java',
7
- 'csharp',
8
- 'go',
9
- 'rust',
10
- 'c',
11
- 'cpp',
12
- 'ruby',
13
- 'php',
14
- ],
15
- ignoredPaths: [
16
- 'node_modules',
17
- '.git',
18
- 'dist',
19
- 'build',
20
- 'out',
21
- '__pycache__',
22
- '.venv',
23
- 'venv',
24
- '.clast',
25
- 'vendor',
26
- 'target',
27
- '.next',
28
- 'coverage',
29
- ],
30
- dbPath: '.clast/clast.db',
32
+ languages: [],
33
+ ignoredPaths: DEFAULT_IGNORED,
34
+ respectGitignore: true,
35
+ dbPath: '.clast/index.db',
36
+ maxFileSize: 1_000_000,
37
+ maxFiles: 150_000,
38
+ workers: 0,
31
39
  llm: {
32
40
  endpoint: 'http://localhost:11434/v1',
33
41
  model: '',
@@ -36,9 +44,8 @@ export const DEFAULT_CONFIG = {
36
44
  alwaysGenerate: false,
37
45
  },
38
46
  watch: {
39
- debounceMs: 300,
47
+ debounceMs: 200,
40
48
  enabled: true,
41
49
  },
42
- maxBodySize: 2000,
43
50
  };
44
51
  //# sourceMappingURL=defaults.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAkBA,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,SAAS,EAAE;QACT,YAAY;QACZ,YAAY;QACZ,QAAQ;QACR,MAAM;QACN,QAAQ;QACR,IAAI;QACJ,MAAM;QACN,GAAG;QACH,KAAK;QACL,MAAM;QACN,KAAK;KACN;IACD,YAAY,EAAE;QACZ,cAAc;QACd,MAAM;QACN,MAAM;QACN,OAAO;QACP,KAAK;QACL,aAAa;QACb,OAAO;QACP,MAAM;QACN,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,OAAO;QACP,UAAU;KACX;IACD,MAAM,EAAE,iBAAiB;IACzB,GAAG,EAAE;QACH,QAAQ,EAAE,2BAA2B;QACrC,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,EAAE;QACV,aAAa,EAAE,CAAC;QAChB,cAAc,EAAE,KAAK;KACtB;IACD,KAAK,EAAE;QACL,UAAU,EAAE,GAAG;QACf,OAAO,EAAE,IAAI;KACd;IACD,WAAW,EAAE,IAAI;CAClB,CAAC"}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AA4BA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,cAAc;IACd,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,OAAO;IACP,KAAK;IACL,aAAa;IACb,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;IACP,UAAU;IACV,OAAO;IACP,cAAc;IACd,SAAS;IACT,MAAM;IACN,aAAa;IACb,eAAe;IACf,kBAAkB;IAClB,MAAM;IACN,UAAU;IACV,WAAW;IACX,aAAa;IACb,YAAY;CACb,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,SAAS,EAAE,EAAE;IACb,YAAY,EAAE,eAAe;IAC7B,gBAAgB,EAAE,IAAI;IACtB,MAAM,EAAE,iBAAiB;IACzB,WAAW,EAAE,SAAS;IACtB,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,CAAC;IACV,GAAG,EAAE;QACH,QAAQ,EAAE,2BAA2B;QACrC,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,EAAE;QACV,aAAa,EAAE,CAAC;QAChB,cAAc,EAAE,KAAK;KACtB;IACD,KAAK,EAAE;QACL,UAAU,EAAE,GAAG;QACf,OAAO,EAAE,IAAI;KACd;CACF,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { type ClastConfig } from './defaults.js';
2
2
  export type { ClastConfig } from './defaults.js';
3
+ export declare function parseConfig(raw: unknown): ClastConfig;
3
4
  export declare function loadConfig(projectRoot: string): ClastConfig;
4
5
  export declare function resolveDbPath(projectRoot: string, config: ClastConfig): string;
5
- //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { readFileSync, existsSync } from 'node:fs';
3
- import { join } from 'node:path';
3
+ import { isAbsolute, join } from 'node:path';
4
4
  import { DEFAULT_CONFIG } from './defaults.js';
5
5
  const LlmConfigSchema = z.object({
6
6
  endpoint: z.string().default(DEFAULT_CONFIG.llm.endpoint),
@@ -10,39 +10,51 @@ const LlmConfigSchema = z.object({
10
10
  alwaysGenerate: z.boolean().default(DEFAULT_CONFIG.llm.alwaysGenerate),
11
11
  });
12
12
  const WatchConfigSchema = z.object({
13
- debounceMs: z.number().int().min(50).max(5000).default(DEFAULT_CONFIG.watch.debounceMs),
13
+ debounceMs: z.number().int().min(20).max(5000).default(DEFAULT_CONFIG.watch.debounceMs),
14
14
  enabled: z.boolean().default(DEFAULT_CONFIG.watch.enabled),
15
15
  });
16
16
  const ClastConfigSchema = z.object({
17
17
  languages: z.array(z.string()).default(DEFAULT_CONFIG.languages),
18
18
  ignoredPaths: z.array(z.string()).default(DEFAULT_CONFIG.ignoredPaths),
19
+ respectGitignore: z.boolean().default(DEFAULT_CONFIG.respectGitignore),
19
20
  dbPath: z.string().default(DEFAULT_CONFIG.dbPath),
21
+ maxFileSize: z.number().int().min(1000).max(100_000_000).default(DEFAULT_CONFIG.maxFileSize),
22
+ maxFiles: z.number().int().min(100).max(5_000_000).default(DEFAULT_CONFIG.maxFiles),
23
+ workers: z.number().int().min(0).max(64).default(DEFAULT_CONFIG.workers),
20
24
  llm: LlmConfigSchema.default(DEFAULT_CONFIG.llm),
21
25
  watch: WatchConfigSchema.default(DEFAULT_CONFIG.watch),
22
- maxBodySize: z.number().int().min(100).max(50000).default(DEFAULT_CONFIG.maxBodySize),
23
26
  });
27
+ export function parseConfig(raw) {
28
+ return ClastConfigSchema.parse(raw ?? {});
29
+ }
24
30
  export function loadConfig(projectRoot) {
25
31
  const candidates = [
26
32
  join(projectRoot, 'clast.config.json'),
27
33
  join(projectRoot, '.claude', 'clast.config.json'),
28
34
  ];
29
35
  for (const candidate of candidates) {
30
- if (existsSync(candidate)) {
31
- try {
32
- const raw = JSON.parse(readFileSync(candidate, 'utf-8'));
33
- return ClastConfigSchema.parse(raw);
34
- }
35
- catch (err) {
36
- console.error(`[clast] Failed to parse config at ${candidate}:`, err);
37
- }
36
+ if (!existsSync(candidate))
37
+ continue;
38
+ try {
39
+ const raw = JSON.parse(readFileSync(candidate, 'utf-8'));
40
+ // The pre-0.2 default pointed at a sql.js database; never reuse that file name.
41
+ if (raw && raw.dbPath === '.clast/clast.db')
42
+ delete raw.dbPath;
43
+ return parseConfig(raw);
44
+ }
45
+ catch (err) {
46
+ console.error(`[clast] Ignoring invalid config at ${candidate}: ${err instanceof Error ? err.message : err}`);
38
47
  }
39
48
  }
40
- return ClastConfigSchema.parse({});
49
+ return parseConfig({});
41
50
  }
42
51
  export function resolveDbPath(projectRoot, config) {
43
- if (config.dbPath.startsWith('/') || config.dbPath.match(/^[a-zA-Z]:\\/)) {
52
+ // CLAST_DB_PATH overrides the configured location (useful for CI caches and experiments).
53
+ const override = process.env.CLAST_DB_PATH;
54
+ if (override)
55
+ return override === ':memory:' || isAbsolute(override) ? override : join(projectRoot, override);
56
+ if (config.dbPath === ':memory:' || isAbsolute(config.dbPath))
44
57
  return config.dbPath;
45
- }
46
58
  return join(projectRoot, config.dbPath);
47
59
  }
48
60
  //# sourceMappingURL=index.js.map