vemora 0.1.0-alpha.15

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 (254) hide show
  1. package/README.md +851 -0
  2. package/dist/cli.d.ts +16 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +682 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/ask.d.ts +14 -0
  7. package/dist/commands/ask.d.ts.map +1 -0
  8. package/dist/commands/ask.js +137 -0
  9. package/dist/commands/ask.js.map +1 -0
  10. package/dist/commands/audit.d.ts +17 -0
  11. package/dist/commands/audit.d.ts.map +1 -0
  12. package/dist/commands/audit.js +398 -0
  13. package/dist/commands/audit.js.map +1 -0
  14. package/dist/commands/brief.d.ts +16 -0
  15. package/dist/commands/brief.d.ts.map +1 -0
  16. package/dist/commands/brief.js +84 -0
  17. package/dist/commands/brief.js.map +1 -0
  18. package/dist/commands/chat.d.ts +7 -0
  19. package/dist/commands/chat.d.ts.map +1 -0
  20. package/dist/commands/chat.js +155 -0
  21. package/dist/commands/chat.js.map +1 -0
  22. package/dist/commands/context.d.ts +63 -0
  23. package/dist/commands/context.d.ts.map +1 -0
  24. package/dist/commands/context.js +794 -0
  25. package/dist/commands/context.js.map +1 -0
  26. package/dist/commands/dead-code.d.ts +15 -0
  27. package/dist/commands/dead-code.d.ts.map +1 -0
  28. package/dist/commands/dead-code.js +206 -0
  29. package/dist/commands/dead-code.js.map +1 -0
  30. package/dist/commands/deps.d.ts +20 -0
  31. package/dist/commands/deps.d.ts.map +1 -0
  32. package/dist/commands/deps.js +138 -0
  33. package/dist/commands/deps.js.map +1 -0
  34. package/dist/commands/focus.d.ts +8 -0
  35. package/dist/commands/focus.d.ts.map +1 -0
  36. package/dist/commands/focus.js +310 -0
  37. package/dist/commands/focus.js.map +1 -0
  38. package/dist/commands/index.d.ts +10 -0
  39. package/dist/commands/index.d.ts.map +1 -0
  40. package/dist/commands/index.js +366 -0
  41. package/dist/commands/index.js.map +1 -0
  42. package/dist/commands/init-agent.d.ts +23 -0
  43. package/dist/commands/init-agent.d.ts.map +1 -0
  44. package/dist/commands/init-agent.js +384 -0
  45. package/dist/commands/init-agent.js.map +1 -0
  46. package/dist/commands/init.d.ts +2 -0
  47. package/dist/commands/init.d.ts.map +1 -0
  48. package/dist/commands/init.js +122 -0
  49. package/dist/commands/init.js.map +1 -0
  50. package/dist/commands/knowledge.d.ts +14 -0
  51. package/dist/commands/knowledge.d.ts.map +1 -0
  52. package/dist/commands/knowledge.js +115 -0
  53. package/dist/commands/knowledge.js.map +1 -0
  54. package/dist/commands/plan.d.ts +24 -0
  55. package/dist/commands/plan.d.ts.map +1 -0
  56. package/dist/commands/plan.js +867 -0
  57. package/dist/commands/plan.js.map +1 -0
  58. package/dist/commands/query.d.ts +39 -0
  59. package/dist/commands/query.d.ts.map +1 -0
  60. package/dist/commands/query.js +392 -0
  61. package/dist/commands/query.js.map +1 -0
  62. package/dist/commands/remember.d.ts +11 -0
  63. package/dist/commands/remember.d.ts.map +1 -0
  64. package/dist/commands/remember.js +267 -0
  65. package/dist/commands/remember.js.map +1 -0
  66. package/dist/commands/report.d.ts +10 -0
  67. package/dist/commands/report.d.ts.map +1 -0
  68. package/dist/commands/report.js +243 -0
  69. package/dist/commands/report.js.map +1 -0
  70. package/dist/commands/status.d.ts +2 -0
  71. package/dist/commands/status.d.ts.map +1 -0
  72. package/dist/commands/status.js +127 -0
  73. package/dist/commands/status.js.map +1 -0
  74. package/dist/commands/summarize.d.ts +14 -0
  75. package/dist/commands/summarize.d.ts.map +1 -0
  76. package/dist/commands/summarize.js +170 -0
  77. package/dist/commands/summarize.js.map +1 -0
  78. package/dist/commands/triage.d.ts +33 -0
  79. package/dist/commands/triage.d.ts.map +1 -0
  80. package/dist/commands/triage.js +419 -0
  81. package/dist/commands/triage.js.map +1 -0
  82. package/dist/commands/usages.d.ts +14 -0
  83. package/dist/commands/usages.d.ts.map +1 -0
  84. package/dist/commands/usages.js +236 -0
  85. package/dist/commands/usages.js.map +1 -0
  86. package/dist/core/config.d.ts +35 -0
  87. package/dist/core/config.d.ts.map +1 -0
  88. package/dist/core/config.js +159 -0
  89. package/dist/core/config.js.map +1 -0
  90. package/dist/core/types.d.ts +287 -0
  91. package/dist/core/types.d.ts.map +1 -0
  92. package/dist/core/types.js +4 -0
  93. package/dist/core/types.js.map +1 -0
  94. package/dist/embeddings/factory.d.ts +9 -0
  95. package/dist/embeddings/factory.d.ts.map +1 -0
  96. package/dist/embeddings/factory.js +26 -0
  97. package/dist/embeddings/factory.js.map +1 -0
  98. package/dist/embeddings/noop.d.ts +17 -0
  99. package/dist/embeddings/noop.d.ts.map +1 -0
  100. package/dist/embeddings/noop.js +22 -0
  101. package/dist/embeddings/noop.js.map +1 -0
  102. package/dist/embeddings/ollama.d.ts +11 -0
  103. package/dist/embeddings/ollama.d.ts.map +1 -0
  104. package/dist/embeddings/ollama.js +49 -0
  105. package/dist/embeddings/ollama.js.map +1 -0
  106. package/dist/embeddings/openai.d.ts +10 -0
  107. package/dist/embeddings/openai.d.ts.map +1 -0
  108. package/dist/embeddings/openai.js +67 -0
  109. package/dist/embeddings/openai.js.map +1 -0
  110. package/dist/embeddings/provider.d.ts +19 -0
  111. package/dist/embeddings/provider.d.ts.map +1 -0
  112. package/dist/embeddings/provider.js +3 -0
  113. package/dist/embeddings/provider.js.map +1 -0
  114. package/dist/indexer/callgraph.d.ts +16 -0
  115. package/dist/indexer/callgraph.d.ts.map +1 -0
  116. package/dist/indexer/callgraph.js +154 -0
  117. package/dist/indexer/callgraph.js.map +1 -0
  118. package/dist/indexer/chunkBySlidingWindow.d.ts +6 -0
  119. package/dist/indexer/chunkBySlidingWindow.d.ts.map +1 -0
  120. package/dist/indexer/chunkBySlidingWindow.js +30 -0
  121. package/dist/indexer/chunkBySlidingWindow.js.map +1 -0
  122. package/dist/indexer/chunkBySymbols.d.ts +7 -0
  123. package/dist/indexer/chunkBySymbols.d.ts.map +1 -0
  124. package/dist/indexer/chunkBySymbols.js +57 -0
  125. package/dist/indexer/chunkBySymbols.js.map +1 -0
  126. package/dist/indexer/chunker.d.ts +15 -0
  127. package/dist/indexer/chunker.d.ts.map +1 -0
  128. package/dist/indexer/chunker.js +26 -0
  129. package/dist/indexer/chunker.js.map +1 -0
  130. package/dist/indexer/classHeader.d.ts +7 -0
  131. package/dist/indexer/classHeader.d.ts.map +1 -0
  132. package/dist/indexer/classHeader.js +37 -0
  133. package/dist/indexer/classHeader.js.map +1 -0
  134. package/dist/indexer/deps.d.ts +66 -0
  135. package/dist/indexer/deps.d.ts.map +1 -0
  136. package/dist/indexer/deps.js +412 -0
  137. package/dist/indexer/deps.js.map +1 -0
  138. package/dist/indexer/hasher.d.ts +17 -0
  139. package/dist/indexer/hasher.d.ts.map +1 -0
  140. package/dist/indexer/hasher.js +38 -0
  141. package/dist/indexer/hasher.js.map +1 -0
  142. package/dist/indexer/parser.d.ts +18 -0
  143. package/dist/indexer/parser.d.ts.map +1 -0
  144. package/dist/indexer/parser.js +355 -0
  145. package/dist/indexer/parser.js.map +1 -0
  146. package/dist/indexer/scanner.d.ts +18 -0
  147. package/dist/indexer/scanner.d.ts.map +1 -0
  148. package/dist/indexer/scanner.js +37 -0
  149. package/dist/indexer/scanner.js.map +1 -0
  150. package/dist/indexer/strategy.d.ts +11 -0
  151. package/dist/indexer/strategy.d.ts.map +1 -0
  152. package/dist/indexer/strategy.js +15 -0
  153. package/dist/indexer/strategy.js.map +1 -0
  154. package/dist/indexer/tests.d.ts +15 -0
  155. package/dist/indexer/tests.d.ts.map +1 -0
  156. package/dist/indexer/tests.js +68 -0
  157. package/dist/indexer/tests.js.map +1 -0
  158. package/dist/indexer/todos.d.ts +9 -0
  159. package/dist/indexer/todos.d.ts.map +1 -0
  160. package/dist/indexer/todos.js +29 -0
  161. package/dist/indexer/todos.js.map +1 -0
  162. package/dist/llm/anthropic.d.ts +8 -0
  163. package/dist/llm/anthropic.d.ts.map +1 -0
  164. package/dist/llm/anthropic.js +76 -0
  165. package/dist/llm/anthropic.js.map +1 -0
  166. package/dist/llm/claude-code.d.ts +37 -0
  167. package/dist/llm/claude-code.d.ts.map +1 -0
  168. package/dist/llm/claude-code.js +97 -0
  169. package/dist/llm/claude-code.js.map +1 -0
  170. package/dist/llm/factory.d.ts +7 -0
  171. package/dist/llm/factory.d.ts.map +1 -0
  172. package/dist/llm/factory.js +47 -0
  173. package/dist/llm/factory.js.map +1 -0
  174. package/dist/llm/ollama.d.ts +8 -0
  175. package/dist/llm/ollama.d.ts.map +1 -0
  176. package/dist/llm/ollama.js +83 -0
  177. package/dist/llm/ollama.js.map +1 -0
  178. package/dist/llm/openai.d.ts +8 -0
  179. package/dist/llm/openai.d.ts.map +1 -0
  180. package/dist/llm/openai.js +68 -0
  181. package/dist/llm/openai.js.map +1 -0
  182. package/dist/llm/provider.d.ts +35 -0
  183. package/dist/llm/provider.d.ts.map +1 -0
  184. package/dist/llm/provider.js +3 -0
  185. package/dist/llm/provider.js.map +1 -0
  186. package/dist/search/bm25.d.ts +3 -0
  187. package/dist/search/bm25.d.ts.map +1 -0
  188. package/dist/search/bm25.js +104 -0
  189. package/dist/search/bm25.js.map +1 -0
  190. package/dist/search/formatter.d.ts +43 -0
  191. package/dist/search/formatter.d.ts.map +1 -0
  192. package/dist/search/formatter.js +208 -0
  193. package/dist/search/formatter.js.map +1 -0
  194. package/dist/search/hybrid.d.ts +10 -0
  195. package/dist/search/hybrid.d.ts.map +1 -0
  196. package/dist/search/hybrid.js +53 -0
  197. package/dist/search/hybrid.js.map +1 -0
  198. package/dist/search/merge.d.ts +33 -0
  199. package/dist/search/merge.d.ts.map +1 -0
  200. package/dist/search/merge.js +158 -0
  201. package/dist/search/merge.js.map +1 -0
  202. package/dist/search/mmr.d.ts +23 -0
  203. package/dist/search/mmr.d.ts.map +1 -0
  204. package/dist/search/mmr.js +95 -0
  205. package/dist/search/mmr.js.map +1 -0
  206. package/dist/search/rerank.d.ts +12 -0
  207. package/dist/search/rerank.d.ts.map +1 -0
  208. package/dist/search/rerank.js +113 -0
  209. package/dist/search/rerank.js.map +1 -0
  210. package/dist/search/signature.d.ts +42 -0
  211. package/dist/search/signature.d.ts.map +1 -0
  212. package/dist/search/signature.js +112 -0
  213. package/dist/search/signature.js.map +1 -0
  214. package/dist/search/vector.d.ts +41 -0
  215. package/dist/search/vector.d.ts.map +1 -0
  216. package/dist/search/vector.js +185 -0
  217. package/dist/search/vector.js.map +1 -0
  218. package/dist/storage/cache.d.ts +30 -0
  219. package/dist/storage/cache.d.ts.map +1 -0
  220. package/dist/storage/cache.js +160 -0
  221. package/dist/storage/cache.js.map +1 -0
  222. package/dist/storage/knowledge.d.ts +23 -0
  223. package/dist/storage/knowledge.d.ts.map +1 -0
  224. package/dist/storage/knowledge.js +81 -0
  225. package/dist/storage/knowledge.js.map +1 -0
  226. package/dist/storage/planSession.d.ts +39 -0
  227. package/dist/storage/planSession.d.ts.map +1 -0
  228. package/dist/storage/planSession.js +78 -0
  229. package/dist/storage/planSession.js.map +1 -0
  230. package/dist/storage/repository.d.ts +27 -0
  231. package/dist/storage/repository.d.ts.map +1 -0
  232. package/dist/storage/repository.js +95 -0
  233. package/dist/storage/repository.js.map +1 -0
  234. package/dist/storage/session.d.ts +38 -0
  235. package/dist/storage/session.d.ts.map +1 -0
  236. package/dist/storage/session.js +100 -0
  237. package/dist/storage/session.js.map +1 -0
  238. package/dist/storage/summaries.d.ts +19 -0
  239. package/dist/storage/summaries.d.ts.map +1 -0
  240. package/dist/storage/summaries.js +66 -0
  241. package/dist/storage/summaries.js.map +1 -0
  242. package/dist/storage/usage.d.ts +39 -0
  243. package/dist/storage/usage.d.ts.map +1 -0
  244. package/dist/storage/usage.js +55 -0
  245. package/dist/storage/usage.js.map +1 -0
  246. package/dist/utils/git.d.ts +20 -0
  247. package/dist/utils/git.d.ts.map +1 -0
  248. package/dist/utils/git.js +49 -0
  249. package/dist/utils/git.js.map +1 -0
  250. package/dist/utils/tokenizer.d.ts +32 -0
  251. package/dist/utils/tokenizer.d.ts.map +1 -0
  252. package/dist/utils/tokenizer.js +66 -0
  253. package/dist/utils/tokenizer.js.map +1 -0
  254. package/package.json +71 -0
package/README.md ADDED
@@ -0,0 +1,851 @@
1
+ # vemora
2
+
3
+ [![npm version](https://img.shields.io/npm/v/vemora?label=npm)](https://www.npmjs.com/package/vemora)
4
+ [![npm alpha](https://img.shields.io/npm/v/vemora/alpha?label=alpha)](https://www.npmjs.com/package/vemora?activeTab=versions)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
+
7
+ Repository-local memory system for LLM-assisted development.
8
+
9
+ Builds a structured, versioned index of your codebase — code chunks, symbols, dependency graph, and LLM-generated summaries — and enables semantic or keyword search over it. The result is a **RAG (Retrieval-Augmented Generation) layer** that lets you give an LLM only the code it actually needs, instead of entire files.
10
+
11
+ ## Why
12
+
13
+ When working on a large codebase with Claude Code or similar LLM tools, you face two problems:
14
+
15
+ 1. **Context cost** — dropping 50 files into the context wastes tokens on irrelevant code
16
+ 2. **Discovery** — you don't always know *which* files are relevant to a given task
17
+
18
+ `vemora` solves both by pre-indexing the repo and making it queryable. It also provides higher-level commands that go beyond retrieval:
19
+
20
+ - **`vemora plan`** — a pro LLM (planner) decomposes a complex task into concrete steps; a smaller/free LLM (executor) carries out each step against targeted code context. Cuts costs by using expensive models only where they matter.
21
+ - **`vemora audit`** — systematic, checklist-driven analysis of your codebase for security vulnerabilities, performance issues, and bugs. Covers every file, produces structured findings with severity levels.
22
+ - **`vemora triage`** — zero-LLM static heuristic scan for bugs, security issues, and performance problems. Instant results with no API calls, useful as a first pass before a deeper audit.
23
+ - **`vemora dead-code`** — zero-LLM static analysis that detects unused private symbols, exports nobody imports, and files that are never imported. Works entirely from the call graph and dependency graph already in the index.
24
+ - **`vemora focus`** — aggregates all structural context about a file or symbol in one shot: implementation, exports, dependency graph, callers, test files, and saved knowledge.
25
+
26
+ ## Architecture in three layers
27
+
28
+ ```
29
+ .vemora/ ← versioned in git, shared across the team
30
+ config.json
31
+ metadata.json
32
+ index/
33
+ files.json ← file hashes for incremental indexing
34
+ chunks.json ← code chunks (function/class/window slices)
35
+ symbols.json ← extracted symbol map
36
+ deps.json ← intra-project dependency graph
37
+ callgraph.json ← function-level call relationships
38
+ todos.json ← TODO/FIXME/HACK/XXX annotations extracted from source
39
+ summaries/
40
+ file-summaries.json ← LLM-generated 2-3 line description per file
41
+ project-summary.json ← LLM-generated ~500 word project overview
42
+ knowledge/
43
+ entries.json ← human/LLM-authored notes: decisions, gotchas, patterns
44
+
45
+ ~/.vemora-cache/<projectId>/ ← local to each developer, NOT in git
46
+ embeddings.json ← metadata (model, dimensions, chunk mapping)
47
+ embeddings.bin ← binary buffer of vectors (Float32Array)
48
+ embeddings.hnsw.json ← serialized HNSW index for ultra-fast search
49
+ ```
50
+
51
+ The index, summaries, and knowledge entries are committed to git so teammates share them. Embeddings are generated locally by each developer from the shared index.
52
+
53
+ ## Installation
54
+
55
+ ```bash
56
+ # Inside the vemora/ directory
57
+ pnpm install
58
+ pnpm build
59
+
60
+ # Link globally (optional)
61
+ pnpm link
62
+ ```
63
+
64
+ Or run directly with `node vemora/dist/cli.js` from the project root.
65
+
66
+ ### Installing the alpha version from npm
67
+
68
+ ```bash
69
+ pnpm install vemora@alpha # local
70
+ pnpm install -g vemora@alpha # global
71
+
72
+ # or with npm:
73
+ npm install -g vemora@alpha
74
+ ```
75
+
76
+ ## The Core Workflow
77
+
78
+ ### 1. Setup (first time only)
79
+
80
+ ```bash
81
+ vemora init # create .vemora/ and config.json
82
+ vemora index --no-embed # build index without embeddings (fast)
83
+ vemora index # or: build index + generate embeddings
84
+ vemora summarize # recommended: generate LLM descriptions per file
85
+ vemora init-agent # generate instruction files for AI agents
86
+ vemora init-agent --hooks # also write Claude Code auto-save hooks
87
+ ```
88
+
89
+ ### 1b. Start of each session
90
+
91
+ ```bash
92
+ vemora brief --root . # compact primer: project overview + critical knowledge
93
+ ```
94
+
95
+ ### 2. Query during development
96
+
97
+ ```bash
98
+ # Search for relevant code
99
+ vemora query "how does IMAP reconnect work?"
100
+
101
+ # Full context block ready to paste into any LLM
102
+ vemora context --query "email retry logic" > context.md
103
+
104
+ # One-shot answer from the configured LLM
105
+ vemora ask "why does the sync queue stall?"
106
+
107
+ # All context about a file or symbol in one call (no LLM needed)
108
+ vemora focus src/core/email/services/email.service.ts
109
+ vemora focus EmailService.send
110
+
111
+ # Static scan for bugs/perf/security (no API key required)
112
+ vemora triage --type bugs,performance
113
+
114
+ # Save a finding for future sessions
115
+ vemora remember "EmailService.send queues if SMTP is offline — see OutboxRepository"
116
+ ```
117
+
118
+ ### 3. Complex tasks with the planner-executor pattern
119
+
120
+ ```bash
121
+ # Pro LLM plans, small/free LLM executes each step
122
+ vemora plan "add rate limiting to the API layer" --confirm --synthesize
123
+
124
+ # Audit the codebase for issues
125
+ vemora audit --type security --root .
126
+ vemora audit --since HEAD~1 # only changed files (great for CI)
127
+ ```
128
+
129
+ ### 4. Keep the index fresh
130
+
131
+ ```bash
132
+ vemora index --watch # incremental re-index on file save
133
+ vemora index --no-embed # after code changes, update structure only
134
+ ```
135
+
136
+ ## Commands
137
+
138
+ ### `vemora init`
139
+
140
+ Creates the `.vemora/` folder structure and adds `.vemora-cache/` to `.gitignore`.
141
+
142
+ ```
143
+ Options:
144
+ --root <dir> project root (default: cwd)
145
+ ```
146
+
147
+ ### `vemora index`
148
+
149
+ Scans the repo, parses symbols, builds the dependency graph, extracts TODO/FIXME/HACK/XXX annotations, and generates embeddings. **Incremental** — only re-processes files whose SHA-256 hash has changed.
150
+
151
+ ```
152
+ Options:
153
+ --root <dir> project root (default: cwd)
154
+ --force re-index all files, ignoring hashes
155
+ --no-embed skip embedding generation (index structure only)
156
+ -w, --watch watch for changes and re-index automatically
157
+ ```
158
+
159
+ ### `vemora query "<question>"`
160
+
161
+ Searches the index using vector similarity (or keyword fallback). Results use a **three-tier display** that compresses output by relevance rank.
162
+
163
+ ```
164
+ Options:
165
+ --root <dir> project root (default: cwd)
166
+ -k, --top-k <n> number of results (default: 10)
167
+ -c, --show-code show full code for all results (overrides tier system)
168
+ --keyword force keyword/BM25 search (no API call needed)
169
+ --format <fmt> output format: terminal (default) | json | markdown | terse
170
+ --rerank re-score results with a cross-encoder model
171
+ --hybrid use hybrid search (vector + BM25)
172
+ --alpha <n> hybrid weight for vector search (0-1, default 0.7)
173
+ --budget <n> max tokens to include across results
174
+ --mmr apply Maximal Marginal Relevance to diversify results
175
+ --merge merge adjacent chunks from the same file
176
+ ```
177
+
178
+ #### Output formats
179
+
180
+ | Format | Use case |
181
+ |---|---|
182
+ | `terminal` | Default coloured output for interactive use |
183
+ | `json` | Machine-readable — for piping to scripts |
184
+ | `markdown` | Paste-ready Markdown with code blocks |
185
+ | `terse` | One line per result — recommended for small/local models |
186
+
187
+ #### Output tiers (terminal/markdown)
188
+
189
+ | Rank | Tier | Content shown |
190
+ |------|------|--------------|
191
+ | 1–3 | high | Full code block (capped at 30 lines) |
192
+ | 4–7 | med | Declaration signature only |
193
+ | 8+ | low | File path + symbol + score + AI summary |
194
+
195
+ ### `vemora context`
196
+
197
+ Generates an **optimized LLM context block** combining project overview, a specific file, and relevant code chunks. Designed to be piped to a file or clipboard.
198
+
199
+ ```
200
+ Options:
201
+ --root <dir> project root (default: cwd)
202
+ -q, --query <text> natural-language query to find relevant code
203
+ -f, --file <path> include a specific file in full with its dependency graph
204
+ -k, --top-k <n> number of search results to include (default: 5)
205
+ --keyword use keyword search instead of semantic search
206
+ --show-code show full code without line cap
207
+ --format <fmt> output format: markdown (default) | plain | terse
208
+ --rerank re-score results with a cross-encoder model
209
+ --hybrid use hybrid search (vector + BM25)
210
+ --budget <n> max tokens to include across retrieved chunks
211
+ --structured emit a structured block (Entry Point / Dependencies / Types / Patterns)
212
+ --since <ref> restrict search to files changed since this git ref (e.g. HEAD~5, main)
213
+ ```
214
+
215
+ At least one of `--query` or `--file` is required.
216
+
217
+ When `--file` is used, the context block also includes:
218
+ - **Recent git commits** that touched the file (last 5, via `git log --follow`)
219
+ - **TODO/FIXME/HACK/XXX annotations** present in the file
220
+ - **Test files** linked to the file — convention-based and import-based discovery
221
+ - **Symbol callers** — for each symbol defined in the file, which other project symbols call it
222
+
223
+ ### `vemora ask "<question>"`
224
+
225
+ One-shot Q&A: retrieves relevant context and calls the configured LLM to answer directly.
226
+
227
+ ```
228
+ Options:
229
+ --root <dir> project root (default: cwd)
230
+ -k, --top-k <n> chunks to retrieve (default: 5)
231
+ --keyword use keyword search (no embeddings needed)
232
+ --hybrid use hybrid vector+BM25 search
233
+ --budget <n> max context tokens to send to LLM (default: 6000)
234
+ --show-context print the retrieved context before the answer
235
+ ```
236
+
237
+ ```bash
238
+ vemora ask "how does the IMAP reconnect logic work?" --root .
239
+ vemora ask "what does EmailService.send do?" --root . --keyword
240
+ ```
241
+
242
+ ### `vemora plan "<task>"`
243
+
244
+ **Planner-executor pattern**: a capable LLM decomposes the task into a structured plan; a smaller/cheaper LLM executes each step against targeted code context.
245
+
246
+ The planner works from **file summaries and the symbol list** — not raw code — so its token cost stays low regardless of codebase size. The executor receives only the chunks relevant to its specific step (targeted by file/symbol, not just search).
247
+
248
+ ```
249
+ Options:
250
+ --root <dir> project root (default: cwd)
251
+ -k, --top-k <n> chunks to retrieve per step when falling back to search (default: 5)
252
+ --keyword use keyword search (no embeddings required)
253
+ --budget <n> max context tokens per step (default: 4000)
254
+ --confirm show the plan and ask for confirmation before executing
255
+ --synthesize call the planner again after all steps to produce a single final answer
256
+ --show-context print retrieved context for each step
257
+ --verify after each executor step, have the planner review the output
258
+ --apply automatically apply unified diffs produced by write steps (via patch -p1)
259
+ --max-retries <n> max re-runs of a step when verification fails (default: 2)
260
+ --resume <id> resume a previous session by short ID (first 8 chars) or full UUID
261
+ ```
262
+
263
+ #### Step action types
264
+
265
+ | Action | Behaviour |
266
+ |---|---|
267
+ | `read` | Pull code into context — no LLM call, zero executor tokens |
268
+ | `analyze` | Executor answers a question in prose |
269
+ | `write` | Executor produces a unified diff ready to apply |
270
+ | `test` | Run a shell command; capture stdout/stderr as step result |
271
+
272
+ #### Key features
273
+
274
+ - **Parallel execution** — steps without dependencies run concurrently; sequential steps stream tokens to stdout in real time
275
+ - **Step dependencies** (`dependsOn`) — later steps receive prior results as context
276
+ - **Context deduplication** — the same file/symbol combination is retrieved only once per session
277
+ - **Adaptive re-planning** — if an executor step reports insufficient context (`INSUFFICIENT:`), the planner adds remediation steps automatically
278
+ - **Planner verification** (`--verify`) — after each executor step, the planner reviews the output and can request a retry with specific feedback
279
+ - **Diff application** (`--apply`) — diffs from `write` steps are applied to the filesystem via `patch -p1`; live file contents are read before write steps to avoid stale index data
280
+ - **Session persistence** — every session is saved to `~/.vemora-cache/<projectId>/sessions/` after each wave; interrupted runs can be resumed with `--resume <id>`
281
+ - **Save synthesis** — after `--synthesize`, optionally save the result as a knowledge entry
282
+
283
+ ```bash
284
+ # Plan, preview, and execute with final synthesis
285
+ vemora plan "add batch() method to OpenAIEmbeddingProvider" --confirm --synthesize
286
+
287
+ # Analysis only (no code changes)
288
+ vemora plan "explain how the hybrid search pipeline works" --keyword
289
+
290
+ # Executor writes diffs, planner verifies each step, apply to disk
291
+ vemora plan "fix the N+1 query in UserRepository.findAll" --verify --apply
292
+
293
+ # Resume an interrupted session (use vemora sessions to find the ID)
294
+ vemora plan "..." --resume a1b2c3d4
295
+ ```
296
+
297
+ #### Configuration
298
+
299
+ ```json
300
+ {
301
+ "planner": { "provider": "anthropic", "model": "claude-opus-4-6" },
302
+ "executor": { "provider": "ollama", "model": "qwen2.5-coder:14b",
303
+ "baseUrl": "http://localhost:11434" }
304
+ }
305
+ ```
306
+
307
+ `executor` is the model that carries out each step. If `executor` is omitted, `summarization` is used as the fallback. If `planner` is omitted, both roles use the same model.
308
+
309
+ ##### Using Claude Code as the planner
310
+
311
+ Set `provider: "claude-code"` to use the local `claude` CLI subprocess as the planner. The subprocess can autonomously explore the codebase with `Read`, `Grep`, and `Glob` tools before generating the plan:
312
+
313
+ ```json
314
+ {
315
+ "planner": {
316
+ "provider": "claude-code",
317
+ "model": "claude-sonnet-4-6",
318
+ "baseUrl": "/path/to/claude",
319
+ "allowedTools": ["Read", "Grep", "Glob"],
320
+ "maxBudgetUsd": 0.50
321
+ }
322
+ }
323
+ ```
324
+
325
+ `baseUrl` is the path to the `claude` binary (default: `"claude"`, assumed on `PATH`).
326
+
327
+ ### `vemora sessions`
328
+
329
+ Lists recent plan sessions for the current project, showing their short ID, status, creation date, and task preview.
330
+
331
+ ```bash
332
+ vemora sessions --root .
333
+ ```
334
+
335
+ Use the short ID printed here with `vemora plan "<task>" --resume <id>` to continue an interrupted run.
336
+
337
+ ### `vemora audit`
338
+
339
+ Systematic, checklist-driven code audit for **security vulnerabilities**, **performance issues**, and **bugs**. Covers every file in the codebase (or only changed files with `--since`).
340
+
341
+ ```
342
+ Options:
343
+ --root <dir> project root (default: cwd)
344
+ --type <types> comma-separated: security, performance, bugs (default: all three)
345
+ --since <ref> only audit files changed since this git ref (e.g. HEAD~5, main)
346
+ --budget <n> max context tokens per step (default: 5000)
347
+ --keyword use keyword search (no embeddings required)
348
+ --output <fmt> terminal (default) | json | markdown
349
+ --save save critical/high findings as knowledge entries
350
+ ```
351
+
352
+ #### Built-in checklists
353
+
354
+ | Type | Examples |
355
+ |---|---|
356
+ | `security` | SQL/command/path injection, hardcoded secrets, weak crypto, missing auth/authz, XSS, CSRF, prototype pollution |
357
+ | `performance` | N+1 queries, sync I/O in async context, unbounded data loading, memory accumulation, blocking event loop |
358
+ | `bugs` | Null dereference, unhandled promise rejections, race conditions, resource leaks, swallowed errors, off-by-one |
359
+
360
+ #### How it works
361
+
362
+ 1. The **planner** receives the file list + summaries and generates a systematic audit plan, grouping 2-5 related files per step with specific checklist items.
363
+ 2. Steps execute in **parallel waves of 3** — the executor returns structured JSON findings for each group.
364
+ 3. Findings are **deduplicated, sorted by severity**, and displayed as a report.
365
+ 4. `--save` persists critical/high findings to the knowledge store for future sessions.
366
+
367
+ ```bash
368
+ # Full audit
369
+ vemora audit --root .
370
+
371
+ # Security only
372
+ vemora audit --type security --root .
373
+
374
+ # Audit only what changed in the last commit (ideal for CI/CD)
375
+ vemora audit --since HEAD~1 --root .
376
+
377
+ # Audit changes vs main branch, save findings
378
+ vemora audit --since main --type security,bugs --save --root .
379
+
380
+ # Export for a PR review
381
+ vemora audit --since main --output markdown --root . > audit-report.md
382
+ ```
383
+
384
+ #### Example output
385
+
386
+ ```
387
+ ── Audit Report [security] ─────────────────────────────
388
+ 12 file(s) analysed · 3 finding(s)
389
+
390
+ [CRITICAL] Injection src/api/users.ts:89
391
+ User input concatenated directly into SQL query without parameterization.
392
+ → Use parameterized queries or a query builder.
393
+
394
+ [HIGH] Hardcoded Secret src/config.ts:12
395
+ API key hardcoded in source — will be exposed in version control.
396
+ → Move to environment variables and rotate the key.
397
+
398
+ [MEDIUM] Missing Authorization src/api/admin.ts:34
399
+ Admin endpoint does not verify that the caller has the admin role.
400
+ → Add role check before processing the request.
401
+
402
+ ─────────────────────────────────────────────────────────
403
+ 1 critical · 1 high · 1 medium
404
+ ```
405
+
406
+ ### `vemora remember "<text>"`
407
+
408
+ Saves a persistent knowledge entry to `.vemora/knowledge/entries.json`. The entry is committed to git and included automatically in future `context` and `ask` results when relevant.
409
+
410
+ When `--category` is omitted, the configured LLM classifies the entry automatically into one of the four categories. Falls back to `pattern` if no LLM is available.
411
+
412
+ ```
413
+ Options:
414
+ --root <dir> project root (default: cwd)
415
+ --category <cat> decision | pattern | gotcha | glossary (auto-classified if omitted)
416
+ --files <paths> comma-separated related file paths
417
+ --symbols <names> comma-separated related symbol names
418
+ --confidence <level> high | medium | low (default: medium)
419
+ ```
420
+
421
+ ```bash
422
+ # Category auto-classified by the LLM
423
+ vemora remember "EmailService.send queues if SMTP offline — see OutboxRepository"
424
+
425
+ # Or specify explicitly
426
+ vemora remember "EmailService.send queues if SMTP offline — see OutboxRepository" \
427
+ --category gotcha \
428
+ --files src/core/email/services/email.service.ts \
429
+ --symbols EmailService.send
430
+ ```
431
+
432
+ ### `vemora brief`
433
+
434
+ Prints a compact session primer — project overview and high-confidence knowledge entries — designed to be run at the start of each LLM session to re-establish context with minimal tokens.
435
+
436
+ ```
437
+ Options:
438
+ --root <dir> project root (default: cwd)
439
+ --all include all knowledge entries, not only high-confidence ones
440
+ ```
441
+
442
+ ```bash
443
+ vemora brief --root . # overview + high-confidence entries only (~170 tokens)
444
+ vemora brief --root . --all # include all entries
445
+ ```
446
+
447
+ ### `vemora knowledge`
448
+
449
+ Manages saved knowledge entries.
450
+
451
+ ```bash
452
+ vemora knowledge list --root . # list all entries grouped by category
453
+ vemora knowledge forget <id> --root . # remove an entry by ID (prefix match)
454
+ ```
455
+
456
+ ### `vemora init-agent`
457
+
458
+ Generates AI agent instruction files from the existing index. Supports Claude Code, Gemini, GitHub Copilot, Cursor, and Windsurf.
459
+
460
+ ```
461
+ Options:
462
+ --root <dir> project root (default: cwd)
463
+ --agent <name> target a single agent: claude, gemini, copilot, cursor, windsurf (default: all)
464
+ --force overwrite existing files that have no vemora markers
465
+ --hooks write Claude Code hooks to .claude/settings.json (claude target only)
466
+ ```
467
+
468
+ Use `--hooks` to register a `PreCompact` hook that reminds Claude Code to persist key decisions before context is compressed:
469
+
470
+ ```bash
471
+ vemora init-agent --agent claude --hooks --root .
472
+ ```
473
+
474
+ | Agent | Output file |
475
+ |---|---|
476
+ | `claude` | `CLAUDE.md` |
477
+ | `gemini` | `GEMINI.md` |
478
+ | `copilot` | `.github/copilot-instructions.md` |
479
+ | `cursor` | `.cursor/rules/vemora.mdc` (with `alwaysApply: true`) |
480
+ | `windsurf` | `.windsurfrules` |
481
+
482
+ Re-running `init-agent` only updates the auto-generated block between `<!-- vemora:generated:start/end -->` markers. Custom content outside the markers is preserved.
483
+
484
+ ### `vemora summarize`
485
+
486
+ Generates LLM-powered summaries for every indexed file and a high-level project overview. **Incremental** — only re-generates summaries for files whose content has changed.
487
+
488
+ Summaries are used by `vemora plan` and `vemora audit` as cheap planner context (instead of raw code chunks).
489
+
490
+ ```
491
+ Options:
492
+ --root <dir> project root (default: cwd)
493
+ --force re-generate all summaries
494
+ --model <name> override LLM model (default: from config)
495
+ --files-only only generate per-file summaries
496
+ --project-only (re)generate project overview from existing file summaries
497
+ --show print the existing project overview without regenerating
498
+ ```
499
+
500
+ ```bash
501
+ vemora summarize --show --root . # print overview without regenerating
502
+ ```
503
+
504
+ ### `vemora status`
505
+
506
+ Prints index stats, embedding cache info, knowledge store summary, and a count of TODO/FIXME/HACK/XXX annotations by type.
507
+
508
+ ### `vemora deps <file>`
509
+
510
+ Shows the full dependency context for a file: what it imports, what imports it.
511
+
512
+ ```
513
+ Options:
514
+ --root <dir> project root (default: cwd)
515
+ -d, --depth <n> transitive depth for outgoing imports (default: 1)
516
+ -r, --reverse-depth <n> transitive depth for incoming importers (default: 1)
517
+ ```
518
+
519
+ ```bash
520
+ # All files that depend on SyncOrchestrator, up to 3 hops
521
+ vemora deps src/core/sync/SyncOrchestrator.ts --root . --reverse-depth 3
522
+ ```
523
+
524
+ ### `vemora usages <SymbolName>`
525
+
526
+ Finds all files that use a named symbol, following re-export chains.
527
+
528
+ ```
529
+ Options:
530
+ --root <dir> project root (default: cwd)
531
+ -d, --depth <n> max re-export chain depth to follow (default: 10)
532
+ --callers-only show only files with call graph data
533
+ ```
534
+
535
+ ### `vemora chat`
536
+
537
+ Interactive chat session with the codebase. Supports OpenAI, Anthropic, Gemini, and Ollama.
538
+
539
+ ```bash
540
+ vemora chat --provider anthropic --model claude-opus-4-6
541
+ vemora chat --provider ollama --model qwen2.5-coder:14b
542
+ ```
543
+
544
+ ### `vemora report`
545
+
546
+ Shows a usage statistics report: commands breakdown, token savings, and most frequent query terms.
547
+
548
+ ```
549
+ Options:
550
+ --root <dir> project root (default: cwd)
551
+ --days <n> limit report to events from the last N days
552
+ -v, --verbose show per-query breakdown (last 20 queries)
553
+ --clear clear all recorded usage data
554
+ ```
555
+
556
+ ### `vemora triage`
557
+
558
+ Zero-LLM static heuristic scan for bugs, security issues, and performance problems. Works entirely from the existing index — no API key or network access required.
559
+
560
+ ```
561
+ Options:
562
+ --root <dir> project root (default: cwd)
563
+ --type <types> comma-separated: bugs, security, performance (default: all)
564
+ -k, --top-k <n> max findings to return, ranked by score (default: 30)
565
+ --min-score <n> skip findings below this threshold (default: 1)
566
+ --file <path> restrict scan to files matching this substring
567
+ --output <fmt> terminal (default) | json | markdown
568
+ ```
569
+
570
+ Each finding includes a severity (high/medium/low), a reason, and the exact code location.
571
+
572
+ ```bash
573
+ # Full scan
574
+ vemora triage --root .
575
+
576
+ # Bugs only, top 10, export to Markdown
577
+ vemora triage --type bugs -k 10 --output markdown --root .
578
+
579
+ # Security scan limited to the API layer
580
+ vemora triage --type security --file src/api --root .
581
+ ```
582
+
583
+ Heuristics cover: empty catch blocks, unguarded `JSON.parse`, sync I/O in loops, `any` casts, hardcoded secrets, dangerous `eval`/`exec`, prototype pollution, SQL/command injection patterns, and more.
584
+
585
+ ### `vemora dead-code`
586
+
587
+ Zero-LLM static analysis for unused code. Works entirely from the existing index — no API key or network access required.
588
+
589
+ ```
590
+ Options:
591
+ --root <dir> project root (default: cwd)
592
+ --type <types> comma-separated: uncalled-private, unused-export, unreachable-file (default: all)
593
+ --output <fmt> terminal (default) | json
594
+ ```
595
+
596
+ Three detection categories:
597
+
598
+ | Type | What it finds |
599
+ |---|---|
600
+ | `uncalled-private` | Private functions and methods with an entry in the call graph but no recorded callers |
601
+ | `unused-export` | Exported symbols not imported by any file in the dep graph (namespace imports excluded) |
602
+ | `unreachable-file` | Files that export symbols but are never imported by any other file in the project |
603
+
604
+ ```bash
605
+ # Full scan — all three categories
606
+ vemora dead-code --root .
607
+
608
+ # Only private methods with no callers
609
+ vemora dead-code --type uncalled-private --root .
610
+
611
+ # Machine-readable output
612
+ vemora dead-code --output json --root . | jq '.[] | select(.type == "unused-export")'
613
+ ```
614
+
615
+ **Caveats:** call graph coverage is incomplete for dynamic dispatch, arrow functions assigned to variables, and `require()` calls. Namespace imports (`import * as X`) prevent false positives on `unused-export` by marking the whole file as used. Entry points (`cli.ts`, `index.ts`, `main.ts`, etc.) are excluded from `unreachable-file`.
616
+
617
+ ### `vemora focus <target>`
618
+
619
+ Aggregates all structural context about a file or symbol in one call — replaces the need to run `context`, `deps`, `usages`, and `knowledge` separately.
620
+
621
+ ```
622
+ Options:
623
+ --root <dir> project root (default: cwd)
624
+ --format <fmt> markdown (default) | plain
625
+ ```
626
+
627
+ `<target>` can be a file path (full or partial) or a symbol name:
628
+
629
+ ```bash
630
+ # File focus — exports, chunks, imports, importers, call graph, tests, knowledge
631
+ vemora focus src/core/email/services/email.service.ts --root .
632
+ vemora focus email.service --root . # partial path match
633
+
634
+ # Symbol focus — implementation, callers, callees, sibling members, tests
635
+ vemora focus EmailService.send --root .
636
+
637
+ # Pipe into a context block for any LLM
638
+ vemora focus src/search/hybrid.ts --root . --format plain > context.md
639
+ ```
640
+
641
+ ---
642
+
643
+ ## Configuration
644
+
645
+ Edit `.vemora/config.json` after `init`:
646
+
647
+ ```json
648
+ {
649
+ "projectId": "b88eb8199f78331e",
650
+ "projectName": "my-app",
651
+ "version": "1.0.0",
652
+ "include": ["**/*.ts", "**/*.tsx"],
653
+ "exclude": ["**/node_modules/**", "**/dist/**"],
654
+ "maxChunkLines": 80,
655
+ "maxChunkChars": 3000,
656
+ "embedding": {
657
+ "provider": "ollama",
658
+ "model": "nomic-embed-text",
659
+ "dimensions": 768
660
+ },
661
+ "summarization": {
662
+ "provider": "ollama",
663
+ "model": "gemma4:e2b",
664
+ "baseUrl": "http://localhost:11434"
665
+ },
666
+ "reranker": {
667
+ "provider": "ollama"
668
+ },
669
+ "display": {
670
+ "format": "terse"
671
+ }
672
+ }
673
+ ```
674
+
675
+ ### Planner-executor configuration
676
+
677
+ Add `planner` and `executor` blocks to use different models for planning and execution:
678
+
679
+ ```json
680
+ {
681
+ "planner": {
682
+ "provider": "anthropic",
683
+ "model": "claude-opus-4-6"
684
+ },
685
+ "executor": {
686
+ "provider": "gemini",
687
+ "model": "gemini-2.0-flash",
688
+ "apiKey": "your-google-ai-studio-key"
689
+ }
690
+ }
691
+ ```
692
+
693
+ `planner` is used by `vemora plan` and `vemora audit`. `executor` handles step execution. Fallback chain: `executor` → `summarization` → same model for both roles.
694
+
695
+ The `planner` config also accepts two extra fields when using `claude-code`:
696
+
697
+ | Field | Type | Description |
698
+ |---|---|---|
699
+ | `allowedTools` | `string[]` | Tools the subprocess may call (default: `["Read","Grep","Glob"]`) |
700
+ | `maxBudgetUsd` | `number` | Spend cap per plan call in USD (default: `0.50`) |
701
+
702
+ ### `display.format`
703
+
704
+ Sets the default output format for `query`, `context`, and `ask`. Set to `"terse"` for small/local models with limited context windows.
705
+
706
+ ### Embedding providers
707
+
708
+ | Provider | Config | Notes |
709
+ |---|---|---|
710
+ | `openai` | `OPENAI_API_KEY` env or `apiKey` in config | Best quality. Requires `npm install openai`. |
711
+ | `ollama` | `baseUrl`, `maxChars` (see below) | Local, no cost. |
712
+ | `none` | — | Keyword search only, no embeddings. |
713
+
714
+ #### Ollama embedding options
715
+
716
+ | Field | Default | Description |
717
+ |---|---|---|
718
+ | `model` | `"nomic-embed-text"` | Embedding model to pull and use |
719
+ | `dimensions` | `768` | Must match the model output dimensions |
720
+ | `baseUrl` | `"http://localhost:11434"` | Ollama server URL |
721
+ | `maxChars` | `3800` | Max characters per chunk before truncation. Prevents exceeding the model's context window. Increase for models with larger context (e.g. `mxbai-embed-large`: ~8000). |
722
+
723
+ ```json
724
+ "embedding": {
725
+ "provider": "ollama",
726
+ "model": "nomic-embed-text",
727
+ "dimensions": 768,
728
+ "maxChars": 3800
729
+ }
730
+ ```
731
+
732
+ ### LLM providers
733
+
734
+ Used by `ask`, `chat`, `summarize`, `plan`, and `audit`.
735
+
736
+ | Provider | Config | Notes |
737
+ |---|---|---|
738
+ | `openai` | `OPENAI_API_KEY` env or `apiKey` in config | Also works with any OpenAI-compatible endpoint via `baseUrl`. |
739
+ | `anthropic` | `ANTHROPIC_API_KEY` env or `apiKey` in config | Requires `npm install @anthropic-ai/sdk`. |
740
+ | `gemini` | `GEMINI_API_KEY` or `GOOGLE_API_KEY` env or `apiKey` in config | Uses Google's OpenAI-compatible endpoint. Free tier available via Google AI Studio. |
741
+ | `ollama` | `baseUrl` (default: `http://localhost:11434`) | Local, no cost. |
742
+ | `claude-code` | `baseUrl` = path to `claude` binary (default: `"claude"`) | Planner-only. Spawns the Claude Code CLI subprocess; the subprocess can explore the codebase with `Read`/`Grep`/`Glob` before answering. Requires Claude Code installed and authenticated. |
743
+
744
+ #### OpenAI-compatible endpoints
745
+
746
+ The `openai` provider accepts a `baseUrl` field, enabling any compatible API:
747
+
748
+ ```json
749
+ { "provider": "openai", "model": "llama-3.3-70b-versatile", "baseUrl": "https://api.groq.com/openai/v1", "apiKey": "..." }
750
+ ```
751
+
752
+ | Service | `baseUrl` | Free tier |
753
+ |---|---|---|
754
+ | Groq | `https://api.groq.com/openai/v1` | Yes (rate limited) |
755
+ | OpenRouter | `https://openrouter.ai/api/v1` | Some free models |
756
+ | Gemini (compat) | `https://generativelanguage.googleapis.com/v1beta/openai/` | Yes |
757
+
758
+ ### Reranker
759
+
760
+ Controls how search results are re-scored when `--rerank` is passed to `query`, `context`, or `ask`, and always in `chat`.
761
+
762
+ | Provider | Config | Notes |
763
+ |---|---|---|
764
+ | `xenova` | _(no extra config)_ | Local cross-encoder (`ms-marco-MiniLM-L-6-v2`). Best quality. Requires `npm install @xenova/transformers`. |
765
+ | `ollama` | `model` (optional), `baseUrl` (optional) | Uses the configured LLM to rank results in a single call. No extra dependency. |
766
+ | `none` | — | Skip reranking entirely. |
767
+
768
+ ```json
769
+ {
770
+ "reranker": { "provider": "ollama" }
771
+ }
772
+ ```
773
+
774
+ When `provider` is `ollama` and `model` is omitted, the model from `summarization` is used.
775
+
776
+ ### Recommended configurations
777
+
778
+ **Maximum quality (cloud)**
779
+ ```json
780
+ {
781
+ "planner": { "provider": "anthropic", "model": "claude-opus-4-6" },
782
+ "executor": { "provider": "openai", "model": "gpt-4o-mini" }
783
+ }
784
+ ```
785
+
786
+ **Claude Code as planner + free executor**
787
+ ```json
788
+ {
789
+ "planner": { "provider": "claude-code", "model": "claude-sonnet-4-6",
790
+ "allowedTools": ["Read","Grep","Glob"], "maxBudgetUsd": 0.50 },
791
+ "executor": { "provider": "ollama", "model": "qwen2.5-coder:14b",
792
+ "baseUrl": "http://localhost:11434" }
793
+ }
794
+ ```
795
+
796
+ **Pro planner + free executor**
797
+ ```json
798
+ {
799
+ "planner": { "provider": "anthropic", "model": "claude-opus-4-6" },
800
+ "executor": { "provider": "gemini", "model": "gemini-2.0-flash", "apiKey": "..." }
801
+ }
802
+ ```
803
+
804
+ **Fully local (no API keys)**
805
+ ```json
806
+ {
807
+ "embedding": { "provider": "ollama", "model": "nomic-embed-text", "dimensions": 768 },
808
+ "summarization": { "provider": "ollama", "model": "gemma4:e2b" },
809
+ "executor": { "provider": "ollama", "model": "qwen2.5-coder:7b" },
810
+ "reranker": { "provider": "ollama" },
811
+ "display": { "format": "terse" }
812
+ }
813
+ ```
814
+
815
+ Other local executor models that work well: `qwen2.5-coder:14b`, `llama3.2`, `mistral`.
816
+
817
+ ---
818
+
819
+ ## What goes in git
820
+
821
+ ```
822
+ ✓ .vemora/config.json
823
+ ✓ .vemora/metadata.json
824
+ ✓ .vemora/index/files.json
825
+ ✓ .vemora/index/chunks.json
826
+ ✓ .vemora/index/symbols.json
827
+ ✓ .vemora/index/deps.json
828
+ ✓ .vemora/index/callgraph.json
829
+ ✓ .vemora/summaries/file-summaries.json
830
+ ✓ .vemora/summaries/project-summary.json
831
+ ✓ .vemora/knowledge/entries.json ← shared knowledge store
832
+
833
+ ✗ .vemora-cache/ ← local embedding vectors (gitignored)
834
+ ```
835
+
836
+ ## Incremental indexing
837
+
838
+ Chunk IDs are derived from `sha256(filePath + content)`. If a function's code doesn't change, its chunk ID is stable across branches — embeddings are reused without any API call.
839
+
840
+ ## Tech stack
841
+
842
+ - **TypeScript + Node.js** (CommonJS, ES2022 target)
843
+ - **commander** — CLI framework
844
+ - **fast-glob** — repository scanning
845
+ - **tree-sitter** (optional) — AST-based symbol extraction for TS/JS
846
+ - **openai** SDK _(optional)_ — embedding generation, OpenAI and Gemini LLM provider; `npm install openai`
847
+ - **@anthropic-ai/sdk** _(optional)_ — Anthropic/Claude LLM provider; `npm install @anthropic-ai/sdk`
848
+ - **@xenova/transformers** _(optional)_ — local cross-encoder model for `--rerank` with `reranker.provider = "xenova"`; `npm install @xenova/transformers`. Not needed if using `reranker.provider = "ollama"` or `"none"`.
849
+ - **hnsw** — HNSW index for sub-millisecond vector search
850
+ - **chokidar** — file watching for `--watch` mode
851
+ - **chalk + ora** — terminal output