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.
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/CHANGELOG.md +119 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/PKG-INFO +1 -1
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/README.md +43 -26
- flurryx_code_memory-0.6.0/install.ps1 +369 -0
- flurryx_code_memory-0.6.0/install.sh +302 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/README.md +13 -17
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/state.js +3 -31
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-post-tool.js +4 -10
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-pre-tool.js +4 -6
- flurryx_code_memory-0.6.0/plugins/claude-code/scripts/on-user-prompt.js +48 -0
- flurryx_code_memory-0.6.0/plugins/cursor/README.md +161 -0
- flurryx_code_memory-0.6.0/plugins/cursor/hooks/hooks.json.template +79 -0
- flurryx_code_memory-0.6.0/plugins/cursor/install.sh +231 -0
- flurryx_code_memory-0.6.0/plugins/cursor/rules/code-memory.mdc +39 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/claim-intent.js +158 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/claim-intent.test.js +159 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/io.js +42 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/memory.js +155 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/lib/state.js +176 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-after-file-edit.js +57 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-before-mcp-execution.js +22 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-before-submit-prompt.js +43 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-post-tool-use.js +33 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-pre-compact.js +54 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-pre-tool-use.js +54 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-session-end.js +18 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-session-start.js +36 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/on-stop.js +54 -0
- flurryx_code_memory-0.6.0/plugins/cursor/scripts/resolver-debounce.js +44 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/README.md +24 -26
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/src/code-memory.ts +14 -190
- flurryx_code_memory-0.6.0/plugins/vibe/README.md +117 -0
- flurryx_code_memory-0.6.0/plugins/vibe/install.sh +184 -0
- flurryx_code_memory-0.6.0/plugins/vibe/skills/code-memory/SKILL.md +62 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/pyproject.toml +1 -1
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/install.ps1 +41 -19
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/install.sh +50 -11
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/indexer.py +79 -1
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/store.py +12 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/cli.py +12 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/config.py +11 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/treesitter.py +538 -11
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/mcp_server.py +49 -1
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/__init__.py +7 -1
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/base.py +35 -1
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/launchd.py +35 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/safety.py +28 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/store.py +47 -2
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/updater.py +98 -1
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_autostart_adapters.py +38 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_claim_indexer.py +108 -2
- flurryx_code_memory-0.6.0/tests/test_extractor_dart.py +151 -0
- flurryx_code_memory-0.6.0/tests/test_extractor_receiver_type.py +192 -0
- flurryx_code_memory-0.6.0/tests/test_mcp_shutdown.py +91 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_watch_safety.py +56 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/uv.lock +56 -56
- flurryx_code_memory-0.5.1/install.ps1 +0 -217
- flurryx_code_memory-0.5.1/install.sh +0 -181
- flurryx_code_memory-0.5.1/plugins/claude-code/scripts/lib/format.js +0 -79
- flurryx_code_memory-0.5.1/plugins/claude-code/scripts/lib/intent.js +0 -53
- flurryx_code_memory-0.5.1/plugins/claude-code/scripts/on-user-prompt.js +0 -110
- flurryx_code_memory-0.5.1/plugins/opencode/src/code-memory-lib/intent.ts +0 -74
- flurryx_code_memory-0.5.1/tests/test_extractor_receiver_type.py +0 -98
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/.claude-plugin/marketplace.json +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/.env.example +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/.gitignore +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docker/docker-compose.yml +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/BENCHMARK.md +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/BENCHMARK_VS_BASELINE.json +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/BENCHMARK_VS_BASELINE.md +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/architecture.png +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/benchmark-raw.json +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/docs/hero.png +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/commands/code-memory.md +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/hooks/hooks.json +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/install.sh +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/claim-intent.js +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/claim-intent.test.js +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/io.js +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/lib/memory.js +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-retrieve-seen.js +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-session-start.js +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/on-stop.js +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/scripts/resolver-debounce.js +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/claude-code/skills/code-memory/SKILL.md +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/install.sh +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/package-lock.json +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/package.json +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/scripts/add-mcp.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/scripts/install.mjs +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/scripts/uninstall.mjs +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/skills/code-memory/SKILL.md +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/src/code-memory-lib/claim-intent.test.mts +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/src/code-memory-lib/claim-intent.ts +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/src/code-memory-lib/memory-client.ts +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/plugins/opencode/tsconfig.json +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/benchmark.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/benchmark_queries.json +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/benchmark_vs_baseline.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/benchmark_vs_grep.sh +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/scripts/ingest.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/__init__.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/__init__.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/extractor.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/claims/resolver.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/__init__.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/cache.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/m3.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/ollama.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/embed/tei.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/episodic/__init__.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/episodic/sqlite_store.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/__init__.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/csproj.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/dll.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/gitignore.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/nuget.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/sanity.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/extractor/sln.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/graph/__init__.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/graph/falkor_store.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/metrics.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/__init__.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/git_delta.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/ingest_state.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/pipeline.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/reset.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/resolver.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/orchestrator/retrieve.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/resilience.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/__init__.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/schtasks.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/autostart/systemd.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/hooks.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/snapshot.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/sync.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/sync/watcher.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/vector/__init__.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/src/code_memory/vector/qdrant_store.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_chunk_text.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_claim_extractor.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_claim_resolver.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_claim_store.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_config_embed_dim.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_config_sentinel.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_csproj.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_dll_members.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_dll_parser.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_embed_backend.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_embed_cache.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_embed_m3.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_embed_tei.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_episode_dedup.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_episode_head_sha.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_csharp.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_filters.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_php.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_python_imports.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_references.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_sanity.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_ts_abstract.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_ts_inject.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_extractor_utf8.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_file_containment.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_git_delta.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_graph_queries.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_graph_temporal.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_graph_vacuum_at_sha.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_hooks_installer.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_ingest_state.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_mcp_assert_claim.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_mcp_server_descriptions.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_mcp_strict_project.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_metrics.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_nuget_resolver.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_overload_resolution.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_partial_class.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_pipeline_references.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_pipeline_temporal_wiring.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_qdrant_legacy_guard.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_razor_inject.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_resilience.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_resolver.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_resolver_assembly.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_retrieve_claims_surfacing.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_retrieve_rerank.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_sln.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_smoke.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_snapshot_e2e.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_snapshot_format.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_snapshot_store.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_sync_decision_tree.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_watcher_debouncer.py +0 -0
- {flurryx_code_memory-0.5.1 → flurryx_code_memory-0.6.0}/tests/test_watcher_exclude.py +0 -0
- {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
|
|
@@ -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-
|
|
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** —
|
|
1345
|
-
|
|
1346
|
-
recording sessions as episodes when the agent stops
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
| Plugin
|
|
1351
|
-
|
|
|
1352
|
-
| [`plugins/opencode`](plugins/opencode/README.md)
|
|
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
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
-
|
|
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-
|
|
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
|
-
|
|
1374
|
-
|
|
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
|
|
1380
|
-
./scripts/install.sh --plugins=claudecode
|
|
1381
|
-
./scripts/install.sh --plugins=
|
|
1382
|
-
./scripts/install.sh --plugins=
|
|
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 (
|
|
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
|