flurryx-code-memory 0.5.0__tar.gz → 0.5.2__tar.gz

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 (192) hide show
  1. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/CHANGELOG.md +44 -0
  2. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/PKG-INFO +1 -1
  3. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/README.md +42 -26
  4. flurryx_code_memory-0.5.2/install.ps1 +369 -0
  5. flurryx_code_memory-0.5.2/install.sh +302 -0
  6. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/README.md +13 -17
  7. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/lib/state.js +3 -31
  8. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/on-post-tool.js +4 -10
  9. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/on-pre-tool.js +4 -6
  10. flurryx_code_memory-0.5.2/plugins/claude-code/scripts/on-user-prompt.js +48 -0
  11. flurryx_code_memory-0.5.2/plugins/cursor/README.md +161 -0
  12. flurryx_code_memory-0.5.2/plugins/cursor/hooks/hooks.json.template +79 -0
  13. flurryx_code_memory-0.5.2/plugins/cursor/install.sh +231 -0
  14. flurryx_code_memory-0.5.2/plugins/cursor/rules/code-memory.mdc +39 -0
  15. flurryx_code_memory-0.5.2/plugins/cursor/scripts/lib/claim-intent.js +158 -0
  16. flurryx_code_memory-0.5.2/plugins/cursor/scripts/lib/claim-intent.test.js +159 -0
  17. flurryx_code_memory-0.5.2/plugins/cursor/scripts/lib/io.js +42 -0
  18. flurryx_code_memory-0.5.2/plugins/cursor/scripts/lib/memory.js +155 -0
  19. flurryx_code_memory-0.5.2/plugins/cursor/scripts/lib/state.js +176 -0
  20. flurryx_code_memory-0.5.2/plugins/cursor/scripts/on-after-file-edit.js +57 -0
  21. flurryx_code_memory-0.5.2/plugins/cursor/scripts/on-before-mcp-execution.js +22 -0
  22. flurryx_code_memory-0.5.2/plugins/cursor/scripts/on-before-submit-prompt.js +43 -0
  23. flurryx_code_memory-0.5.2/plugins/cursor/scripts/on-post-tool-use.js +33 -0
  24. flurryx_code_memory-0.5.2/plugins/cursor/scripts/on-pre-compact.js +54 -0
  25. flurryx_code_memory-0.5.2/plugins/cursor/scripts/on-pre-tool-use.js +54 -0
  26. flurryx_code_memory-0.5.2/plugins/cursor/scripts/on-session-end.js +18 -0
  27. flurryx_code_memory-0.5.2/plugins/cursor/scripts/on-session-start.js +36 -0
  28. flurryx_code_memory-0.5.2/plugins/cursor/scripts/on-stop.js +54 -0
  29. flurryx_code_memory-0.5.2/plugins/cursor/scripts/resolver-debounce.js +44 -0
  30. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/README.md +24 -26
  31. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/src/code-memory.ts +14 -190
  32. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/pyproject.toml +1 -1
  33. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/scripts/install.ps1 +27 -14
  34. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/scripts/install.sh +32 -11
  35. flurryx_code_memory-0.5.2/src/code_memory/__init__.py +16 -0
  36. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/claims/indexer.py +79 -1
  37. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/claims/store.py +12 -0
  38. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/cli.py +12 -0
  39. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/config.py +11 -0
  40. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/mcp_server.py +49 -1
  41. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/autostart/__init__.py +7 -1
  42. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/autostart/base.py +35 -1
  43. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/autostart/launchd.py +35 -0
  44. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/safety.py +28 -0
  45. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/updater.py +181 -27
  46. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_autostart_adapters.py +38 -0
  47. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_claim_indexer.py +108 -2
  48. flurryx_code_memory-0.5.2/tests/test_mcp_shutdown.py +91 -0
  49. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_watch_safety.py +56 -0
  50. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/uv.lock +56 -56
  51. flurryx_code_memory-0.5.0/install.ps1 +0 -217
  52. flurryx_code_memory-0.5.0/install.sh +0 -181
  53. flurryx_code_memory-0.5.0/plugins/claude-code/scripts/lib/format.js +0 -79
  54. flurryx_code_memory-0.5.0/plugins/claude-code/scripts/lib/intent.js +0 -53
  55. flurryx_code_memory-0.5.0/plugins/claude-code/scripts/on-user-prompt.js +0 -110
  56. flurryx_code_memory-0.5.0/plugins/opencode/src/code-memory-lib/intent.ts +0 -74
  57. flurryx_code_memory-0.5.0/src/code_memory/__init__.py +0 -8
  58. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/.claude-plugin/marketplace.json +0 -0
  59. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/.env.example +0 -0
  60. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/.gitignore +0 -0
  61. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/docker/docker-compose.yml +0 -0
  62. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/docs/BENCHMARK.md +0 -0
  63. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/docs/BENCHMARK_VS_BASELINE.json +0 -0
  64. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/docs/BENCHMARK_VS_BASELINE.md +0 -0
  65. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/docs/architecture.png +0 -0
  66. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/docs/benchmark-raw.json +0 -0
  67. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/docs/hero.png +0 -0
  68. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  69. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/commands/code-memory.md +0 -0
  70. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/hooks/hooks.json +0 -0
  71. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/install.sh +0 -0
  72. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/lib/claim-intent.js +0 -0
  73. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/lib/claim-intent.test.js +0 -0
  74. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/lib/io.js +0 -0
  75. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/lib/memory.js +0 -0
  76. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/on-retrieve-seen.js +0 -0
  77. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/on-session-start.js +0 -0
  78. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/on-stop.js +0 -0
  79. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/scripts/resolver-debounce.js +0 -0
  80. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/claude-code/skills/code-memory/SKILL.md +0 -0
  81. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/install.sh +0 -0
  82. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/package-lock.json +0 -0
  83. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/package.json +0 -0
  84. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/scripts/add-mcp.py +0 -0
  85. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/scripts/install.mjs +0 -0
  86. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/scripts/uninstall.mjs +0 -0
  87. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/skills/code-memory/SKILL.md +0 -0
  88. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/src/code-memory-lib/claim-intent.test.mts +0 -0
  89. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/src/code-memory-lib/claim-intent.ts +0 -0
  90. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/src/code-memory-lib/memory-client.ts +0 -0
  91. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/plugins/opencode/tsconfig.json +0 -0
  92. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/scripts/benchmark.py +0 -0
  93. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/scripts/benchmark_queries.json +0 -0
  94. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/scripts/benchmark_vs_baseline.py +0 -0
  95. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/scripts/benchmark_vs_grep.sh +0 -0
  96. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/scripts/ingest.py +0 -0
  97. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/claims/__init__.py +0 -0
  98. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/claims/extractor.py +0 -0
  99. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/claims/resolver.py +0 -0
  100. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/embed/__init__.py +0 -0
  101. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/embed/cache.py +0 -0
  102. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/embed/m3.py +0 -0
  103. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/embed/ollama.py +0 -0
  104. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/embed/tei.py +0 -0
  105. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/episodic/__init__.py +0 -0
  106. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/episodic/sqlite_store.py +0 -0
  107. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/extractor/__init__.py +0 -0
  108. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/extractor/csproj.py +0 -0
  109. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/extractor/dll.py +0 -0
  110. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/extractor/gitignore.py +0 -0
  111. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/extractor/nuget.py +0 -0
  112. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/extractor/sanity.py +0 -0
  113. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/extractor/sln.py +0 -0
  114. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/extractor/treesitter.py +0 -0
  115. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/graph/__init__.py +0 -0
  116. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/graph/falkor_store.py +0 -0
  117. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/metrics.py +0 -0
  118. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/orchestrator/__init__.py +0 -0
  119. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/orchestrator/git_delta.py +0 -0
  120. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/orchestrator/ingest_state.py +0 -0
  121. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/orchestrator/pipeline.py +0 -0
  122. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/orchestrator/reset.py +0 -0
  123. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/orchestrator/resolver.py +0 -0
  124. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/orchestrator/retrieve.py +0 -0
  125. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/resilience.py +0 -0
  126. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/__init__.py +0 -0
  127. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/autostart/schtasks.py +0 -0
  128. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/autostart/systemd.py +0 -0
  129. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/hooks.py +0 -0
  130. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/snapshot.py +0 -0
  131. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/store.py +0 -0
  132. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/sync.py +0 -0
  133. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/sync/watcher.py +0 -0
  134. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/vector/__init__.py +0 -0
  135. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/src/code_memory/vector/qdrant_store.py +0 -0
  136. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_chunk_text.py +0 -0
  137. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_claim_extractor.py +0 -0
  138. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_claim_resolver.py +0 -0
  139. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_claim_store.py +0 -0
  140. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_config_embed_dim.py +0 -0
  141. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_config_sentinel.py +0 -0
  142. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_csproj.py +0 -0
  143. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_dll_members.py +0 -0
  144. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_dll_parser.py +0 -0
  145. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_embed_backend.py +0 -0
  146. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_embed_cache.py +0 -0
  147. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_embed_m3.py +0 -0
  148. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_embed_tei.py +0 -0
  149. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_episode_dedup.py +0 -0
  150. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_episode_head_sha.py +0 -0
  151. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_csharp.py +0 -0
  152. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_filters.py +0 -0
  153. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_php.py +0 -0
  154. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_python_imports.py +0 -0
  155. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_receiver_type.py +0 -0
  156. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_references.py +0 -0
  157. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_sanity.py +0 -0
  158. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_ts_abstract.py +0 -0
  159. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_ts_inject.py +0 -0
  160. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_extractor_utf8.py +0 -0
  161. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_file_containment.py +0 -0
  162. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_git_delta.py +0 -0
  163. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_graph_queries.py +0 -0
  164. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_graph_temporal.py +0 -0
  165. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_graph_vacuum_at_sha.py +0 -0
  166. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_hooks_installer.py +0 -0
  167. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_ingest_state.py +0 -0
  168. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_mcp_assert_claim.py +0 -0
  169. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_mcp_server_descriptions.py +0 -0
  170. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_mcp_strict_project.py +0 -0
  171. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_metrics.py +0 -0
  172. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_nuget_resolver.py +0 -0
  173. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_overload_resolution.py +0 -0
  174. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_partial_class.py +0 -0
  175. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_pipeline_references.py +0 -0
  176. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_pipeline_temporal_wiring.py +0 -0
  177. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_qdrant_legacy_guard.py +0 -0
  178. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_razor_inject.py +0 -0
  179. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_resilience.py +0 -0
  180. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_resolver.py +0 -0
  181. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_resolver_assembly.py +0 -0
  182. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_retrieve_claims_surfacing.py +0 -0
  183. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_retrieve_rerank.py +0 -0
  184. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_sln.py +0 -0
  185. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_smoke.py +0 -0
  186. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_snapshot_e2e.py +0 -0
  187. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_snapshot_format.py +0 -0
  188. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_snapshot_store.py +0 -0
  189. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_sync_decision_tree.py +0 -0
  190. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_watcher_debouncer.py +0 -0
  191. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_watcher_exclude.py +0 -0
  192. {flurryx_code_memory-0.5.0 → flurryx_code_memory-0.5.2}/tests/test_watcher_ref_events.py +0 -0
@@ -8,6 +8,50 @@ when the repo grows.
8
8
  This file complements `git log`: commits explain mechanics, this file
9
9
  explains intent.
10
10
 
11
+ ## [0.5.2] — 2026-05-30
12
+
13
+ Release theme: **the watcher stops leaking**. A diagnosis of runaway RAM
14
+ turned up dozens of orphaned `code-memory watch` daemons — one permanent
15
+ launchd agent per directory any MCP server had ever booted in, including
16
+ throwaway per-session dirs. This release stops the bleed and self-heals
17
+ the cruft. Also lands semantic dedupe for near-duplicate user claims.
18
+
19
+ ### Fixed — Unbounded launchd watcher accumulation
20
+
21
+ **What:** `ensure_autostart()` no longer registers a persistent OS agent
22
+ for ephemeral / per-session directories (`~/.claude/homunculus/*`,
23
+ `.cursor/worktrees/*`, `plugins/cache/*`); the session-scoped in-process
24
+ watcher still covers them. `LaunchdAdapter.prune_stale()` (run on every
25
+ MCP bootstrap) boots out and removes agents whose `WorkingDirectory` is
26
+ gone or ephemeral.
27
+
28
+ **Reason:** each MCP boot registered a `KeepAlive` + `RunAtLoad` agent for
29
+ its cwd. Ephemeral session dirs got permanent watchers that survived kill
30
+ (launchd relaunched them) and reboot, piling up dozens of daemons and the
31
+ RAM/CPU they pin. `prune_stale` is launchd-only for now; systemd/schtasks
32
+ GC is a follow-up.
33
+
34
+ ### Fixed — Graceful watcher teardown on MCP shutdown
35
+
36
+ **What:** the MCP server registers `atexit` + `SIGTERM` handlers that call
37
+ `Watcher.stop()`.
38
+
39
+ **Reason:** the in-process watcher ran as a daemon thread with no clean
40
+ stop, so an in-flight debounced sync was dropped and the watchdog Observer
41
+ never joined cleanly on exit.
42
+
43
+ ### Added — Semantic dedupe of near-duplicate claims
44
+
45
+ **What:** `ClaimsIndexer` collapses a new claim into the closest open claim
46
+ when cosine similarity is `>= CLAIMS_SEMANTIC_DEDUP_THRESHOLD` (default
47
+ 0.90), ahead of the SQL write.
48
+
49
+ **Reason:** exact (subject, predicate, object) dedupe missed paraphrases
50
+ ("project uses flurryx" / "project depends-on flurryx"), so semantically
51
+ identical claims were stored three times. Best-effort — embedder/backend
52
+ errors fall through to the existing SQL-level dedupe; set `>= 1.0` to
53
+ disable.
54
+
11
55
  ## [0.3.0] — 2026-05-26
12
56
 
13
57
  Release theme: **the claim loop closes**. v0.2.0 shipped the storage
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flurryx-code-memory
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Local lightweight memory layer for coding agents: FalkorDB + Qdrant + Ollama (BGE-M3) + tree-sitter
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: anyio>=4.4
@@ -199,6 +199,10 @@ claude mcp add code-memory --scope user \
199
199
  # 5. OpenCode plugin
200
200
  npm i -g code-memory-opencode
201
201
  code-memory-opencode-install
202
+
203
+ # 6. Cursor plugin (requires repo cloned; package release pending)
204
+ git clone https://github.com/fmflurry/code-memory ~/.code-memory/repo
205
+ ~/.code-memory/repo/plugins/cursor/install.sh
202
206
  ```
203
207
 
204
208
  </details>
@@ -206,7 +210,7 @@ code-memory-opencode-install
206
210
  <details>
207
211
  <summary><strong>MCP-only (lightest, ~10 s)</strong></summary>
208
212
 
209
- Just the Claude Code MCP server — no auto-retrieve / auto-record hooks, no Docker, no Ollama. Useful when FalkorDB + Qdrant already run elsewhere, or you only want the `codememory_*` tools by hand.
213
+ Just the Claude Code MCP server — no auto-learn / auto-record hooks, no Docker, no Ollama. Useful when FalkorDB + Qdrant already run elsewhere, or you only want the `codememory_*` tools by hand.
210
214
 
211
215
  ```bash
212
216
  claude mcp add code-memory \
@@ -1341,45 +1345,55 @@ uvx --from git+https://github.com/dev/code-memory code-memory-mcp
1341
1345
  ### Harness plugins
1342
1346
 
1343
1347
  The MCP server above exposes manual tools. The **harness plugins** make
1344
- the same backend **ambient** — auto-retrieving a Context Pack on every
1345
- substantive user prompt, auto-reingesting on every `Write` / `Edit`, and
1346
- recording sessions as episodes when the agent stops. The plugins are
1347
- optional and live alongside the MCP server; install both for the best
1348
- experience.
1349
-
1350
- | Plugin | Hook model |
1351
- | ----------------------------------------------- | ----------------------------------------------------------------------------- |
1352
- | [`plugins/opencode`](plugins/opencode/README.md) | Bun-loaded TypeScript module; uses `chat.message`, `experimental.chat.system.transform`, `tool.execute.after`, `session.idle`. |
1353
- | [`plugins/claude-code`](plugins/claude-code/README.md) | Plain Node scripts wired via `hooks.json`; uses `SessionStart`, `UserPromptSubmit`, `PostToolUse` (`Write`/`Edit`/`MultiEdit`), `Stop`. |
1354
-
1355
- Both plugins:
1356
-
1357
- - Detect substantive code intent (trivial follow-ups skip retrieval).
1358
- - Dedup the same query within 60 s.
1348
+ the same backend **ambient** — steering the agent toward the index
1349
+ before grep / read / shell, auto-reingesting on every `Write` / `Edit`,
1350
+ recording sessions as episodes when the agent stops, and nudging on
1351
+ durable user assertions. The plugins are optional and live alongside
1352
+ the MCP server; install whichever your agent harness uses.
1353
+
1354
+ | Plugin | Hook model |
1355
+ | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1356
+ | [`plugins/opencode`](plugins/opencode/README.md) | Bun-loaded TypeScript module; uses `chat.message`, `experimental.chat.system.transform`, `tool.execute.after`, `session.idle`. |
1357
+ | [`plugins/claude-code`](plugins/claude-code/README.md) | Plain Node scripts wired via `hooks.json`; uses `SessionStart`, `UserPromptSubmit`, `PostToolUse` (`Write`/`Edit`/`MultiEdit`), `Stop`. |
1358
+ | [`plugins/cursor`](plugins/cursor/README.md) | Plain Node scripts wired via `hooks.json`; uses `sessionStart`, `beforeSubmitPrompt`, `preToolUse`, `beforeMCPExecution`, `postToolUse`, `afterFileEdit`, `preCompact`, `stop`, `sessionEnd`. |
1359
+
1360
+ All three plugins:
1361
+
1362
+ - Steer the agent toward `codememory_retrieve` via a one-shot gate
1363
+ nudge before grep / read / shell (never blocks).
1359
1364
  - Debounce the cross-file resolver (~1.5 s after the last write) so a
1360
1365
  20-file refactor collapses to exactly one resolver run.
1361
1366
  - Run a one-shot git-delta ingest at session start to catch
1362
1367
  out-of-band edits (vim, IDE, `git pull`).
1363
1368
  - Record the session as an episode on idle / stop with the first user
1364
- message + `git diff` as the patch.
1369
+ message + `git diff` as the patch. The Cursor plugin additionally
1370
+ records on `preCompact`, catching state before context compaction.
1365
1371
  - **Detect durable user assertions on every prompt** — preferences
1366
1372
  (`I love X`), decisions (`we use X`), rejections (`don't use Y`),
1367
1373
  ownership (`Alice owns billing`), location (`auth lives at apps/api`)
1368
- — and inject an in-system-prompt nudge that demands the agent call
1374
+ — and inject an in-prompt nudge that demands the agent call
1369
1375
  `codememory_assert_claim` *before* answering. The nudge is
1370
1376
  polarity-flipped: asserting is the default, skipping requires a
1371
1377
  one-line written justification. See
1372
- [`plugins/claude-code/scripts/lib/claim-intent.js`](plugins/claude-code/scripts/lib/claim-intent.js)
1373
- and [`plugins/opencode/src/code-memory-lib/claim-intent.ts`](plugins/opencode/src/code-memory-lib/claim-intent.ts)
1374
- for the regex patterns and nudge template — they are kept in lockstep.
1378
+ [`plugins/claude-code/scripts/lib/claim-intent.js`](plugins/claude-code/scripts/lib/claim-intent.js),
1379
+ [`plugins/opencode/src/code-memory-lib/claim-intent.ts`](plugins/opencode/src/code-memory-lib/claim-intent.ts),
1380
+ and [`plugins/cursor/scripts/lib/claim-intent.js`](plugins/cursor/scripts/lib/claim-intent.js)
1381
+ for the regex patterns and nudge template — kept in lockstep.
1382
+
1383
+ > Cursor caveat: `beforeSubmitPrompt` cannot inject context, so the
1384
+ > Cursor plugin stashes the claim nudge on `beforeSubmitPrompt` and
1385
+ > drains it on the first `postToolUse` of the turn. If the reply uses
1386
+ > no tools, the nudge does not surface for that turn — uncommon in
1387
+ > substantive sessions.
1375
1388
 
1376
1389
  Install via the top-level installer:
1377
1390
 
1378
1391
  ```bash
1379
- ./scripts/install.sh --plugins=all # both, global
1380
- ./scripts/install.sh --plugins=claudecode # Claude Code only
1381
- ./scripts/install.sh --plugins=opencode,claudecode # both, csv form
1382
- ./scripts/install.sh --plugins=all --plugins-scope=project # ./.opencode and ./.claude
1392
+ ./scripts/install.sh --plugins=all # all three, global
1393
+ ./scripts/install.sh --plugins=claudecode # Claude Code only
1394
+ ./scripts/install.sh --plugins=cursor # Cursor only
1395
+ ./scripts/install.sh --plugins=opencode,claudecode,cursor # csv form
1396
+ ./scripts/install.sh --plugins=all --plugins-scope=project # ./.opencode, ./.claude, ./.cursor
1383
1397
  ```
1384
1398
 
1385
1399
  Or install a single plugin directly without re-running the backend
@@ -1390,6 +1404,8 @@ installer:
1390
1404
  ./plugins/claude-code/install.sh # registers a local Claude Code
1391
1405
  # marketplace at the repo root and runs
1392
1406
  # `claude plugin install code-memory@code-memory`
1407
+ ./plugins/cursor/install.sh # ~/.cursor/hooks.json + mcp.json
1408
+ # (add --scope project for ./.cursor/)
1393
1409
  ```
1394
1410
 
1395
1411
  > **Claude Code only:** symlinking the plugin into `~/.claude/plugins/`
@@ -1744,7 +1760,7 @@ See `CHANGELOG.md` for the design rationale.
1744
1760
  - [x] `.gitignore`-aware walker that skips minified bundles + generated junk
1745
1761
  - [x] Resolved call / import edges (bind `CALLS` / `IMPORTS` to real nodes)
1746
1762
  - [x] Lightweight rerank (entrypoint / generated boost, idle-episode filter)
1747
- - [x] Harness plugins for OpenCode and Claude Code (auto-retrieve + auto-learn)
1763
+ - [x] Harness plugins for OpenCode and Claude Code (steering + auto-learn)
1748
1764
  - [x] `code-memory reset` CLI + auto-purge on `ingest --full`
1749
1765
  - [x] File-watcher daemon for live re-ingest (cross-platform via `watchdog`)
1750
1766
  - [x] Team-shared snapshots (orphan branch, content-addressed, model-aware verify)
@@ -0,0 +1,369 @@
1
+ <#
2
+ .SYNOPSIS
3
+ code-memory zero-clone installer (Windows PowerShell).
4
+
5
+ .DESCRIPTION
6
+ No `git clone` required. Installs the `code-memory` CLI via `uv`, drops
7
+ infra files into $HOME\.code-memory\, waits for Docker + Ollama,
8
+ pulls the bge-m3 embedding model (and optionally gemma2:9b for claim
9
+ extraction), and wires up the Claude Code plugin + MCP server.
10
+ Optionally installs the OpenCode plugin from npm.
11
+
12
+ Interactive by default. Pass -Yes to accept defaults; pass any -No*
13
+ switch to skip a step; pass -NonInteractive to refuse all prompts.
14
+
15
+ One-liner (interactive):
16
+ irm https://raw.githubusercontent.com/fmflurry/code-memory/main/install.ps1 | iex
17
+
18
+ Contributors hacking on the repo should still `git clone` and run
19
+ `scripts/install.ps1` instead.
20
+
21
+ .PARAMETER Yes
22
+ Accept default for every prompt (Claude=Y, OpenCode=N, claims=N).
23
+
24
+ .PARAMETER NonInteractive
25
+ Refuse all prompts; use defaults (same as -Yes but without confirmation).
26
+
27
+ .PARAMETER NoDocker
28
+ Skip starting FalkorDB + Qdrant via docker compose.
29
+
30
+ .PARAMETER NoOllama
31
+ Skip pulling bge-m3.
32
+
33
+ .PARAMETER NoClaude
34
+ Skip Claude Code marketplace + plugin registration.
35
+
36
+ .PARAMETER NoOpencode
37
+ Skip OpenCode plugin install from npm.
38
+
39
+ .PARAMETER NoMcp
40
+ Skip MCP server registration with Claude Code.
41
+
42
+ .PARAMETER NoClaims
43
+ Skip pulling gemma2:9b for claim extraction.
44
+
45
+ .PARAMETER WithClaims
46
+ Force-pull gemma2:9b without prompting.
47
+
48
+ .EXAMPLE
49
+ irm https://raw.githubusercontent.com/fmflurry/code-memory/main/install.ps1 | iex
50
+
51
+ .EXAMPLE
52
+ # Download then run with flags:
53
+ iwr https://raw.githubusercontent.com/fmflurry/code-memory/main/install.ps1 -OutFile install.ps1
54
+ ./install.ps1 -NoOpencode -NoOllama
55
+ #>
56
+
57
+ [CmdletBinding()]
58
+ param(
59
+ [switch]$Yes,
60
+ [switch]$NonInteractive,
61
+ [switch]$NoDocker,
62
+ [switch]$NoOllama,
63
+ [switch]$NoClaude,
64
+ [switch]$NoOpencode,
65
+ [switch]$NoMcp,
66
+ [switch]$NoClaims,
67
+ [switch]$WithClaims
68
+ )
69
+
70
+ $ErrorActionPreference = 'Stop'
71
+
72
+ $RepoUrl = if ($env:CODEMEMORY_REPO_URL) { $env:CODEMEMORY_REPO_URL } else { 'https://github.com/fmflurry/code-memory' }
73
+ $RawUrl = if ($env:CODEMEMORY_RAW_URL) { $env:CODEMEMORY_RAW_URL } else { 'https://raw.githubusercontent.com/fmflurry/code-memory/main' }
74
+ $HomeDir = if ($env:CODEMEMORY_HOME) { $env:CODEMEMORY_HOME } else { Join-Path $HOME '.code-memory' }
75
+ $NpmPkg = if ($env:CODEMEMORY_OPENCODE_PKG) { $env:CODEMEMORY_OPENCODE_PKG } else { 'code-memory-opencode' }
76
+
77
+ function Step($msg) { Write-Host "`n==> $msg" -ForegroundColor Cyan }
78
+ function Ok($msg) { Write-Host "[ok] $msg" -ForegroundColor Green }
79
+ function Warn($msg) { Write-Host "[warn] $msg" -ForegroundColor Yellow }
80
+ function Err($msg) { Write-Host "[err] $msg" -ForegroundColor Red }
81
+ function Dim($msg) { Write-Host " $msg" -ForegroundColor DarkGray }
82
+ function Test-Cmd($name) { return [bool](Get-Command $name -ErrorAction SilentlyContinue) }
83
+
84
+ function Test-Interactive() {
85
+ if ($NonInteractive) { return $false }
86
+ # Read-Host targets console host. When invoked via `irm | iex`, the
87
+ # console host is still attached, so prompts work even though stdin is
88
+ # the script body.
89
+ try {
90
+ return [Environment]::UserInteractive -and ($Host.Name -ne 'Default Host')
91
+ } catch { return $false }
92
+ }
93
+
94
+ # Returns $true for yes, $false for no.
95
+ function Ask-YesNo([string]$Prompt, [string]$Default = 'Y') {
96
+ $hint = if ($Default -match '^[Yy]') { '[Y/n]' } else { '[y/N]' }
97
+ $defaultYes = $Default -match '^[Yy]'
98
+ if ($Yes -or -not (Test-Interactive)) { return $defaultYes }
99
+ Write-Host "? $Prompt $hint " -ForegroundColor Yellow -NoNewline
100
+ $ans = Read-Host
101
+ if ([string]::IsNullOrWhiteSpace($ans)) { return $defaultYes }
102
+ return ($ans -match '^[Yy]')
103
+ }
104
+
105
+ # Waits until a CLI is on PATH. Returns $true if present, $false if user skipped.
106
+ function Wait-ForCmd([string]$Cmd, [string]$Label, [string]$Url) {
107
+ while (-not (Test-Cmd $Cmd)) {
108
+ Warn "$Label not found."
109
+ Dim "Install from: $Url"
110
+ if (-not (Test-Interactive)) {
111
+ Warn "non-interactive: skipping $Label"
112
+ return $false
113
+ }
114
+ Write-Host "? Press Enter once installed (or type 'skip' to skip): " -ForegroundColor Yellow -NoNewline
115
+ $ans = Read-Host
116
+ if ($ans -eq 'skip') { return $false }
117
+ # Refresh PATH from machine + user so newly installed tools show up
118
+ # without restarting the shell.
119
+ $env:Path = [System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + `
120
+ [System.Environment]::GetEnvironmentVariable('Path','User')
121
+ }
122
+ return $true
123
+ }
124
+
125
+ # ---------- 1. uv ----------
126
+ Step "Ensuring uv is installed"
127
+ if (Test-Cmd 'uv') {
128
+ Ok "uv $(uv --version 2>$null)"
129
+ } else {
130
+ # Run uv installer in a child powershell so its `exit` cannot tear down
131
+ # the parent session (especially when this script itself was launched via
132
+ # `irm | iex`).
133
+ $uvInstaller = Join-Path ([System.IO.Path]::GetTempPath()) ("uv-install-{0}.ps1" -f ([guid]::NewGuid()))
134
+ $prevEAP = $ErrorActionPreference
135
+ $ErrorActionPreference = 'Continue'
136
+ try {
137
+ Invoke-WebRequest -Uri 'https://astral.sh/uv/install.ps1' -OutFile $uvInstaller -UseBasicParsing
138
+ $psExe = (Get-Process -Id $PID).Path
139
+ if (-not $psExe) { $psExe = 'powershell.exe' }
140
+ & $psExe -NoProfile -ExecutionPolicy Bypass -File $uvInstaller
141
+ $uvExit = $LASTEXITCODE
142
+ if ($uvExit -ne 0) { throw "uv installer exited with code $uvExit" }
143
+ } catch {
144
+ Err "Failed to install uv: $($_.Exception.Message)"
145
+ Err "Install manually: winget install --id=astral-sh.uv -e then re-run."
146
+ exit 3
147
+ } finally {
148
+ Remove-Item $uvInstaller -ErrorAction SilentlyContinue
149
+ $ErrorActionPreference = $prevEAP
150
+ }
151
+ $env:Path = "$HOME\.local\bin;$HOME\.cargo\bin;$env:Path"
152
+ if (-not (Test-Cmd 'uv')) {
153
+ Err "uv installed but not on PATH; re-open shell and re-run."
154
+ exit 3
155
+ }
156
+ Ok "uv installed"
157
+ }
158
+
159
+ # ---------- 2. code-memory CLI ----------
160
+ Step "Installing code-memory CLI"
161
+ & uv tool install --force --from "git+$RepoUrl" flurryx-code-memory
162
+ if ($LASTEXITCODE -ne 0) { Err "uv tool install failed"; exit 1 }
163
+ $cliPath = (Get-Command code-memory -ErrorAction SilentlyContinue)
164
+ Ok "code-memory CLI: $($cliPath.Source)"
165
+
166
+ # ---------- 3. side files ----------
167
+ Step "Writing infra files to $HomeDir"
168
+ New-Item -ItemType Directory -Force -Path (Join-Path $HomeDir 'docker') | Out-Null
169
+ Invoke-WebRequest -Uri "$RawUrl/docker/docker-compose.yml" -OutFile (Join-Path $HomeDir 'docker/docker-compose.yml') -UseBasicParsing
170
+ Ok "wrote $HomeDir\docker\docker-compose.yml"
171
+ $envFile = Join-Path $HomeDir '.env'
172
+ if (-not (Test-Path $envFile)) {
173
+ Invoke-WebRequest -Uri "$RawUrl/.env.example" -OutFile $envFile -UseBasicParsing
174
+ Ok "wrote $envFile (from .env.example)"
175
+ } else {
176
+ Ok ".env already present (not overwritten)"
177
+ }
178
+
179
+ # ---------- 4. docker ----------
180
+ $doDocker = -not $NoDocker
181
+ if ($doDocker -and -not $Yes -and (Test-Interactive)) {
182
+ $doDocker = Ask-YesNo "Start FalkorDB + Qdrant via Docker?" "Y"
183
+ }
184
+ if ($doDocker) {
185
+ Step "Starting FalkorDB + Qdrant"
186
+ if (Wait-ForCmd 'docker' 'Docker Desktop' 'https://www.docker.com/products/docker-desktop') {
187
+ # ensure daemon up
188
+ & docker info *>$null
189
+ if ($LASTEXITCODE -ne 0) {
190
+ Warn "Docker CLI present but daemon not running. Start Docker Desktop."
191
+ if (Test-Interactive) {
192
+ Write-Host "? Press Enter once the daemon is up (or 'skip'): " -ForegroundColor Yellow -NoNewline
193
+ $ans = Read-Host
194
+ if ($ans -eq 'skip') { $doDocker = $false }
195
+ }
196
+ }
197
+ if ($doDocker) {
198
+ & docker compose -f (Join-Path $HomeDir 'docker/docker-compose.yml') --project-directory $HomeDir up -d
199
+ if ($LASTEXITCODE -ne 0) {
200
+ Warn "docker compose up failed"
201
+ } else {
202
+ Ok "containers up"
203
+ Dim "FalkorDB browser: http://localhost:3000"
204
+ Dim "Qdrant dashboard: http://localhost:6333/dashboard"
205
+ }
206
+ }
207
+ } else {
208
+ Warn "docker step skipped"
209
+ }
210
+ } else {
211
+ Warn "docker step skipped"
212
+ }
213
+
214
+ # ---------- 5. ollama ----------
215
+ $doOllama = -not $NoOllama
216
+ if ($doOllama -and -not $Yes -and (Test-Interactive)) {
217
+ $doOllama = Ask-YesNo "Pull embedding model via Ollama?" "Y"
218
+ }
219
+ if ($doOllama) {
220
+ Step "Embedding model (bge-m3)"
221
+ if (Wait-ForCmd 'ollama' 'Ollama' 'https://ollama.com/download/windows') {
222
+ & ollama list 2>$null | Out-Null
223
+ if ($LASTEXITCODE -ne 0) {
224
+ try { Start-Process -FilePath 'ollama' -ArgumentList 'serve' -WindowStyle Hidden -ErrorAction Stop } catch {}
225
+ for ($i = 0; $i -lt 30; $i++) {
226
+ Start-Sleep -Seconds 1
227
+ & ollama list 2>$null | Out-Null
228
+ if ($LASTEXITCODE -eq 0) { break }
229
+ }
230
+ }
231
+ $models = (& ollama list 2>$null) -join "`n"
232
+ if ($models -match '(?m)^bge-m3(\s|:)') {
233
+ Ok "bge-m3 already present"
234
+ } else {
235
+ & ollama pull bge-m3
236
+ if ($LASTEXITCODE -eq 0) { Ok "bge-m3 pulled" } else { Warn "ollama pull bge-m3 returned exit $LASTEXITCODE" }
237
+ }
238
+
239
+ # optional gemma2:9b for claim extraction
240
+ $doClaims = $false
241
+ if ($WithClaims) {
242
+ $doClaims = $true
243
+ } elseif (-not $NoClaims) {
244
+ $doClaims = Ask-YesNo "Also pull gemma2:9b for user-claim extraction (~5.4 GB)?" "N"
245
+ }
246
+ if ($doClaims) {
247
+ $models2 = (& ollama list 2>$null) -join "`n"
248
+ if ($models2 -match '(?m)^gemma2:9b\s') {
249
+ Ok "gemma2:9b already present"
250
+ } else {
251
+ & ollama pull gemma2:9b
252
+ if ($LASTEXITCODE -eq 0) { Ok "gemma2:9b pulled" } else { Warn "ollama pull gemma2:9b returned exit $LASTEXITCODE" }
253
+ }
254
+ }
255
+ } else {
256
+ Warn "ollama step skipped"
257
+ }
258
+ } else {
259
+ Warn "ollama step skipped"
260
+ }
261
+
262
+ # ---------- 6. Claude Code ----------
263
+ $doClaude = -not $NoClaude
264
+ if ($doClaude -and -not $Yes -and (Test-Interactive)) {
265
+ $doClaude = Ask-YesNo "Install Claude Code plugin + MCP?" "Y"
266
+ }
267
+ if ($doClaude) {
268
+ if (-not (Test-Cmd 'claude')) {
269
+ Step "Installing Claude Code CLI"
270
+ $claudeInstaller = Join-Path ([System.IO.Path]::GetTempPath()) ("claude-install-{0}.ps1" -f ([guid]::NewGuid()))
271
+ $prevEAP = $ErrorActionPreference
272
+ $ErrorActionPreference = 'Continue'
273
+ try {
274
+ Invoke-WebRequest -Uri 'https://claude.ai/install.ps1' -OutFile $claudeInstaller -UseBasicParsing
275
+ $psExe = (Get-Process -Id $PID).Path
276
+ if (-not $psExe) { $psExe = 'powershell.exe' }
277
+ & $psExe -NoProfile -ExecutionPolicy Bypass -File $claudeInstaller
278
+ if ($LASTEXITCODE -ne 0) { Warn "claude installer exited with code $LASTEXITCODE" }
279
+ } catch {
280
+ Warn "claude install failed: $($_.Exception.Message)"
281
+ } finally {
282
+ Remove-Item $claudeInstaller -ErrorAction SilentlyContinue
283
+ $ErrorActionPreference = $prevEAP
284
+ }
285
+ # Refresh PATH from machine + user so the freshly installed claude shim is visible.
286
+ $env:Path = [System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + `
287
+ [System.Environment]::GetEnvironmentVariable('Path','User') + ';' + `
288
+ "$HOME\.local\bin"
289
+ }
290
+ if (-not (Test-Cmd 'claude')) {
291
+ Warn "claude CLI still not found after install attempt — skipping Claude Code plugin"
292
+ Dim "Install manually: https://docs.anthropic.com/claude/docs/claude-code"
293
+ } else {
294
+ Step "Registering Claude Code plugin + MCP"
295
+ & claude plugin marketplace add $RepoUrl 2>$null
296
+ if ($LASTEXITCODE -ne 0) { Warn "marketplace add failed (may already be registered)" }
297
+
298
+ $pluginList = & claude plugin list 2>$null
299
+ if ($pluginList -match 'code-memory@code-memory') {
300
+ Ok "plugin already installed"
301
+ } else {
302
+ & claude plugin install code-memory@code-memory --scope user
303
+ if ($LASTEXITCODE -eq 0) { Ok "plugin installed" } else { Warn "plugin install failed" }
304
+ }
305
+
306
+ if (-not $NoMcp) {
307
+ $mcpList = & claude mcp list 2>$null
308
+ if ($mcpList -match '(?m)^\s*code-memory\s') {
309
+ Ok "MCP already registered"
310
+ } else {
311
+ & claude mcp add code-memory `
312
+ --scope user `
313
+ -e CODE_MEMORY_PROJECT=auto `
314
+ -- uvx --from "git+$RepoUrl" code-memory-mcp
315
+ if ($LASTEXITCODE -eq 0) { Ok "MCP registered (restart Claude Code to pick it up)" }
316
+ else { Warn "claude mcp add failed; see README §MCP server" }
317
+ }
318
+ }
319
+ }
320
+ } else {
321
+ Warn "Claude Code step skipped"
322
+ }
323
+
324
+ # ---------- 7. OpenCode ----------
325
+ $doOpencode = -not $NoOpencode -and ($Yes -or $false)
326
+ # OpenCode defaults to N — only prompt if not explicitly skipped.
327
+ if (-not $NoOpencode -and -not $Yes -and (Test-Interactive)) {
328
+ $doOpencode = Ask-YesNo "Install OpenCode plugin (npm global)?" "N"
329
+ } elseif ($Yes) {
330
+ $doOpencode = $false # -Yes accepts the default (N) for OpenCode
331
+ }
332
+ if ($doOpencode) {
333
+ Step "Installing OpenCode plugin"
334
+ if (-not (Test-Cmd 'npm')) {
335
+ Warn "npm not found — skipping. Install Node.js, then: npm i -g $NpmPkg ; code-memory-opencode-install"
336
+ } else {
337
+ & npm i -g $NpmPkg
338
+ if ($LASTEXITCODE -ne 0) {
339
+ Warn "npm install failed"
340
+ } elseif (Test-Cmd 'code-memory-opencode-install') {
341
+ & code-memory-opencode-install
342
+ } else {
343
+ Warn "$NpmPkg installed but code-memory-opencode-install not on PATH"
344
+ Warn "Add npm global bin to PATH (npm bin -g) and re-run: code-memory-opencode-install"
345
+ }
346
+ }
347
+ } else {
348
+ Warn "OpenCode step skipped"
349
+ }
350
+
351
+ # ---------- done ----------
352
+ Step "Done"
353
+ @"
354
+
355
+ Side files: $HomeDir\
356
+ CLI: $(if ($cliPath) { $cliPath.Source } else { 'code-memory (not on PATH)' })
357
+
358
+ Ingest a repo:
359
+ code-memory ingest C:\path\to\repo
360
+
361
+ Query:
362
+ code-memory retrieve "where is the auth middleware?"
363
+
364
+ Browse:
365
+ FalkorDB http://localhost:3000
366
+ Qdrant http://localhost:6333/dashboard
367
+
368
+ Edit defaults: $HomeDir\.env
369
+ "@ | Write-Host