flurryx-code-memory 0.5.1__tar.gz → 0.6.0__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 (196) hide show
  1. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/CHANGELOG.md +119 -0
  2. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/PKG-INFO +1 -1
  3. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/README.md +43 -26
  4. flurryx_code_memory-0.6.0/install.ps1 +369 -0
  5. flurryx_code_memory-0.6.0/install.sh +302 -0
  6. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/README.md +13 -17
  7. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/state.js +3 -31
  8. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-post-tool.js +4 -10
  9. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-pre-tool.js +4 -6
  10. flurryx_code_memory-0.6.0/plugins/claude-code/scripts/on-user-prompt.js +48 -0
  11. flurryx_code_memory-0.6.0/plugins/cursor/README.md +161 -0
  12. flurryx_code_memory-0.6.0/plugins/cursor/hooks/hooks.json.template +79 -0
  13. flurryx_code_memory-0.6.0/plugins/cursor/install.sh +231 -0
  14. flurryx_code_memory-0.6.0/plugins/cursor/rules/code-memory.mdc +39 -0
  15. flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/claim-intent.js +158 -0
  16. flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/claim-intent.test.js +159 -0
  17. flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/io.js +42 -0
  18. flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/memory.js +155 -0
  19. flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/state.js +176 -0
  20. flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-after-file-edit.js +57 -0
  21. flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-before-mcp-execution.js +22 -0
  22. flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-before-submit-prompt.js +43 -0
  23. flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-post-tool-use.js +33 -0
  24. flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-pre-compact.js +54 -0
  25. flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-pre-tool-use.js +54 -0
  26. flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-session-end.js +18 -0
  27. flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-session-start.js +36 -0
  28. flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-stop.js +54 -0
  29. flurryx_code_memory-0.6.0/plugins/cursor/scripts/resolver-debounce.js +44 -0
  30. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/README.md +24 -26
  31. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/src/code-memory.ts +14 -190
  32. flurryx_code_memory-0.6.0/plugins/vibe/README.md +117 -0
  33. flurryx_code_memory-0.6.0/plugins/vibe/install.sh +184 -0
  34. flurryx_code_memory-0.6.0/plugins/vibe/skills/code-memory/SKILL.md +62 -0
  35. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/pyproject.toml +1 -1
  36. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/install.ps1 +41 -19
  37. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/install.sh +50 -11
  38. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/indexer.py +79 -1
  39. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/store.py +12 -0
  40. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/cli.py +12 -0
  41. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/config.py +11 -0
  42. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/treesitter.py +538 -11
  43. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/mcp_server.py +49 -1
  44. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/__init__.py +7 -1
  45. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/base.py +35 -1
  46. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/launchd.py +35 -0
  47. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/safety.py +28 -0
  48. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/store.py +47 -2
  49. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/updater.py +98 -1
  50. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_autostart_adapters.py +38 -0
  51. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_claim_indexer.py +108 -2
  52. flurryx_code_memory-0.6.0/tests/test_extractor_dart.py +151 -0
  53. flurryx_code_memory-0.6.0/tests/test_extractor_receiver_type.py +192 -0
  54. flurryx_code_memory-0.6.0/tests/test_mcp_shutdown.py +91 -0
  55. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_watch_safety.py +56 -0
  56. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/uv.lock +56 -56
  57. flurryx_code_memory-0.5.1/install.ps1 +0 -217
  58. flurryx_code_memory-0.5.1/install.sh +0 -181
  59. flurryx_code_memory-0.5.1/plugins/claude-code/scripts/lib/format.js +0 -79
  60. flurryx_code_memory-0.5.1/plugins/claude-code/scripts/lib/intent.js +0 -53
  61. flurryx_code_memory-0.5.1/plugins/claude-code/scripts/on-user-prompt.js +0 -110
  62. flurryx_code_memory-0.5.1/plugins/opencode/src/code-memory-lib/intent.ts +0 -74
  63. flurryx_code_memory-0.5.1/tests/test_extractor_receiver_type.py +0 -98
  64. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/.claude-plugin/marketplace.json +0 -0
  65. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/.env.example +0 -0
  66. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/.gitignore +0 -0
  67. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docker/docker-compose.yml +0 -0
  68. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/BENCHMARK.md +0 -0
  69. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/BENCHMARK_VS_BASELINE.json +0 -0
  70. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/BENCHMARK_VS_BASELINE.md +0 -0
  71. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/architecture.png +0 -0
  72. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/benchmark-raw.json +0 -0
  73. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/hero.png +0 -0
  74. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  75. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/commands/code-memory.md +0 -0
  76. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/hooks/hooks.json +0 -0
  77. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/install.sh +0 -0
  78. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/claim-intent.js +0 -0
  79. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/claim-intent.test.js +0 -0
  80. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/io.js +0 -0
  81. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/memory.js +0 -0
  82. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-retrieve-seen.js +0 -0
  83. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-session-start.js +0 -0
  84. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-stop.js +0 -0
  85. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/resolver-debounce.js +0 -0
  86. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/skills/code-memory/SKILL.md +0 -0
  87. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/install.sh +0 -0
  88. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/package-lock.json +0 -0
  89. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/package.json +0 -0
  90. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/scripts/add-mcp.py +0 -0
  91. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/scripts/install.mjs +0 -0
  92. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/scripts/uninstall.mjs +0 -0
  93. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/skills/code-memory/SKILL.md +0 -0
  94. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/src/code-memory-lib/claim-intent.test.mts +0 -0
  95. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/src/code-memory-lib/claim-intent.ts +0 -0
  96. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/src/code-memory-lib/memory-client.ts +0 -0
  97. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/tsconfig.json +0 -0
  98. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/benchmark.py +0 -0
  99. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/benchmark_queries.json +0 -0
  100. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/benchmark_vs_baseline.py +0 -0
  101. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/benchmark_vs_grep.sh +0 -0
  102. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/ingest.py +0 -0
  103. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/__init__.py +0 -0
  104. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/__init__.py +0 -0
  105. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/extractor.py +0 -0
  106. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/resolver.py +0 -0
  107. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/__init__.py +0 -0
  108. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/cache.py +0 -0
  109. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/m3.py +0 -0
  110. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/ollama.py +0 -0
  111. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/tei.py +0 -0
  112. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/episodic/__init__.py +0 -0
  113. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/episodic/sqlite_store.py +0 -0
  114. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/__init__.py +0 -0
  115. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/csproj.py +0 -0
  116. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/dll.py +0 -0
  117. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/gitignore.py +0 -0
  118. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/nuget.py +0 -0
  119. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/sanity.py +0 -0
  120. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/sln.py +0 -0
  121. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/graph/__init__.py +0 -0
  122. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/graph/falkor_store.py +0 -0
  123. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/metrics.py +0 -0
  124. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/__init__.py +0 -0
  125. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/git_delta.py +0 -0
  126. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/ingest_state.py +0 -0
  127. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/pipeline.py +0 -0
  128. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/reset.py +0 -0
  129. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/resolver.py +0 -0
  130. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/retrieve.py +0 -0
  131. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/resilience.py +0 -0
  132. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/__init__.py +0 -0
  133. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/schtasks.py +0 -0
  134. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/systemd.py +0 -0
  135. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/hooks.py +0 -0
  136. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/snapshot.py +0 -0
  137. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/sync.py +0 -0
  138. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/watcher.py +0 -0
  139. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/vector/__init__.py +0 -0
  140. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/vector/qdrant_store.py +0 -0
  141. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_chunk_text.py +0 -0
  142. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_claim_extractor.py +0 -0
  143. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_claim_resolver.py +0 -0
  144. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_claim_store.py +0 -0
  145. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_config_embed_dim.py +0 -0
  146. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_config_sentinel.py +0 -0
  147. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_csproj.py +0 -0
  148. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_dll_members.py +0 -0
  149. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_dll_parser.py +0 -0
  150. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_embed_backend.py +0 -0
  151. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_embed_cache.py +0 -0
  152. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_embed_m3.py +0 -0
  153. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_embed_tei.py +0 -0
  154. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_episode_dedup.py +0 -0
  155. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_episode_head_sha.py +0 -0
  156. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_csharp.py +0 -0
  157. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_filters.py +0 -0
  158. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_php.py +0 -0
  159. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_python_imports.py +0 -0
  160. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_references.py +0 -0
  161. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_sanity.py +0 -0
  162. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_ts_abstract.py +0 -0
  163. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_ts_inject.py +0 -0
  164. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_utf8.py +0 -0
  165. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_file_containment.py +0 -0
  166. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_git_delta.py +0 -0
  167. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_graph_queries.py +0 -0
  168. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_graph_temporal.py +0 -0
  169. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_graph_vacuum_at_sha.py +0 -0
  170. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_hooks_installer.py +0 -0
  171. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_ingest_state.py +0 -0
  172. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_mcp_assert_claim.py +0 -0
  173. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_mcp_server_descriptions.py +0 -0
  174. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_mcp_strict_project.py +0 -0
  175. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_metrics.py +0 -0
  176. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_nuget_resolver.py +0 -0
  177. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_overload_resolution.py +0 -0
  178. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_partial_class.py +0 -0
  179. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_pipeline_references.py +0 -0
  180. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_pipeline_temporal_wiring.py +0 -0
  181. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_qdrant_legacy_guard.py +0 -0
  182. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_razor_inject.py +0 -0
  183. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_resilience.py +0 -0
  184. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_resolver.py +0 -0
  185. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_resolver_assembly.py +0 -0
  186. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_retrieve_claims_surfacing.py +0 -0
  187. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_retrieve_rerank.py +0 -0
  188. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_sln.py +0 -0
  189. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_smoke.py +0 -0
  190. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_snapshot_e2e.py +0 -0
  191. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_snapshot_format.py +0 -0
  192. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_snapshot_store.py +0 -0
  193. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_sync_decision_tree.py +0 -0
  194. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_watcher_debouncer.py +0 -0
  195. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_watcher_exclude.py +0 -0
  196. {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_watcher_ref_events.py +0 -0
@@ -8,6 +8,125 @@ when the repo grows.
8
8
  This file complements `git log`: commits explain mechanics, this file
9
9
  explains intent.
10
10
 
11
+ ## [0.6.0] — 2026-06-04
12
+
13
+ Release theme: **Dart joins the graph, and `this.field.method()` resolves
14
+ across languages**. The extractor gains a ninth language and the
15
+ receiver-type tier — previously TypeScript-only — now narrows method
16
+ calls in C#, PHP, and Dart too.
17
+
18
+ ### Added — Dart / Flutter language support
19
+
20
+ **What:** `.dart` files are now parsed. Symbols cover classes, mixins,
21
+ enums, extensions, typedefs, top-level functions, methods,
22
+ getters/setters, and constructors (with parameter arity); imports and
23
+ re-exports surface their URI (`package:…`, `dart:…`, relative); calls and
24
+ type references (inheritance, field/parameter/return types, generic
25
+ arguments) are extracted. Dart's grammar differs structurally from the
26
+ other languages — function names follow the return type inside
27
+ `function_signature`, calls are a `selector` + `argument_part` chain
28
+ rather than a single call-expression node, and import URIs are nested
29
+ under `configurable_uri > uri` — so each needed dedicated handling.
30
+ Node-type names that collide with TypeScript (`function_signature`,
31
+ `declaration`, …) are gated on `lang == "dart"` so TS output is
32
+ unchanged.
33
+
34
+ **Reason:** Flutter/Dart codebases were a blind spot — every `.dart`
35
+ file was skipped at `lang_for`, so half of a mobile + backend stack had
36
+ no graph topology, leaving retrieval to dense vectors alone.
37
+
38
+ ### Added — Cross-language receiver-type inference (C#, PHP, Dart)
39
+
40
+ **What:** the `this.<field>.<method>()` narrowing that let the resolver
41
+ disambiguate a call against the methods of the field's declared type now
42
+ works beyond TypeScript. The class-scope stack is language-aware: C#
43
+ reads fields, properties, and C# 12 primary-constructor parameters and
44
+ resolves both `_repo.Get()` and `this.Bar.Save()`; PHP reads properties
45
+ and PHP 8 constructor promotion and resolves `$this->repo->m()`; Dart
46
+ reads typed fields and resolves `repo.m()` / `this.repo.m()`. A shared
47
+ `_bare_type_name` reduces qualified / generic / nullable types to the
48
+ bare identifier the resolver matches on, dropping primitives.
49
+
50
+ **Reason:** the resolver's receiver tier is language-agnostic — it
51
+ matches a bare type name against files defining that symbol — but the
52
+ extractor only ever emitted `receiver_type` for TS. On C#/PHP/Dart, a
53
+ method call like `byId` collapsed to a bare identifier that the resolver
54
+ could never narrow against the dozens of same-named methods elsewhere in
55
+ the codebase. Emitting the inferred receiver type fixes that with no
56
+ resolver changes.
57
+
58
+ ## [0.5.3] — 2026-06-04
59
+
60
+ Release theme: **git operations never block on credentials**. The
61
+ snapshot store talked to `origin` with plain `git fetch` / `git push`
62
+ and nothing to suppress interactive auth. On any HTTPS remote without
63
+ cached credentials that froze the MCP server at boot and re-prompted on
64
+ every `code-memory status` and watcher tick.
65
+
66
+ ### Fixed — Interactive git credential prompts froze the MCP server
67
+
68
+ **What:** every best-effort / read git call in `SnapshotStore` (`fetch`,
69
+ listing, the snapshot existence check) now runs with
70
+ `GIT_TERMINAL_PROMPT=0`, `GIT_SSH_COMMAND=ssh -oBatchMode=yes`, and an
71
+ empty `-c credential.helper=` so it fails fast instead of blocking. Only
72
+ the explicit publish path (`push` during `snapshot publish` / `gc`) opts
73
+ back into credentials via `allow_credentials=True`, so opted-in remotes
74
+ still authenticate.
75
+
76
+ **Reason:** `GIT_TERMINAL_PROMPT=0` alone was not enough — a configured
77
+ credential helper such as Git Credential Manager is a separate program
78
+ git still launches, and it pops its own dialog. The MCP bootstrap runs a
79
+ synchronous `sync_repo(trigger="mcp-boot")` with `fetch=True`; on an
80
+ auth-required remote that `git fetch` hung waiting for a password the
81
+ stdio server could never supply, so OpenCode reported the server as not
82
+ running. The watcher's per-quiet-period sync and `code-memory status`
83
+ hit the same wall. Resetting the helper list makes git return in ~0.1s
84
+ (no remote snapshots) instead of waiting on a human.
85
+
86
+ ## [0.5.2] — 2026-05-30
87
+
88
+ Release theme: **the watcher stops leaking**. A diagnosis of runaway RAM
89
+ turned up dozens of orphaned `code-memory watch` daemons — one permanent
90
+ launchd agent per directory any MCP server had ever booted in, including
91
+ throwaway per-session dirs. This release stops the bleed and self-heals
92
+ the cruft. Also lands semantic dedupe for near-duplicate user claims.
93
+
94
+ ### Fixed — Unbounded launchd watcher accumulation
95
+
96
+ **What:** `ensure_autostart()` no longer registers a persistent OS agent
97
+ for ephemeral / per-session directories (`~/.claude/homunculus/*`,
98
+ `.cursor/worktrees/*`, `plugins/cache/*`); the session-scoped in-process
99
+ watcher still covers them. `LaunchdAdapter.prune_stale()` (run on every
100
+ MCP bootstrap) boots out and removes agents whose `WorkingDirectory` is
101
+ gone or ephemeral.
102
+
103
+ **Reason:** each MCP boot registered a `KeepAlive` + `RunAtLoad` agent for
104
+ its cwd. Ephemeral session dirs got permanent watchers that survived kill
105
+ (launchd relaunched them) and reboot, piling up dozens of daemons and the
106
+ RAM/CPU they pin. `prune_stale` is launchd-only for now; systemd/schtasks
107
+ GC is a follow-up.
108
+
109
+ ### Fixed — Graceful watcher teardown on MCP shutdown
110
+
111
+ **What:** the MCP server registers `atexit` + `SIGTERM` handlers that call
112
+ `Watcher.stop()`.
113
+
114
+ **Reason:** the in-process watcher ran as a daemon thread with no clean
115
+ stop, so an in-flight debounced sync was dropped and the watchdog Observer
116
+ never joined cleanly on exit.
117
+
118
+ ### Added — Semantic dedupe of near-duplicate claims
119
+
120
+ **What:** `ClaimsIndexer` collapses a new claim into the closest open claim
121
+ when cosine similarity is `>= CLAIMS_SEMANTIC_DEDUP_THRESHOLD` (default
122
+ 0.90), ahead of the SQL write.
123
+
124
+ **Reason:** exact (subject, predicate, object) dedupe missed paraphrases
125
+ ("project uses flurryx" / "project depends-on flurryx"), so semantically
126
+ identical claims were stored three times. Best-effort — embedder/backend
127
+ errors fall through to the existing SQL-level dedupe; set `>= 1.0` to
128
+ disable.
129
+
11
130
  ## [0.3.0] — 2026-05-26
12
131
 
13
132
  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.1
3
+ Version: 0.6.0
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)
@@ -1756,6 +1772,7 @@ See `CHANGELOG.md` for the design rationale.
1756
1772
  - [x] `code-memory vacuum --before <sha>` / `--older-than` / `--all` (tombstone GC)
1757
1773
  - [x] MCP tools: `codememory_drift`, `codememory_at_sha`, `codememory_callers_at_sha`
1758
1774
  - [x] .NET ecosystem (C#, Razor, VB.NET, F#)
1775
+ - [x] Dart / Flutter (classes, mixins, enums, extensions, typedefs, imports/exports, calls, type refs)
1759
1776
  - [ ] More languages (Rust, Go, Java)
1760
1777
  - [ ] Cursor hook recipe
1761
1778
  - [ ] PyPI release (drops the `--from git+…` from the `uvx` install)
@@ -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