feat(install): SQLite-first plugin install — full hook experience, zero system PostgreSQL - #160
Merged
Conversation
New mcp_server/infrastructure/backend_marker.py: the installer persists its provisioned backend to ~/.claude/methodology/backend.json (backend NAME only, never a URL) and scripts/launcher.py — the single entry point for the MCP server and every hook — resolves it into CORTEX_MEMORY_STORE_BACKEND at launch. Precedence guarantees an operator's explicit configuration (CORTEX_MEMORY_STORE_BACKEND, CORTEX_BACKEND, DATABASE_URL, CORTEX_MEMORY_DATABASE_URL) always wins, so an existing PostgreSQL install can never be silently downgraded to SQLite by a plugin update. The launcher also stops injecting the PostgreSQL DATABASE_URL default when the resolved backend is sqlite, and normalizes the plugin manifest's now-empty user_config URL to absent. Engine backend selection (memory_store) is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…opt-in The plugin postInstall now defaults to the zero-config SQLite path on every OS: Python deps + verification only — no brew/apt PostgreSQL, no pgvector, no eager embedding-model download (the model fetches lazily on first encode; embedding_engine's download log now states the ~100 MB one-time size and cache location, figure per PRIVACY.md / the pre-cache step it replaces). install-plugin.sh gains a --postgres flag (and CORTEX_BACKEND=postgres env) that runs the previous full path, and an existing PostgreSQL install is auto-detected (env URL, prior marker, or a reachable local cortex database at 127.0.0.1:5432) and kept — never downgraded. The provisioned backend is persisted to the backend marker via Path.home() inside python (Windows Git Bash $HOME is POSIX-style and native python.exe would misresolve it). plugin.json's postInstall message now matches reality and user_config.database_url defaults to empty (set it only to opt into PostgreSQL). scripts/setup.py's SQLite mode is promoted from CI-testing convenience to the supported plugin default and skips the eager model pre-cache; the PostgreSQL path keeps it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On the zero-config SQLite default the two context-injecting hooks previously spoke raw psycopg SQL and degraded to nothing (session_start even printed brew-install-PostgreSQL instructions). Both now branch on the resolved backend (backend_marker.effective_backend) and go through the store abstraction: session_start builds the same banner (checkpoint + anchors + hot memories + injection receipt via emit_injection_receipt) from SqliteMemoryStore; auto_recall runs an FTS5 recall with the PG contract (heat floor, protected-first, benchmarks excluded, receipts). The FTS query is built from stopword-stripped OR'd terms because FTS5's unicode61 tokenizer has no stemming/stopwords — MATCHing the raw prompt ANDs every token and almost never hits (mirrors plainto_tsquery's stopword strip; terms are double-quoted so user text cannot inject FTS5 operators; term count bounded by the existing query[:200] cap). PG-only banner extras (team decisions, pending wiki curation, grooming staleness) are skipped on SQLite — disclosed in README. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
doctor previously required PG driver / DATABASE_URL / connection / extensions unconditionally, so every zero-config SQLite install failed four checks and check_setup / /preflight reported a healthy install as broken. active_checks() now resolves the backend exactly like the launcher and hooks do (env var, then the installer's backend marker) and swaps the four PG checks for a single SQLite store-open check (SqliteMemoryStore's constructor runs DDL + migrations, so a successful open proves the storage path). check_setup consumes active_checks() instead of CHECKS; the PostgreSQL list is unchanged and remains the fallback on any resolution failure. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
README: the Claude Code plugin section is promoted out of the collapsed details block and rewritten — zero-config SQLite path first (deps only, lazy ~100 MB one-time model download, all hooks registered), the --postgres upgrade second with the one-line honest claim of what it adds (connection-pooled concurrency, server-side PL/pgSQL WRRF fusion, pgvector HNSW ANN at very large scale — figures already asserted in Under the Hood), plus an explicit disclosure of what SQLite mode does NOT do (in-process fusion without HNSW; team-decision injection, preemptive context, and pipeline heat-bumps degrade to silent no-ops). PRIVACY.md/CLAUDE.md/module-inventory stop asserting the plugin path is PostgreSQL. cortex-setup-project Phase 1 verifies via memory_stats first so a healthy SQLite install never triggers a PostgreSQL install. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The plugin install now delivers the complete experience (all 9 hooks + memory) with no system-level PostgreSQL: default backend is SQLite, provisioned by
setup.pywith pip deps only — no brew/apt, no pgvector, no eager model download. Postgres becomes the documented opt-in upgrade (install-plugin.sh --postgres).DATABASE_URL, prior backend marker, reachable localcortexDB at 127.0.0.1:5432) force the full PostgreSQL path — verified live against a real local Postgres.~/.claude/methodology/backend.json(name only, never a URL) and resolves at runtime via newmcp_server/infrastructure/backend_marker.py; any operator env var beats the marker.encode()prints size + cache dir + "then runs fully offline".session_start(full banner incl. receipts; previously printed brew-install instructions on SQLite) andauto_recall(FTS5 recall with stopword-stripped OR terms).doctor/check_setup//preflightare backend-aware.Test plan
ruff check+ruff format --checkclean🤖 Generated with Claude Code