@vinaes/succ 1.4.0 → 1.5.42

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 (687) hide show
  1. package/README.md +64 -10
  2. package/dist/cli.js +81 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/agents-md.d.ts.map +1 -1
  5. package/dist/commands/agents-md.js +3 -2
  6. package/dist/commands/agents-md.js.map +1 -1
  7. package/dist/commands/analyze-profile.d.ts.map +1 -1
  8. package/dist/commands/analyze-profile.js +32 -8
  9. package/dist/commands/analyze-profile.js.map +1 -1
  10. package/dist/commands/analyze-recursive.d.ts.map +1 -1
  11. package/dist/commands/analyze-recursive.js +6 -2
  12. package/dist/commands/analyze-recursive.js.map +1 -1
  13. package/dist/commands/analyze-utils.d.ts.map +1 -1
  14. package/dist/commands/analyze-utils.js +17 -4
  15. package/dist/commands/analyze-utils.js.map +1 -1
  16. package/dist/commands/benchmark-quality.d.ts.map +1 -1
  17. package/dist/commands/benchmark-quality.js +11 -4
  18. package/dist/commands/benchmark-quality.js.map +1 -1
  19. package/dist/commands/benchmark-sqlite-vec.d.ts.map +1 -1
  20. package/dist/commands/benchmark-sqlite-vec.js +4 -0
  21. package/dist/commands/benchmark-sqlite-vec.js.map +1 -1
  22. package/dist/commands/benchmark.d.ts.map +1 -1
  23. package/dist/commands/benchmark.js +5 -1
  24. package/dist/commands/benchmark.js.map +1 -1
  25. package/dist/commands/codex-chat.d.ts +8 -0
  26. package/dist/commands/codex-chat.d.ts.map +1 -0
  27. package/dist/commands/codex-chat.js +161 -0
  28. package/dist/commands/codex-chat.js.map +1 -0
  29. package/dist/commands/config.d.ts.map +1 -1
  30. package/dist/commands/config.js +32 -4
  31. package/dist/commands/config.js.map +1 -1
  32. package/dist/commands/daemon.d.ts.map +1 -1
  33. package/dist/commands/daemon.js +13 -4
  34. package/dist/commands/daemon.js.map +1 -1
  35. package/dist/commands/index-code.d.ts +4 -0
  36. package/dist/commands/index-code.d.ts.map +1 -1
  37. package/dist/commands/index-code.js +1 -1
  38. package/dist/commands/index-code.js.map +1 -1
  39. package/dist/commands/init.d.ts.map +1 -1
  40. package/dist/commands/init.js +305 -203
  41. package/dist/commands/init.js.map +1 -1
  42. package/dist/commands/memories.d.ts.map +1 -1
  43. package/dist/commands/memories.js +25 -14
  44. package/dist/commands/memories.js.map +1 -1
  45. package/dist/commands/progress.d.ts.map +1 -1
  46. package/dist/commands/progress.js +3 -2
  47. package/dist/commands/progress.js.map +1 -1
  48. package/dist/commands/reindex.d.ts.map +1 -1
  49. package/dist/commands/reindex.js +54 -36
  50. package/dist/commands/reindex.js.map +1 -1
  51. package/dist/commands/retention.d.ts.map +1 -1
  52. package/dist/commands/retention.js +7 -5
  53. package/dist/commands/retention.js.map +1 -1
  54. package/dist/commands/scan-code.d.ts +76 -0
  55. package/dist/commands/scan-code.d.ts.map +1 -0
  56. package/dist/commands/scan-code.js +385 -0
  57. package/dist/commands/scan-code.js.map +1 -0
  58. package/dist/commands/score.d.ts.map +1 -1
  59. package/dist/commands/score.js +3 -2
  60. package/dist/commands/score.js.map +1 -1
  61. package/dist/commands/session.d.ts +33 -0
  62. package/dist/commands/session.d.ts.map +1 -0
  63. package/dist/commands/session.js +163 -0
  64. package/dist/commands/session.js.map +1 -0
  65. package/dist/commands/setup.d.ts.map +1 -1
  66. package/dist/commands/setup.js +254 -15
  67. package/dist/commands/setup.js.map +1 -1
  68. package/dist/commands/soul.js +3 -2
  69. package/dist/commands/soul.js.map +1 -1
  70. package/dist/commands/status.d.ts.map +1 -1
  71. package/dist/commands/status.js +14 -5
  72. package/dist/commands/status.js.map +1 -1
  73. package/dist/commands/watch.d.ts.map +1 -1
  74. package/dist/commands/watch.js +13 -4
  75. package/dist/commands/watch.js.map +1 -1
  76. package/dist/daemon/analyzer.d.ts.map +1 -1
  77. package/dist/daemon/analyzer.js +21 -5
  78. package/dist/daemon/analyzer.js.map +1 -1
  79. package/dist/daemon/client.d.ts.map +1 -1
  80. package/dist/daemon/client.js +32 -8
  81. package/dist/daemon/client.js.map +1 -1
  82. package/dist/daemon/routes/analyzer.d.ts +3 -0
  83. package/dist/daemon/routes/analyzer.d.ts.map +1 -0
  84. package/dist/daemon/routes/analyzer.js +27 -0
  85. package/dist/daemon/routes/analyzer.js.map +1 -0
  86. package/dist/daemon/routes/hooks.d.ts +14 -0
  87. package/dist/daemon/routes/hooks.d.ts.map +1 -0
  88. package/dist/daemon/routes/hooks.js +1212 -0
  89. package/dist/daemon/routes/hooks.js.map +1 -0
  90. package/dist/daemon/routes/memory.d.ts +4 -0
  91. package/dist/daemon/routes/memory.d.ts.map +1 -0
  92. package/dist/daemon/routes/memory.js +71 -0
  93. package/dist/daemon/routes/memory.js.map +1 -0
  94. package/dist/daemon/routes/reflection.d.ts +10 -0
  95. package/dist/daemon/routes/reflection.d.ts.map +1 -0
  96. package/dist/daemon/routes/reflection.js +397 -0
  97. package/dist/daemon/routes/reflection.js.map +1 -0
  98. package/dist/daemon/routes/search.d.ts +5 -0
  99. package/dist/daemon/routes/search.d.ts.map +1 -0
  100. package/dist/daemon/routes/search.js +93 -0
  101. package/dist/daemon/routes/search.js.map +1 -0
  102. package/dist/daemon/routes/sessions.d.ts +3 -0
  103. package/dist/daemon/routes/sessions.d.ts.map +1 -0
  104. package/dist/daemon/routes/sessions.js +160 -0
  105. package/dist/daemon/routes/sessions.js.map +1 -0
  106. package/dist/daemon/routes/skills.d.ts +3 -0
  107. package/dist/daemon/routes/skills.d.ts.map +1 -0
  108. package/dist/daemon/routes/skills.js +36 -0
  109. package/dist/daemon/routes/skills.js.map +1 -0
  110. package/dist/daemon/routes/status.d.ts +3 -0
  111. package/dist/daemon/routes/status.d.ts.map +1 -0
  112. package/dist/daemon/routes/status.js +47 -0
  113. package/dist/daemon/routes/status.js.map +1 -0
  114. package/dist/daemon/routes/types.d.ts +240 -0
  115. package/dist/daemon/routes/types.d.ts.map +1 -0
  116. package/dist/daemon/routes/types.js +97 -0
  117. package/dist/daemon/routes/types.js.map +1 -0
  118. package/dist/daemon/routes/versioning.d.ts +27 -0
  119. package/dist/daemon/routes/versioning.d.ts.map +1 -0
  120. package/dist/daemon/routes/versioning.js +44 -0
  121. package/dist/daemon/routes/versioning.js.map +1 -0
  122. package/dist/daemon/routes/watcher.d.ts +3 -0
  123. package/dist/daemon/routes/watcher.d.ts.map +1 -0
  124. package/dist/daemon/routes/watcher.js +28 -0
  125. package/dist/daemon/routes/watcher.js.map +1 -0
  126. package/dist/daemon/service.d.ts +5 -23
  127. package/dist/daemon/service.d.ts.map +1 -1
  128. package/dist/daemon/service.js +201 -933
  129. package/dist/daemon/service.js.map +1 -1
  130. package/dist/daemon/session-processor.d.ts +4 -8
  131. package/dist/daemon/session-processor.d.ts.map +1 -1
  132. package/dist/daemon/session-processor.js +39 -38
  133. package/dist/daemon/session-processor.js.map +1 -1
  134. package/dist/lib/ai-readiness.d.ts.map +1 -1
  135. package/dist/lib/ai-readiness.js +33 -8
  136. package/dist/lib/ai-readiness.js.map +1 -1
  137. package/dist/lib/analyze-state.d.ts.map +1 -1
  138. package/dist/lib/analyze-state.js +25 -3
  139. package/dist/lib/analyze-state.js.map +1 -1
  140. package/dist/lib/auto-memory/consolidation.d.ts +41 -0
  141. package/dist/lib/auto-memory/consolidation.d.ts.map +1 -0
  142. package/dist/lib/auto-memory/consolidation.js +151 -0
  143. package/dist/lib/auto-memory/consolidation.js.map +1 -0
  144. package/dist/lib/bpe.d.ts.map +1 -1
  145. package/dist/lib/bpe.js +9 -10
  146. package/dist/lib/bpe.js.map +1 -1
  147. package/dist/lib/brain-export.d.ts +65 -0
  148. package/dist/lib/brain-export.d.ts.map +1 -0
  149. package/dist/lib/brain-export.js +413 -0
  150. package/dist/lib/brain-export.js.map +1 -0
  151. package/dist/lib/checkpoint.d.ts.map +1 -1
  152. package/dist/lib/checkpoint.js +22 -6
  153. package/dist/lib/checkpoint.js.map +1 -1
  154. package/dist/lib/chunker.d.ts.map +1 -1
  155. package/dist/lib/chunker.js +6 -1
  156. package/dist/lib/chunker.js.map +1 -1
  157. package/dist/lib/claude-ws-transport.d.ts.map +1 -1
  158. package/dist/lib/claude-ws-transport.js +12 -4
  159. package/dist/lib/claude-ws-transport.js.map +1 -1
  160. package/dist/lib/command-safety.d.ts +64 -0
  161. package/dist/lib/command-safety.d.ts.map +1 -0
  162. package/dist/lib/command-safety.js +625 -0
  163. package/dist/lib/command-safety.js.map +1 -0
  164. package/dist/lib/compact-briefing.d.ts.map +1 -1
  165. package/dist/lib/compact-briefing.js +10 -13
  166. package/dist/lib/compact-briefing.js.map +1 -1
  167. package/dist/lib/config-defaults.d.ts.map +1 -1
  168. package/dist/lib/config-defaults.js +3 -0
  169. package/dist/lib/config-defaults.js.map +1 -1
  170. package/dist/lib/config-display.d.ts +4 -0
  171. package/dist/lib/config-display.d.ts.map +1 -1
  172. package/dist/lib/config-display.js +6 -1
  173. package/dist/lib/config-display.js.map +1 -1
  174. package/dist/lib/config-types.d.ts +156 -0
  175. package/dist/lib/config-types.d.ts.map +1 -1
  176. package/dist/lib/config-validation.d.ts.map +1 -1
  177. package/dist/lib/config-validation.js +5 -0
  178. package/dist/lib/config-validation.js.map +1 -1
  179. package/dist/lib/config.d.ts.map +1 -1
  180. package/dist/lib/config.js +92 -9
  181. package/dist/lib/config.js.map +1 -1
  182. package/dist/lib/consolidate.d.ts.map +1 -1
  183. package/dist/lib/consolidate.js +66 -47
  184. package/dist/lib/consolidate.js.map +1 -1
  185. package/dist/lib/content-sanitizer.d.ts +29 -0
  186. package/dist/lib/content-sanitizer.d.ts.map +1 -0
  187. package/dist/lib/content-sanitizer.js +72 -0
  188. package/dist/lib/content-sanitizer.js.map +1 -0
  189. package/dist/lib/cross-repo.d.ts +44 -0
  190. package/dist/lib/cross-repo.d.ts.map +1 -0
  191. package/dist/lib/cross-repo.js +108 -0
  192. package/dist/lib/cross-repo.js.map +1 -0
  193. package/dist/lib/daemon-port.d.ts +12 -0
  194. package/dist/lib/daemon-port.d.ts.map +1 -0
  195. package/dist/lib/daemon-port.js +20 -0
  196. package/dist/lib/daemon-port.js.map +1 -0
  197. package/dist/lib/db/auto-memory.d.ts +40 -0
  198. package/dist/lib/db/auto-memory.d.ts.map +1 -0
  199. package/dist/lib/db/auto-memory.js +74 -0
  200. package/dist/lib/db/auto-memory.js.map +1 -0
  201. package/dist/lib/db/bm25-indexes.d.ts.map +1 -1
  202. package/dist/lib/db/bm25-indexes.js +16 -4
  203. package/dist/lib/db/bm25-indexes.js.map +1 -1
  204. package/dist/lib/db/documents.d.ts.map +1 -1
  205. package/dist/lib/db/documents.js +4 -1
  206. package/dist/lib/db/documents.js.map +1 -1
  207. package/dist/lib/db/global-memories.d.ts +2 -10
  208. package/dist/lib/db/global-memories.d.ts.map +1 -1
  209. package/dist/lib/db/global-memories.js +13 -6
  210. package/dist/lib/db/global-memories.js.map +1 -1
  211. package/dist/lib/db/graph.d.ts +5 -1
  212. package/dist/lib/db/graph.d.ts.map +1 -1
  213. package/dist/lib/db/graph.js +38 -8
  214. package/dist/lib/db/graph.js.map +1 -1
  215. package/dist/lib/db/hybrid-search.d.ts +4 -2
  216. package/dist/lib/db/hybrid-search.d.ts.map +1 -1
  217. package/dist/lib/db/hybrid-search.js +29 -11
  218. package/dist/lib/db/hybrid-search.js.map +1 -1
  219. package/dist/lib/db/index.d.ts +6 -1
  220. package/dist/lib/db/index.d.ts.map +1 -1
  221. package/dist/lib/db/index.js +5 -1
  222. package/dist/lib/db/index.js.map +1 -1
  223. package/dist/lib/db/memories.d.ts +19 -14
  224. package/dist/lib/db/memories.d.ts.map +1 -1
  225. package/dist/lib/db/memories.js +100 -37
  226. package/dist/lib/db/memories.js.map +1 -1
  227. package/dist/lib/db/parse-helpers.d.ts +14 -0
  228. package/dist/lib/db/parse-helpers.d.ts.map +1 -0
  229. package/dist/lib/db/parse-helpers.js +59 -0
  230. package/dist/lib/db/parse-helpers.js.map +1 -0
  231. package/dist/lib/db/recall-events.d.ts +49 -0
  232. package/dist/lib/db/recall-events.d.ts.map +1 -0
  233. package/dist/lib/db/recall-events.js +196 -0
  234. package/dist/lib/db/recall-events.js.map +1 -0
  235. package/dist/lib/db/retention.d.ts +4 -3
  236. package/dist/lib/db/retention.d.ts.map +1 -1
  237. package/dist/lib/db/retention.js +12 -1
  238. package/dist/lib/db/retention.js.map +1 -1
  239. package/dist/lib/db/schema.d.ts +2 -0
  240. package/dist/lib/db/schema.d.ts.map +1 -1
  241. package/dist/lib/db/schema.js +140 -80
  242. package/dist/lib/db/schema.js.map +1 -1
  243. package/dist/lib/db/skills.d.ts.map +1 -1
  244. package/dist/lib/db/skills.js +10 -6
  245. package/dist/lib/db/skills.js.map +1 -1
  246. package/dist/lib/diff-brain.d.ts +24 -0
  247. package/dist/lib/diff-brain.d.ts.map +1 -0
  248. package/dist/lib/diff-brain.js +114 -0
  249. package/dist/lib/diff-brain.js.map +1 -0
  250. package/dist/lib/diff-parser.d.ts +74 -0
  251. package/dist/lib/diff-parser.d.ts.map +1 -0
  252. package/dist/lib/diff-parser.js +200 -0
  253. package/dist/lib/diff-parser.js.map +1 -0
  254. package/dist/lib/embedding-pool.d.ts.map +1 -1
  255. package/dist/lib/embedding-pool.js +5 -1
  256. package/dist/lib/embedding-pool.js.map +1 -1
  257. package/dist/lib/embeddings.d.ts +12 -0
  258. package/dist/lib/embeddings.d.ts.map +1 -1
  259. package/dist/lib/embeddings.js +77 -19
  260. package/dist/lib/embeddings.js.map +1 -1
  261. package/dist/lib/errors.d.ts +2 -0
  262. package/dist/lib/errors.d.ts.map +1 -1
  263. package/dist/lib/errors.js +4 -0
  264. package/dist/lib/errors.js.map +1 -1
  265. package/dist/lib/fault-logger.d.ts.map +1 -1
  266. package/dist/lib/fault-logger.js +22 -7
  267. package/dist/lib/fault-logger.js.map +1 -1
  268. package/dist/lib/git/co-change.d.ts +39 -0
  269. package/dist/lib/git/co-change.d.ts.map +1 -0
  270. package/dist/lib/git/co-change.js +139 -0
  271. package/dist/lib/git/co-change.js.map +1 -0
  272. package/dist/lib/graph/bridge-edges.d.ts +93 -0
  273. package/dist/lib/graph/bridge-edges.d.ts.map +1 -0
  274. package/dist/lib/graph/bridge-edges.js +276 -0
  275. package/dist/lib/graph/bridge-edges.js.map +1 -0
  276. package/dist/lib/graph/centrality.d.ts +11 -0
  277. package/dist/lib/graph/centrality.d.ts.map +1 -1
  278. package/dist/lib/graph/centrality.js +51 -3
  279. package/dist/lib/graph/centrality.js.map +1 -1
  280. package/dist/lib/graph/cleanup.d.ts.map +1 -1
  281. package/dist/lib/graph/cleanup.js +2 -1
  282. package/dist/lib/graph/cleanup.js.map +1 -1
  283. package/dist/lib/graph/community-detection.d.ts +17 -2
  284. package/dist/lib/graph/community-detection.d.ts.map +1 -1
  285. package/dist/lib/graph/community-detection.js +147 -48
  286. package/dist/lib/graph/community-detection.js.map +1 -1
  287. package/dist/lib/graph/community-summaries.d.ts +26 -0
  288. package/dist/lib/graph/community-summaries.d.ts.map +1 -0
  289. package/dist/lib/graph/community-summaries.js +130 -0
  290. package/dist/lib/graph/community-summaries.js.map +1 -0
  291. package/dist/lib/graph/contextual-proximity.d.ts.map +1 -1
  292. package/dist/lib/graph/contextual-proximity.js +11 -4
  293. package/dist/lib/graph/contextual-proximity.js.map +1 -1
  294. package/dist/lib/graph/graphology-bridge.d.ts +101 -0
  295. package/dist/lib/graph/graphology-bridge.d.ts.map +1 -0
  296. package/dist/lib/graph/graphology-bridge.js +488 -0
  297. package/dist/lib/graph/graphology-bridge.js.map +1 -0
  298. package/dist/lib/graph/llm-relations.d.ts.map +1 -1
  299. package/dist/lib/graph/llm-relations.js +27 -5
  300. package/dist/lib/graph/llm-relations.js.map +1 -1
  301. package/dist/lib/graph-export.d.ts.map +1 -1
  302. package/dist/lib/graph-export.js +2 -2
  303. package/dist/lib/graph-export.js.map +1 -1
  304. package/dist/lib/graph-scheduler.d.ts +0 -5
  305. package/dist/lib/graph-scheduler.d.ts.map +1 -1
  306. package/dist/lib/graph-scheduler.js +5 -1
  307. package/dist/lib/graph-scheduler.js.map +1 -1
  308. package/dist/lib/guardrails.d.ts +50 -0
  309. package/dist/lib/guardrails.d.ts.map +1 -0
  310. package/dist/lib/guardrails.js +502 -0
  311. package/dist/lib/guardrails.js.map +1 -0
  312. package/dist/lib/hook-rules.d.ts +1 -1
  313. package/dist/lib/hook-rules.d.ts.map +1 -1
  314. package/dist/lib/hook-rules.js +8 -2
  315. package/dist/lib/hook-rules.js.map +1 -1
  316. package/dist/lib/ifc/file-labels.d.ts +35 -0
  317. package/dist/lib/ifc/file-labels.d.ts.map +1 -0
  318. package/dist/lib/ifc/file-labels.js +208 -0
  319. package/dist/lib/ifc/file-labels.js.map +1 -0
  320. package/dist/lib/ifc/label.d.ts +38 -0
  321. package/dist/lib/ifc/label.d.ts.map +1 -0
  322. package/dist/lib/ifc/label.js +80 -0
  323. package/dist/lib/ifc/label.js.map +1 -0
  324. package/dist/lib/ifc/session-ifc.d.ts +92 -0
  325. package/dist/lib/ifc/session-ifc.d.ts.map +1 -0
  326. package/dist/lib/ifc/session-ifc.js +222 -0
  327. package/dist/lib/ifc/session-ifc.js.map +1 -0
  328. package/dist/lib/indexer.js +2 -2
  329. package/dist/lib/indexer.js.map +1 -1
  330. package/dist/lib/injection-detector.d.ts +83 -0
  331. package/dist/lib/injection-detector.d.ts.map +1 -0
  332. package/dist/lib/injection-detector.js +586 -0
  333. package/dist/lib/injection-detector.js.map +1 -0
  334. package/dist/lib/injection-semantic.d.ts +31 -0
  335. package/dist/lib/injection-semantic.d.ts.map +1 -0
  336. package/dist/lib/injection-semantic.js +230 -0
  337. package/dist/lib/injection-semantic.js.map +1 -0
  338. package/dist/lib/llm.d.ts.map +1 -1
  339. package/dist/lib/llm.js +19 -4
  340. package/dist/lib/llm.js.map +1 -1
  341. package/dist/lib/lock.d.ts.map +1 -1
  342. package/dist/lib/lock.js +24 -3
  343. package/dist/lib/lock.js.map +1 -1
  344. package/dist/lib/md-fetch.d.ts.map +1 -1
  345. package/dist/lib/md-fetch.js +9 -2
  346. package/dist/lib/md-fetch.js.map +1 -1
  347. package/dist/lib/observability.d.ts +75 -0
  348. package/dist/lib/observability.d.ts.map +1 -0
  349. package/dist/lib/observability.js +201 -0
  350. package/dist/lib/observability.js.map +1 -0
  351. package/dist/lib/ort-session.d.ts +26 -0
  352. package/dist/lib/ort-session.d.ts.map +1 -1
  353. package/dist/lib/ort-session.js +107 -3
  354. package/dist/lib/ort-session.js.map +1 -1
  355. package/dist/lib/prd/codebase-context.d.ts.map +1 -1
  356. package/dist/lib/prd/codebase-context.js +9 -2
  357. package/dist/lib/prd/codebase-context.js.map +1 -1
  358. package/dist/lib/prd/context.d.ts.map +1 -1
  359. package/dist/lib/prd/context.js +11 -3
  360. package/dist/lib/prd/context.js.map +1 -1
  361. package/dist/lib/prd/export.js +1 -1
  362. package/dist/lib/prd/export.js.map +1 -1
  363. package/dist/lib/prd/generate.d.ts.map +1 -1
  364. package/dist/lib/prd/generate.js +17 -4
  365. package/dist/lib/prd/generate.js.map +1 -1
  366. package/dist/lib/prd/parse.d.ts.map +1 -1
  367. package/dist/lib/prd/parse.js +6 -1
  368. package/dist/lib/prd/parse.js.map +1 -1
  369. package/dist/lib/prd/runner.d.ts +1 -2
  370. package/dist/lib/prd/runner.d.ts.map +1 -1
  371. package/dist/lib/prd/runner.js +43 -32
  372. package/dist/lib/prd/runner.js.map +1 -1
  373. package/dist/lib/prd/worktree.d.ts +1 -2
  374. package/dist/lib/prd/worktree.d.ts.map +1 -1
  375. package/dist/lib/prd/worktree.js +62 -70
  376. package/dist/lib/prd/worktree.js.map +1 -1
  377. package/dist/lib/precompute-context.d.ts.map +1 -1
  378. package/dist/lib/precompute-context.js +15 -34
  379. package/dist/lib/precompute-context.js.map +1 -1
  380. package/dist/lib/pricing.d.ts.map +1 -1
  381. package/dist/lib/pricing.js +5 -1
  382. package/dist/lib/pricing.js.map +1 -1
  383. package/dist/lib/process-registry.js +3 -3
  384. package/dist/lib/process-registry.js.map +1 -1
  385. package/dist/lib/public-api.d.ts +41 -1
  386. package/dist/lib/public-api.d.ts.map +1 -1
  387. package/dist/lib/public-api.js +38 -0
  388. package/dist/lib/public-api.js.map +1 -1
  389. package/dist/lib/quality.d.ts.map +1 -1
  390. package/dist/lib/quality.js +15 -6
  391. package/dist/lib/quality.js.map +1 -1
  392. package/dist/lib/query-expansion.d.ts +32 -0
  393. package/dist/lib/query-expansion.d.ts.map +1 -1
  394. package/dist/lib/query-expansion.js +62 -1
  395. package/dist/lib/query-expansion.js.map +1 -1
  396. package/dist/lib/reference-embeddings.d.ts.map +1 -1
  397. package/dist/lib/reference-embeddings.js +17 -4
  398. package/dist/lib/reference-embeddings.js.map +1 -1
  399. package/dist/lib/reflection-synthesizer.d.ts.map +1 -1
  400. package/dist/lib/reflection-synthesizer.js +7 -1
  401. package/dist/lib/reflection-synthesizer.js.map +1 -1
  402. package/dist/lib/reranker.d.ts +41 -0
  403. package/dist/lib/reranker.d.ts.map +1 -0
  404. package/dist/lib/reranker.js +294 -0
  405. package/dist/lib/reranker.js.map +1 -0
  406. package/dist/lib/retrieval-feedback.d.ts +100 -0
  407. package/dist/lib/retrieval-feedback.d.ts.map +1 -0
  408. package/dist/lib/retrieval-feedback.js +174 -0
  409. package/dist/lib/retrieval-feedback.js.map +1 -0
  410. package/dist/lib/review/context-pack.d.ts +58 -0
  411. package/dist/lib/review/context-pack.d.ts.map +1 -0
  412. package/dist/lib/review/context-pack.js +300 -0
  413. package/dist/lib/review/context-pack.js.map +1 -0
  414. package/dist/lib/search/hierarchical-summaries.d.ts +65 -0
  415. package/dist/lib/search/hierarchical-summaries.d.ts.map +1 -0
  416. package/dist/lib/search/hierarchical-summaries.js +423 -0
  417. package/dist/lib/search/hierarchical-summaries.js.map +1 -0
  418. package/dist/lib/search/hyde.d.ts +27 -0
  419. package/dist/lib/search/hyde.d.ts.map +1 -0
  420. package/dist/lib/search/hyde.js +141 -0
  421. package/dist/lib/search/hyde.js.map +1 -0
  422. package/dist/lib/search/late-chunking.d.ts +53 -0
  423. package/dist/lib/search/late-chunking.d.ts.map +1 -0
  424. package/dist/lib/search/late-chunking.js +230 -0
  425. package/dist/lib/search/late-chunking.js.map +1 -0
  426. package/dist/lib/search/ppr-retrieval.d.ts +49 -0
  427. package/dist/lib/search/ppr-retrieval.d.ts.map +1 -0
  428. package/dist/lib/search/ppr-retrieval.js +135 -0
  429. package/dist/lib/search/ppr-retrieval.js.map +1 -0
  430. package/dist/lib/search/repo-map.d.ts +43 -0
  431. package/dist/lib/search/repo-map.d.ts.map +1 -0
  432. package/dist/lib/search/repo-map.js +165 -0
  433. package/dist/lib/search/repo-map.js.map +1 -0
  434. package/dist/lib/session-analyzer.d.ts +90 -0
  435. package/dist/lib/session-analyzer.d.ts.map +1 -0
  436. package/dist/lib/session-analyzer.js +467 -0
  437. package/dist/lib/session-analyzer.js.map +1 -0
  438. package/dist/lib/session-observations.d.ts.map +1 -1
  439. package/dist/lib/session-observations.js +13 -3
  440. package/dist/lib/session-observations.js.map +1 -1
  441. package/dist/lib/session-summary.d.ts.map +1 -1
  442. package/dist/lib/session-summary.js +57 -50
  443. package/dist/lib/session-summary.js.map +1 -1
  444. package/dist/lib/session-surgeon.d.ts +53 -0
  445. package/dist/lib/session-surgeon.d.ts.map +1 -0
  446. package/dist/lib/session-surgeon.js +501 -0
  447. package/dist/lib/session-surgeon.js.map +1 -0
  448. package/dist/lib/similarity-utils.d.ts +26 -0
  449. package/dist/lib/similarity-utils.d.ts.map +1 -0
  450. package/dist/lib/similarity-utils.js +66 -0
  451. package/dist/lib/similarity-utils.js.map +1 -0
  452. package/dist/lib/skills.d.ts.map +1 -1
  453. package/dist/lib/skills.js +11 -11
  454. package/dist/lib/skills.js.map +1 -1
  455. package/dist/lib/storage/backends/interface.d.ts +13 -3
  456. package/dist/lib/storage/backends/interface.d.ts.map +1 -1
  457. package/dist/lib/storage/backends/postgresql.d.ts +52 -3
  458. package/dist/lib/storage/backends/postgresql.d.ts.map +1 -1
  459. package/dist/lib/storage/backends/postgresql.js +694 -49
  460. package/dist/lib/storage/backends/postgresql.js.map +1 -1
  461. package/dist/lib/storage/benchmark.js +2 -2
  462. package/dist/lib/storage/benchmark.js.map +1 -1
  463. package/dist/lib/storage/dispatcher/base.d.ts +114 -0
  464. package/dist/lib/storage/dispatcher/base.d.ts.map +1 -0
  465. package/dist/lib/storage/dispatcher/base.js +160 -0
  466. package/dist/lib/storage/dispatcher/base.js.map +1 -0
  467. package/dist/lib/storage/dispatcher/documents.d.ts +25 -0
  468. package/dist/lib/storage/dispatcher/documents.d.ts.map +1 -0
  469. package/dist/lib/storage/dispatcher/documents.js +194 -0
  470. package/dist/lib/storage/dispatcher/documents.js.map +1 -0
  471. package/dist/lib/storage/dispatcher/embeddings.d.ts +34 -0
  472. package/dist/lib/storage/dispatcher/embeddings.d.ts.map +1 -0
  473. package/dist/lib/storage/dispatcher/embeddings.js +144 -0
  474. package/dist/lib/storage/dispatcher/embeddings.js.map +1 -0
  475. package/dist/lib/storage/dispatcher/export-import.d.ts +139 -0
  476. package/dist/lib/storage/dispatcher/export-import.d.ts.map +1 -0
  477. package/dist/lib/storage/dispatcher/export-import.js +191 -0
  478. package/dist/lib/storage/dispatcher/export-import.js.map +1 -0
  479. package/dist/lib/storage/dispatcher/file-hashes.d.ts +13 -0
  480. package/dist/lib/storage/dispatcher/file-hashes.d.ts.map +1 -0
  481. package/dist/lib/storage/dispatcher/file-hashes.js +36 -0
  482. package/dist/lib/storage/dispatcher/file-hashes.js.map +1 -0
  483. package/dist/lib/storage/dispatcher/global-memories.d.ts +28 -0
  484. package/dist/lib/storage/dispatcher/global-memories.d.ts.map +1 -0
  485. package/dist/lib/storage/dispatcher/global-memories.js +151 -0
  486. package/dist/lib/storage/dispatcher/global-memories.js.map +1 -0
  487. package/dist/lib/storage/dispatcher/graph.d.ts +32 -0
  488. package/dist/lib/storage/dispatcher/graph.d.ts.map +1 -0
  489. package/dist/lib/storage/dispatcher/graph.js +146 -0
  490. package/dist/lib/storage/dispatcher/graph.js.map +1 -0
  491. package/dist/lib/storage/dispatcher/index.d.ts +34 -0
  492. package/dist/lib/storage/dispatcher/index.d.ts.map +1 -0
  493. package/dist/lib/storage/dispatcher/index.js +139 -0
  494. package/dist/lib/storage/dispatcher/index.js.map +1 -0
  495. package/dist/lib/storage/dispatcher/memories.d.ts +65 -0
  496. package/dist/lib/storage/dispatcher/memories.d.ts.map +1 -0
  497. package/dist/lib/storage/dispatcher/memories.js +466 -0
  498. package/dist/lib/storage/dispatcher/memories.js.map +1 -0
  499. package/dist/lib/storage/dispatcher/mixin-helper.d.ts +6 -0
  500. package/dist/lib/storage/dispatcher/mixin-helper.d.ts.map +1 -0
  501. package/dist/lib/storage/dispatcher/mixin-helper.js +10 -0
  502. package/dist/lib/storage/dispatcher/mixin-helper.js.map +1 -0
  503. package/dist/lib/storage/dispatcher/retention.d.ts +20 -0
  504. package/dist/lib/storage/dispatcher/retention.d.ts.map +1 -0
  505. package/dist/lib/storage/dispatcher/retention.js +123 -0
  506. package/dist/lib/storage/dispatcher/retention.js.map +1 -0
  507. package/dist/lib/storage/dispatcher/search.d.ts +34 -0
  508. package/dist/lib/storage/dispatcher/search.d.ts.map +1 -0
  509. package/dist/lib/storage/dispatcher/search.js +222 -0
  510. package/dist/lib/storage/dispatcher/search.js.map +1 -0
  511. package/dist/lib/storage/dispatcher/skills.d.ts +53 -0
  512. package/dist/lib/storage/dispatcher/skills.d.ts.map +1 -0
  513. package/dist/lib/storage/dispatcher/skills.js +98 -0
  514. package/dist/lib/storage/dispatcher/skills.js.map +1 -0
  515. package/dist/lib/storage/dispatcher/token-stats.d.ts +23 -0
  516. package/dist/lib/storage/dispatcher/token-stats.d.ts.map +1 -0
  517. package/dist/lib/storage/dispatcher/token-stats.js +92 -0
  518. package/dist/lib/storage/dispatcher/token-stats.js.map +1 -0
  519. package/dist/lib/storage/dispatcher/web-search.d.ts +10 -0
  520. package/dist/lib/storage/dispatcher/web-search.d.ts.map +1 -0
  521. package/dist/lib/storage/dispatcher/web-search.js +39 -0
  522. package/dist/lib/storage/dispatcher/web-search.js.map +1 -0
  523. package/dist/lib/storage/dispatcher-export.d.ts.map +1 -1
  524. package/dist/lib/storage/dispatcher-export.js +48 -39
  525. package/dist/lib/storage/dispatcher-export.js.map +1 -1
  526. package/dist/lib/storage/dispatcher.d.ts +1 -468
  527. package/dist/lib/storage/dispatcher.d.ts.map +1 -1
  528. package/dist/lib/storage/dispatcher.js +1 -1931
  529. package/dist/lib/storage/dispatcher.js.map +1 -1
  530. package/dist/lib/storage/index.d.ts +20 -5
  531. package/dist/lib/storage/index.d.ts.map +1 -1
  532. package/dist/lib/storage/index.js +36 -7
  533. package/dist/lib/storage/index.js.map +1 -1
  534. package/dist/lib/storage/migration/export-import.d.ts.map +1 -1
  535. package/dist/lib/storage/migration/export-import.js +9 -2
  536. package/dist/lib/storage/migration/export-import.js.map +1 -1
  537. package/dist/lib/storage/types.d.ts +152 -10
  538. package/dist/lib/storage/types.d.ts.map +1 -1
  539. package/dist/lib/storage/types.js +13 -0
  540. package/dist/lib/storage/types.js.map +1 -1
  541. package/dist/lib/storage/vector/interface.d.ts +4 -0
  542. package/dist/lib/storage/vector/interface.d.ts.map +1 -1
  543. package/dist/lib/storage/vector/qdrant.d.ts +13 -2
  544. package/dist/lib/storage/vector/qdrant.d.ts.map +1 -1
  545. package/dist/lib/storage/vector/qdrant.js +147 -61
  546. package/dist/lib/storage/vector/qdrant.js.map +1 -1
  547. package/dist/lib/token-budget.d.ts.map +1 -1
  548. package/dist/lib/token-budget.js +9 -2
  549. package/dist/lib/token-budget.js.map +1 -1
  550. package/dist/lib/transcript-utils.d.ts +60 -0
  551. package/dist/lib/transcript-utils.d.ts.map +1 -0
  552. package/dist/lib/transcript-utils.js +69 -0
  553. package/dist/lib/transcript-utils.js.map +1 -0
  554. package/dist/lib/tree-sitter/extractor.d.ts +1 -1
  555. package/dist/lib/tree-sitter/extractor.d.ts.map +1 -1
  556. package/dist/lib/tree-sitter/extractor.js +34 -9
  557. package/dist/lib/tree-sitter/extractor.js.map +1 -1
  558. package/dist/lib/tree-sitter/parser.d.ts.map +1 -1
  559. package/dist/lib/tree-sitter/parser.js +45 -11
  560. package/dist/lib/tree-sitter/parser.js.map +1 -1
  561. package/dist/lib/tree-sitter/public.d.ts +12 -0
  562. package/dist/lib/tree-sitter/public.d.ts.map +1 -1
  563. package/dist/lib/tree-sitter/public.js +33 -1
  564. package/dist/lib/tree-sitter/public.js.map +1 -1
  565. package/dist/lib/tree-sitter/queries.d.ts.map +1 -1
  566. package/dist/lib/tree-sitter/queries.js +8 -0
  567. package/dist/lib/tree-sitter/queries.js.map +1 -1
  568. package/dist/lib/version-check.d.ts +29 -0
  569. package/dist/lib/version-check.d.ts.map +1 -0
  570. package/dist/lib/version-check.js +187 -0
  571. package/dist/lib/version-check.js.map +1 -0
  572. package/dist/lib/working-memory-pipeline.d.ts.map +1 -1
  573. package/dist/lib/working-memory-pipeline.js +12 -3
  574. package/dist/lib/working-memory-pipeline.js.map +1 -1
  575. package/dist/lib/worktree-detect.d.ts +43 -0
  576. package/dist/lib/worktree-detect.d.ts.map +1 -0
  577. package/dist/lib/worktree-detect.js +154 -0
  578. package/dist/lib/worktree-detect.js.map +1 -0
  579. package/dist/lsp/client.d.ts +96 -0
  580. package/dist/lsp/client.d.ts.map +1 -0
  581. package/dist/lsp/client.js +435 -0
  582. package/dist/lsp/client.js.map +1 -0
  583. package/dist/lsp/installer.d.ts +39 -0
  584. package/dist/lsp/installer.d.ts.map +1 -0
  585. package/dist/lsp/installer.js +275 -0
  586. package/dist/lsp/installer.js.map +1 -0
  587. package/dist/lsp/manager.d.ts +62 -0
  588. package/dist/lsp/manager.d.ts.map +1 -0
  589. package/dist/lsp/manager.js +234 -0
  590. package/dist/lsp/manager.js.map +1 -0
  591. package/dist/lsp/servers.d.ts +52 -0
  592. package/dist/lsp/servers.d.ts.map +1 -0
  593. package/dist/lsp/servers.js +162 -0
  594. package/dist/lsp/servers.js.map +1 -0
  595. package/dist/mcp/helpers.d.ts.map +1 -1
  596. package/dist/mcp/helpers.js +8 -2
  597. package/dist/mcp/helpers.js.map +1 -1
  598. package/dist/mcp/profile.js +1 -1
  599. package/dist/mcp/server.d.ts +3 -2
  600. package/dist/mcp/server.d.ts.map +1 -1
  601. package/dist/mcp/server.js +19 -7
  602. package/dist/mcp/server.js.map +1 -1
  603. package/dist/mcp/tools/config.d.ts.map +1 -1
  604. package/dist/mcp/tools/config.js +28 -118
  605. package/dist/mcp/tools/config.js.map +1 -1
  606. package/dist/mcp/tools/dead-end.d.ts.map +1 -1
  607. package/dist/mcp/tools/dead-end.js +4 -3
  608. package/dist/mcp/tools/dead-end.js.map +1 -1
  609. package/dist/mcp/tools/debug.d.ts.map +1 -1
  610. package/dist/mcp/tools/debug.js +27 -112
  611. package/dist/mcp/tools/debug.js.map +1 -1
  612. package/dist/mcp/tools/graph.d.ts.map +1 -1
  613. package/dist/mcp/tools/graph.js +164 -176
  614. package/dist/mcp/tools/graph.js.map +1 -1
  615. package/dist/mcp/tools/indexing.d.ts +1 -1
  616. package/dist/mcp/tools/indexing.d.ts.map +1 -1
  617. package/dist/mcp/tools/indexing.js +63 -164
  618. package/dist/mcp/tools/indexing.js.map +1 -1
  619. package/dist/mcp/tools/memory/forget.d.ts +3 -0
  620. package/dist/mcp/tools/memory/forget.d.ts.map +1 -0
  621. package/dist/mcp/tools/memory/forget.js +175 -0
  622. package/dist/mcp/tools/memory/forget.js.map +1 -0
  623. package/dist/mcp/tools/memory/memory-helpers.d.ts +45 -0
  624. package/dist/mcp/tools/memory/memory-helpers.d.ts.map +1 -0
  625. package/dist/mcp/tools/memory/memory-helpers.js +291 -0
  626. package/dist/mcp/tools/memory/memory-helpers.js.map +1 -0
  627. package/dist/mcp/tools/memory/recall.d.ts +3 -0
  628. package/dist/mcp/tools/memory/recall.d.ts.map +1 -0
  629. package/dist/mcp/tools/memory/recall.js +495 -0
  630. package/dist/mcp/tools/memory/recall.js.map +1 -0
  631. package/dist/mcp/tools/memory/remember.d.ts +3 -0
  632. package/dist/mcp/tools/memory/remember.d.ts.map +1 -0
  633. package/dist/mcp/tools/memory/remember.js +256 -0
  634. package/dist/mcp/tools/memory/remember.js.map +1 -0
  635. package/dist/mcp/tools/memory/temporal-query.d.ts +8 -0
  636. package/dist/mcp/tools/memory/temporal-query.d.ts.map +1 -0
  637. package/dist/mcp/tools/memory/temporal-query.js +68 -0
  638. package/dist/mcp/tools/memory/temporal-query.js.map +1 -0
  639. package/dist/mcp/tools/memory.d.ts +0 -11
  640. package/dist/mcp/tools/memory.d.ts.map +1 -1
  641. package/dist/mcp/tools/memory.js +6 -1228
  642. package/dist/mcp/tools/memory.js.map +1 -1
  643. package/dist/mcp/tools/prd.d.ts.map +1 -1
  644. package/dist/mcp/tools/prd.js +19 -70
  645. package/dist/mcp/tools/prd.js.map +1 -1
  646. package/dist/mcp/tools/review.d.ts +8 -0
  647. package/dist/mcp/tools/review.d.ts.map +1 -0
  648. package/dist/mcp/tools/review.js +133 -0
  649. package/dist/mcp/tools/review.js.map +1 -0
  650. package/dist/mcp/tools/search.d.ts.map +1 -1
  651. package/dist/mcp/tools/search.js +79 -8
  652. package/dist/mcp/tools/search.js.map +1 -1
  653. package/dist/mcp/tools/status.d.ts.map +1 -1
  654. package/dist/mcp/tools/status.js +50 -75
  655. package/dist/mcp/tools/status.js.map +1 -1
  656. package/dist/mcp/tools/web-fetch.d.ts.map +1 -1
  657. package/dist/mcp/tools/web-fetch.js +5 -1
  658. package/dist/mcp/tools/web-fetch.js.map +1 -1
  659. package/dist/mcp/tools/web-search.d.ts.map +1 -1
  660. package/dist/mcp/tools/web-search.js +25 -103
  661. package/dist/mcp/tools/web-search.js.map +1 -1
  662. package/dist/prompts/guardrails.d.ts +14 -0
  663. package/dist/prompts/guardrails.d.ts.map +1 -0
  664. package/dist/prompts/guardrails.js +115 -0
  665. package/dist/prompts/guardrails.js.map +1 -0
  666. package/dist/prompts/index.d.ts +2 -1
  667. package/dist/prompts/index.d.ts.map +1 -1
  668. package/dist/prompts/index.js +3 -1
  669. package/dist/prompts/index.js.map +1 -1
  670. package/dist/prompts/prd.d.ts +0 -2
  671. package/dist/prompts/prd.d.ts.map +1 -1
  672. package/dist/prompts/prd.js +0 -2
  673. package/dist/prompts/prd.js.map +1 -1
  674. package/hooks/core/__tests__/adapter.test.cjs +340 -0
  675. package/hooks/core/adapter.cjs +463 -0
  676. package/hooks/core/config.cjs +83 -0
  677. package/hooks/core/daemon-boot.cjs +140 -0
  678. package/hooks/core/log.cjs +41 -0
  679. package/hooks/core/worktree.cjs +119 -0
  680. package/hooks/succ-post-tool.cjs +198 -134
  681. package/hooks/succ-pre-compact.cjs +262 -0
  682. package/hooks/succ-pre-tool.cjs +526 -182
  683. package/hooks/succ-session-end.cjs +40 -64
  684. package/hooks/succ-session-start.cjs +528 -427
  685. package/hooks/succ-stop-reflection.cjs +36 -62
  686. package/hooks/succ-user-prompt.cjs +137 -180
  687. package/package.json +17 -6
@@ -2,17 +2,83 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import os from 'os';
4
4
  import { fileURLToPath } from 'url';
5
+ import { execFileSync } from 'child_process';
5
6
  import { select, input, password } from '@inquirer/prompts';
6
7
  import ora from 'ora';
7
8
  import isInstalledGlobally from 'is-installed-globally';
8
- import { getProjectRoot, getSuccDir, isOnboardingCompleted, markOnboardingCompleted, } from '../lib/config.js';
9
+ import { getProjectRoot, getSuccDir, getConfig, isOnboardingCompleted, markOnboardingCompleted, } from '../lib/config.js';
9
10
  import { runStaticWizard, runAiOnboarding } from '../lib/onboarding/index.js';
10
11
  import { logWarn } from '../lib/fault-logger.js';
11
12
  import { getSoulTemplate, getLearningsTemplate, getContextRulesTemplate, getInboxMocTemplate, getProjectMocTemplate, getDecisionsMocTemplate, getFeaturesMocTemplate, getFilesMocTemplate, getTechnicalMocTemplate, getSystemsMocTemplate, getStrategyMocTemplate, getSessionsMocTemplate, getKnowledgeMocTemplate, getArchiveMocTemplate, getPrdMocTemplate, getCommunicationMocTemplate, } from './init-templates.js';
13
+ import { getStablePort } from '../lib/daemon-port.js';
12
14
  // Get the directory where succ is installed
13
15
  const __filename = fileURLToPath(import.meta.url);
14
16
  const __dirname = path.dirname(__filename);
15
17
  const SUCC_PACKAGE_DIR = path.resolve(__dirname, '..', '..');
18
+ /** Check if a URL points to a known cloud LLM provider */
19
+ function isCloudProvider(url) {
20
+ try {
21
+ const hostname = new URL(url).hostname;
22
+ return (hostname === 'openrouter.ai' ||
23
+ hostname.endsWith('.openrouter.ai') ||
24
+ hostname === 'openai.com' ||
25
+ hostname.endsWith('.openai.com'));
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ /** Detect Claude Code CLI version. Returns null if not installed. */
32
+ function getClaudeCodeVersion() {
33
+ try {
34
+ const stdout = execFileSync('claude', ['--version'], {
35
+ timeout: 5000,
36
+ stdio: ['pipe', 'pipe', 'pipe'],
37
+ encoding: 'utf8',
38
+ });
39
+ const match = stdout.match(/(\d+\.\d+\.\d+)/);
40
+ return match ? match[1] : null;
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ /** Check if version supports HTTP hooks (v2.1.63+) */
47
+ function supportsHttpHooks(version) {
48
+ if (!version)
49
+ return false;
50
+ const parts = version.split('.').map(Number);
51
+ if (parts.length < 3)
52
+ return false;
53
+ const [major, minor, patch] = parts;
54
+ if (major > 2)
55
+ return true;
56
+ if (major === 2 && minor > 1)
57
+ return true;
58
+ if (major === 2 && minor === 1 && patch >= 63)
59
+ return true;
60
+ return false;
61
+ }
62
+ /** Check if a hook entry belongs to succ (command or HTTP) */
63
+ function isSuccHook(h) {
64
+ const hooks = h.hooks;
65
+ if (!hooks || hooks.length === 0)
66
+ return false;
67
+ const hook = hooks[0];
68
+ const cmd = hook.command || '';
69
+ const url = hook.url || '';
70
+ // Command hooks
71
+ if (cmd.includes('.succ/hooks/') ||
72
+ cmd.includes('/hooks/succ-') ||
73
+ cmd.includes('\\hooks\\succ-'))
74
+ return true;
75
+ if (/succ-(session|stop|user|post|pre)-/.test(cmd))
76
+ return true;
77
+ // HTTP hooks
78
+ if (url.includes('/api/hooks/'))
79
+ return true;
80
+ return false;
81
+ }
16
82
  export async function init(options = {}) {
17
83
  const projectRoot = getProjectRoot();
18
84
  const succDir = getSuccDir();
@@ -21,11 +87,6 @@ export async function init(options = {}) {
21
87
  // Determine if running in global mode
22
88
  // --global flag forces global mode (for testing), otherwise auto-detect
23
89
  const useGlobalHooks = options.global || isInstalledGlobally;
24
- // Check if already initialized
25
- if (fs.existsSync(path.join(succDir, 'succ.db')) && !options.force) {
26
- console.log('succ is already initialized. Use --force to reinitialize.');
27
- return;
28
- }
29
90
  // Create directories - flat brain vault structure (no numbered prefixes)
30
91
  const projectName = path.basename(projectRoot);
31
92
  const dirs = [
@@ -153,30 +214,46 @@ export async function init(options = {}) {
153
214
  'succ-user-prompt.cjs',
154
215
  'succ-post-tool.cjs',
155
216
  'succ-pre-tool.cjs',
217
+ 'succ-pre-compact.cjs',
156
218
  ];
157
219
  for (const hookFile of hooksToCreate) {
158
220
  const destPath = path.join(succDir, 'hooks', hookFile);
159
221
  const srcPath = path.join(SUCC_PACKAGE_DIR, 'hooks', hookFile);
160
- if (!fs.existsSync(destPath) || options.force) {
161
- // Try to copy from package hooks/ directory (source of truth)
162
- if (fs.existsSync(srcPath)) {
163
- fs.copyFileSync(srcPath, destPath);
164
- log(options.force && fs.existsSync(destPath)
165
- ? `Updated hooks/${hookFile}`
166
- : `Created hooks/${hookFile}`);
167
- }
168
- else {
169
- // Fallback to inline templates for backwards compatibility
222
+ const existed = fs.existsSync(destPath);
223
+ // Always overwrite hook scripts so re-running `succ init` keeps them
224
+ // at the version shipped with the current package. This is intentional:
225
+ // hooks are generated files, not user-editable.
226
+ if (fs.existsSync(srcPath)) {
227
+ fs.copyFileSync(srcPath, destPath);
228
+ log(existed ? `Updated hooks/${hookFile}` : `Created hooks/${hookFile}`);
229
+ }
230
+ else {
231
+ // Fallback to inline templates for backwards compatibility
232
+ if (!existed || options.force) {
170
233
  const hookContent = getHookContent(hookFile);
171
234
  if (hookContent) {
172
235
  fs.writeFileSync(destPath, hookContent);
173
- log(options.force && fs.existsSync(destPath)
174
- ? `Updated hooks/${hookFile}`
175
- : `Created hooks/${hookFile}`);
236
+ log(existed ? `Updated hooks/${hookFile}` : `Created hooks/${hookFile}`);
176
237
  }
177
238
  }
178
239
  }
179
240
  }
241
+ // Copy hooks/core/ shared modules (adapter, daemon-boot)
242
+ // Always overwrite so re-runs stay in sync with the installed package.
243
+ const coreSrcDir = path.join(SUCC_PACKAGE_DIR, 'hooks', 'core');
244
+ const coreDestDir = path.join(succDir, 'hooks', 'core');
245
+ if (fs.existsSync(coreSrcDir)) {
246
+ if (!fs.existsSync(coreDestDir)) {
247
+ fs.mkdirSync(coreDestDir, { recursive: true });
248
+ }
249
+ const coreFiles = fs.readdirSync(coreSrcDir).filter((f) => f.endsWith('.cjs'));
250
+ for (const coreFile of coreFiles) {
251
+ const dest = path.join(coreDestDir, coreFile);
252
+ const existed = fs.existsSync(dest);
253
+ fs.copyFileSync(path.join(coreSrcDir, coreFile), dest);
254
+ log(existed ? `Updated hooks/core/${coreFile}` : `Created hooks/core/${coreFile}`);
255
+ }
256
+ }
180
257
  }
181
258
  // Create or merge settings.json in .claude/ (Claude Code looks for it there)
182
259
  const claudeDir = path.join(projectRoot, '.claude');
@@ -227,223 +304,190 @@ export async function init(options = {}) {
227
304
  }
228
305
  const settingsPath = path.join(claudeDir, 'settings.json');
229
306
  const settingsExisted = fs.existsSync(settingsPath);
230
- if (!settingsExisted || options.force) {
307
+ {
308
+ // Always install/update hooks and settings so re-running `succ init` on an existing
309
+ // project updates hooks to the latest version. The merge logic inside preserves
310
+ // existing permissions and any non-succ hooks.
231
311
  // Determine hooks path based on installation mode
232
- // Global install: hooks are in the succ package directory
233
- // Local dev: hooks are copied to .succ/hooks/ in the project
312
+ // Use $CLAUDE_PROJECT_DIR for portability (works regardless of cwd)
234
313
  const hooksPath = useGlobalHooks
235
314
  ? path.join(SUCC_PACKAGE_DIR, 'hooks').replace(/\\/g, '/')
236
- : '.succ/hooks';
315
+ : '$CLAUDE_PROJECT_DIR/.succ/hooks';
316
+ // Detect Claude Code version for HTTP hooks support
317
+ const claudeVersion = getClaudeCodeVersion();
318
+ const useHttp = supportsHttpHooks(claudeVersion);
319
+ // Compute stable port for HTTP hook URLs (getConfig merges global + project config)
320
+ const mergedConfig = getConfig();
321
+ const hookPort = mergedConfig.daemon?.port ?? getStablePort(projectRoot);
322
+ const baseUrl = `http://127.0.0.1:${hookPort}/api/hooks`;
237
323
  if (verbose) {
238
324
  console.log(` Installation mode: ${useGlobalHooks ? 'global' : 'local development'}`);
239
325
  console.log(` Hooks path: ${hooksPath}`);
326
+ console.log(` Claude Code version: ${claudeVersion || 'not detected'}`);
327
+ console.log(` HTTP hooks: ${useHttp ? 'yes' : 'no (command fallback)'}`);
328
+ console.log(` Hook port: ${hookPort}`);
240
329
  }
241
- // Define succ hooks
242
- // Hook files prefixed with "succ-" to avoid conflicts with other hooks
330
+ // Helper to build a command hook entry
331
+ const cmdHook = (script, timeout, statusMsg) => ({
332
+ type: 'command',
333
+ command: `node --no-warnings --no-deprecation "${hooksPath}/${script}"`,
334
+ timeout,
335
+ statusMessage: statusMsg,
336
+ });
337
+ // Helper to build an HTTP hook entry
338
+ const httpHook = (route, timeout, statusMsg) => ({
339
+ type: 'http',
340
+ url: `${baseUrl}/${route}`,
341
+ timeout,
342
+ statusMessage: statusMsg,
343
+ });
344
+ // Define succ hooks — HTTP when supported, command fallback
243
345
  const succHooks = {
346
+ // Command-only events (Claude Code limitation)
244
347
  SessionStart: [
245
348
  {
246
- hooks: [
247
- {
248
- type: 'command',
249
- command: `node --no-warnings --no-deprecation "${hooksPath}/succ-session-start.cjs"`,
250
- timeout: 10,
251
- },
252
- ],
349
+ hooks: [cmdHook('succ-session-start.cjs', 10, 'succ: loading context...')],
253
350
  },
254
351
  ],
255
- Stop: [
352
+ SessionEnd: [
256
353
  {
257
- hooks: [
258
- {
259
- type: 'command',
260
- command: `node --no-warnings --no-deprecation "${hooksPath}/succ-stop-reflection.cjs"`,
261
- timeout: 60,
262
- },
263
- ],
354
+ hooks: [cmdHook('succ-session-end.cjs', 60, 'succ: saving session...')],
264
355
  },
265
356
  ],
266
- SessionEnd: [
357
+ // HTTP when supported, command fallback
358
+ Stop: [
267
359
  {
268
360
  hooks: [
269
- {
270
- type: 'command',
271
- command: `node --no-warnings --no-deprecation "${hooksPath}/succ-session-end.cjs"`,
272
- timeout: 60,
273
- },
361
+ useHttp
362
+ ? httpHook('stop', 60, 'succ: recording activity...')
363
+ : cmdHook('succ-stop-reflection.cjs', 60, 'succ: recording activity...'),
274
364
  ],
275
365
  },
276
366
  ],
277
367
  UserPromptSubmit: [
278
368
  {
279
369
  hooks: [
280
- {
281
- type: 'command',
282
- command: `node --no-warnings --no-deprecation "${hooksPath}/succ-user-prompt.cjs"`,
283
- timeout: 10,
284
- },
370
+ useHttp
371
+ ? httpHook('user-prompt', 10, 'succ: checking context...')
372
+ : cmdHook('succ-user-prompt.cjs', 10, 'succ: checking context...'),
285
373
  ],
286
374
  },
287
375
  ],
288
376
  PostToolUse: [
289
377
  {
290
378
  hooks: [
291
- {
292
- type: 'command',
293
- command: `node --no-warnings --no-deprecation "${hooksPath}/succ-post-tool.cjs"`,
294
- timeout: 5,
295
- },
379
+ useHttp
380
+ ? httpHook('post-tool', 5, 'succ: capturing...')
381
+ : cmdHook('succ-post-tool.cjs', 5, 'succ: capturing...'),
296
382
  ],
297
383
  },
298
384
  ],
299
385
  PreToolUse: [
300
386
  {
301
- matcher: 'Bash',
302
387
  hooks: [
303
- {
304
- type: 'command',
305
- command: `node --no-warnings --no-deprecation "${hooksPath}/succ-pre-tool.cjs"`,
306
- timeout: 10,
307
- },
388
+ useHttp
389
+ ? httpHook('pre-tool', 10, 'succ: checking rules...')
390
+ : cmdHook('succ-pre-tool.cjs', 10, 'succ: checking rules...'),
308
391
  ],
309
392
  },
310
393
  ],
394
+ // PreCompact — command-only (Claude Code limitation)
395
+ PreCompact: [
396
+ {
397
+ hooks: [cmdHook('succ-pre-compact.cjs', 5, 'succ: analyzing session...')],
398
+ },
399
+ ],
400
+ // New hooks (HTTP only, no command fallback needed)
401
+ ...(useHttp
402
+ ? {
403
+ PermissionRequest: [
404
+ {
405
+ hooks: [httpHook('permission', 5, 'succ: checking permission rules...')],
406
+ },
407
+ ],
408
+ SubagentStop: [
409
+ {
410
+ hooks: [httpHook('subagent-stop', 5, 'succ: saving agent results...')],
411
+ },
412
+ ],
413
+ TaskCompleted: [
414
+ {
415
+ hooks: [httpHook('task-completed', 5, 'succ: consolidating...')],
416
+ },
417
+ ],
418
+ }
419
+ : {}),
311
420
  };
312
421
  let finalSettings;
313
- if (settingsExisted && !options.force) {
314
- // Merge with existing settings (non-force mode)
315
- try {
316
- const existingContent = fs.readFileSync(settingsPath, 'utf-8');
317
- const existingSettings = JSON.parse(existingContent);
318
- // Preserve all existing settings
319
- finalSettings = { ...existingSettings };
320
- // Ensure hooks object exists
321
- if (!finalSettings.hooks) {
322
- finalSettings.hooks = {};
422
+ // Unified merge logic: strip old succ hooks (command + HTTP), add fresh ones.
423
+ // Works for both merge and force modes — always upgrades hook transport.
424
+ const stripAndAddSuccHooks = (existingSettings) => {
425
+ const settings = { ...existingSettings };
426
+ if (!settings.hooks)
427
+ settings.hooks = {};
428
+ // Strip all existing succ hooks from every event type
429
+ for (const [hookType, hookConfig] of Object.entries(settings.hooks)) {
430
+ if (!Array.isArray(hookConfig))
431
+ continue;
432
+ const nonSucc = hookConfig.filter((h) => !isSuccHook(h));
433
+ if (nonSucc.length > 0) {
434
+ settings.hooks[hookType] = nonSucc;
323
435
  }
324
- // Merge hooks: add succ hooks without duplicating
325
- for (const [hookType, hookConfig] of Object.entries(succHooks)) {
326
- if (!finalSettings.hooks[hookType]) {
327
- // No existing hooks of this type, just add ours
328
- finalSettings.hooks[hookType] = hookConfig;
329
- }
330
- else {
331
- const existingHooks = finalSettings.hooks[hookType];
332
- const succHookEntries = hookConfig;
333
- for (const succEntry of succHookEntries) {
334
- // Check if this exact succ hook is already present
335
- const succCommand = succEntry.hooks?.[0]?.command || '';
336
- const succMatcher = succEntry.matcher || '';
337
- const alreadyExists = existingHooks.some((existing) => {
338
- const existingCommand = existing.hooks?.[0]?.command || '';
339
- // Check for succ hook files (prefixed with "succ-")
340
- if (succCommand.includes('succ-session-start.cjs') &&
341
- existingCommand.includes('succ-session-start.cjs'))
342
- return true;
343
- if (succCommand.includes('succ-session-end.cjs') &&
344
- existingCommand.includes('succ-session-end.cjs'))
345
- return true;
346
- if (succCommand.includes('succ-stop-reflection.cjs') &&
347
- existingCommand.includes('succ-stop-reflection.cjs'))
348
- return true;
349
- if (succCommand.includes('succ-user-prompt.cjs') &&
350
- existingCommand.includes('succ-user-prompt.cjs'))
351
- return true;
352
- if (succCommand.includes('succ-post-tool.cjs') &&
353
- existingCommand.includes('succ-post-tool.cjs'))
354
- return true;
355
- if (succCommand.includes('succ-pre-tool.cjs') &&
356
- existingCommand.includes('succ-pre-tool.cjs'))
357
- return true;
358
- // For Notification hooks, check matcher
359
- if (succMatcher && existing.matcher === succMatcher)
360
- return true;
361
- return false;
362
- });
363
- if (!alreadyExists) {
364
- existingHooks.push(succEntry);
365
- }
366
- }
367
- }
436
+ else {
437
+ delete settings.hooks[hookType];
368
438
  }
369
- log('Merged settings.json (preserved existing permissions and hooks)');
370
439
  }
371
- catch {
372
- // Failed to parse existing, create new
373
- finalSettings = { hooks: succHooks };
374
- log('Created settings.json (failed to parse existing)');
440
+ // Add fresh succ hooks
441
+ for (const [hookType, hookConfig] of Object.entries(succHooks)) {
442
+ const entries = hookConfig;
443
+ if (entries.length === 0)
444
+ continue;
445
+ if (!settings.hooks[hookType]) {
446
+ settings.hooks[hookType] = entries;
447
+ }
448
+ else {
449
+ settings.hooks[hookType] = [...settings.hooks[hookType], ...entries];
450
+ }
375
451
  }
376
- }
377
- else if (settingsExisted && options.force) {
378
- // Force mode: replace succ hooks but preserve other settings
452
+ return settings;
453
+ };
454
+ if (settingsExisted) {
379
455
  try {
380
456
  const existingContent = fs.readFileSync(settingsPath, 'utf-8');
381
- const existingSettings = JSON.parse(existingContent);
382
- // Preserve non-hook settings (permissions, etc.)
383
- finalSettings = { ...existingSettings };
384
- // Replace hooks entirely with new succ hooks
385
- // but preserve any non-succ hooks
386
- if (finalSettings.hooks) {
387
- for (const [hookType, hookConfig] of Object.entries(finalSettings.hooks)) {
388
- const existingHooks = hookConfig;
389
- // Filter out old succ hooks (both old names and new "succ-" prefixed names)
390
- const nonSuccHooks = existingHooks.filter((h) => {
391
- const cmd = h.hooks?.[0]?.command || '';
392
- // Remove hooks in .succ/hooks/ directory (local dev)
393
- if (cmd.includes('.succ/hooks/'))
394
- return false;
395
- // Remove hooks from global succ install (contains /hooks/succ- pattern)
396
- if (cmd.includes('/hooks/succ-') || cmd.includes('\\hooks\\succ-'))
397
- return false;
398
- // Also remove any legacy hooks with succ hook names
399
- if (cmd.includes('session-start.cjs') ||
400
- cmd.includes('session-end.cjs') ||
401
- cmd.includes('stop-reflection.cjs') ||
402
- cmd.includes('user-prompt.cjs') ||
403
- cmd.includes('post-tool.cjs') ||
404
- cmd.includes('pre-tool.cjs') ||
405
- cmd.includes('idle-reflection.cjs'))
406
- return false;
407
- return true;
408
- });
409
- if (nonSuccHooks.length > 0) {
410
- finalSettings.hooks[hookType] = nonSuccHooks;
411
- }
412
- else {
413
- delete finalSettings.hooks[hookType];
414
- }
415
- }
457
+ const parsed = JSON.parse(existingContent);
458
+ // Guard against valid JSON that isn't a plain object (null, array, primitive).
459
+ // Spreading a non-object would silently discard the value or throw at runtime.
460
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
461
+ throw new Error(`settings.json contains ${parsed === null ? 'null' : Array.isArray(parsed) ? 'an array' : `a ${typeof parsed}`} — expected a plain object`);
416
462
  }
417
- // Now add fresh succ hooks
418
- if (!finalSettings.hooks) {
419
- finalSettings.hooks = {};
420
- }
421
- for (const [hookType, hookConfig] of Object.entries(succHooks)) {
422
- if (!finalSettings.hooks[hookType]) {
423
- finalSettings.hooks[hookType] = hookConfig;
424
- }
425
- else {
426
- finalSettings.hooks[hookType] = [
427
- ...finalSettings.hooks[hookType],
428
- ...hookConfig,
429
- ];
430
- }
431
- }
432
- log('Replaced succ hooks in settings.json (--force)');
463
+ const existingSettings = parsed;
464
+ finalSettings = stripAndAddSuccHooks(existingSettings);
465
+ log(options.force
466
+ ? 'Replaced succ hooks in settings.json (--force)'
467
+ : 'Merged settings.json (preserved existing permissions and hooks)');
433
468
  }
434
- catch {
435
- // Failed to parse existing, create new
469
+ catch (error) {
470
+ logWarn('init', 'Failed to parse existing Claude settings.json for hook merge', {
471
+ error: error instanceof Error ? error.message : String(error),
472
+ });
436
473
  finalSettings = { hooks: succHooks };
437
474
  log('Created settings.json (failed to parse existing)');
438
475
  }
439
476
  }
440
477
  else {
441
- // Create new settings
442
478
  finalSettings = { hooks: succHooks };
443
479
  log('Created settings.json');
444
480
  }
445
481
  fs.writeFileSync(settingsPath, JSON.stringify(finalSettings, null, 2));
446
482
  }
483
+ // Check if already initialized (after hooks/settings so re-runs always refresh them)
484
+ if (fs.existsSync(path.join(succDir, 'succ.db')) && !options.force) {
485
+ // Always reconcile MCP server config even if DB exists — ensures older installs
486
+ // or previous failures get the Claude entry added.
487
+ addMcpServer(projectRoot);
488
+ spinner.succeed('succ hooks/settings refreshed (already initialized).');
489
+ return;
490
+ }
447
491
  // Note: All hooks are now created in the earlier block using copyFileSync from hooks/ directory
448
492
  // Add MCP server to Claude Code config
449
493
  const mcpResult = addMcpServer(projectRoot);
@@ -506,7 +550,7 @@ async function runOnboarding(useAi) {
506
550
  return;
507
551
  }
508
552
  // Ask for onboarding style (unless --ai flag was used)
509
- let onboardingStyle = 'quick';
553
+ let onboardingStyle;
510
554
  if (useAi) {
511
555
  onboardingStyle = 'interactive';
512
556
  }
@@ -576,6 +620,22 @@ async function runInteractiveSetup(projectRoot, _verbose = false) {
576
620
  default: 'global',
577
621
  });
578
622
  const targetConfig = configScope === 'global' ? newGlobalConfig : newProjectConfig;
623
+ // When user chose global scope, warn if project config already contains LLM overrides.
624
+ // Project-level llm keys take precedence over global, so stale entries can shadow the
625
+ // new global settings the wizard is about to write.
626
+ if (configScope === 'global' && fs.existsSync(projectConfigPath)) {
627
+ try {
628
+ const existingProjectCfg = JSON.parse(fs.readFileSync(projectConfigPath, 'utf-8'));
629
+ if (existingProjectCfg?.llm && Object.keys(existingProjectCfg.llm).length > 0) {
630
+ console.log('\n \x1b[33mNote:\x1b[0m Your project config (.succ/config.json) has existing LLM');
631
+ console.log(' settings that will override the global config for this project.');
632
+ console.log(' Remove the `llm` key from .succ/config.json to use global settings.\n');
633
+ }
634
+ }
635
+ catch {
636
+ // Ignore parse errors — non-critical warning path
637
+ }
638
+ }
579
639
  // Step 2: Embedding mode
580
640
  console.log('\n┌─────────────────────────────────────────────────────────┐');
581
641
  console.log('│ succ converts text to vectors (embeddings) for search. │');
@@ -630,7 +690,7 @@ async function runInteractiveSetup(projectRoot, _verbose = false) {
630
690
  targetConfig.llm.embeddings.model = embeddingModel;
631
691
  targetConfig.llm.embeddings.dimensions = embeddingDimensions;
632
692
  // Prompt for API key if the URL looks like a cloud provider
633
- if (embeddingApiUrl.includes('openrouter.ai') || embeddingApiUrl.includes('openai.com')) {
693
+ if (isCloudProvider(embeddingApiUrl)) {
634
694
  const apiKey = await password({
635
695
  message: 'API key:',
636
696
  mask: '*',
@@ -691,8 +751,7 @@ async function runInteractiveSetup(projectRoot, _verbose = false) {
691
751
  targetConfig.llm.analyze.api_url = analyzeApiUrl;
692
752
  targetConfig.llm.analyze.model = analyzeModel;
693
753
  // Prompt for API key if cloud provider and not already set
694
- if (!targetConfig.llm.api_key &&
695
- (analyzeApiUrl.includes('openrouter.ai') || analyzeApiUrl.includes('openai.com'))) {
754
+ if (!targetConfig.llm.api_key && isCloudProvider(analyzeApiUrl)) {
696
755
  const apiKey = await password({
697
756
  message: 'API key:',
698
757
  mask: '*',
@@ -751,30 +810,69 @@ async function runInteractiveSetup(projectRoot, _verbose = false) {
751
810
  console.log('\n ✓ Background services disabled');
752
811
  console.log(' Run `succ index` and `succ analyze` manually when needed');
753
812
  }
754
- // Save daemon config to target scope
755
- if (daemonMode !== 'none') {
756
- targetConfig.daemon = daemonConfig;
757
- }
813
+ // Daemon settings are always written to the project config, never global.
814
+ // Background-service toggles are per-project: writing them to the global
815
+ // config would bleed across unrelated projects.
816
+ // When daemonMode is 'none', explicitly write a disabled block so that
817
+ // mergeAndWriteConfig's additive deep merge does not leave behind any
818
+ // pre-existing daemon.enabled / auto_start values set to true.
819
+ newProjectConfig.daemon =
820
+ daemonMode === 'none'
821
+ ? { enabled: false, watch: { auto_start: false }, analyze: { auto_start: false } }
822
+ : daemonConfig;
758
823
  console.log('');
759
- // Save config to chosen scope
760
- if (configScope === 'global') {
761
- if (Object.keys(newGlobalConfig).length > 0) {
762
- if (!fs.existsSync(globalConfigDir)) {
763
- fs.mkdirSync(globalConfigDir, { recursive: true });
824
+ // Save config to chosen scope — merge with existing to avoid overwriting
825
+ // user-configured fields (storage backend, Qdrant, custom settings, etc.)
826
+ const mergeAndWriteConfig = (configPath, configDir, newConfig) => {
827
+ if (Object.keys(newConfig).length === 0)
828
+ return;
829
+ if (!fs.existsSync(configDir)) {
830
+ fs.mkdirSync(configDir, { recursive: true });
831
+ }
832
+ let existing = {};
833
+ if (fs.existsSync(configPath)) {
834
+ try {
835
+ const raw = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
836
+ if (typeof raw === 'object' && raw !== null && !Array.isArray(raw)) {
837
+ existing = raw;
838
+ }
839
+ else {
840
+ logWarn('init', `${configPath} is not a plain object — treating as empty`, {});
841
+ }
842
+ }
843
+ catch (e) {
844
+ logWarn('init', `Failed to parse existing ${configPath}, will overwrite`, {
845
+ error: e instanceof Error ? e.message : String(e),
846
+ });
764
847
  }
765
- fs.writeFileSync(globalConfigPath, JSON.stringify(newGlobalConfig, null, 2));
766
- console.log(` Saved: ${globalConfigPath}`);
767
848
  }
768
- }
769
- else {
770
- if (Object.keys(newProjectConfig).length > 0) {
771
- if (!fs.existsSync(projectConfigDir)) {
772
- fs.mkdirSync(projectConfigDir, { recursive: true });
849
+ // Deep merge: wizard keys override, but preserve keys not covered by wizard
850
+ const merged = { ...existing };
851
+ for (const [key, value] of Object.entries(newConfig)) {
852
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
853
+ merged[key] = { ...(existing[key] ?? {}), ...value };
854
+ // One level deeper for nested objects (llm.embeddings, llm.analyze, daemon.watch, etc.)
855
+ for (const [subKey, subValue] of Object.entries(value)) {
856
+ if (typeof subValue === 'object' && subValue !== null && !Array.isArray(subValue)) {
857
+ merged[key][subKey] = { ...(existing[key]?.[subKey] ?? {}), ...subValue };
858
+ }
859
+ }
860
+ }
861
+ else {
862
+ merged[key] = value;
773
863
  }
774
- fs.writeFileSync(projectConfigPath, JSON.stringify(newProjectConfig, null, 2));
775
- console.log(` Saved: ${projectConfigPath}`);
776
864
  }
865
+ fs.writeFileSync(configPath, JSON.stringify(merged, null, 2));
866
+ const isNew = Object.keys(existing).length === 0;
867
+ console.log(` ${isNew ? 'Created' : 'Merged into'}: ${configPath}`);
868
+ };
869
+ if (configScope === 'global') {
870
+ mergeAndWriteConfig(globalConfigPath, globalConfigDir, newGlobalConfig);
777
871
  }
872
+ // Always write project config — daemon settings are project-scoped even when
873
+ // embedding/analyze settings are global. mergeAndWriteConfig is a no-op when
874
+ // newProjectConfig is empty so this is safe for pure global setups.
875
+ mergeAndWriteConfig(projectConfigPath, projectConfigDir, newProjectConfig);
778
876
  // Final message
779
877
  console.log('\n┌─────────────────────────────────────────────────────────┐');
780
878
  console.log('│ Setup Complete! │');
@@ -790,7 +888,8 @@ async function runInteractiveSetup(projectRoot, _verbose = false) {
790
888
  }
791
889
  catch (error) {
792
890
  // Handle Ctrl+C gracefully
793
- if (error?.name === 'ExitPromptError' || error?.message?.includes('closed')) {
891
+ if (error instanceof Error &&
892
+ (error.name === 'ExitPromptError' || error.message?.includes('closed'))) {
794
893
  console.log('\n\n Setup cancelled.\n');
795
894
  process.exit(0);
796
895
  }
@@ -837,7 +936,7 @@ function addMcpServer(_projectRoot) {
837
936
  }
838
937
  catch (error) {
839
938
  logWarn('init', `Failed to add MCP server to ${claudeConfigPath}`, { error: String(error) });
840
- console.warn(` Warning: Failed to add MCP server to ${claudeConfigPath}: ${error.message}`);
939
+ console.warn(` Warning: Failed to add MCP server to ${claudeConfigPath}: ${error instanceof Error ? error.message : String(error)}`);
841
940
  logWarn('init', 'You can add it manually: succ init --force');
842
941
  console.warn(' You can add it manually: succ init --force');
843
942
  return 'failed';
@@ -857,7 +956,10 @@ function getHookContent(hookFile) {
857
956
  return fs.readFileSync(hookPath, 'utf-8');
858
957
  }
859
958
  }
860
- catch {
959
+ catch (error) {
960
+ logWarn('init', 'Failed to read hook file from package directory', {
961
+ error: error instanceof Error ? error.message : String(error),
962
+ });
861
963
  // File read error
862
964
  }
863
965
  return null;