flurryx-code-memory 0.4.0__tar.gz → 0.5.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.4.0 → flurryx_code_memory-0.5.0}/PKG-INFO +1 -1
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/README.md +74 -5
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/pyproject.toml +1 -1
- flurryx_code_memory-0.5.0/src/code_memory/__init__.py +8 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/cli.py +55 -0
- flurryx_code_memory-0.5.0/src/code_memory/updater.py +396 -0
- flurryx_code_memory-0.4.0/src/code_memory/__init__.py +0 -1
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/.claude-plugin/marketplace.json +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/.env.example +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/.gitignore +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/CHANGELOG.md +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/docker/docker-compose.yml +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/docs/BENCHMARK.md +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/docs/BENCHMARK_VS_BASELINE.json +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/docs/BENCHMARK_VS_BASELINE.md +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/docs/architecture.png +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/docs/benchmark-raw.json +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/docs/hero.png +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/install.ps1 +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/install.sh +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/README.md +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/commands/code-memory.md +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/hooks/hooks.json +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/install.sh +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/claim-intent.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/claim-intent.test.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/format.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/intent.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/io.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/memory.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/state.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/on-post-tool.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/on-pre-tool.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/on-retrieve-seen.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/on-session-start.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/on-stop.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/on-user-prompt.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/resolver-debounce.js +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/skills/code-memory/SKILL.md +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/README.md +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/install.sh +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/package-lock.json +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/package.json +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/scripts/add-mcp.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/scripts/install.mjs +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/scripts/uninstall.mjs +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/skills/code-memory/SKILL.md +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/src/code-memory-lib/claim-intent.test.mts +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/src/code-memory-lib/claim-intent.ts +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/src/code-memory-lib/intent.ts +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/src/code-memory-lib/memory-client.ts +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/src/code-memory.ts +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/opencode/tsconfig.json +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/scripts/benchmark.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/scripts/benchmark_queries.json +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/scripts/benchmark_vs_baseline.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/scripts/benchmark_vs_grep.sh +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/scripts/ingest.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/scripts/install.ps1 +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/scripts/install.sh +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/claims/__init__.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/claims/extractor.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/claims/indexer.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/claims/resolver.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/claims/store.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/config.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/embed/__init__.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/embed/cache.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/embed/m3.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/embed/ollama.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/embed/tei.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/episodic/__init__.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/episodic/sqlite_store.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/extractor/__init__.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/extractor/csproj.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/extractor/dll.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/extractor/gitignore.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/extractor/nuget.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/extractor/sanity.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/extractor/sln.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/extractor/treesitter.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/graph/__init__.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/graph/falkor_store.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/mcp_server.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/metrics.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/orchestrator/__init__.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/orchestrator/git_delta.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/orchestrator/ingest_state.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/orchestrator/pipeline.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/orchestrator/reset.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/orchestrator/resolver.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/orchestrator/retrieve.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/resilience.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/__init__.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/autostart/__init__.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/autostart/base.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/autostart/launchd.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/autostart/schtasks.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/autostart/systemd.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/hooks.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/safety.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/snapshot.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/store.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/sync.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/sync/watcher.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/vector/__init__.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/src/code_memory/vector/qdrant_store.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_autostart_adapters.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_chunk_text.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_claim_extractor.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_claim_indexer.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_claim_resolver.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_claim_store.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_config_embed_dim.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_config_sentinel.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_csproj.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_dll_members.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_dll_parser.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_embed_backend.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_embed_cache.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_embed_m3.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_embed_tei.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_episode_dedup.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_episode_head_sha.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_csharp.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_filters.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_php.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_python_imports.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_receiver_type.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_references.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_sanity.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_ts_abstract.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_ts_inject.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_extractor_utf8.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_file_containment.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_git_delta.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_graph_queries.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_graph_temporal.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_graph_vacuum_at_sha.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_hooks_installer.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_ingest_state.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_mcp_assert_claim.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_mcp_server_descriptions.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_mcp_strict_project.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_metrics.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_nuget_resolver.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_overload_resolution.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_partial_class.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_pipeline_references.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_pipeline_temporal_wiring.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_qdrant_legacy_guard.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_razor_inject.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_resilience.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_resolver.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_resolver_assembly.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_retrieve_claims_surfacing.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_retrieve_rerank.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_sln.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_smoke.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_snapshot_e2e.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_snapshot_format.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_snapshot_store.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_sync_decision_tree.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_watch_safety.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_watcher_debouncer.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_watcher_exclude.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/tests/test_watcher_ref_events.py +0 -0
- {flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/uv.lock +0 -0
|
@@ -17,7 +17,7 @@ Structural symbol graph · semantic vector recall · epi
|
|
|
17
17
|
[](https://tree-sitter.github.io/)
|
|
18
18
|
[](LICENSE)
|
|
19
19
|
|
|
20
|
-
**Jump to:** [Get it running](#installation) · [Plug it into your agent](#mcp-server) · [How it scores vs `rg`](#benchmarks)
|
|
20
|
+
**Jump to:** [Get it running](#installation) · [Update it](#updating) · [Plug it into your agent](#mcp-server) · [How it scores vs `rg`](#benchmarks)
|
|
21
21
|
|
|
22
22
|
</div>
|
|
23
23
|
|
|
@@ -66,6 +66,22 @@ _Full tables + methodology in [Benchmarks](#benchmarks)._
|
|
|
66
66
|
|
|
67
67
|
## Installation
|
|
68
68
|
|
|
69
|
+
> [!TIP]
|
|
70
|
+
> ### 🔄 Already installed? Update in one command.
|
|
71
|
+
>
|
|
72
|
+
> ```bash
|
|
73
|
+
> code-memory update # smart refresh: CLI + Docker images + present Ollama models + plugins
|
|
74
|
+
> code-memory update --check # dry-run: print current vs latest, exit non-zero if behind
|
|
75
|
+
> code-memory update --full # re-run the one-liner installer (adds anything missing)
|
|
76
|
+
> ```
|
|
77
|
+
>
|
|
78
|
+
> `update` is **idempotent and selective** — it only touches components that are already
|
|
79
|
+
> installed locally. No re-prompting for extras you opted out of, no docker churn if
|
|
80
|
+
> compose isn't on this machine. Run it weekly, or after a release announcement.
|
|
81
|
+
>
|
|
82
|
+
> Bleeding edge from `main`: `code-memory update --bleeding`. Full details below in
|
|
83
|
+
> [Updating](#updating).
|
|
84
|
+
|
|
69
85
|
`code-memory` installs in **one command**. Pick your OS, paste it, you're done.
|
|
70
86
|
|
|
71
87
|
**🍎 macOS**
|
|
@@ -154,8 +170,13 @@ iwr https://raw.githubusercontent.com/fmflurry/code-memory/main/install.ps1 -Out
|
|
|
154
170
|
<summary><strong>Manual install (à la carte, no one-liner)</strong></summary>
|
|
155
171
|
|
|
156
172
|
```bash
|
|
157
|
-
# 1. CLI (
|
|
158
|
-
uv tool install
|
|
173
|
+
# 1. CLI (PyPI — recommended)
|
|
174
|
+
uv tool install flurryx-code-memory
|
|
175
|
+
# or: pipx install flurryx-code-memory
|
|
176
|
+
# or: pip install flurryx-code-memory
|
|
177
|
+
#
|
|
178
|
+
# Bleeding edge from main:
|
|
179
|
+
# uv tool install --from git+https://github.com/fmflurry/code-memory flurryx-code-memory
|
|
159
180
|
|
|
160
181
|
# 2. Infra (compose + env)
|
|
161
182
|
mkdir -p ~/.code-memory/docker
|
|
@@ -173,7 +194,7 @@ claude plugin marketplace add https://github.com/fmflurry/code-memory
|
|
|
173
194
|
claude plugin install code-memory@code-memory --scope user
|
|
174
195
|
claude mcp add code-memory --scope user \
|
|
175
196
|
-e CODE_MEMORY_PROJECT=auto \
|
|
176
|
-
-- uvx --from
|
|
197
|
+
-- uvx --from flurryx-code-memory code-memory-mcp
|
|
177
198
|
|
|
178
199
|
# 5. OpenCode plugin
|
|
179
200
|
npm i -g code-memory-opencode
|
|
@@ -189,7 +210,7 @@ Just the Claude Code MCP server — no auto-retrieve / auto-record hooks, no Doc
|
|
|
189
210
|
|
|
190
211
|
```bash
|
|
191
212
|
claude mcp add code-memory \
|
|
192
|
-
-- uvx --from
|
|
213
|
+
-- uvx --from flurryx-code-memory code-memory-mcp
|
|
193
214
|
```
|
|
194
215
|
|
|
195
216
|
</details>
|
|
@@ -238,6 +259,54 @@ cd code-memory
|
|
|
238
259
|
|
|
239
260
|
---
|
|
240
261
|
|
|
262
|
+
## Updating
|
|
263
|
+
|
|
264
|
+
After the initial install, never run the one-liner again — use the built-in updater:
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
code-memory update # smart, idempotent, no re-prompts
|
|
268
|
+
code-memory update --check # dry-run; exit 1 if behind, 0 if current
|
|
269
|
+
code-memory update --full # behave like a fresh one-liner install
|
|
270
|
+
code-memory update --bleeding # install CLI from git+main instead of PyPI
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### What it does
|
|
274
|
+
|
|
275
|
+
`update` introspects your machine and refreshes **only what is already installed**:
|
|
276
|
+
|
|
277
|
+
| Component | Detection | Refresh action |
|
|
278
|
+
| --------------------------- | ------------------------------------------------------ | ------------------------------------------------- |
|
|
279
|
+
| **CLI** | `sys.prefix` (uv tool / pipx / pip / editable) | upgrade via the same channel |
|
|
280
|
+
| **FalkorDB + Qdrant** | `~/.code-memory/docker/docker-compose.yml` or running | `docker compose pull && up -d` |
|
|
281
|
+
| **Ollama models** | present in `ollama list` (`bge-m3`, `gemma2:9b`, …) | `ollama pull <model>` (only for already-pulled) |
|
|
282
|
+
| **Claude Code plugin** | `claude plugin list \| grep code-memory` | `claude plugin install … --force` |
|
|
283
|
+
| **OpenCode plugin** | `npm ls -g code-memory-opencode` | `npm i -g code-memory-opencode` |
|
|
284
|
+
| **Python extras** | `FlagEmbedding` / `dnfile` import probe | covered by the CLI upgrade |
|
|
285
|
+
|
|
286
|
+
Anything you **didn't** install stays untouched. No "do you want gemma?" prompt, no
|
|
287
|
+
docker churn on a machine that hits remote infra, no plugin re-registration if you
|
|
288
|
+
deliberately removed it.
|
|
289
|
+
|
|
290
|
+
### Sample output
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
$ code-memory update --check
|
|
294
|
+
code-memory updater (install: uv-tool)
|
|
295
|
+
CLI: 0.4.0 → latest: 0.5.0
|
|
296
|
+
Components detected locally:
|
|
297
|
+
• Docker: FalkorDB (running)
|
|
298
|
+
• Docker: Qdrant (running)
|
|
299
|
+
• Ollama: bge-m3
|
|
300
|
+
· Ollama: gemma2:9b [not installed — skip]
|
|
301
|
+
• Claude Code plugin
|
|
302
|
+
• Claude Code MCP
|
|
303
|
+
· OpenCode plugin (npm) [not installed — skip]
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Use `code-memory update --check` from CI or a cron to nudge devs when a release ships.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
241
310
|
## What is this?
|
|
242
311
|
|
|
243
312
|
`code-memory` gives a coding agent (Claude Code, OpenCode, Cursor, your own harness) a memory it can actually use:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "flurryx-code-memory"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.0"
|
|
8
8
|
description = "Local lightweight memory layer for coding agents: FalkorDB + Qdrant + Ollama (BGE-M3) + tree-sitter"
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
dependencies = [
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version as _pkg_version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = _pkg_version("flurryx-code-memory")
|
|
7
|
+
except PackageNotFoundError: # editable / source checkout without install
|
|
8
|
+
__version__ = "0.0.0+local"
|
|
@@ -27,6 +27,28 @@ def _graph_for(project: str | None) -> FalkorStore:
|
|
|
27
27
|
app = typer.Typer(no_args_is_help=True, add_completion=False, help="code-memory CLI")
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
def _version_callback(value: bool) -> None:
|
|
31
|
+
if value:
|
|
32
|
+
from . import __version__
|
|
33
|
+
|
|
34
|
+
typer.echo(__version__)
|
|
35
|
+
raise typer.Exit()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@app.callback()
|
|
39
|
+
def _main(
|
|
40
|
+
version: bool = typer.Option(
|
|
41
|
+
False,
|
|
42
|
+
"--version",
|
|
43
|
+
"-V",
|
|
44
|
+
callback=_version_callback,
|
|
45
|
+
is_eager=True,
|
|
46
|
+
help="Print version and exit.",
|
|
47
|
+
),
|
|
48
|
+
) -> None:
|
|
49
|
+
"""code-memory CLI."""
|
|
50
|
+
|
|
51
|
+
|
|
30
52
|
ProjectOpt = typer.Option(
|
|
31
53
|
None,
|
|
32
54
|
"--project",
|
|
@@ -1188,5 +1210,38 @@ def autostart_status(
|
|
|
1188
1210
|
)
|
|
1189
1211
|
|
|
1190
1212
|
|
|
1213
|
+
@app.command()
|
|
1214
|
+
def update(
|
|
1215
|
+
check: bool = typer.Option(
|
|
1216
|
+
False,
|
|
1217
|
+
"--check",
|
|
1218
|
+
help="Only print the current/latest state and exit (no changes).",
|
|
1219
|
+
),
|
|
1220
|
+
full: bool = typer.Option(
|
|
1221
|
+
False,
|
|
1222
|
+
"--full",
|
|
1223
|
+
help="Re-run the one-liner installer (refresh docker/env/plugins from scratch).",
|
|
1224
|
+
),
|
|
1225
|
+
bleeding: bool = typer.Option(
|
|
1226
|
+
False,
|
|
1227
|
+
"--bleeding",
|
|
1228
|
+
help="Install CLI from git+main instead of PyPI.",
|
|
1229
|
+
),
|
|
1230
|
+
) -> None:
|
|
1231
|
+
"""Smart-update code-memory: refresh only components already installed locally.
|
|
1232
|
+
|
|
1233
|
+
Default behavior detects the CLI install method (uv tool / pipx / pip) and
|
|
1234
|
+
upgrades it in place, then refreshes Docker images, present Ollama models,
|
|
1235
|
+
and registered Claude/OpenCode plugins. Pieces that were never installed
|
|
1236
|
+
stay untouched — no prompts, no re-asking.
|
|
1237
|
+
|
|
1238
|
+
Use ``--check`` for a dry-run, ``--full`` to behave like a fresh install.
|
|
1239
|
+
"""
|
|
1240
|
+
from .updater import run_update
|
|
1241
|
+
|
|
1242
|
+
rc = run_update(check_only=check, full=full, bleeding=bleeding)
|
|
1243
|
+
raise typer.Exit(code=rc)
|
|
1244
|
+
|
|
1245
|
+
|
|
1191
1246
|
if __name__ == "__main__":
|
|
1192
1247
|
app()
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
"""Smart updater for code-memory.
|
|
2
|
+
|
|
3
|
+
Detects which components are already installed locally and refreshes
|
|
4
|
+
only those — never asks the user to re-confirm pieces they already opted
|
|
5
|
+
into during the initial one-liner install.
|
|
6
|
+
|
|
7
|
+
Components inspected:
|
|
8
|
+
|
|
9
|
+
* CLI install method (``uv tool`` / ``pipx`` / ``pip``) + version vs PyPI
|
|
10
|
+
* Docker stack (FalkorDB + Qdrant)
|
|
11
|
+
* Ollama models present locally (``bge-m3``, optionally ``gemma2:9b``)
|
|
12
|
+
* Optional Python extras (``hybrid`` via ``FlagEmbedding``, ``dotnet`` via ``dnfile``)
|
|
13
|
+
* Claude Code plugin + MCP server registration
|
|
14
|
+
* OpenCode global npm package
|
|
15
|
+
|
|
16
|
+
The update flow is intentionally idempotent and noisy-on-change only:
|
|
17
|
+
already-current items print one line each, anything actually upgraded
|
|
18
|
+
prints its old/new state.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import importlib.util
|
|
24
|
+
import json
|
|
25
|
+
import os
|
|
26
|
+
import shutil
|
|
27
|
+
import subprocess
|
|
28
|
+
import sys
|
|
29
|
+
from dataclasses import dataclass, field
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
from typing import Literal
|
|
32
|
+
|
|
33
|
+
import httpx
|
|
34
|
+
|
|
35
|
+
from . import __version__ as _LOCAL_VERSION
|
|
36
|
+
|
|
37
|
+
PYPI_PACKAGE = "flurryx-code-memory"
|
|
38
|
+
DEFAULT_REPO_URL = os.environ.get(
|
|
39
|
+
"CODEMEMORY_REPO_URL", "https://github.com/fmflurry/code-memory"
|
|
40
|
+
)
|
|
41
|
+
CODEMEMORY_HOME = Path(os.environ.get("CODEMEMORY_HOME", str(Path.home() / ".code-memory")))
|
|
42
|
+
|
|
43
|
+
InstallMethod = Literal["uv-tool", "pipx", "pip", "editable", "unknown"]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class ComponentState:
|
|
48
|
+
name: str
|
|
49
|
+
present: bool
|
|
50
|
+
detail: str = ""
|
|
51
|
+
current: str | None = None
|
|
52
|
+
latest: str | None = None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class UpdatePlan:
|
|
57
|
+
install_method: InstallMethod
|
|
58
|
+
components: list[ComponentState] = field(default_factory=list)
|
|
59
|
+
cli_current: str = ""
|
|
60
|
+
cli_latest: str = ""
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# ---------- detection ----------
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _run(cmd: list[str], *, check: bool = False, capture: bool = True) -> subprocess.CompletedProcess[str]:
|
|
67
|
+
return subprocess.run(
|
|
68
|
+
cmd, check=check, capture_output=capture, text=True, env={**os.environ}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _have(binary: str) -> bool:
|
|
73
|
+
return shutil.which(binary) is not None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def current_cli_version() -> str:
|
|
77
|
+
return _LOCAL_VERSION
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def latest_pypi_version(pkg: str = PYPI_PACKAGE, *, timeout: float = 5.0) -> str | None:
|
|
81
|
+
try:
|
|
82
|
+
r = httpx.get(f"https://pypi.org/pypi/{pkg}/json", timeout=timeout)
|
|
83
|
+
r.raise_for_status()
|
|
84
|
+
return r.json()["info"]["version"]
|
|
85
|
+
except Exception: # noqa: BLE001
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def detect_install_method() -> InstallMethod:
|
|
90
|
+
"""Best-effort: where is the running interpreter living?
|
|
91
|
+
|
|
92
|
+
Editable installs are detected via PEP 610 ``direct_url.json``;
|
|
93
|
+
uv tool / pipx are detected from ``sys.prefix`` (the venv root),
|
|
94
|
+
not ``sys.executable`` which on macOS often resolves through a
|
|
95
|
+
symlink into Homebrew/conda.
|
|
96
|
+
"""
|
|
97
|
+
if _is_editable_install():
|
|
98
|
+
return "editable"
|
|
99
|
+
|
|
100
|
+
prefix = str(Path(sys.prefix).resolve()).lower()
|
|
101
|
+
if "/uv/tools/" in prefix or "\\uv\\tools\\" in prefix:
|
|
102
|
+
return "uv-tool"
|
|
103
|
+
if "/pipx/venvs/" in prefix or "\\pipx\\venvs\\" in prefix:
|
|
104
|
+
return "pipx"
|
|
105
|
+
if _have("pip") and _pip_shows():
|
|
106
|
+
return "pip"
|
|
107
|
+
return "unknown"
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _is_editable_install() -> bool:
|
|
111
|
+
try:
|
|
112
|
+
from importlib.metadata import distribution
|
|
113
|
+
|
|
114
|
+
d = distribution(PYPI_PACKAGE)
|
|
115
|
+
raw = d.read_text("direct_url.json") or ""
|
|
116
|
+
if not raw:
|
|
117
|
+
return False
|
|
118
|
+
return bool(json.loads(raw).get("dir_info", {}).get("editable"))
|
|
119
|
+
except Exception: # noqa: BLE001
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _pip_shows() -> bool:
|
|
124
|
+
p = _run([sys.executable, "-m", "pip", "show", PYPI_PACKAGE])
|
|
125
|
+
return p.returncode == 0
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _ollama_models() -> list[str]:
|
|
129
|
+
if not _have("ollama"):
|
|
130
|
+
return []
|
|
131
|
+
p = _run(["ollama", "list"])
|
|
132
|
+
if p.returncode != 0:
|
|
133
|
+
return []
|
|
134
|
+
names: list[str] = []
|
|
135
|
+
for line in p.stdout.splitlines()[1:]:
|
|
136
|
+
first = line.split()
|
|
137
|
+
if first:
|
|
138
|
+
names.append(first[0])
|
|
139
|
+
return names
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _docker_compose_present() -> bool:
|
|
143
|
+
return (CODEMEMORY_HOME / "docker" / "docker-compose.yml").exists()
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _docker_running(service: str) -> bool:
|
|
147
|
+
if not _have("docker"):
|
|
148
|
+
return False
|
|
149
|
+
p = _run(["docker", "ps", "--format", "{{.Names}}"])
|
|
150
|
+
if p.returncode != 0:
|
|
151
|
+
return False
|
|
152
|
+
return any(service in name for name in p.stdout.splitlines())
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _claude_plugin_present() -> bool:
|
|
156
|
+
if not _have("claude"):
|
|
157
|
+
return False
|
|
158
|
+
p = _run(["claude", "plugin", "list"])
|
|
159
|
+
return p.returncode == 0 and "code-memory" in p.stdout
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _claude_mcp_present() -> bool:
|
|
163
|
+
if not _have("claude"):
|
|
164
|
+
return False
|
|
165
|
+
p = _run(["claude", "mcp", "list"])
|
|
166
|
+
return p.returncode == 0 and "code-memory" in p.stdout
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _npm_pkg_present(pkg: str = "code-memory-opencode") -> bool:
|
|
170
|
+
if not _have("npm"):
|
|
171
|
+
return False
|
|
172
|
+
p = _run(["npm", "ls", "-g", "--depth=0", "--json"])
|
|
173
|
+
if p.returncode != 0:
|
|
174
|
+
return False
|
|
175
|
+
try:
|
|
176
|
+
deps = json.loads(p.stdout).get("dependencies", {})
|
|
177
|
+
return pkg in deps
|
|
178
|
+
except Exception: # noqa: BLE001
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _python_module_present(mod: str) -> bool:
|
|
183
|
+
return importlib.util.find_spec(mod) is not None
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def build_plan() -> UpdatePlan:
|
|
187
|
+
plan = UpdatePlan(install_method=detect_install_method())
|
|
188
|
+
plan.cli_current = current_cli_version()
|
|
189
|
+
plan.cli_latest = latest_pypi_version() or "?"
|
|
190
|
+
|
|
191
|
+
falkor_running = _docker_running("falkor")
|
|
192
|
+
qdrant_running = _docker_running("qdrant")
|
|
193
|
+
compose_here = _docker_compose_present()
|
|
194
|
+
|
|
195
|
+
plan.components = [
|
|
196
|
+
ComponentState(
|
|
197
|
+
name="CLI (flurryx-code-memory)",
|
|
198
|
+
present=True,
|
|
199
|
+
detail=f"via {plan.install_method}",
|
|
200
|
+
current=plan.cli_current,
|
|
201
|
+
latest=plan.cli_latest,
|
|
202
|
+
),
|
|
203
|
+
ComponentState(
|
|
204
|
+
name="Docker: FalkorDB",
|
|
205
|
+
present=compose_here or falkor_running,
|
|
206
|
+
detail="running" if falkor_running else ("compose present" if compose_here else "stopped"),
|
|
207
|
+
),
|
|
208
|
+
ComponentState(
|
|
209
|
+
name="Docker: Qdrant",
|
|
210
|
+
present=compose_here or qdrant_running,
|
|
211
|
+
detail="running" if qdrant_running else ("compose present" if compose_here else "stopped"),
|
|
212
|
+
),
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
models = _ollama_models()
|
|
216
|
+
for m in ("bge-m3", "gemma2:9b"):
|
|
217
|
+
plan.components.append(
|
|
218
|
+
ComponentState(
|
|
219
|
+
name=f"Ollama: {m}",
|
|
220
|
+
present=any(name.startswith(m) for name in models),
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
plan.components.append(
|
|
225
|
+
ComponentState(
|
|
226
|
+
name="Extra: hybrid (FlagEmbedding)",
|
|
227
|
+
present=_python_module_present("FlagEmbedding"),
|
|
228
|
+
)
|
|
229
|
+
)
|
|
230
|
+
plan.components.append(
|
|
231
|
+
ComponentState(
|
|
232
|
+
name="Extra: dotnet (dnfile)",
|
|
233
|
+
present=_python_module_present("dnfile"),
|
|
234
|
+
)
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
plan.components.append(
|
|
238
|
+
ComponentState(name="Claude Code plugin", present=_claude_plugin_present())
|
|
239
|
+
)
|
|
240
|
+
plan.components.append(
|
|
241
|
+
ComponentState(name="Claude Code MCP", present=_claude_mcp_present())
|
|
242
|
+
)
|
|
243
|
+
plan.components.append(
|
|
244
|
+
ComponentState(name="OpenCode plugin (npm)", present=_npm_pkg_present())
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
return plan
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# ---------- upgrade actions ----------
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def upgrade_cli(method: InstallMethod, *, bleeding: bool = False) -> tuple[bool, str]:
|
|
254
|
+
"""Upgrade the CLI in-place via the same channel it was installed from."""
|
|
255
|
+
source = f"git+{DEFAULT_REPO_URL}" if bleeding else PYPI_PACKAGE
|
|
256
|
+
if method == "uv-tool":
|
|
257
|
+
if bleeding:
|
|
258
|
+
cmd = ["uv", "tool", "install", "--force", "--from", source, "code-memory"]
|
|
259
|
+
else:
|
|
260
|
+
cmd = ["uv", "tool", "upgrade", PYPI_PACKAGE]
|
|
261
|
+
elif method == "pipx":
|
|
262
|
+
cmd = ["pipx", "upgrade", PYPI_PACKAGE] if not bleeding else [
|
|
263
|
+
"pipx", "install", "--force", source
|
|
264
|
+
]
|
|
265
|
+
elif method == "pip":
|
|
266
|
+
cmd = [sys.executable, "-m", "pip", "install", "--upgrade", source]
|
|
267
|
+
elif method == "editable":
|
|
268
|
+
return False, "editable install — `git pull` in the repo to update"
|
|
269
|
+
else:
|
|
270
|
+
return False, "unknown install method — re-run the one-liner installer"
|
|
271
|
+
p = _run(cmd, capture=False)
|
|
272
|
+
return p.returncode == 0, " ".join(cmd)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def upgrade_docker_images() -> tuple[bool, str]:
|
|
276
|
+
if not _docker_compose_present() or not _have("docker"):
|
|
277
|
+
return False, "skipped (no compose / docker)"
|
|
278
|
+
compose = CODEMEMORY_HOME / "docker" / "docker-compose.yml"
|
|
279
|
+
pull = _run(
|
|
280
|
+
["docker", "compose", "-f", str(compose), "--project-directory", str(CODEMEMORY_HOME), "pull"],
|
|
281
|
+
capture=False,
|
|
282
|
+
)
|
|
283
|
+
if pull.returncode != 0:
|
|
284
|
+
return False, "docker compose pull failed"
|
|
285
|
+
up = _run(
|
|
286
|
+
["docker", "compose", "-f", str(compose), "--project-directory", str(CODEMEMORY_HOME), "up", "-d"],
|
|
287
|
+
capture=False,
|
|
288
|
+
)
|
|
289
|
+
return up.returncode == 0, "compose pulled + up"
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def upgrade_ollama_model(model: str) -> tuple[bool, str]:
|
|
293
|
+
if not _have("ollama"):
|
|
294
|
+
return False, "ollama not on PATH"
|
|
295
|
+
p = _run(["ollama", "pull", model], capture=False)
|
|
296
|
+
return p.returncode == 0, f"pulled {model}"
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def upgrade_claude_plugin() -> tuple[bool, str]:
|
|
300
|
+
if not _have("claude"):
|
|
301
|
+
return False, "claude CLI not on PATH"
|
|
302
|
+
# `claude plugin install` is idempotent — re-pin to latest from marketplace
|
|
303
|
+
p = _run(
|
|
304
|
+
["claude", "plugin", "install", "code-memory@code-memory", "--scope", "user", "--force"],
|
|
305
|
+
capture=False,
|
|
306
|
+
)
|
|
307
|
+
return p.returncode == 0, "claude plugin refreshed"
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def upgrade_npm_pkg(pkg: str = "code-memory-opencode") -> tuple[bool, str]:
|
|
311
|
+
if not _have("npm"):
|
|
312
|
+
return False, "npm not on PATH"
|
|
313
|
+
p = _run(["npm", "i", "-g", pkg], capture=False)
|
|
314
|
+
return p.returncode == 0, f"npm i -g {pkg}"
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
# ---------- orchestrator ----------
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def run_update(*, check_only: bool, full: bool, bleeding: bool) -> int:
|
|
321
|
+
"""Top-level entry point used by the CLI.
|
|
322
|
+
|
|
323
|
+
``check_only`` prints the plan and exits 0/1 based on whether anything
|
|
324
|
+
is behind. ``full`` re-runs the one-liner installer (curl … | bash).
|
|
325
|
+
Default is the smart path: upgrade-in-place only what is already present.
|
|
326
|
+
"""
|
|
327
|
+
plan = build_plan()
|
|
328
|
+
_print_plan(plan)
|
|
329
|
+
|
|
330
|
+
behind_cli = plan.cli_latest not in ("?", plan.cli_current)
|
|
331
|
+
|
|
332
|
+
if check_only:
|
|
333
|
+
return 1 if behind_cli else 0
|
|
334
|
+
|
|
335
|
+
if full:
|
|
336
|
+
return _run_full_installer()
|
|
337
|
+
|
|
338
|
+
rc = 0
|
|
339
|
+
if behind_cli:
|
|
340
|
+
ok, detail = upgrade_cli(plan.install_method, bleeding=bleeding)
|
|
341
|
+
print(f" CLI upgrade: {'ok' if ok else 'FAILED'} — {detail}")
|
|
342
|
+
rc |= 0 if ok else 1
|
|
343
|
+
else:
|
|
344
|
+
print(f" CLI: already {plan.cli_current}")
|
|
345
|
+
|
|
346
|
+
for comp in plan.components:
|
|
347
|
+
if not comp.present:
|
|
348
|
+
continue
|
|
349
|
+
if comp.name == "Docker: FalkorDB" or comp.name == "Docker: Qdrant":
|
|
350
|
+
# one pass for both
|
|
351
|
+
continue
|
|
352
|
+
if comp.name.startswith("Ollama: "):
|
|
353
|
+
model = comp.name.split(": ", 1)[1]
|
|
354
|
+
ok, detail = upgrade_ollama_model(model)
|
|
355
|
+
print(f" {comp.name}: {'ok' if ok else 'skip'} — {detail}")
|
|
356
|
+
elif comp.name == "Claude Code plugin":
|
|
357
|
+
ok, detail = upgrade_claude_plugin()
|
|
358
|
+
print(f" {comp.name}: {'ok' if ok else 'skip'} — {detail}")
|
|
359
|
+
elif comp.name == "OpenCode plugin (npm)":
|
|
360
|
+
ok, detail = upgrade_npm_pkg()
|
|
361
|
+
print(f" {comp.name}: {'ok' if ok else 'skip'} — {detail}")
|
|
362
|
+
|
|
363
|
+
if any(c.present for c in plan.components if c.name.startswith("Docker:")):
|
|
364
|
+
ok, detail = upgrade_docker_images()
|
|
365
|
+
print(f" Docker stack: {'ok' if ok else 'skip'} — {detail}")
|
|
366
|
+
|
|
367
|
+
return rc
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def _print_plan(plan: UpdatePlan) -> None:
|
|
371
|
+
print(f"code-memory updater (install: {plan.install_method})")
|
|
372
|
+
print(f" CLI: {plan.cli_current} → latest: {plan.cli_latest}")
|
|
373
|
+
print(" Components detected locally:")
|
|
374
|
+
for c in plan.components[1:]: # skip CLI row, already shown
|
|
375
|
+
mark = "•" if c.present else "·"
|
|
376
|
+
suffix = f" ({c.detail})" if c.detail else ""
|
|
377
|
+
state = "" if c.present else " [not installed — skip]"
|
|
378
|
+
print(f" {mark} {c.name}{suffix}{state}")
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def _run_full_installer() -> int:
|
|
382
|
+
"""Pipe the one-liner installer through bash (or PowerShell on Windows)."""
|
|
383
|
+
raw = os.environ.get(
|
|
384
|
+
"CODEMEMORY_RAW_URL", "https://raw.githubusercontent.com/fmflurry/code-memory/main"
|
|
385
|
+
)
|
|
386
|
+
if sys.platform == "win32":
|
|
387
|
+
cmd = [
|
|
388
|
+
"powershell",
|
|
389
|
+
"-NoProfile",
|
|
390
|
+
"-Command",
|
|
391
|
+
f"irm {raw}/install.ps1 | iex",
|
|
392
|
+
]
|
|
393
|
+
else:
|
|
394
|
+
cmd = ["bash", "-c", f"curl -fsSL {raw}/install.sh | bash"]
|
|
395
|
+
p = _run(cmd, capture=False)
|
|
396
|
+
return p.returncode
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/commands/code-memory.md
RENAMED
|
File without changes
|
{flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/hooks/hooks.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/format.js
RENAMED
|
File without changes
|
{flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/intent.js
RENAMED
|
File without changes
|
{flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/io.js
RENAMED
|
File without changes
|
{flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/memory.js
RENAMED
|
File without changes
|
{flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/lib/state.js
RENAMED
|
File without changes
|
{flurryx_code_memory-0.4.0 → flurryx_code_memory-0.5.0}/plugins/claude-code/scripts/on-post-tool.js
RENAMED
|
File without changes
|