lmgrep 0.1.18 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/README.md +253 -62
  2. package/completions/_lmgrep +49 -40
  3. package/dist/application/Lmgrep.d.ts +107 -0
  4. package/dist/application/Lmgrep.js +99 -0
  5. package/dist/application/Lmgrep.js.map +1 -0
  6. package/dist/application/LmgrepFactory.d.ts +40 -0
  7. package/dist/application/LmgrepFactory.js +155 -0
  8. package/dist/application/LmgrepFactory.js.map +1 -0
  9. package/dist/application/indexing/BranchBootstrapper.d.ts +21 -0
  10. package/dist/application/indexing/BranchBootstrapper.js +52 -0
  11. package/dist/application/indexing/BranchBootstrapper.js.map +1 -0
  12. package/dist/application/indexing/BranchManifestSweeper.d.ts +17 -0
  13. package/dist/application/indexing/BranchManifestSweeper.js +35 -0
  14. package/dist/application/indexing/BranchManifestSweeper.js.map +1 -0
  15. package/dist/application/indexing/Duration.d.ts +9 -0
  16. package/dist/application/indexing/Duration.js +25 -0
  17. package/dist/application/indexing/Duration.js.map +1 -0
  18. package/dist/application/indexing/EmbeddingAbortError.d.ts +11 -0
  19. package/dist/application/indexing/EmbeddingAbortError.js +20 -0
  20. package/dist/application/indexing/EmbeddingAbortError.js.map +1 -0
  21. package/dist/application/indexing/EmbeddingPipeline.d.ts +59 -0
  22. package/dist/application/indexing/EmbeddingPipeline.js +140 -0
  23. package/dist/application/indexing/EmbeddingPipeline.js.map +1 -0
  24. package/dist/application/indexing/IndexBuilder.d.ts +112 -0
  25. package/dist/application/indexing/IndexBuilder.js +370 -0
  26. package/dist/application/indexing/IndexBuilder.js.map +1 -0
  27. package/dist/application/indexing/IndexingProgress.d.ts +34 -0
  28. package/dist/application/indexing/IndexingProgress.js +2 -0
  29. package/dist/application/indexing/IndexingProgress.js.map +1 -0
  30. package/dist/application/operations/Deadline.d.ts +13 -0
  31. package/dist/application/operations/Deadline.js +29 -0
  32. package/dist/application/operations/Deadline.js.map +1 -0
  33. package/dist/application/operations/HealthMonitor.d.ts +58 -0
  34. package/dist/application/operations/HealthMonitor.js +128 -0
  35. package/dist/application/operations/HealthMonitor.js.map +1 -0
  36. package/dist/application/operations/IndexAlternatives.d.ts +35 -0
  37. package/dist/application/operations/IndexAlternatives.js +61 -0
  38. package/dist/application/operations/IndexAlternatives.js.map +1 -0
  39. package/dist/application/operations/IndexInventory.d.ts +69 -0
  40. package/dist/application/operations/IndexInventory.js +99 -0
  41. package/dist/application/operations/IndexInventory.js.map +1 -0
  42. package/dist/application/operations/StatusService.d.ts +90 -0
  43. package/dist/application/operations/StatusService.js +171 -0
  44. package/dist/application/operations/StatusService.js.map +1 -0
  45. package/dist/application/operations/WatchService.d.ts +67 -0
  46. package/dist/application/operations/WatchService.js +145 -0
  47. package/dist/application/operations/WatchService.js.map +1 -0
  48. package/dist/application/operations/WorkingTreeDiff.d.ts +19 -0
  49. package/dist/application/operations/WorkingTreeDiff.js +36 -0
  50. package/dist/application/operations/WorkingTreeDiff.js.map +1 -0
  51. package/dist/application/research/ResearchAgent.d.ts +68 -0
  52. package/dist/application/research/ResearchAgent.js +201 -0
  53. package/dist/application/research/ResearchAgent.js.map +1 -0
  54. package/dist/application/research/ResearchPrompts.d.ts +16 -0
  55. package/dist/application/research/ResearchPrompts.js +34 -0
  56. package/dist/application/research/ResearchPrompts.js.map +1 -0
  57. package/dist/application/search/SearchCriteria.d.ts +37 -0
  58. package/dist/application/search/SearchCriteria.js +48 -0
  59. package/dist/application/search/SearchCriteria.js.map +1 -0
  60. package/dist/application/search/SearchService.d.ts +36 -0
  61. package/dist/application/search/SearchService.js +108 -0
  62. package/dist/application/search/SearchService.js.map +1 -0
  63. package/dist/application/search/SearchTargetResolver.d.ts +56 -0
  64. package/dist/application/search/SearchTargetResolver.js +104 -0
  65. package/dist/application/search/SearchTargetResolver.js.map +1 -0
  66. package/dist/cli.d.ts +1 -1
  67. package/dist/cli.js +4 -953
  68. package/dist/cli.js.map +1 -1
  69. package/dist/domain/config/ConfigSource.d.ts +16 -0
  70. package/dist/domain/config/ConfigSource.js +2 -0
  71. package/dist/domain/config/ConfigSource.js.map +1 -0
  72. package/dist/domain/config/LmgrepConfig.d.ts +53 -0
  73. package/dist/domain/config/LmgrepConfig.js +2 -0
  74. package/dist/domain/config/LmgrepConfig.js.map +1 -0
  75. package/dist/domain/corpus/Chunk.d.ts +49 -0
  76. package/dist/domain/corpus/Chunk.js +60 -0
  77. package/dist/domain/corpus/Chunk.js.map +1 -0
  78. package/dist/domain/corpus/CodeLocation.d.ts +18 -0
  79. package/dist/domain/corpus/CodeLocation.js +34 -0
  80. package/dist/domain/corpus/CodeLocation.js.map +1 -0
  81. package/dist/domain/corpus/ContentHash.d.ts +15 -0
  82. package/dist/domain/corpus/ContentHash.js +30 -0
  83. package/dist/domain/corpus/ContentHash.js.map +1 -0
  84. package/dist/domain/corpus/FileVersion.d.ts +31 -0
  85. package/dist/domain/corpus/FileVersion.js +47 -0
  86. package/dist/domain/corpus/FileVersion.js.map +1 -0
  87. package/dist/domain/corpus/SourceFile.d.ts +26 -0
  88. package/dist/domain/corpus/SourceFile.js +47 -0
  89. package/dist/domain/corpus/SourceFile.js.map +1 -0
  90. package/dist/domain/corpus/Vector.d.ts +37 -0
  91. package/dist/domain/corpus/Vector.js +96 -0
  92. package/dist/domain/corpus/Vector.js.map +1 -0
  93. package/dist/domain/ports/ChatModelPort.d.ts +57 -0
  94. package/dist/domain/ports/ChatModelPort.js +2 -0
  95. package/dist/domain/ports/ChatModelPort.js.map +1 -0
  96. package/dist/domain/ports/ChunkRepositoryPort.d.ts +42 -0
  97. package/dist/domain/ports/ChunkRepositoryPort.js +2 -0
  98. package/dist/domain/ports/ChunkRepositoryPort.js.map +1 -0
  99. package/dist/domain/ports/ChunkerPort.d.ts +5 -0
  100. package/dist/domain/ports/ChunkerPort.js +2 -0
  101. package/dist/domain/ports/ChunkerPort.js.map +1 -0
  102. package/dist/domain/ports/DatabaseSessionPort.d.ts +10 -0
  103. package/dist/domain/ports/DatabaseSessionPort.js +2 -0
  104. package/dist/domain/ports/DatabaseSessionPort.js.map +1 -0
  105. package/dist/domain/ports/EmbedderPort.d.ts +14 -0
  106. package/dist/domain/ports/EmbedderPort.js +2 -0
  107. package/dist/domain/ports/EmbedderPort.js.map +1 -0
  108. package/dist/domain/ports/FileManifestRepositoryPort.d.ts +32 -0
  109. package/dist/domain/ports/FileManifestRepositoryPort.js +2 -0
  110. package/dist/domain/ports/FileManifestRepositoryPort.js.map +1 -0
  111. package/dist/domain/ports/GitPort.d.ts +24 -0
  112. package/dist/domain/ports/GitPort.js +2 -0
  113. package/dist/domain/ports/GitPort.js.map +1 -0
  114. package/dist/domain/ports/IndexMaintenancePort.d.ts +58 -0
  115. package/dist/domain/ports/IndexMaintenancePort.js +2 -0
  116. package/dist/domain/ports/IndexMaintenancePort.js.map +1 -0
  117. package/dist/domain/ports/IndexMetadataPort.d.ts +23 -0
  118. package/dist/domain/ports/IndexMetadataPort.js +2 -0
  119. package/dist/domain/ports/IndexMetadataPort.js.map +1 -0
  120. package/dist/domain/ports/LockPort.d.ts +17 -0
  121. package/dist/domain/ports/LockPort.js +2 -0
  122. package/dist/domain/ports/LockPort.js.map +1 -0
  123. package/dist/domain/ports/LoggerPort.d.ts +5 -0
  124. package/dist/domain/ports/LoggerPort.js +2 -0
  125. package/dist/domain/ports/LoggerPort.js.map +1 -0
  126. package/dist/domain/ports/ProjectIndexesPort.d.ts +20 -0
  127. package/dist/domain/ports/ProjectIndexesPort.js +2 -0
  128. package/dist/domain/ports/ProjectIndexesPort.js.map +1 -0
  129. package/dist/domain/ports/ProjectRegistryPort.d.ts +42 -0
  130. package/dist/domain/ports/ProjectRegistryPort.js +2 -0
  131. package/dist/domain/ports/ProjectRegistryPort.js.map +1 -0
  132. package/dist/domain/ports/StateDirectoryPort.d.ts +29 -0
  133. package/dist/domain/ports/StateDirectoryPort.js +2 -0
  134. package/dist/domain/ports/StateDirectoryPort.js.map +1 -0
  135. package/dist/domain/ports/WorkspacePort.d.ts +38 -0
  136. package/dist/domain/ports/WorkspacePort.js +2 -0
  137. package/dist/domain/ports/WorkspacePort.js.map +1 -0
  138. package/dist/domain/project/Branch.d.ts +20 -0
  139. package/dist/domain/project/Branch.js +33 -0
  140. package/dist/domain/project/Branch.js.map +1 -0
  141. package/dist/domain/project/DatabaseLocation.d.ts +32 -0
  142. package/dist/domain/project/DatabaseLocation.js +35 -0
  143. package/dist/domain/project/DatabaseLocation.js.map +1 -0
  144. package/dist/domain/project/IndexMetadata.d.ts +17 -0
  145. package/dist/domain/project/IndexMetadata.js +2 -0
  146. package/dist/domain/project/IndexMetadata.js.map +1 -0
  147. package/dist/domain/project/ModelIdentity.d.ts +58 -0
  148. package/dist/domain/project/ModelIdentity.js +94 -0
  149. package/dist/domain/project/ModelIdentity.js.map +1 -0
  150. package/dist/domain/project/Project.d.ts +17 -0
  151. package/dist/domain/project/Project.js +21 -0
  152. package/dist/domain/project/Project.js.map +1 -0
  153. package/dist/domain/project/ProjectId.d.ts +28 -0
  154. package/dist/domain/project/ProjectId.js +58 -0
  155. package/dist/domain/project/ProjectId.js.map +1 -0
  156. package/dist/domain/project/ProjectLocator.d.ts +112 -0
  157. package/dist/domain/project/ProjectLocator.js +178 -0
  158. package/dist/domain/project/ProjectLocator.js.map +1 -0
  159. package/dist/domain/research/Citation.d.ts +27 -0
  160. package/dist/domain/research/Citation.js +43 -0
  161. package/dist/domain/research/Citation.js.map +1 -0
  162. package/dist/domain/research/EvidenceLedger.d.ts +47 -0
  163. package/dist/domain/research/EvidenceLedger.js +111 -0
  164. package/dist/domain/research/EvidenceLedger.js.map +1 -0
  165. package/dist/domain/research/ResearchTrace.d.ts +19 -0
  166. package/dist/domain/research/ResearchTrace.js +22 -0
  167. package/dist/domain/research/ResearchTrace.js.map +1 -0
  168. package/dist/domain/retrieval/Hit.d.ts +19 -0
  169. package/dist/domain/retrieval/Hit.js +28 -0
  170. package/dist/domain/retrieval/Hit.js.map +1 -0
  171. package/dist/domain/retrieval/HitList.d.ts +35 -0
  172. package/dist/domain/retrieval/HitList.js +81 -0
  173. package/dist/domain/retrieval/HitList.js.map +1 -0
  174. package/dist/domain/retrieval/MissingIndexError.d.ts +11 -0
  175. package/dist/domain/retrieval/MissingIndexError.js +15 -0
  176. package/dist/domain/retrieval/MissingIndexError.js.map +1 -0
  177. package/dist/index.d.ts +43 -45
  178. package/dist/index.js +30 -567
  179. package/dist/index.js.map +1 -1
  180. package/dist/infrastructure/ai/AiSdkChatModel.d.ts +31 -0
  181. package/dist/infrastructure/ai/AiSdkChatModel.js +137 -0
  182. package/dist/infrastructure/ai/AiSdkChatModel.js.map +1 -0
  183. package/dist/infrastructure/ai/AiSdkEmbedder.d.ts +28 -0
  184. package/dist/infrastructure/ai/AiSdkEmbedder.js +79 -0
  185. package/dist/infrastructure/ai/AiSdkEmbedder.js.map +1 -0
  186. package/dist/infrastructure/ai/DockerModelRunnerProbe.d.ts +16 -0
  187. package/dist/infrastructure/ai/DockerModelRunnerProbe.js +52 -0
  188. package/dist/infrastructure/ai/DockerModelRunnerProbe.js.map +1 -0
  189. package/dist/infrastructure/ai/EmbeddingPrefixes.d.ts +21 -0
  190. package/dist/infrastructure/ai/EmbeddingPrefixes.js +40 -0
  191. package/dist/infrastructure/ai/EmbeddingPrefixes.js.map +1 -0
  192. package/dist/infrastructure/ai/LmStudioProbe.d.ts +18 -0
  193. package/dist/infrastructure/ai/LmStudioProbe.js +49 -0
  194. package/dist/infrastructure/ai/LmStudioProbe.js.map +1 -0
  195. package/dist/infrastructure/ai/LocalModelReloader.d.ts +21 -0
  196. package/dist/infrastructure/ai/LocalModelReloader.js +61 -0
  197. package/dist/infrastructure/ai/LocalModelReloader.js.map +1 -0
  198. package/dist/infrastructure/ai/LocalRuntimeDetector.d.ts +36 -0
  199. package/dist/infrastructure/ai/LocalRuntimeDetector.js +63 -0
  200. package/dist/infrastructure/ai/LocalRuntimeDetector.js.map +1 -0
  201. package/dist/infrastructure/ai/ModelRuntime.d.ts +32 -0
  202. package/dist/infrastructure/ai/ModelRuntime.js +2 -0
  203. package/dist/infrastructure/ai/ModelRuntime.js.map +1 -0
  204. package/dist/infrastructure/ai/OllamaProbe.d.ts +22 -0
  205. package/dist/infrastructure/ai/OllamaProbe.js +71 -0
  206. package/dist/infrastructure/ai/OllamaProbe.js.map +1 -0
  207. package/dist/infrastructure/ai/ProviderFailure.d.ts +16 -0
  208. package/dist/infrastructure/ai/ProviderFailure.js +35 -0
  209. package/dist/infrastructure/ai/ProviderFailure.js.map +1 -0
  210. package/dist/infrastructure/ai/ProviderModuleLoader.d.ts +14 -0
  211. package/dist/infrastructure/ai/ProviderModuleLoader.js +56 -0
  212. package/dist/infrastructure/ai/ProviderModuleLoader.js.map +1 -0
  213. package/dist/infrastructure/ai/ProviderRegistry.d.ts +38 -0
  214. package/dist/infrastructure/ai/ProviderRegistry.js +63 -0
  215. package/dist/infrastructure/ai/ProviderRegistry.js.map +1 -0
  216. package/dist/infrastructure/fs/ConfigLoader.d.ts +59 -0
  217. package/dist/infrastructure/fs/ConfigLoader.js +194 -0
  218. package/dist/infrastructure/fs/ConfigLoader.js.map +1 -0
  219. package/dist/infrastructure/fs/DatabaseLocks.d.ts +52 -0
  220. package/dist/infrastructure/fs/DatabaseLocks.js +92 -0
  221. package/dist/infrastructure/fs/DatabaseLocks.js.map +1 -0
  222. package/dist/infrastructure/fs/DiskUsage.d.ts +6 -0
  223. package/dist/infrastructure/fs/DiskUsage.js +41 -0
  224. package/dist/infrastructure/fs/DiskUsage.js.map +1 -0
  225. package/dist/infrastructure/fs/IndexableFileRules.d.ts +33 -0
  226. package/dist/infrastructure/fs/IndexableFileRules.js +177 -0
  227. package/dist/infrastructure/fs/IndexableFileRules.js.map +1 -0
  228. package/dist/infrastructure/fs/Loggers.d.ts +14 -0
  229. package/dist/infrastructure/fs/Loggers.js +18 -0
  230. package/dist/infrastructure/fs/Loggers.js.map +1 -0
  231. package/dist/infrastructure/fs/PidFileLock.d.ts +40 -0
  232. package/dist/infrastructure/fs/PidFileLock.js +97 -0
  233. package/dist/infrastructure/fs/PidFileLock.js.map +1 -0
  234. package/dist/infrastructure/fs/ProjectIndexes.d.ts +8 -0
  235. package/dist/infrastructure/fs/ProjectIndexes.js +35 -0
  236. package/dist/infrastructure/fs/ProjectIndexes.js.map +1 -0
  237. package/dist/infrastructure/fs/ProjectMetadataStore.d.ts +42 -0
  238. package/dist/infrastructure/fs/ProjectMetadataStore.js +86 -0
  239. package/dist/infrastructure/fs/ProjectMetadataStore.js.map +1 -0
  240. package/dist/infrastructure/fs/ProjectRegistry.d.ts +25 -0
  241. package/dist/infrastructure/fs/ProjectRegistry.js +83 -0
  242. package/dist/infrastructure/fs/ProjectRegistry.js.map +1 -0
  243. package/dist/infrastructure/fs/StateDirectory.d.ts +28 -0
  244. package/dist/infrastructure/fs/StateDirectory.js +71 -0
  245. package/dist/infrastructure/fs/StateDirectory.js.map +1 -0
  246. package/dist/infrastructure/fs/Workspace.d.ts +25 -0
  247. package/dist/infrastructure/fs/Workspace.js +90 -0
  248. package/dist/infrastructure/fs/Workspace.js.map +1 -0
  249. package/dist/infrastructure/git/GitClient.d.ts +34 -0
  250. package/dist/infrastructure/git/GitClient.js +74 -0
  251. package/dist/infrastructure/git/GitClient.js.map +1 -0
  252. package/dist/infrastructure/lancedb/ChunkRepository.d.ts +38 -0
  253. package/dist/infrastructure/lancedb/ChunkRepository.js +166 -0
  254. package/dist/infrastructure/lancedb/ChunkRepository.js.map +1 -0
  255. package/dist/infrastructure/lancedb/DatabaseImporter.d.ts +22 -0
  256. package/dist/infrastructure/lancedb/DatabaseImporter.js +74 -0
  257. package/dist/infrastructure/lancedb/DatabaseImporter.js.map +1 -0
  258. package/dist/infrastructure/lancedb/FileManifestRepository.d.ts +34 -0
  259. package/dist/infrastructure/lancedb/FileManifestRepository.js +137 -0
  260. package/dist/infrastructure/lancedb/FileManifestRepository.js.map +1 -0
  261. package/dist/infrastructure/lancedb/IndexMaintenance.d.ts +53 -0
  262. package/dist/infrastructure/lancedb/IndexMaintenance.js +227 -0
  263. package/dist/infrastructure/lancedb/IndexMaintenance.js.map +1 -0
  264. package/dist/infrastructure/lancedb/LanceTables.d.ts +67 -0
  265. package/dist/infrastructure/lancedb/LanceTables.js +159 -0
  266. package/dist/infrastructure/lancedb/LanceTables.js.map +1 -0
  267. package/dist/{lib/native-tuning.js → infrastructure/lancedb/NativeTuning.js} +1 -1
  268. package/dist/infrastructure/lancedb/NativeTuning.js.map +1 -0
  269. package/dist/infrastructure/lancedb/RowReplication.d.ts +27 -0
  270. package/dist/infrastructure/lancedb/RowReplication.js +82 -0
  271. package/dist/infrastructure/lancedb/RowReplication.js.map +1 -0
  272. package/dist/infrastructure/lancedb/VectorIndexPolicy.d.ts +60 -0
  273. package/dist/infrastructure/lancedb/VectorIndexPolicy.js +72 -0
  274. package/dist/infrastructure/lancedb/VectorIndexPolicy.js.map +1 -0
  275. package/dist/infrastructure/p2p/IndexShare.d.ts +45 -0
  276. package/dist/infrastructure/p2p/IndexShare.js +160 -0
  277. package/dist/infrastructure/p2p/IndexShare.js.map +1 -0
  278. package/dist/infrastructure/p2p/PeerSwarm.d.ts +16 -0
  279. package/dist/infrastructure/p2p/PeerSwarm.js +41 -0
  280. package/dist/infrastructure/p2p/PeerSwarm.js.map +1 -0
  281. package/dist/infrastructure/p2p/SecureChannel.d.ts +60 -0
  282. package/dist/infrastructure/p2p/SecureChannel.js +71 -0
  283. package/dist/infrastructure/p2p/SecureChannel.js.map +1 -0
  284. package/dist/infrastructure/p2p/ShareCode.d.ts +25 -0
  285. package/dist/infrastructure/p2p/ShareCode.js +304 -0
  286. package/dist/infrastructure/p2p/ShareCode.js.map +1 -0
  287. package/dist/infrastructure/process/ProcessRegistry.d.ts +50 -0
  288. package/dist/infrastructure/process/ProcessRegistry.js +109 -0
  289. package/dist/infrastructure/process/ProcessRegistry.js.map +1 -0
  290. package/dist/infrastructure/treesitter/ChunkContextBuilder.d.ts +45 -0
  291. package/dist/infrastructure/treesitter/ChunkContextBuilder.js +159 -0
  292. package/dist/infrastructure/treesitter/ChunkContextBuilder.js.map +1 -0
  293. package/dist/infrastructure/treesitter/EmbeddedTreeSitterAssets.d.ts +8 -0
  294. package/dist/infrastructure/treesitter/EmbeddedTreeSitterAssets.js +12 -0
  295. package/dist/infrastructure/treesitter/EmbeddedTreeSitterAssets.js.map +1 -0
  296. package/dist/infrastructure/treesitter/LanguageCatalog.d.ts +30 -0
  297. package/dist/{lib/chunker/languages.js → infrastructure/treesitter/LanguageCatalog.js} +38 -29
  298. package/dist/infrastructure/treesitter/LanguageCatalog.js.map +1 -0
  299. package/dist/infrastructure/treesitter/SlidingWindowChunker.d.ts +15 -0
  300. package/dist/infrastructure/treesitter/SlidingWindowChunker.js +42 -0
  301. package/dist/infrastructure/treesitter/SlidingWindowChunker.js.map +1 -0
  302. package/dist/infrastructure/treesitter/TreeSitterChunker.d.ts +42 -0
  303. package/dist/infrastructure/treesitter/TreeSitterChunker.js +165 -0
  304. package/dist/infrastructure/treesitter/TreeSitterChunker.js.map +1 -0
  305. package/dist/mcp.d.ts +1 -1
  306. package/dist/mcp.js +14 -72
  307. package/dist/mcp.js.map +1 -1
  308. package/dist/presentation/cli/Cli.d.ts +31 -0
  309. package/dist/presentation/cli/Cli.js +120 -0
  310. package/dist/presentation/cli/Cli.js.map +1 -0
  311. package/dist/presentation/cli/CliOptions.d.ts +18 -0
  312. package/dist/presentation/cli/CliOptions.js +25 -0
  313. package/dist/presentation/cli/CliOptions.js.map +1 -0
  314. package/dist/presentation/cli/CommandContext.d.ts +50 -0
  315. package/dist/presentation/cli/CommandContext.js +88 -0
  316. package/dist/presentation/cli/CommandContext.js.map +1 -0
  317. package/dist/presentation/cli/ConfigTemplate.d.ts +31 -0
  318. package/dist/presentation/cli/ConfigTemplate.js +83 -0
  319. package/dist/presentation/cli/ConfigTemplate.js.map +1 -0
  320. package/dist/presentation/cli/Renderer.d.ts +90 -0
  321. package/dist/presentation/cli/Renderer.js +290 -0
  322. package/dist/presentation/cli/Renderer.js.map +1 -0
  323. package/dist/presentation/cli/commands/AskCommand.d.ts +14 -0
  324. package/dist/presentation/cli/commands/AskCommand.js +48 -0
  325. package/dist/presentation/cli/commands/AskCommand.js.map +1 -0
  326. package/dist/presentation/cli/commands/CompletionsCommand.d.ts +18 -0
  327. package/dist/presentation/cli/commands/CompletionsCommand.js +96 -0
  328. package/dist/presentation/cli/commands/CompletionsCommand.js.map +1 -0
  329. package/dist/presentation/cli/commands/ConfigCommands.d.ts +56 -0
  330. package/dist/presentation/cli/commands/ConfigCommands.js +220 -0
  331. package/dist/presentation/cli/commands/ConfigCommands.js.map +1 -0
  332. package/dist/presentation/cli/commands/IndexCommand.d.ts +18 -0
  333. package/dist/presentation/cli/commands/IndexCommand.js +54 -0
  334. package/dist/presentation/cli/commands/IndexCommand.js.map +1 -0
  335. package/dist/presentation/cli/commands/ProjectsCommand.d.ts +48 -0
  336. package/dist/presentation/cli/commands/ProjectsCommand.js +240 -0
  337. package/dist/presentation/cli/commands/ProjectsCommand.js.map +1 -0
  338. package/dist/presentation/cli/commands/SearchCommand.d.ts +19 -0
  339. package/dist/presentation/cli/commands/SearchCommand.js +55 -0
  340. package/dist/presentation/cli/commands/SearchCommand.js.map +1 -0
  341. package/dist/presentation/cli/commands/ServerCommands.d.ts +13 -0
  342. package/dist/presentation/cli/commands/ServerCommands.js +40 -0
  343. package/dist/presentation/cli/commands/ServerCommands.js.map +1 -0
  344. package/dist/presentation/cli/commands/ShareCommands.d.ts +22 -0
  345. package/dist/presentation/cli/commands/ShareCommands.js +134 -0
  346. package/dist/presentation/cli/commands/ShareCommands.js.map +1 -0
  347. package/dist/presentation/cli/commands/StatusCommand.d.ts +15 -0
  348. package/dist/presentation/cli/commands/StatusCommand.js +53 -0
  349. package/dist/presentation/cli/commands/StatusCommand.js.map +1 -0
  350. package/dist/presentation/mcp/HitFormatter.d.ts +17 -0
  351. package/dist/presentation/mcp/HitFormatter.js +42 -0
  352. package/dist/presentation/mcp/HitFormatter.js.map +1 -0
  353. package/dist/presentation/mcp/IndexWatchController.d.ts +17 -0
  354. package/dist/presentation/mcp/IndexWatchController.js +31 -0
  355. package/dist/presentation/mcp/IndexWatchController.js.map +1 -0
  356. package/dist/presentation/mcp/LmgrepCore.d.ts +66 -0
  357. package/dist/presentation/mcp/LmgrepCore.js +178 -0
  358. package/dist/presentation/mcp/LmgrepCore.js.map +1 -0
  359. package/dist/presentation/mcp/McpServer.d.ts +18 -0
  360. package/dist/presentation/mcp/McpServer.js +63 -0
  361. package/dist/presentation/mcp/McpServer.js.map +1 -0
  362. package/dist/presentation/mcp/ToolDescriptions.d.ts +40 -0
  363. package/dist/presentation/mcp/ToolDescriptions.js +85 -0
  364. package/dist/presentation/mcp/ToolDescriptions.js.map +1 -0
  365. package/package.json +93 -89
  366. package/dist/lib/build.d.ts +0 -21
  367. package/dist/lib/build.js +0 -374
  368. package/dist/lib/build.js.map +0 -1
  369. package/dist/lib/chunker/context.d.ts +0 -21
  370. package/dist/lib/chunker/context.js +0 -131
  371. package/dist/lib/chunker/context.js.map +0 -1
  372. package/dist/lib/chunker/index.d.ts +0 -7
  373. package/dist/lib/chunker/index.js +0 -209
  374. package/dist/lib/chunker/index.js.map +0 -1
  375. package/dist/lib/chunker/languages.d.ts +0 -15
  376. package/dist/lib/chunker/languages.js.map +0 -1
  377. package/dist/lib/config.d.ts +0 -12
  378. package/dist/lib/config.js +0 -83
  379. package/dist/lib/config.js.map +0 -1
  380. package/dist/lib/embedder.d.ts +0 -65
  381. package/dist/lib/embedder.js +0 -236
  382. package/dist/lib/embedder.js.map +0 -1
  383. package/dist/lib/facet-session.d.ts +0 -44
  384. package/dist/lib/facet-session.js +0 -125
  385. package/dist/lib/facet-session.js.map +0 -1
  386. package/dist/lib/native-tuning.js.map +0 -1
  387. package/dist/lib/p2p.d.ts +0 -32
  388. package/dist/lib/p2p.js +0 -281
  389. package/dist/lib/p2p.js.map +0 -1
  390. package/dist/lib/providers.d.ts +0 -1
  391. package/dist/lib/providers.js +0 -41
  392. package/dist/lib/providers.js.map +0 -1
  393. package/dist/lib/repair.d.ts +0 -10
  394. package/dist/lib/repair.js +0 -57
  395. package/dist/lib/repair.js.map +0 -1
  396. package/dist/lib/scanner.d.ts +0 -34
  397. package/dist/lib/scanner.js +0 -242
  398. package/dist/lib/scanner.js.map +0 -1
  399. package/dist/lib/search-tool.d.ts +0 -55
  400. package/dist/lib/search-tool.js +0 -319
  401. package/dist/lib/search-tool.js.map +0 -1
  402. package/dist/lib/serve.d.ts +0 -11
  403. package/dist/lib/serve.js +0 -144
  404. package/dist/lib/serve.js.map +0 -1
  405. package/dist/lib/store.d.ts +0 -252
  406. package/dist/lib/store.js +0 -1216
  407. package/dist/lib/store.js.map +0 -1
  408. package/dist/lib/types.d.ts +0 -194
  409. package/dist/lib/types.js +0 -13
  410. package/dist/lib/types.js.map +0 -1
  411. package/dist/lib/vocab.d.ts +0 -20
  412. package/dist/lib/vocab.js +0 -275
  413. package/dist/lib/vocab.js.map +0 -1
  414. /package/dist/{lib/native-tuning.d.ts → infrastructure/lancedb/NativeTuning.d.ts} +0 -0
package/README.md CHANGED
@@ -8,12 +8,14 @@ lmgrep uses [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) to parse s
8
8
 
9
9
  - **Any embedding provider** — works with Ollama, OpenAI, Google, or any provider supported by the [Vercel AI SDK](https://sdk.vercel.ai/)
10
10
  - **Tree-sitter chunking** — splits code at AST boundaries so search results are complete, meaningful units
11
+ - **The index lives in the repo** — under `.git/lmgrep/`, so `du` finds it, `rm -rf` removes it, and deleting a clone deletes its index
12
+ - **One index per model** — switching embedding models selects a different database instead of invalidating the one you have; switching back is instant
13
+ - **Ask (research mode)** — `lmgrep ask` runs a local model that searches, reads, and synthesizes a cited answer, so agents spend one call instead of many searches
11
14
  - **MCP server** — built-in MCP server (`lmgrep mcp`) for integration with Claude Code, Cursor, and other AI tools
12
15
  - **File watching** — `lmgrep serve` watches for changes and incrementally re-indexes
13
16
  - **P2P sharing** — share your index with teammates via direct peer-to-peer transfer
14
17
  - **Cross-project search** — search across multiple indexed projects
15
- - **Git-aware** — respects `.gitignore`, deduplicates across worktrees sharing the same remote
16
- - **Configurable** — global or per-project config, custom ignore patterns, extension filtering
18
+ - **Git-aware** — respects `.gitignore`, and every worktree of a repository shares one index
17
19
 
18
20
  ## Quick start
19
21
 
@@ -23,21 +25,54 @@ lmgrep uses [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) to parse s
23
25
  pnpm install -g lmgrep
24
26
  ```
25
27
 
28
+ Requires Node.js 20 or newer.
29
+
30
+ #### Standalone executable
31
+
32
+ Release builds can bundle lmgrep, the Bun runtime, the OpenAI-compatible model
33
+ adapter, LanceDB native binding, and every Tree-sitter grammar into one file:
34
+
35
+ ```sh
36
+ pnpm install
37
+ pnpm build:standalone
38
+ ./artifacts/lmgrep --help
39
+ ```
40
+
41
+ The executable targets the operating system and architecture running Bun, so
42
+ build each release artifact on its target platform. For the auto-detected
43
+ local runtimes, users need neither Node.js, Bun, npm packages, nor a separately
44
+ installed provider adapter.
45
+
26
46
  ### 2. Set up an embedding model
27
47
 
28
- The fastest way to get started is with [Ollama](https://ollama.com/):
48
+ Start a local inference server, then let lmgrep configure itself.
49
+
50
+ With [Ollama](https://ollama.com/):
29
51
 
30
52
  ```sh
31
- # Install Ollama
32
53
  curl -fsSL https://ollama.com/install.sh | sh
33
-
34
- # Pull an embedding model
35
54
  ollama pull nomic-embed-text
55
+ lmgrep init
56
+ ```
57
+
58
+ Or with [Docker Model Runner](https://docs.docker.com/ai/model-runner/):
36
59
 
37
- # Auto-detect and write config
60
+ ```sh
61
+ docker model pull ai/mxbai-embed-large
38
62
  lmgrep init
39
63
  ```
40
64
 
65
+ LM Studio is supported too: install an embedding model, enable its local
66
+ server, and run `lmgrep init`.
67
+
68
+ `init` detects whichever server is running, picks an embedding model, and
69
+ writes the provider, base URL and any prefixes that model requires. Where the
70
+ server also reports a chat model it configures `chatModel` too, which is what
71
+ enables `lmgrep ask`.
72
+
73
+ Use `lmgrep init --preview` to inspect the detected YAML without creating or
74
+ overwriting the config file.
75
+
41
76
  This creates a config file at `~/.config/lmgrep/config.yml` (Linux) or `~/Library/Application Support/lmgrep/config.yml` (macOS).
42
77
 
43
78
  ### 3. Index your project
@@ -49,63 +84,186 @@ lmgrep index
49
84
 
50
85
  ### 4. Search
51
86
 
87
+ A bare query searches — `search` is the default command:
88
+
52
89
  ```sh
53
- lmgrep search "how are users authenticated"
90
+ lmgrep how are users authenticated
54
91
  lmgrep search "database connection pooling" --limit 5
55
- lmgrep search "error handling" --file-prefix src/lib --language .ts
92
+ lmgrep search "error handling" --under src/lib --language .ts
56
93
  ```
57
94
 
58
95
  ## CLI commands
59
96
 
97
+ Two of these are the product; the rest you run once.
98
+
60
99
  | Command | Description |
61
100
  |---|---|
62
- | `lmgrep index` | Index the current directory |
63
- | `lmgrep search <query>` | Search using natural language |
64
- | `lmgrep status` | Show index stats, embedding connectivity, and running processes |
65
- | `lmgrep serve` | Watch for changes and re-index automatically |
101
+ | `lmgrep <query>` | Search using natural language (`search` is the default command) |
102
+ | `lmgrep ask <question>` | Answer a question with a local research loop (search → read → cited answer) |
103
+ | `lmgrep index` | Index this project, and keep it current |
104
+ | `lmgrep status` | Report whether search works, and why not |
105
+ | `lmgrep projects` | List every index on this machine, and reclaim their space |
106
+ | `lmgrep init` | Detect your local models and write the machine config |
107
+ | `lmgrep config` | Open the machine config in your editor |
66
108
  | `lmgrep mcp` | Start the MCP server (stdio transport) |
67
- | `lmgrep init` | Detect embedding setup and create config |
68
- | `lmgrep config` | Open the global config in your editor |
69
- | `lmgrep repair` | Detect and fix index inconsistencies |
70
- | `lmgrep migrate` | Rename existing index directories to match the current slug scheme |
71
- | `lmgrep compact` | Compact the index to reclaim disk space |
72
- | `lmgrep export` | Share this project's index with a peer via P2P |
73
- | `lmgrep import [source]` | Import from a peer (share code) or local database |
74
- | `lmgrep prune` | Delete the index for the current directory |
109
+ | `lmgrep serve` | Watch this project and re-index as files change |
110
+ | `lmgrep share` | Offer this project's index to a peer over P2P |
111
+ | `lmgrep import <source>` | Import from a peer (share code) or another database (path) |
75
112
  | `lmgrep completions zsh` | Output or install zsh completions |
76
113
 
114
+ There is no `repair`, `compact`, or `migrate`. Reconciling the manifest,
115
+ dropping duplicate rows, compacting fragments and training the vector index all
116
+ happen inside `lmgrep index`, which is the one moment you are already waiting.
117
+ `prune` became `lmgrep projects rm`, which can see what it is deleting.
118
+
77
119
  ### Search options
78
120
 
79
121
  ```
80
- --limit <n> Max results (default: 25)
81
- --file-prefix <path> Only search files under this path
82
- --language <exts> Filter by file extension (e.g. .ts,.py)
83
- --type <types> Filter by AST node type (e.g. function_declaration)
84
- --not <query> Exclude results similar to this query
85
- --scores Show relevance scores
86
- --compact Show file paths only
87
- --json Output as JSON
88
- --project <path> Search a different project's index
89
- --across <paths> Search multiple projects (comma-separated)
122
+ --limit <n> Max results (default: 25)
123
+ --under <path> Only search files under this path
124
+ --language <exts> Only search these extensions (e.g. .ts,.py)
125
+ --compact Print matching file paths only
126
+ --json Print results as JSON
127
+ --in <target> Repeatable: a project directory, or a standalone index name
90
128
  ```
91
129
 
92
130
  ### Index options
93
131
 
94
132
  ```
95
- --reset Rebuild the entire index from scratch
96
- --since <dur> Only re-index files modified within duration (e.g. 10m, 2h, 1d)
97
- --force Force re-embed even if file hash is unchanged
98
- --dry Show what would be indexed without doing it
133
+ --reset Discard the index and rebuild from scratch
134
+ --since <dur> Only consider files modified within duration (e.g. 10m, 2h, 1d)
135
+ --dry Report what would be indexed, and stop
99
136
  --verbose Show file-by-file progress
137
+ --in <target> A project directory, or a standalone index name
138
+ ```
139
+
140
+ ## Ask (research mode)
141
+
142
+ `lmgrep ask` answers a question *about the codebase* instead of returning raw chunks. A local chat model runs a short agentic loop — it searches the index, reads the matching code, and writes a concise answer where every claim is cited as `[n] → file:line`. This is aimed at AI agents: one `ask` call replaces several searches and pages of chunks, so it's far cheaper on the agent's context.
143
+
144
+ It requires a generative `chatModel` in addition to your embedding `model`. On a local runtime (LM Studio, Ollama) it reuses the same provider and `baseURL`, so one extra config line is enough:
145
+
146
+ ```yaml
147
+ # ~/.config/lmgrep/config.yml
148
+ model: lmstudio:text-embedding-nomic-embed-code # embeddings (retrieval)
149
+ chatModel: lmstudio:google/gemma-4-e2b # generation (the research loop)
150
+ ```
151
+
152
+ ```sh
153
+ lmgrep ask "how does the file watcher trigger reindexing"
154
+ lmgrep ask "where are webhooks authenticated and what token format" --json
155
+ ```
156
+
157
+ The answer, its `Sources:` list, and a one-line trace (queries run, steps, time) are printed; the live search trace streams to stderr (silence it with `--quiet`). When configured, `ask` is also exposed as an MCP tool alongside `search`.
158
+
159
+ ```
160
+ --json Print the full result (answer, sources, trace) as JSON
161
+ --quiet Suppress the live research trace on stderr
162
+ --in A project directory, or a standalone index name
100
163
  ```
101
164
 
165
+ Config keys: `chatModel` (required for `ask`), `chatProvider` / `chatBaseURL` (default to the embedding `provider` / `baseURL`), `chatMaxSteps` (default 8), `chatTimeoutMs` (per model call, default 240000).
166
+
167
+ ## The vector index
168
+
169
+ Above a few thousand chunks lmgrep trains an ANN index over the embeddings.
170
+ Without one, every search brute-force scans the whole table: roughly the
171
+ index's own size in peak memory per query, and an order of magnitude more
172
+ latency. `lmgrep status` reports which mode you are in.
173
+
174
+ It is built automatically by `lmgrep index`, and by `lmgrep serve` / the MCP
175
+ server on their first catch-up pass. Training briefly needs several GB, so it
176
+ happens once rather than on every incremental update — and never behind a
177
+ background watcher that has not caught up yet. If `status` reports it missing,
178
+ `lmgrep index` builds it.
179
+
180
+ ## Where the index lives
181
+
182
+ Inside the repository it indexes:
183
+
184
+ ```
185
+ <repo>/.git/lmgrep/<model>/
186
+ ```
187
+
188
+ Git resolves `.git` to the main checkout even from a linked worktree, so every
189
+ worktree of a repository shares one index automatically — no registry, nothing
190
+ to keep in sync. Git never walks its own directory, so the index is never
191
+ committed and never indexed. And because it is *there*, `du -sh` finds it,
192
+ `rm -rf` removes it, and deleting a clone deletes its index with it.
193
+
194
+ Each embedding model gets its own subdirectory. Changing `model` in your config
195
+ selects a different database rather than invalidating the one you have, so
196
+ trying another model costs one re-index and switching back costs nothing.
197
+
198
+ ### Changing your embedding model
199
+
200
+ The new model has no index yet, so lmgrep says so and names what you already
201
+ have:
202
+
203
+ ```
204
+ $ lmgrep how are webhooks authenticated
205
+ This project has no index for "qwen3-embedding-4b" — but it is indexed with
206
+ "nomic-embed-code".
207
+ Set `model` back to lmstudio:nomic-embed-code to use that index immediately, or
208
+ run `lmgrep index` to embed this project with the new model (the other index is
209
+ kept).
210
+ ```
211
+
212
+ `status` gives the same answer, and `lmgrep index` says what it is about to do
213
+ before it starts — embedding a large repository takes a while, and trying a
214
+ model out should not commit you to it by accident. Both indexes then coexist,
215
+ and `model` decides which one answers.
216
+
217
+ Note that `serve` and the MCP server read configuration once, at startup. A
218
+ server already running keeps using the model it started with — self-consistent,
219
+ but it will disagree with the CLI until you restart it. `lmgrep status
220
+ --verbose` prints the database each running process is holding.
221
+
222
+ Projects outside a git repository, and indexes you name yourself, live under
223
+ `~/.local/state/lmgrep/db/`. Lock files and a small pointer registry live
224
+ beside it — that registry is what `lmgrep projects` and cross-project search
225
+ read, since an index inside a repository cannot be found by listing a
226
+ directory.
227
+
228
+ ### Targeting another index
229
+
230
+ `--in` takes a project directory or the name of a standalone index, and repeats:
231
+
232
+ ```sh
233
+ # A standalone index, for a corpus that is not a repository
234
+ lmgrep index --in notes
235
+ lmgrep search "retry policy" --in notes
236
+
237
+ # Another project
238
+ lmgrep search "retry policy" --in ../other-repo
239
+
240
+ # Several at once; `.` includes the current project
241
+ lmgrep search "retry policy" --in . --in ../other-repo
242
+ ```
243
+
244
+ For write commands the files indexed still come from the current directory;
245
+ only the database identity changes. A standalone index is flat — branch-agnostic,
246
+ so switching git branches never hides results.
247
+
248
+ ### Seeing and reclaiming
249
+
250
+ ```sh
251
+ lmgrep projects # every index, largest first, with its model and size
252
+ lmgrep projects adopt # move a pre-0.2 index into this repository, no re-embed
253
+ lmgrep projects rm # delete this project's index
254
+ lmgrep projects gc # delete indexes whose project no longer exists
255
+ ```
256
+
257
+ `rm` and `gc` refuse to recurse into anything that is not recognizably an
258
+ lmgrep database.
259
+
102
260
  ## P2P index sharing
103
261
 
104
262
  Share your index with a teammate without any server or infrastructure. Uses [Hyperswarm](https://github.com/holepunchto/hyperswarm) for direct encrypted peer-to-peer transfer with NAT hole punching.
105
263
 
106
264
  ```sh
107
265
  # On your machine — start sharing
108
- lmgrep export
266
+ lmgrep share
109
267
  # → Share code: lmgrepoceantiger7f3a
110
268
  # → Waiting for peer...
111
269
 
@@ -164,18 +322,6 @@ gemini mcp add lmgrep -- lmgrep mcp
164
322
  gemini mcp add lmgrep -- npx -y lmgrep mcp
165
323
  ```
166
324
 
167
- ### Pi coding agent
168
-
169
- Pi doesn't speak MCP — it uses TypeScript extensions instead. lmgrep ships one at [`pi-extension/`](./pi-extension) that registers two tools: `lmgrep_search` and `lmgrep_list_other_indexed_projects`. It imports lmgrep directly, runs an in-process file watcher to keep the index fresh, and gates tool visibility on embedder health — if lmgrep isn't configured, or the embedding provider is unreachable, the tools stay hidden so you get a clean tool surface instead of a broken one. Configure lmgrep first (`lmgrep init`) before relying on it inside Pi.
170
-
171
- Install via Pi's package manager:
172
-
173
- ```sh
174
- pi install git:github.com/Aetherall/lmgrep
175
- ```
176
-
177
- Update with `pi update`, remove with `pi remove git:github.com/Aetherall/lmgrep`, and list installed extensions with `pi list`.
178
-
179
325
  ### OpenCode
180
326
 
181
327
  OpenCode has no one-shot install flag — add an entry to `~/.config/opencode/opencode.json` (or project-level `opencode.json`):
@@ -200,13 +346,27 @@ The MCP server exposes a `search` tool and a `list_other_indexed_projects` tool.
200
346
 
201
347
  ## Configuration
202
348
 
203
- lmgrep looks for configuration in this order:
349
+ There are two kinds of setting, split by what they describe.
204
350
 
205
- 1. `.lmgrep.yml` in the project root (per-project)
206
- 2. `~/.config/lmgrep/config.yml` (global, Linux) or `~/Library/Application Support/lmgrep/config.yml` (macOS)
207
- 3. `~/.lmgrep.yml` (legacy fallback)
351
+ **Machine settings** which model to embed with, which to answer with, where
352
+ those servers listen describe this computer. They live in one file:
208
353
 
209
- ### Example config
354
+ - `~/.config/lmgrep/config.yml` (Linux) or `~/Library/Application Support/lmgrep/config.yml` (macOS)
355
+ - `~/.lmgrep.yml` still works, as a deprecated location
356
+
357
+ **Project settings** — what to ignore, which extensions to index — describe a
358
+ repository, are worth committing, and go in a `.lmgrep.yml` inside it.
359
+
360
+ A machine setting written in a project file is reported and ignored. The model
361
+ decides what a stored vector *means*, so a project file able to change it was
362
+ the single most confusing thing about lmgrep: two files could set `model`, and
363
+ `status` would print the winner without saying which file it came from. If you
364
+ want a different model for one corpus, index it under `--in <name>` — the model
365
+ is a property of an index, not of a directory.
366
+
367
+ `lmgrep status` prints exactly which file supplied which keys.
368
+
369
+ ### Machine config
210
370
 
211
371
  ```yaml
212
372
  # Embedding model in "provider:model" format
@@ -218,7 +378,10 @@ baseURL: http://localhost:11434/v1
218
378
  # Batch size for embedding API calls
219
379
  batchSize: 100
220
380
 
221
- # Optional: embedding dimensions (if model supports it)
381
+ # Generative model for `lmgrep ask`. Optional without it, `ask` is hidden.
382
+ # chatModel: lmstudio:qwen/qwen3.5-9b
383
+
384
+ # Optional: embedding dimensions (if the model supports it)
222
385
  # dimensions: 384
223
386
 
224
387
  # Optional: max tokens per chunk (estimated at 4 chars/token)
@@ -227,16 +390,20 @@ batchSize: 100
227
390
  # Optional: prefixes for asymmetric embedding models
228
391
  # queryPrefix: "search_query: "
229
392
  # documentPrefix: "search_document: "
393
+ ```
230
394
 
231
- # Optional: additional ignore patterns (merged with .gitignore)
232
- # ignore:
233
- # - "*.generated.ts"
234
- # - "fixtures/"
395
+ ### Project config `.lmgrep.yml`
235
396
 
236
- # Optional: file extension control
237
- # extensions:
238
- # include: [".sql", ".graphql", ".proto"]
239
- # exclude: [".json"]
397
+ ```yaml
398
+ # Additional ignore patterns (merged with .gitignore)
399
+ ignore:
400
+ - "*.generated.ts"
401
+ - "fixtures/"
402
+
403
+ # File extension control
404
+ extensions:
405
+ include: [".sql", ".graphql", ".proto"]
406
+ exclude: [".json"]
240
407
  ```
241
408
 
242
409
  ### Using other providers
@@ -262,6 +429,30 @@ pnpm dev # watch mode
262
429
  pnpm check # format and lint (Biome)
263
430
  ```
264
431
 
432
+ ### Architecture
433
+
434
+ The source is layered, with dependencies pointing inward only:
435
+
436
+ ```
437
+ src/
438
+ domain/ entities, value objects, and the port interfaces
439
+ application/ use cases that orchestrate the domain
440
+ infrastructure/ adapters: LanceDB, filesystem, git, AI SDK, tree-sitter, p2p
441
+ presentation/ the CLI and the MCP server
442
+ ```
443
+
444
+ `domain/` knows nothing outside itself. `application/` depends on domain ports,
445
+ never on a concrete adapter. `LmgrepFactory` is the single place that wires the
446
+ graph together, so no entry point needs to know the assembly order.
447
+
448
+ ### Conventions
449
+
450
+ - **No free functions.** Behaviour lives on the type that owns it. Constant
451
+ tables and pure helpers land as static-only classes, which is why Biome's
452
+ `noStaticOnlyClass` rule is disabled — the shape is intended here.
453
+ - **Comments explain why, not what.** A measured constant records what the
454
+ measurement was; a non-obvious ordering records what breaks if it changes.
455
+
265
456
  ## License
266
457
 
267
458
  GPL-3.0
@@ -1,19 +1,23 @@
1
1
  #compdef lmgrep
2
2
 
3
+ # Regenerate by hand when commands change; `lmgrep completions zsh` prints this
4
+ # file verbatim.
5
+
3
6
  _lmgrep() {
4
7
  local -a commands
5
8
  commands=(
6
- 'index:Index the current directory for semantic search'
7
9
  'search:Search the codebase using natural language'
8
- 'status:Show index stats and check embedding connectivity'
9
- 'repair:Detect and fix index inconsistencies'
10
- 'serve:Watch the current directory and re-index on changes'
11
- 'init:Detect your embedding setup and create config'
12
- 'config:Open the global config file in your editor'
13
- 'compact:Compact the index to reclaim disk space'
14
- 'prune:Delete the index database for the current directory'
15
- 'import:Import chunks and file hashes from another lmgrep database'
10
+ 'ask:Answer a question with a local research loop'
11
+ 'index:Index this project for semantic search'
12
+ 'status:Report whether search works, and why not'
13
+ 'projects:List indexes on this machine, and reclaim their space'
14
+ 'init:Detect your local models and write the machine config'
15
+ 'config:Open the machine config in your editor'
16
+ 'mcp:Start the MCP server (stdio transport)'
16
17
  'completions:Output shell completions'
18
+ 'serve:Watch this project and re-index as files change'
19
+ 'share:Offer this project index to a peer over P2P'
20
+ 'import:Import chunks from a peer or another lmgrep database'
17
21
  )
18
22
 
19
23
  _arguments -C \
@@ -30,55 +34,60 @@ _lmgrep() {
30
34
  case "$words[1]" in
31
35
  index)
32
36
  _arguments \
33
- '(-r --reset)'{-r,--reset}'[Reset and rebuild the entire index]' \
37
+ '(-r --reset)'{-r,--reset}'[Discard the index and rebuild from scratch]' \
34
38
  '(-v --verbose)'{-v,--verbose}'[Show file-by-file progress]' \
35
39
  '(-s --since)'{-s,--since}'[Only consider files modified within duration]:duration' \
36
- '(-f --force)'{-f,--force}'[Force re-embed even if file hash unchanged]' \
37
- '(-d --dry)'{-d,--dry}'[Show what would be indexed without actually doing it]'
40
+ '(-d --dry)'{-d,--dry}'[Report what would be indexed, and stop]' \
41
+ '*--in[Project directory, or the name of a standalone index]:project or name:_files -/'
38
42
  ;;
39
43
  search)
40
44
  _arguments \
41
- '1:query' \
42
- '(-m --limit)'{-m,--limit}'[Max results]:number' \
43
- '--scores[Show relevance scores]' \
44
- '--compact[Show file paths only]' \
45
- '--json[Output results as JSON]' \
46
- '--min-score[Minimum score threshold]:score' \
47
- '--file-prefix[Only search files matching this path prefix]:prefix:_files -/' \
48
- '--not[Exclude results similar to this query]:query' \
49
- '--type[Only return chunks of these AST types]:types' \
50
- '--language[Only return chunks from files with these extensions]:extensions' \
51
- '--project[Search a different project index]:path:_files -/' \
52
- '--across[Search multiple project indexes]:paths'
45
+ '(-m --limit)'{-m,--limit}'[Max results]:count' \
46
+ '--under[Only search files under this path]:path:_files -/' \
47
+ '--language[Only search these file extensions]:extensions' \
48
+ '--compact[Print matching file paths only]' \
49
+ '--json[Print results as JSON]' \
50
+ '*--in[Project directory, or the name of a standalone index]:project or name:_files -/'
53
51
  ;;
54
- status)
52
+ ask)
55
53
  _arguments \
56
- '(-c --changes)'{-c,--changes}'[Scan for changed files since last index]' \
57
- '--json[Output status as JSON]'
54
+ '--json[Print the full result as JSON]' \
55
+ '--quiet[Suppress the live research trace on stderr]' \
56
+ '*--in[Project directory, or the name of a standalone index]:project or name:_files -/'
58
57
  ;;
59
- repair)
58
+ status)
60
59
  _arguments \
61
- '(-d --dry)'{-d,--dry}'[Show what would be repaired without making changes]' \
62
- '--json[Output repair results as JSON]'
60
+ '(-v --verbose)'{-v,--verbose}'[Also show index statistics and probes]' \
61
+ '(-c --changes)'{-c,--changes}'[Scan for files changed since the last index]' \
62
+ '--json[Print status as JSON]' \
63
+ '*--in[Project directory, or the name of a standalone index]:project or name:_files -/'
64
+ ;;
65
+ projects)
66
+ local -a subcommands
67
+ subcommands=(
68
+ 'list:Show every index, largest first'
69
+ 'adopt:Move this project index from the state directory into the repository'
70
+ 'rm:Delete an index'
71
+ 'gc:Delete indexes whose project no longer exists'
72
+ )
73
+ _describe 'subcommand' subcommands
63
74
  ;;
64
75
  init)
65
- _arguments \
66
- '--force[Overwrite existing config]' \
67
- '--local[Write a project-local .lmgrep.yml instead of the global config]'
76
+ _arguments '--force[Overwrite the existing config]'
68
77
  ;;
69
- prune)
78
+ serve|mcp)
70
79
  _arguments \
71
- '--force[Skip confirmation]'
80
+ '*--in[Project directory, or the name of a standalone index]:project or name:_files -/'
72
81
  ;;
73
82
  import)
74
83
  _arguments \
75
- '1:database path:_files' \
76
- '--reset[Reset the current index before importing]'
84
+ '--reset[Reset the current index before importing]' \
85
+ '1:share code or database path:_files -/'
77
86
  ;;
78
87
  completions)
79
- _arguments \
80
- '1:shell:(zsh)' \
81
- '--install[Install to site-functions]'
88
+ local -a shells
89
+ shells=('zsh:Output zsh completions')
90
+ _describe 'shell' shells
82
91
  ;;
83
92
  esac
84
93
  ;;
@@ -0,0 +1,107 @@
1
+ import type { LmgrepConfig } from "../domain/config/LmgrepConfig.js";
2
+ import type { FileManifest } from "../domain/corpus/SourceFile.js";
3
+ import type { ChunkerPort } from "../domain/ports/ChunkerPort.js";
4
+ import type { ChunkRepositoryPort } from "../domain/ports/ChunkRepositoryPort.js";
5
+ import type { DatabaseSessionPort } from "../domain/ports/DatabaseSessionPort.js";
6
+ import type { EmbedderPort } from "../domain/ports/EmbedderPort.js";
7
+ import type { FileManifestRepositoryPort } from "../domain/ports/FileManifestRepositoryPort.js";
8
+ import type { DedupeReport, IndexMaintenancePort, OptimizeReport } from "../domain/ports/IndexMaintenancePort.js";
9
+ import type { IndexMetadataPort } from "../domain/ports/IndexMetadataPort.js";
10
+ import type { LoggerPort } from "../domain/ports/LoggerPort.js";
11
+ import type { ProjectRegistryPort } from "../domain/ports/ProjectRegistryPort.js";
12
+ import type { DatabaseLocation } from "../domain/project/DatabaseLocation.js";
13
+ import type { ProjectId } from "../domain/project/ProjectId.js";
14
+ import type { ProjectLocator } from "../domain/project/ProjectLocator.js";
15
+ import type { TraceEntry } from "../domain/research/ResearchTrace.js";
16
+ import type { HitList } from "../domain/retrieval/HitList.js";
17
+ import type { BranchManifestSweeper } from "./indexing/BranchManifestSweeper.js";
18
+ import type { IndexBuilder } from "./indexing/IndexBuilder.js";
19
+ import type { IndexBuildOptions, IndexBuildResult } from "./indexing/IndexingProgress.js";
20
+ import type { IndexAlternatives } from "./operations/IndexAlternatives.js";
21
+ import type { StatusInfo, StatusService } from "./operations/StatusService.js";
22
+ import type { WatchService } from "./operations/WatchService.js";
23
+ import type { ResearchAgent, ResearchResult } from "./research/ResearchAgent.js";
24
+ import { type SearchOptions } from "./search/SearchCriteria.js";
25
+ import type { SearchService } from "./search/SearchService.js";
26
+ /** What a maintenance pass changed. */
27
+ export interface TidyReport {
28
+ deduped: DedupeReport;
29
+ optimized: OptimizeReport;
30
+ }
31
+ /** Everything an Lmgrep instance owns, assembled by the composition root. */
32
+ export interface LmgrepServices {
33
+ cwd: string;
34
+ config: LmgrepConfig;
35
+ location: DatabaseLocation;
36
+ locator: ProjectLocator;
37
+ logger: LoggerPort;
38
+ tables: DatabaseSessionPort;
39
+ chunks: ChunkRepositoryPort;
40
+ manifest: FileManifestRepositoryPort;
41
+ maintenance: IndexMaintenancePort;
42
+ metadata: IndexMetadataPort;
43
+ registry: ProjectRegistryPort;
44
+ alternatives: IndexAlternatives;
45
+ embedder: EmbedderPort;
46
+ chunker: ChunkerPort;
47
+ builder: IndexBuilder;
48
+ sweeper: BranchManifestSweeper;
49
+ searcher: SearchService;
50
+ statusReporter: StatusService;
51
+ watcher: WatchService;
52
+ researcher: ResearchAgent;
53
+ projectId: () => ProjectId;
54
+ }
55
+ /**
56
+ * The application façade: one object exposing every operation the CLI, the MCP
57
+ * server and the Pi extension need.
58
+ *
59
+ * It holds no logic of its own — each method delegates to the service that
60
+ * owns that behaviour. Its job is to be the single place where a caller
61
+ * acquires a working, wired-up lmgrep, so no entry point has to know the
62
+ * assembly order.
63
+ */
64
+ export declare class Lmgrep {
65
+ private readonly services;
66
+ constructor(services: LmgrepServices);
67
+ get cwd(): string;
68
+ get config(): LmgrepConfig;
69
+ get location(): DatabaseLocation;
70
+ build(options?: IndexBuildOptions): Promise<IndexBuildResult>;
71
+ search(query: string, options?: SearchOptions): Promise<HitList>;
72
+ ask(question: string, onTrace?: (entry: TraceEntry) => void): Promise<ResearchResult>;
73
+ status(): Promise<StatusInfo>;
74
+ /** Start watching; returns a function that stops it. */
75
+ watch(): () => void;
76
+ /** The current branch's file manifest, for change previews. */
77
+ currentManifest(): Promise<FileManifest>;
78
+ /**
79
+ * Everything the index needs done to it that is not indexing: drop dead
80
+ * branches' manifests, remove duplicate and superseded rows, compact the
81
+ * fragments, and train the vector index if the table has grown into
82
+ * wanting one.
83
+ *
84
+ * These were three separate commands. They are one call because they are
85
+ * one intent and because the order between them is not optional: `dedupe`
86
+ * keeps any chunk version some manifest still references, so sweeping dead
87
+ * branches has to happen first or their leftover rows shield their own
88
+ * orphaned chunks from collection.
89
+ */
90
+ tidy(): Promise<TidyReport>;
91
+ get maintenance(): IndexMaintenancePort;
92
+ /** Every index this machine knows about. */
93
+ get registry(): ProjectRegistryPort;
94
+ /** This project's indexes under other embedding models. */
95
+ get alternatives(): IndexAlternatives;
96
+ get projectId(): ProjectId;
97
+ /**
98
+ * Whether this working directory has a usable index.
99
+ *
100
+ * An indexed ancestor counts: running from a subdirectory of an indexed
101
+ * tree is ordinary, and reporting it as unindexed would disable search for
102
+ * no reason. A manually targeted database is flat, so only its own path
103
+ * matters.
104
+ */
105
+ isIndexed(): boolean;
106
+ close(): Promise<void>;
107
+ }