@stupidloud/codegraph 0.8.1 → 0.9.9

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 (341) hide show
  1. package/README.md +319 -152
  2. package/dist/bin/codegraph.d.ts +4 -0
  3. package/dist/bin/codegraph.d.ts.map +1 -1
  4. package/dist/bin/codegraph.js +354 -90
  5. package/dist/bin/codegraph.js.map +1 -1
  6. package/dist/bin/node-version-check.d.ts +17 -0
  7. package/dist/bin/node-version-check.d.ts.map +1 -1
  8. package/dist/bin/node-version-check.js +37 -0
  9. package/dist/bin/node-version-check.js.map +1 -1
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +1 -11
  12. package/dist/config.js.map +1 -1
  13. package/dist/context/formatter.d.ts.map +1 -1
  14. package/dist/context/formatter.js +25 -6
  15. package/dist/context/formatter.js.map +1 -1
  16. package/dist/context/index.d.ts +22 -0
  17. package/dist/context/index.d.ts.map +1 -1
  18. package/dist/context/index.js +257 -6
  19. package/dist/context/index.js.map +1 -1
  20. package/dist/context/markers.d.ts +19 -0
  21. package/dist/context/markers.d.ts.map +1 -0
  22. package/dist/context/markers.js +22 -0
  23. package/dist/context/markers.js.map +1 -0
  24. package/dist/db/index.d.ts +30 -1
  25. package/dist/db/index.d.ts.map +1 -1
  26. package/dist/db/index.js +75 -25
  27. package/dist/db/index.js.map +1 -1
  28. package/dist/db/queries.d.ts +104 -0
  29. package/dist/db/queries.d.ts.map +1 -1
  30. package/dist/db/queries.js +328 -31
  31. package/dist/db/queries.js.map +1 -1
  32. package/dist/db/sqlite-adapter.d.ts +24 -23
  33. package/dist/db/sqlite-adapter.d.ts.map +1 -1
  34. package/dist/db/sqlite-adapter.js +54 -174
  35. package/dist/db/sqlite-adapter.js.map +1 -1
  36. package/dist/directory.d.ts.map +1 -1
  37. package/dist/directory.js +6 -20
  38. package/dist/directory.js.map +1 -1
  39. package/dist/extraction/generated-detection.d.ts +30 -0
  40. package/dist/extraction/generated-detection.d.ts.map +1 -0
  41. package/dist/extraction/generated-detection.js +80 -0
  42. package/dist/extraction/generated-detection.js.map +1 -0
  43. package/dist/extraction/grammars.d.ts +23 -1
  44. package/dist/extraction/grammars.d.ts.map +1 -1
  45. package/dist/extraction/grammars.js +107 -3
  46. package/dist/extraction/grammars.js.map +1 -1
  47. package/dist/extraction/index.d.ts +22 -14
  48. package/dist/extraction/index.d.ts.map +1 -1
  49. package/dist/extraction/index.js +272 -183
  50. package/dist/extraction/index.js.map +1 -1
  51. package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  52. package/dist/extraction/languages/c-cpp.js +45 -0
  53. package/dist/extraction/languages/c-cpp.js.map +1 -1
  54. package/dist/extraction/languages/csharp.d.ts.map +1 -1
  55. package/dist/extraction/languages/csharp.js +2 -1
  56. package/dist/extraction/languages/csharp.js.map +1 -1
  57. package/dist/extraction/languages/go.d.ts.map +1 -1
  58. package/dist/extraction/languages/go.js +18 -2
  59. package/dist/extraction/languages/go.js.map +1 -1
  60. package/dist/extraction/languages/index.d.ts.map +1 -1
  61. package/dist/extraction/languages/index.js +6 -0
  62. package/dist/extraction/languages/index.js.map +1 -1
  63. package/dist/extraction/languages/java.d.ts.map +1 -1
  64. package/dist/extraction/languages/java.js +6 -0
  65. package/dist/extraction/languages/java.js.map +1 -1
  66. package/dist/extraction/languages/kotlin.d.ts.map +1 -1
  67. package/dist/extraction/languages/kotlin.js +6 -0
  68. package/dist/extraction/languages/kotlin.js.map +1 -1
  69. package/dist/extraction/languages/lua.d.ts +3 -0
  70. package/dist/extraction/languages/lua.d.ts.map +1 -0
  71. package/dist/extraction/languages/lua.js +150 -0
  72. package/dist/extraction/languages/lua.js.map +1 -0
  73. package/dist/extraction/languages/luau.d.ts +3 -0
  74. package/dist/extraction/languages/luau.d.ts.map +1 -0
  75. package/dist/extraction/languages/luau.js +37 -0
  76. package/dist/extraction/languages/luau.js.map +1 -0
  77. package/dist/extraction/languages/objc.d.ts +3 -0
  78. package/dist/extraction/languages/objc.d.ts.map +1 -0
  79. package/dist/extraction/languages/objc.js +133 -0
  80. package/dist/extraction/languages/objc.js.map +1 -0
  81. package/dist/extraction/mybatis-extractor.d.ts +48 -0
  82. package/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  83. package/dist/extraction/mybatis-extractor.js +198 -0
  84. package/dist/extraction/mybatis-extractor.js.map +1 -0
  85. package/dist/extraction/tree-sitter-types.d.ts +14 -0
  86. package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
  87. package/dist/extraction/tree-sitter.d.ts +84 -0
  88. package/dist/extraction/tree-sitter.d.ts.map +1 -1
  89. package/dist/extraction/tree-sitter.js +715 -16
  90. package/dist/extraction/tree-sitter.js.map +1 -1
  91. package/dist/extraction/vue-extractor.d.ts +15 -0
  92. package/dist/extraction/vue-extractor.d.ts.map +1 -1
  93. package/dist/extraction/vue-extractor.js +88 -0
  94. package/dist/extraction/vue-extractor.js.map +1 -1
  95. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  96. package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
  97. package/dist/extraction/wasm-runtime-flags.d.ts +38 -0
  98. package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
  99. package/dist/extraction/wasm-runtime-flags.js +106 -0
  100. package/dist/extraction/wasm-runtime-flags.js.map +1 -0
  101. package/dist/graph/traversal.d.ts.map +1 -1
  102. package/dist/graph/traversal.js +76 -38
  103. package/dist/graph/traversal.js.map +1 -1
  104. package/dist/index.d.ts +77 -8
  105. package/dist/index.d.ts.map +1 -1
  106. package/dist/index.js +133 -19
  107. package/dist/index.js.map +1 -1
  108. package/dist/installer/config-writer.d.ts +7 -8
  109. package/dist/installer/config-writer.d.ts.map +1 -1
  110. package/dist/installer/config-writer.js +7 -27
  111. package/dist/installer/config-writer.js.map +1 -1
  112. package/dist/installer/index.d.ts +51 -16
  113. package/dist/installer/index.d.ts.map +1 -1
  114. package/dist/installer/index.js +120 -29
  115. package/dist/installer/index.js.map +1 -1
  116. package/dist/installer/instructions-template.d.ts +11 -21
  117. package/dist/installer/instructions-template.d.ts.map +1 -1
  118. package/dist/installer/instructions-template.js +12 -56
  119. package/dist/installer/instructions-template.js.map +1 -1
  120. package/dist/installer/targets/antigravity.d.ts +57 -0
  121. package/dist/installer/targets/antigravity.d.ts.map +1 -0
  122. package/dist/installer/targets/antigravity.js +308 -0
  123. package/dist/installer/targets/antigravity.js.map +1 -0
  124. package/dist/installer/targets/claude.d.ts +26 -1
  125. package/dist/installer/targets/claude.d.ts.map +1 -1
  126. package/dist/installer/targets/claude.js +118 -40
  127. package/dist/installer/targets/claude.js.map +1 -1
  128. package/dist/installer/targets/codex.d.ts.map +1 -1
  129. package/dist/installer/targets/codex.js +15 -13
  130. package/dist/installer/targets/codex.js.map +1 -1
  131. package/dist/installer/targets/cursor.d.ts.map +1 -1
  132. package/dist/installer/targets/cursor.js +61 -36
  133. package/dist/installer/targets/cursor.js.map +1 -1
  134. package/dist/installer/targets/gemini.d.ts +26 -0
  135. package/dist/installer/targets/gemini.d.ts.map +1 -0
  136. package/dist/installer/targets/gemini.js +167 -0
  137. package/dist/installer/targets/gemini.js.map +1 -0
  138. package/dist/installer/targets/hermes.d.ts +18 -0
  139. package/dist/installer/targets/hermes.d.ts.map +1 -0
  140. package/dist/installer/targets/hermes.js +359 -0
  141. package/dist/installer/targets/hermes.js.map +1 -0
  142. package/dist/installer/targets/kiro.d.ts +27 -0
  143. package/dist/installer/targets/kiro.d.ts.map +1 -0
  144. package/dist/installer/targets/kiro.js +178 -0
  145. package/dist/installer/targets/kiro.js.map +1 -0
  146. package/dist/installer/targets/opencode.d.ts.map +1 -1
  147. package/dist/installer/targets/opencode.js +15 -13
  148. package/dist/installer/targets/opencode.js.map +1 -1
  149. package/dist/installer/targets/registry.d.ts.map +1 -1
  150. package/dist/installer/targets/registry.js +8 -0
  151. package/dist/installer/targets/registry.js.map +1 -1
  152. package/dist/installer/targets/shared.d.ts.map +1 -1
  153. package/dist/installer/targets/shared.js +3 -2
  154. package/dist/installer/targets/shared.js.map +1 -1
  155. package/dist/installer/targets/types.d.ts +1 -16
  156. package/dist/installer/targets/types.d.ts.map +1 -1
  157. package/dist/mcp/daemon-paths.d.ts +46 -0
  158. package/dist/mcp/daemon-paths.d.ts.map +1 -0
  159. package/dist/mcp/daemon-paths.js +125 -0
  160. package/dist/mcp/daemon-paths.js.map +1 -0
  161. package/dist/mcp/daemon.d.ts +161 -0
  162. package/dist/mcp/daemon.d.ts.map +1 -0
  163. package/dist/mcp/daemon.js +403 -0
  164. package/dist/mcp/daemon.js.map +1 -0
  165. package/dist/mcp/engine.d.ts +105 -0
  166. package/dist/mcp/engine.d.ts.map +1 -0
  167. package/dist/mcp/engine.js +270 -0
  168. package/dist/mcp/engine.js.map +1 -0
  169. package/dist/mcp/index.d.ts +70 -52
  170. package/dist/mcp/index.d.ts.map +1 -1
  171. package/dist/mcp/index.js +355 -331
  172. package/dist/mcp/index.js.map +1 -1
  173. package/dist/mcp/proxy.d.ts +81 -0
  174. package/dist/mcp/proxy.d.ts.map +1 -0
  175. package/dist/mcp/proxy.js +510 -0
  176. package/dist/mcp/proxy.js.map +1 -0
  177. package/dist/mcp/server-instructions.d.ts +1 -1
  178. package/dist/mcp/server-instructions.d.ts.map +1 -1
  179. package/dist/mcp/server-instructions.js +21 -21
  180. package/dist/mcp/session.d.ts +77 -0
  181. package/dist/mcp/session.d.ts.map +1 -0
  182. package/dist/mcp/session.js +294 -0
  183. package/dist/mcp/session.js.map +1 -0
  184. package/dist/mcp/tools.d.ts +171 -15
  185. package/dist/mcp/tools.d.ts.map +1 -1
  186. package/dist/mcp/tools.js +1714 -298
  187. package/dist/mcp/tools.js.map +1 -1
  188. package/dist/mcp/transport.d.ts +111 -29
  189. package/dist/mcp/transport.d.ts.map +1 -1
  190. package/dist/mcp/transport.js +181 -71
  191. package/dist/mcp/transport.js.map +1 -1
  192. package/dist/mcp/version.d.ts +19 -0
  193. package/dist/mcp/version.d.ts.map +1 -0
  194. package/dist/mcp/version.js +71 -0
  195. package/dist/mcp/version.js.map +1 -0
  196. package/dist/resolution/callback-synthesizer.d.ts +10 -0
  197. package/dist/resolution/callback-synthesizer.d.ts.map +1 -0
  198. package/dist/resolution/callback-synthesizer.js +1300 -0
  199. package/dist/resolution/callback-synthesizer.js.map +1 -0
  200. package/dist/resolution/frameworks/csharp.d.ts.map +1 -1
  201. package/dist/resolution/frameworks/csharp.js +36 -8
  202. package/dist/resolution/frameworks/csharp.js.map +1 -1
  203. package/dist/resolution/frameworks/drupal.d.ts +51 -0
  204. package/dist/resolution/frameworks/drupal.d.ts.map +1 -0
  205. package/dist/resolution/frameworks/drupal.js +367 -0
  206. package/dist/resolution/frameworks/drupal.js.map +1 -0
  207. package/dist/resolution/frameworks/expo-modules.d.ts +3 -0
  208. package/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
  209. package/dist/resolution/frameworks/expo-modules.js +143 -0
  210. package/dist/resolution/frameworks/expo-modules.js.map +1 -0
  211. package/dist/resolution/frameworks/express.d.ts.map +1 -1
  212. package/dist/resolution/frameworks/express.js +102 -19
  213. package/dist/resolution/frameworks/express.js.map +1 -1
  214. package/dist/resolution/frameworks/fabric.d.ts +3 -0
  215. package/dist/resolution/frameworks/fabric.d.ts.map +1 -0
  216. package/dist/resolution/frameworks/fabric.js +354 -0
  217. package/dist/resolution/frameworks/fabric.js.map +1 -0
  218. package/dist/resolution/frameworks/go.d.ts.map +1 -1
  219. package/dist/resolution/frameworks/go.js +6 -3
  220. package/dist/resolution/frameworks/go.js.map +1 -1
  221. package/dist/resolution/frameworks/index.d.ts +6 -0
  222. package/dist/resolution/frameworks/index.d.ts.map +1 -1
  223. package/dist/resolution/frameworks/index.js +29 -1
  224. package/dist/resolution/frameworks/index.js.map +1 -1
  225. package/dist/resolution/frameworks/java.d.ts.map +1 -1
  226. package/dist/resolution/frameworks/java.js +339 -12
  227. package/dist/resolution/frameworks/java.js.map +1 -1
  228. package/dist/resolution/frameworks/laravel.d.ts.map +1 -1
  229. package/dist/resolution/frameworks/laravel.js +17 -8
  230. package/dist/resolution/frameworks/laravel.js.map +1 -1
  231. package/dist/resolution/frameworks/nestjs.d.ts.map +1 -1
  232. package/dist/resolution/frameworks/nestjs.js +324 -0
  233. package/dist/resolution/frameworks/nestjs.js.map +1 -1
  234. package/dist/resolution/frameworks/play.d.ts +19 -0
  235. package/dist/resolution/frameworks/play.d.ts.map +1 -0
  236. package/dist/resolution/frameworks/play.js +111 -0
  237. package/dist/resolution/frameworks/play.js.map +1 -0
  238. package/dist/resolution/frameworks/python.d.ts.map +1 -1
  239. package/dist/resolution/frameworks/python.js +134 -16
  240. package/dist/resolution/frameworks/python.js.map +1 -1
  241. package/dist/resolution/frameworks/react-native.d.ts +3 -0
  242. package/dist/resolution/frameworks/react-native.d.ts.map +1 -0
  243. package/dist/resolution/frameworks/react-native.js +360 -0
  244. package/dist/resolution/frameworks/react-native.js.map +1 -0
  245. package/dist/resolution/frameworks/react.d.ts.map +1 -1
  246. package/dist/resolution/frameworks/react.js +96 -3
  247. package/dist/resolution/frameworks/react.js.map +1 -1
  248. package/dist/resolution/frameworks/ruby.d.ts.map +1 -1
  249. package/dist/resolution/frameworks/ruby.js +106 -2
  250. package/dist/resolution/frameworks/ruby.js.map +1 -1
  251. package/dist/resolution/frameworks/rust.d.ts.map +1 -1
  252. package/dist/resolution/frameworks/rust.js +102 -5
  253. package/dist/resolution/frameworks/rust.js.map +1 -1
  254. package/dist/resolution/frameworks/swift-objc.d.ts +37 -0
  255. package/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
  256. package/dist/resolution/frameworks/swift-objc.js +252 -0
  257. package/dist/resolution/frameworks/swift-objc.js.map +1 -0
  258. package/dist/resolution/frameworks/swift.d.ts.map +1 -1
  259. package/dist/resolution/frameworks/swift.js +30 -6
  260. package/dist/resolution/frameworks/swift.js.map +1 -1
  261. package/dist/resolution/go-module.d.ts +26 -0
  262. package/dist/resolution/go-module.d.ts.map +1 -0
  263. package/dist/resolution/go-module.js +78 -0
  264. package/dist/resolution/go-module.js.map +1 -0
  265. package/dist/resolution/import-resolver.d.ts +28 -0
  266. package/dist/resolution/import-resolver.d.ts.map +1 -1
  267. package/dist/resolution/import-resolver.js +617 -5
  268. package/dist/resolution/import-resolver.js.map +1 -1
  269. package/dist/resolution/index.d.ts +11 -0
  270. package/dist/resolution/index.d.ts.map +1 -1
  271. package/dist/resolution/index.js +196 -10
  272. package/dist/resolution/index.js.map +1 -1
  273. package/dist/resolution/lru-cache.d.ts +24 -0
  274. package/dist/resolution/lru-cache.d.ts.map +1 -0
  275. package/dist/resolution/lru-cache.js +62 -0
  276. package/dist/resolution/lru-cache.js.map +1 -0
  277. package/dist/resolution/name-matcher.d.ts.map +1 -1
  278. package/dist/resolution/name-matcher.js +212 -0
  279. package/dist/resolution/name-matcher.js.map +1 -1
  280. package/dist/resolution/swift-objc-bridge.d.ts +134 -0
  281. package/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
  282. package/dist/resolution/swift-objc-bridge.js +256 -0
  283. package/dist/resolution/swift-objc-bridge.js.map +1 -0
  284. package/dist/resolution/types.d.ts +44 -0
  285. package/dist/resolution/types.d.ts.map +1 -1
  286. package/dist/resolution/workspace-packages.d.ts +48 -0
  287. package/dist/resolution/workspace-packages.d.ts.map +1 -0
  288. package/dist/resolution/workspace-packages.js +208 -0
  289. package/dist/resolution/workspace-packages.js.map +1 -0
  290. package/dist/search/query-utils.d.ts +18 -0
  291. package/dist/search/query-utils.d.ts.map +1 -1
  292. package/dist/search/query-utils.js +30 -0
  293. package/dist/search/query-utils.js.map +1 -1
  294. package/dist/sync/git-hooks.d.ts.map +1 -1
  295. package/dist/sync/git-hooks.js +2 -0
  296. package/dist/sync/git-hooks.js.map +1 -1
  297. package/dist/sync/index.d.ts +3 -1
  298. package/dist/sync/index.d.ts.map +1 -1
  299. package/dist/sync/index.js +8 -1
  300. package/dist/sync/index.js.map +1 -1
  301. package/dist/sync/watcher.d.ts +214 -12
  302. package/dist/sync/watcher.d.ts.map +1 -1
  303. package/dist/sync/watcher.js +467 -55
  304. package/dist/sync/watcher.js.map +1 -1
  305. package/dist/sync/worktree.d.ts +54 -0
  306. package/dist/sync/worktree.d.ts.map +1 -0
  307. package/dist/sync/worktree.js +137 -0
  308. package/dist/sync/worktree.js.map +1 -0
  309. package/dist/types.d.ts +9 -1
  310. package/dist/types.d.ts.map +1 -1
  311. package/dist/types.js +14 -0
  312. package/dist/types.js.map +1 -1
  313. package/dist/utils.js +1 -1
  314. package/package.json +2 -2
  315. package/scripts/add-lang/bench.sh +60 -0
  316. package/scripts/add-lang/check-grammar.mjs +75 -0
  317. package/scripts/add-lang/dump-ast.mjs +103 -0
  318. package/scripts/add-lang/verify-extraction.mjs +70 -0
  319. package/scripts/agent-eval/arms-F.sh +21 -0
  320. package/scripts/agent-eval/arms-matrix.sh +37 -0
  321. package/scripts/agent-eval/bench-readme.sh +28 -0
  322. package/scripts/agent-eval/bench-why-repo.sh +22 -0
  323. package/scripts/agent-eval/block-read-hook.sh +19 -0
  324. package/scripts/agent-eval/hook-settings.json +15 -0
  325. package/scripts/agent-eval/itrun.sh +24 -11
  326. package/scripts/agent-eval/parse-arms.mjs +116 -0
  327. package/scripts/agent-eval/parse-bench-readme.mjs +84 -0
  328. package/scripts/agent-eval/probe-context.mjs +21 -0
  329. package/scripts/agent-eval/probe-explore.mjs +40 -0
  330. package/scripts/agent-eval/probe-node.mjs +20 -0
  331. package/scripts/agent-eval/probe-sweep.mjs +119 -0
  332. package/scripts/agent-eval/probe-trace.mjs +20 -0
  333. package/scripts/agent-eval/run-arms.sh +56 -0
  334. package/scripts/agent-eval/seq-matrix.mjs +137 -0
  335. package/scripts/build-bundle.sh +118 -0
  336. package/scripts/npm-sdk.js +75 -0
  337. package/scripts/npm-shim.js +246 -0
  338. package/scripts/pack-npm.sh +119 -0
  339. package/scripts/prepare-release.mjs +270 -0
  340. package/scripts/patch-tree-sitter-dart.js +0 -112
  341. package/scripts/release.sh +0 -68
@@ -7,6 +7,7 @@
7
7
  * Usage:
8
8
  * codegraph Run interactive installer (when no args)
9
9
  * codegraph install Run interactive installer
10
+ * codegraph uninstall Remove CodeGraph from your agents
10
11
  * codegraph init [path] Initialize CodeGraph in a project
11
12
  * codegraph uninit [path] Remove CodeGraph from a project
12
13
  * codegraph index [path] Index all files in the project
@@ -15,6 +16,9 @@
15
16
  * codegraph query <search> Search for symbols
16
17
  * codegraph files [options] Show project file structure
17
18
  * codegraph context <task> Build context for a task
19
+ * codegraph callers <symbol> Find what calls a function/method
20
+ * codegraph callees <symbol> Find what a function/method calls
21
+ * codegraph impact <symbol> Analyze what code is affected by changing a symbol
18
22
  * codegraph affected [files] Find test files affected by changes
19
23
  */
20
24
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"codegraph.d.ts","sourceRoot":"","sources":["../../src/bin/codegraph.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
1
+ {"version":3,"file":"codegraph.d.ts","sourceRoot":"","sources":["../../src/bin/codegraph.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
@@ -8,6 +8,7 @@
8
8
  * Usage:
9
9
  * codegraph Run interactive installer (when no args)
10
10
  * codegraph install Run interactive installer
11
+ * codegraph uninstall Remove CodeGraph from your agents
11
12
  * codegraph init [path] Initialize CodeGraph in a project
12
13
  * codegraph uninit [path] Remove CodeGraph from a project
13
14
  * codegraph index [path] Index all files in the project
@@ -16,6 +17,9 @@
16
17
  * codegraph query <search> Search for symbols
17
18
  * codegraph files [options] Show project file structure
18
19
  * codegraph context <task> Build context for a task
20
+ * codegraph callers <symbol> Find what calls a function/method
21
+ * codegraph callees <symbol> Find what a function/method calls
22
+ * codegraph impact <symbol> Analyze what code is affected by changing a symbol
19
23
  * codegraph affected [files] Find test files affected by changes
20
24
  */
21
25
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
@@ -57,9 +61,11 @@ const path = __importStar(require("path"));
57
61
  const fs = __importStar(require("fs"));
58
62
  const child_process_1 = require("child_process");
59
63
  const directory_1 = require("../directory");
64
+ const worktree_1 = require("../sync/worktree");
60
65
  const shimmer_progress_1 = require("../ui/shimmer-progress");
61
66
  const glyphs_1 = require("../ui/glyphs");
62
67
  const node_version_check_1 = require("./node-version-check");
68
+ const wasm_runtime_flags_1 = require("../extraction/wasm-runtime-flags");
63
69
  // Lazy-load heavy modules (CodeGraph, runInstaller) to keep CLI startup fast.
64
70
  async function loadCodeGraph() {
65
71
  try {
@@ -94,6 +100,22 @@ if (nodeMajor >= 25) {
94
100
  }
95
101
  // Override active — banner shown for visibility, continuing.
96
102
  }
103
+ // Enforce the supported Node floor. `engines` in package.json only *warns* on
104
+ // install (unless engine-strict), so hard-block here to actually keep users off
105
+ // unsupported versions. Mirrors the 25+ block above. See package.json `engines`.
106
+ if (nodeMajor < node_version_check_1.MIN_NODE_MAJOR) {
107
+ process.stderr.write((0, node_version_check_1.buildNodeTooOldBanner)(nodeVersion) + '\n');
108
+ if (!process.env.CODEGRAPH_ALLOW_UNSAFE_NODE) {
109
+ process.exit(1);
110
+ }
111
+ // Override active — banner shown for visibility, continuing.
112
+ }
113
+ // Re-exec with V8's `--liftoff-only` if it isn't already set, so tree-sitter's
114
+ // large WASM grammars never hit the turboshaft Zone OOM (`Fatal process out of
115
+ // memory: Zone`) on Node >= 22. No-op under the bundled launcher, which already
116
+ // passes the flag. Must run before any grammar (in the parse worker, which
117
+ // inherits this process's flags) is compiled. See ../extraction/wasm-runtime-flags.
118
+ (0, wasm_runtime_flags_1.relaunchWithWasmRuntimeFlagsIfNeeded)(__filename);
97
119
  // Check if running with no arguments - run installer
98
120
  if (process.argv.length === 2) {
99
121
  Promise.resolve().then(() => __importStar(require('../installer'))).then(({ runInstaller }) => runInstaller()).catch((err) => {
@@ -381,8 +403,8 @@ function main() {
381
403
  */
382
404
  program
383
405
  .command('init [path]')
384
- .description('Initialize CodeGraph in a project directory')
385
- .option('-i, --index', 'Run initial indexing after initialization')
406
+ .description('Initialize CodeGraph in a project directory and build the initial index')
407
+ .option('-i, --index', 'Deprecated: indexing now runs by default; flag accepted for backward compatibility')
386
408
  .option('-v, --verbose', 'Show detailed worker lifecycle and memory info')
387
409
  .action(async (pathArg, options) => {
388
410
  const projectPath = path.resolve(pathArg || process.cwd());
@@ -392,16 +414,6 @@ function main() {
392
414
  if ((0, directory_1.isInitialized)(projectPath)) {
393
415
  clack.log.warn(`Already initialized in ${projectPath}`);
394
416
  clack.log.info('Use "codegraph index" to re-index or "codegraph sync" to update');
395
- // Re-run agent surface wiring so re-running `init` is the
396
- // documented way to recover a project that's missing its
397
- // Cursor rules file (or future per-agent project surfaces).
398
- try {
399
- const { wireProjectSurfacesForGlobalAgents } = await Promise.resolve().then(() => __importStar(require('../installer')));
400
- for (const { target, file } of wireProjectSurfacesForGlobalAgents()) {
401
- clack.log.success(`${target.displayName}: ${file.action} ${file.path}`);
402
- }
403
- }
404
- catch { /* non-fatal */ }
405
417
  try {
406
418
  const { offerWatchFallback } = await Promise.resolve().then(() => __importStar(require('../installer')));
407
419
  await offerWatchFallback(clack, projectPath);
@@ -418,41 +430,25 @@ function main() {
418
430
  config: semanticConfig,
419
431
  });
420
432
  clack.log.success(`Initialized in ${projectPath}`);
421
- // Bootstrap project-local surfaces for any agent that's
422
- // configured globally (Cursor needs ./.cursor/rules/codegraph.mdc
423
- // to actually prefer codegraph over native grep). Silent when
424
- // there's nothing to write.
425
- try {
426
- const { wireProjectSurfacesForGlobalAgents } = await Promise.resolve().then(() => __importStar(require('../installer')));
427
- for (const { target, file } of wireProjectSurfacesForGlobalAgents()) {
428
- clack.log.success(`${target.displayName}: ${file.action} ${file.path}`);
429
- }
430
- }
431
- catch (err) {
432
- const msg = err instanceof Error ? err.message : String(err);
433
- clack.log.warn(`Skipped wiring project-local agent surfaces: ${msg}`);
434
- }
435
- if (options.index) {
436
- let result;
437
- if (options.verbose) {
438
- result = await cg.indexAll({
439
- onProgress: createVerboseProgress(),
440
- verbose: true,
441
- });
442
- }
443
- else {
444
- process.stdout.write(`${colors.dim}${(0, glyphs_1.getGlyphs)().rail}${colors.reset}\n`);
445
- const progress = (0, shimmer_progress_1.createShimmerProgress)();
446
- result = await cg.indexAll({
447
- onProgress: progress.onProgress,
448
- });
449
- await progress.stop();
450
- }
451
- printIndexResult(clack, result, projectPath);
433
+ // Indexing runs by default now. The legacy -i/--index flag is still
434
+ // accepted (so existing muscle memory and scripts don't break) but is a
435
+ // no-op initializing always builds the initial index.
436
+ let result;
437
+ if (options.verbose) {
438
+ result = await cg.indexAll({
439
+ onProgress: createVerboseProgress(),
440
+ verbose: true,
441
+ });
452
442
  }
453
443
  else {
454
- clack.log.info('Run "codegraph index" to index the project');
444
+ process.stdout.write(`${colors.dim}${(0, glyphs_1.getGlyphs)().rail}${colors.reset}\n`);
445
+ const progress = (0, shimmer_progress_1.createShimmerProgress)();
446
+ result = await cg.indexAll({
447
+ onProgress: progress.onProgress,
448
+ });
449
+ await progress.stop();
455
450
  }
451
+ printIndexResult(clack, result, projectPath);
456
452
  try {
457
453
  const { offerWatchFallback } = await Promise.resolve().then(() => __importStar(require('../installer')));
458
454
  await offerWatchFallback(clack, projectPath);
@@ -639,10 +635,21 @@ function main() {
639
635
  .option('-j, --json', 'Output as JSON')
640
636
  .action(async (pathArg, options) => {
641
637
  const projectPath = resolveProjectPath(pathArg);
638
+ // The directory the user actually ran from, before walking up to the index
639
+ // root. Used to detect when the resolved index lives in a different git
640
+ // working tree (e.g. a nested worktree borrowing the main checkout's index).
641
+ const startPath = path.resolve(pathArg || process.cwd());
642
+ const worktreeMismatch = (0, worktree_1.detectWorktreeIndexMismatch)(startPath, projectPath);
642
643
  try {
643
644
  if (!(0, directory_1.isInitialized)(projectPath)) {
644
645
  if (options.json) {
645
- console.log(JSON.stringify({ initialized: false, projectPath }));
646
+ console.log(JSON.stringify({
647
+ initialized: false,
648
+ version: packageJson.version,
649
+ projectPath,
650
+ indexPath: (0, directory_1.getCodeGraphDir)(projectPath),
651
+ lastIndexed: null,
652
+ }));
646
653
  return;
647
654
  }
648
655
  console.log(chalk.bold('\nCodeGraph Status\n'));
@@ -656,16 +663,22 @@ function main() {
656
663
  const stats = cg.getStats();
657
664
  const changes = cg.getChangedFiles();
658
665
  const backend = cg.getBackend();
666
+ const journalMode = cg.getJournalMode();
659
667
  // JSON output mode
660
668
  if (options.json) {
669
+ const lastIndexedMs = cg.getLastIndexedAt();
661
670
  console.log(JSON.stringify({
662
671
  initialized: true,
672
+ version: packageJson.version,
663
673
  projectPath,
674
+ indexPath: (0, directory_1.getCodeGraphDir)(projectPath),
675
+ lastIndexed: lastIndexedMs != null ? new Date(lastIndexedMs).toISOString() : null,
664
676
  fileCount: stats.fileCount,
665
677
  nodeCount: stats.nodeCount,
666
678
  edgeCount: stats.edgeCount,
667
679
  dbSizeBytes: stats.dbSizeBytes,
668
680
  backend,
681
+ journalMode,
669
682
  nodesByKind: stats.nodesByKind,
670
683
  languages: Object.entries(stats.filesByLanguage).filter(([, count]) => count > 0).map(([lang]) => lang),
671
684
  pendingChanges: {
@@ -673,6 +686,9 @@ function main() {
673
686
  modified: changes.modified.length,
674
687
  removed: changes.removed.length,
675
688
  },
689
+ worktreeMismatch: worktreeMismatch
690
+ ? { worktreeRoot: worktreeMismatch.worktreeRoot, indexRoot: worktreeMismatch.indexRoot }
691
+ : null,
676
692
  }));
677
693
  cg.destroy();
678
694
  return;
@@ -680,6 +696,9 @@ function main() {
680
696
  console.log(chalk.bold('\nCodeGraph Status\n'));
681
697
  // Project info
682
698
  console.log(chalk.cyan('Project:'), projectPath);
699
+ if (worktreeMismatch) {
700
+ warn((0, worktree_1.worktreeMismatchWarning)(worktreeMismatch));
701
+ }
683
702
  console.log();
684
703
  // Index stats
685
704
  console.log(chalk.bold('Index Statistics:'));
@@ -687,14 +706,18 @@ function main() {
687
706
  console.log(` Nodes: ${formatNumber(stats.nodeCount)}`);
688
707
  console.log(` Edges: ${formatNumber(stats.edgeCount)}`);
689
708
  console.log(` DB Size: ${(stats.dbSizeBytes / 1024 / 1024).toFixed(2)} MB`);
690
- // Surface the active SQLite backend so users can spot the silent
691
- // WASM fallback (5-10x slower). better-sqlite3 is in
692
- // `optionalDependencies`, so `npm install` succeeds without it
693
- // when the native build fails.
694
- const backendLabel = backend === 'native'
695
- ? chalk.green('native')
696
- : chalk.yellow(`wasm ${(0, glyphs_1.getGlyphs)().dash} slower fallback; run \`npm rebuild better-sqlite3\``);
709
+ // Surface the active SQLite backend (node:sqlite Node's built-in real
710
+ // SQLite, full WAL + FTS5, no native build).
711
+ const backendLabel = chalk.green(`node:sqlite ${(0, glyphs_1.getGlyphs)().dash} built-in (full WAL)`);
697
712
  console.log(` Backend: ${backendLabel}`);
713
+ // Effective journal mode: 'wal' means concurrent reads never block on a
714
+ // writer; anything else means they can ("database is locked"). node:sqlite
715
+ // supports WAL everywhere, so a non-wal mode means the filesystem can't
716
+ // (network mounts, WSL2 /mnt). See issue #238.
717
+ const journalLabel = journalMode === 'wal'
718
+ ? chalk.green('wal')
719
+ : chalk.yellow(`${journalMode || 'unknown'} ${(0, glyphs_1.getGlyphs)().dash} WAL inactive; reads can block on writes`);
720
+ console.log(` Journal: ${journalLabel}`);
698
721
  console.log();
699
722
  // Node breakdown
700
723
  console.log(chalk.bold('Nodes by Kind:'));
@@ -760,10 +783,19 @@ function main() {
760
783
  const { default: CodeGraph } = await loadCodeGraph();
761
784
  const cg = await CodeGraph.open(projectPath);
762
785
  const limit = parseInt(options.limit || '10', 10);
763
- const results = cg.searchNodes(search, {
786
+ const rawResults = cg.searchNodes(search, {
764
787
  limit,
765
788
  kinds: options.kind ? [options.kind] : undefined,
766
789
  });
790
+ // Mirror the MCP search down-rank so the CLI also surfaces the
791
+ // hand-written implementation before protobuf/gRPC scaffolding
792
+ // when both share a name. See extraction/generated-detection.ts.
793
+ const { isGeneratedFile } = await Promise.resolve().then(() => __importStar(require('../extraction/generated-detection')));
794
+ const results = [...rawResults].sort((a, b) => {
795
+ const aGen = isGeneratedFile(a.node.filePath) ? 1 : 0;
796
+ const bGen = isGeneratedFile(b.node.filePath) ? 1 : 0;
797
+ return aGen - bGen;
798
+ });
767
799
  if (options.json) {
768
800
  console.log(JSON.stringify(results, null, 2));
769
801
  }
@@ -964,41 +996,6 @@ function main() {
964
996
  };
965
997
  renderNode(root, '', true, 0);
966
998
  }
967
- /**
968
- * codegraph context <task>
969
- */
970
- program
971
- .command('context <task>')
972
- .description('Build context for a task (outputs markdown)')
973
- .option('-p, --path <path>', 'Project path')
974
- .option('-n, --max-nodes <number>', 'Maximum nodes to include', '50')
975
- .option('-c, --max-code <number>', 'Maximum code blocks', '10')
976
- .option('--no-code', 'Exclude code blocks')
977
- .option('-f, --format <format>', 'Output format (markdown, json)', 'markdown')
978
- .action(async (task, options) => {
979
- const projectPath = resolveProjectPath(options.path);
980
- try {
981
- if (!(0, directory_1.isInitialized)(projectPath)) {
982
- error(`CodeGraph not initialized in ${projectPath}`);
983
- process.exit(1);
984
- }
985
- const { default: CodeGraph } = await loadCodeGraph();
986
- const cg = await CodeGraph.open(projectPath);
987
- const context = await cg.buildContext(task, {
988
- maxNodes: parseInt(options.maxNodes || '50', 10),
989
- maxCodeBlocks: parseInt(options.maxCode || '10', 10),
990
- includeCode: options.code !== false,
991
- format: options.format,
992
- });
993
- // Output the context
994
- console.log(context);
995
- cg.destroy();
996
- }
997
- catch (err) {
998
- error(`Failed to build context: ${err instanceof Error ? err.message : String(err)}`);
999
- process.exit(1);
1000
- }
1001
- });
1002
999
  /**
1003
1000
  * codegraph serve
1004
1001
  */
@@ -1040,8 +1037,8 @@ function main() {
1040
1037
  }
1041
1038
  `));
1042
1039
  console.error('Available tools:');
1040
+ console.error(chalk.cyan(' codegraph_explore') + ' - Primary: source of the relevant symbols for any question');
1043
1041
  console.error(chalk.cyan(' codegraph_search') + ' - Search for code symbols');
1044
- console.error(chalk.cyan(' codegraph_context') + ' - Build context for a task');
1045
1042
  console.error(chalk.cyan(' codegraph_callers') + ' - Find callers of a symbol');
1046
1043
  console.error(chalk.cyan(' codegraph_callees') + ' - Find what a symbol calls');
1047
1044
  console.error(chalk.cyan(' codegraph_impact') + ' - Analyze impact of changes');
@@ -1214,6 +1211,241 @@ function main() {
1214
1211
  process.exit(1);
1215
1212
  }
1216
1213
  });
1214
+ /**
1215
+ * codegraph callers <symbol>
1216
+ *
1217
+ * CLI parity with the MCP graph tools (codegraph_callers/callees/impact) so the
1218
+ * traversal queries work in scripts, CI, and git hooks without a running MCP
1219
+ * server.
1220
+ */
1221
+ program
1222
+ .command('callers <symbol>')
1223
+ .description('Find all functions/methods that call a specific symbol')
1224
+ .option('-p, --path <path>', 'Project path')
1225
+ .option('-l, --limit <number>', 'Maximum results', '20')
1226
+ .option('-j, --json', 'Output as JSON')
1227
+ .action(async (symbol, options) => {
1228
+ const projectPath = resolveProjectPath(options.path);
1229
+ try {
1230
+ if (!(0, directory_1.isInitialized)(projectPath)) {
1231
+ error(`CodeGraph not initialized in ${projectPath}`);
1232
+ process.exit(1);
1233
+ }
1234
+ const { default: CodeGraph } = await loadCodeGraph();
1235
+ const cg = await CodeGraph.open(projectPath);
1236
+ const limit = parseInt(options.limit || '20', 10);
1237
+ const matches = cg.searchNodes(symbol, { limit: 50 });
1238
+ if (matches.length === 0) {
1239
+ info(`Symbol "${symbol}" not found`);
1240
+ cg.destroy();
1241
+ return;
1242
+ }
1243
+ const seen = new Set();
1244
+ const allCallers = [];
1245
+ for (const match of matches) {
1246
+ const exactMatch = match.node.name === symbol || match.node.name.endsWith(`.${symbol}`) || match.node.name.endsWith(`::${symbol}`);
1247
+ if (!exactMatch && matches.length > 1)
1248
+ continue;
1249
+ for (const c of cg.getCallers(match.node.id)) {
1250
+ if (!seen.has(c.node.id)) {
1251
+ seen.add(c.node.id);
1252
+ allCallers.push({ name: c.node.name, kind: c.node.kind, filePath: c.node.filePath, startLine: c.node.startLine });
1253
+ }
1254
+ }
1255
+ }
1256
+ // Fallback: if exact filter removed everything, use the top match
1257
+ if (allCallers.length === 0 && matches[0]) {
1258
+ for (const c of cg.getCallers(matches[0].node.id)) {
1259
+ if (!seen.has(c.node.id)) {
1260
+ seen.add(c.node.id);
1261
+ allCallers.push({ name: c.node.name, kind: c.node.kind, filePath: c.node.filePath, startLine: c.node.startLine });
1262
+ }
1263
+ }
1264
+ }
1265
+ const limited = allCallers.slice(0, limit);
1266
+ if (options.json) {
1267
+ console.log(JSON.stringify({ symbol, callers: limited }, null, 2));
1268
+ }
1269
+ else if (limited.length === 0) {
1270
+ info(`No callers found for "${symbol}"`);
1271
+ }
1272
+ else {
1273
+ console.log(chalk.bold(`\nCallers of "${symbol}" (${limited.length}):\n`));
1274
+ for (const node of limited) {
1275
+ const loc = node.startLine ? `:${node.startLine}` : '';
1276
+ console.log(chalk.cyan(node.kind.padEnd(12)) +
1277
+ chalk.white(node.name));
1278
+ console.log(chalk.dim(` ${node.filePath}${loc}`));
1279
+ console.log();
1280
+ }
1281
+ }
1282
+ cg.destroy();
1283
+ }
1284
+ catch (err) {
1285
+ error(`callers failed: ${err instanceof Error ? err.message : String(err)}`);
1286
+ process.exit(1);
1287
+ }
1288
+ });
1289
+ /**
1290
+ * codegraph callees <symbol>
1291
+ */
1292
+ program
1293
+ .command('callees <symbol>')
1294
+ .description('Find all functions/methods that a specific symbol calls')
1295
+ .option('-p, --path <path>', 'Project path')
1296
+ .option('-l, --limit <number>', 'Maximum results', '20')
1297
+ .option('-j, --json', 'Output as JSON')
1298
+ .action(async (symbol, options) => {
1299
+ const projectPath = resolveProjectPath(options.path);
1300
+ try {
1301
+ if (!(0, directory_1.isInitialized)(projectPath)) {
1302
+ error(`CodeGraph not initialized in ${projectPath}`);
1303
+ process.exit(1);
1304
+ }
1305
+ const { default: CodeGraph } = await loadCodeGraph();
1306
+ const cg = await CodeGraph.open(projectPath);
1307
+ const limit = parseInt(options.limit || '20', 10);
1308
+ const matches = cg.searchNodes(symbol, { limit: 50 });
1309
+ if (matches.length === 0) {
1310
+ info(`Symbol "${symbol}" not found`);
1311
+ cg.destroy();
1312
+ return;
1313
+ }
1314
+ const seen = new Set();
1315
+ const allCallees = [];
1316
+ for (const match of matches) {
1317
+ const exactMatch = match.node.name === symbol || match.node.name.endsWith(`.${symbol}`) || match.node.name.endsWith(`::${symbol}`);
1318
+ if (!exactMatch && matches.length > 1)
1319
+ continue;
1320
+ for (const c of cg.getCallees(match.node.id)) {
1321
+ if (!seen.has(c.node.id)) {
1322
+ seen.add(c.node.id);
1323
+ allCallees.push({ name: c.node.name, kind: c.node.kind, filePath: c.node.filePath, startLine: c.node.startLine });
1324
+ }
1325
+ }
1326
+ }
1327
+ if (allCallees.length === 0 && matches[0]) {
1328
+ for (const c of cg.getCallees(matches[0].node.id)) {
1329
+ if (!seen.has(c.node.id)) {
1330
+ seen.add(c.node.id);
1331
+ allCallees.push({ name: c.node.name, kind: c.node.kind, filePath: c.node.filePath, startLine: c.node.startLine });
1332
+ }
1333
+ }
1334
+ }
1335
+ const limited = allCallees.slice(0, limit);
1336
+ if (options.json) {
1337
+ console.log(JSON.stringify({ symbol, callees: limited }, null, 2));
1338
+ }
1339
+ else if (limited.length === 0) {
1340
+ info(`No callees found for "${symbol}"`);
1341
+ }
1342
+ else {
1343
+ console.log(chalk.bold(`\nCallees of "${symbol}" (${limited.length}):\n`));
1344
+ for (const node of limited) {
1345
+ const loc = node.startLine ? `:${node.startLine}` : '';
1346
+ console.log(chalk.cyan(node.kind.padEnd(12)) +
1347
+ chalk.white(node.name));
1348
+ console.log(chalk.dim(` ${node.filePath}${loc}`));
1349
+ console.log();
1350
+ }
1351
+ }
1352
+ cg.destroy();
1353
+ }
1354
+ catch (err) {
1355
+ error(`callees failed: ${err instanceof Error ? err.message : String(err)}`);
1356
+ process.exit(1);
1357
+ }
1358
+ });
1359
+ /**
1360
+ * codegraph impact <symbol>
1361
+ */
1362
+ program
1363
+ .command('impact <symbol>')
1364
+ .description('Analyze what code is affected by changing a symbol')
1365
+ .option('-p, --path <path>', 'Project path')
1366
+ .option('-d, --depth <number>', 'Traversal depth', '2')
1367
+ .option('-j, --json', 'Output as JSON')
1368
+ .action(async (symbol, options) => {
1369
+ const projectPath = resolveProjectPath(options.path);
1370
+ try {
1371
+ if (!(0, directory_1.isInitialized)(projectPath)) {
1372
+ error(`CodeGraph not initialized in ${projectPath}`);
1373
+ process.exit(1);
1374
+ }
1375
+ const { default: CodeGraph } = await loadCodeGraph();
1376
+ const cg = await CodeGraph.open(projectPath);
1377
+ const depth = Math.min(Math.max(parseInt(options.depth || '2', 10), 1), 10);
1378
+ const matches = cg.searchNodes(symbol, { limit: 50 });
1379
+ if (matches.length === 0) {
1380
+ info(`Symbol "${symbol}" not found`);
1381
+ cg.destroy();
1382
+ return;
1383
+ }
1384
+ // Merge impact subgraphs across all exact-matching symbols
1385
+ const mergedNodes = new Map();
1386
+ const seenEdges = new Set();
1387
+ let edgeCount = 0;
1388
+ for (const match of matches) {
1389
+ const exactMatch = match.node.name === symbol || match.node.name.endsWith(`.${symbol}`) || match.node.name.endsWith(`::${symbol}`);
1390
+ if (!exactMatch && matches.length > 1)
1391
+ continue;
1392
+ const impact = cg.getImpactRadius(match.node.id, depth);
1393
+ for (const [id, n] of impact.nodes) {
1394
+ mergedNodes.set(id, { name: n.name, kind: n.kind, filePath: n.filePath, startLine: n.startLine });
1395
+ }
1396
+ for (const e of impact.edges) {
1397
+ const key = `${e.source}->${e.target}:${e.kind}`;
1398
+ if (!seenEdges.has(key)) {
1399
+ seenEdges.add(key);
1400
+ edgeCount++;
1401
+ }
1402
+ }
1403
+ }
1404
+ // Fallback to top match if exact filter removed everything
1405
+ if (mergedNodes.size === 0 && matches[0]) {
1406
+ const impact = cg.getImpactRadius(matches[0].node.id, depth);
1407
+ for (const [id, n] of impact.nodes) {
1408
+ mergedNodes.set(id, { name: n.name, kind: n.kind, filePath: n.filePath, startLine: n.startLine });
1409
+ }
1410
+ edgeCount = impact.edges.length;
1411
+ }
1412
+ if (options.json) {
1413
+ console.log(JSON.stringify({
1414
+ symbol,
1415
+ depth,
1416
+ nodeCount: mergedNodes.size,
1417
+ edgeCount,
1418
+ affected: Array.from(mergedNodes.values()),
1419
+ }, null, 2));
1420
+ }
1421
+ else if (mergedNodes.size === 0) {
1422
+ info(`No affected symbols found for "${symbol}"`);
1423
+ }
1424
+ else {
1425
+ console.log(chalk.bold(`\nImpact of changing "${symbol}" — ${mergedNodes.size} affected symbols:\n`));
1426
+ // Group by file
1427
+ const byFile = new Map();
1428
+ for (const node of mergedNodes.values()) {
1429
+ const list = byFile.get(node.filePath) || [];
1430
+ list.push({ name: node.name, kind: node.kind, startLine: node.startLine });
1431
+ byFile.set(node.filePath, list);
1432
+ }
1433
+ for (const [file, nodes] of byFile) {
1434
+ console.log(chalk.cyan(file));
1435
+ for (const node of nodes) {
1436
+ const loc = node.startLine ? `:${node.startLine}` : '';
1437
+ console.log(` ${chalk.dim(node.kind.padEnd(12))}${node.name}${chalk.dim(loc)}`);
1438
+ }
1439
+ console.log();
1440
+ }
1441
+ }
1442
+ cg.destroy();
1443
+ }
1444
+ catch (err) {
1445
+ error(`impact failed: ${err instanceof Error ? err.message : String(err)}`);
1446
+ process.exit(1);
1447
+ }
1448
+ });
1217
1449
  /**
1218
1450
  * codegraph affected [files...]
1219
1451
  *
@@ -1349,7 +1581,7 @@ function main() {
1349
1581
  */
1350
1582
  program
1351
1583
  .command('install')
1352
- .description('Install codegraph MCP server into one or more agents (Claude Code, Cursor, Codex CLI, opencode)')
1584
+ .description('Install codegraph MCP server into one or more agents (Claude Code, Cursor, Codex CLI, opencode, Hermes Agent)')
1353
1585
  .option('-t, --target <ids>', 'Target agent(s): comma-separated ids, or "auto"|"all"|"none". Default: prompt')
1354
1586
  .option('-l, --location <where>', 'Install location: "global" or "local". Default: prompt')
1355
1587
  .option('-y, --yes', 'Non-interactive: defaults to --location=global --target=auto, auto-allow on')
@@ -1398,6 +1630,38 @@ function main() {
1398
1630
  process.exit(1);
1399
1631
  }
1400
1632
  });
1633
+ /**
1634
+ * codegraph uninstall
1635
+ *
1636
+ * Inverse of `install`. Removes the codegraph MCP server entry,
1637
+ * instructions block, and permissions from every agent (or a
1638
+ * `--target` subset). Prompts global-vs-local when not given. Does NOT
1639
+ * delete the `.codegraph/` index — that's `codegraph uninit`.
1640
+ */
1641
+ program
1642
+ .command('uninstall')
1643
+ .description('Remove codegraph from your agents (Claude Code, Cursor, Codex CLI, opencode, Hermes Agent)')
1644
+ .option('-t, --target <ids>', 'Target agent(s): comma-separated ids, or "all". Default: all')
1645
+ .option('-l, --location <where>', 'Uninstall location: "global" or "local". Default: prompt')
1646
+ .option('-y, --yes', 'Non-interactive: defaults to --location=global --target=all')
1647
+ .action(async (opts) => {
1648
+ const { runUninstaller } = await Promise.resolve().then(() => __importStar(require('../installer')));
1649
+ if (opts.location && opts.location !== 'global' && opts.location !== 'local') {
1650
+ error(`--location must be "global" or "local" (got "${opts.location}").`);
1651
+ process.exit(1);
1652
+ }
1653
+ try {
1654
+ await runUninstaller({
1655
+ target: opts.target,
1656
+ location: opts.location,
1657
+ yes: opts.yes,
1658
+ });
1659
+ }
1660
+ catch (err) {
1661
+ error(err instanceof Error ? err.message : String(err));
1662
+ process.exit(1);
1663
+ }
1664
+ });
1401
1665
  // Parse and run
1402
1666
  program.parse();
1403
1667
  } // end main()