@lotargo/memory_plugin 1.6.6 → 1.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +148 -101
  2. package/README.md +436 -304
  3. package/mcp-server/cli/direct_commands.js +39 -0
  4. package/mcp-server/cli.js +16 -5
  5. package/mcp-server/cli_boot.js +4 -1
  6. package/mcp-server/client_cli.js +73 -0
  7. package/mcp-server/client_paths.js +44 -0
  8. package/mcp-server/client_registration.js +38 -0
  9. package/mcp-server/codex_config.js +86 -8
  10. package/mcp-server/db/database.js +14 -21
  11. package/mcp-server/db/migrations.js +66 -77
  12. package/mcp-server/db/rag_blob_transport.js +143 -0
  13. package/mcp-server/db/rag_sync.js +284 -0
  14. package/mcp-server/db/sync_queue.js +219 -307
  15. package/mcp-server/dev_link.js +142 -0
  16. package/mcp-server/fact_format.js +44 -12
  17. package/mcp-server/index.js +17 -7
  18. package/mcp-server/ingest/exporter.js +44 -38
  19. package/mcp-server/ingest/normalizer.js +1 -1
  20. package/mcp-server/ingest/pipeline.js +260 -248
  21. package/mcp-server/persona_migration.js +39 -0
  22. package/mcp-server/prompt_manager.js +162 -55
  23. package/mcp-server/retrieval/retriever.js +99 -64
  24. package/mcp-server/setup.js +150 -100
  25. package/mcp-server/storage/blob_store.js +53 -1
  26. package/mcp-server/tools/core/knowledge_read_core.js +163 -0
  27. package/mcp-server/tools/core/memory_core.js +24 -4
  28. package/mcp-server/tools/core/memory_routing.js +10 -0
  29. package/mcp-server/tools/core/note_core.js +53 -0
  30. package/mcp-server/tools/core/rag_query_core.js +169 -0
  31. package/mcp-server/tools/index.js +11 -9
  32. package/mcp-server/tools/memory_tools.js +4 -1
  33. package/mcp-server/tools/note_tools.js +35 -0
  34. package/mcp-server/tools/rag_tools.js +211 -364
  35. package/mcp-server/uninstall.js +627 -0
  36. package/opencode-plugin/index.js +80 -12
  37. package/opencode-plugin/main.js +136 -0
  38. package/package.json +25 -5
  39. package/skills/using-memory/SKILL.md +28 -19
  40. package/mcp-server/benchmarks/fetch_real_corpus.js +0 -351
  41. package/mcp-server/benchmarks/gpu_profile_benchmark.js +0 -170
  42. package/mcp-server/benchmarks/policy_dominance_test.js +0 -221
  43. package/mcp-server/benchmarks/quality_evaluator.js +0 -598
  44. package/mcp-server/benchmarks/raw_corpus_data.js +0 -613
  45. package/mcp-server/benchmarks/run_benchmarks.js +0 -366
  46. package/mcp-server/benchmarks/stress_ingestion.js +0 -195
  47. package/mcp-server/benchmarks/table_code_retrieval.js +0 -453
  48. package/mcp-server/benchmarks/test_dual_layer.js +0 -141
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  <div align="center">
2
2
 
3
- <img src="./assets/hero.jpg" alt="@lotargo/memory_plugin" width="800" style="max-width: 100%; border-radius: 12px; margin-bottom: 16px;">
3
+ <img src="https://raw.githubusercontent.com/Lotargo/memory_plugin/main/assets/hero.jpg" alt="@lotargo/memory_plugin" width="800" style="max-width: 100%; border-radius: 12px; margin-bottom: 16px;">
4
4
 
5
5
  <br>
6
6
 
7
- <img src="./assets/title.svg" alt="@lotargo/memory_plugin" width="520" style="max-width: 100%; margin-bottom: 12px;">
7
+ <img src="https://raw.githubusercontent.com/Lotargo/memory_plugin/main/assets/title.svg" alt="@lotargo/memory_plugin" width="520" style="max-width: 100%; margin-bottom: 12px;">
8
8
 
9
9
  <br>
10
10
 
@@ -13,438 +13,570 @@
13
13
  [![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
14
14
  [![node version](https://img.shields.io/badge/node-%3E%3D22.5.0-brightgreen)](https://nodejs.org)
15
15
  [![mcp](https://img.shields.io/badge/MCP-Supported-8A2BE2)](https://modelcontextprotocol.io)
16
- [![storage](https://img.shields.io/badge/Storage-Local%20%2B%20Cloud%20Sync-success)](#storage--privacy)
16
+ [![storage](https://img.shields.io/badge/Storage-Local%20%2B%20Cloud%20Sync-success)](#storage-privacy-and-security)
17
17
 
18
18
  <br>
19
19
 
20
- **Zero-Docker Local Hybrid RAG Engine & Long-Term Memory for AI Coding Agents**
20
+ **Local-first long-term memory, hybrid RAG, and agent personalization for AI coding agents**
21
21
 
22
- Automatically remembers durable user facts, ingests complex document repositories, and performs high-precision hybrid retrieval across sessions, platforms, and devices.
22
+ One memory system for OpenCode, Codex, Claude Code, Gemini CLI, Antigravity, Google Jules, and other MCP clients.
23
23
 
24
24
  </div>
25
25
 
26
+ # @lotargo/memory_plugin — Local-First Memory, Hybrid RAG & Agent Personalization
27
+
26
28
  ---
27
29
 
28
- ## Overview
30
+ ## Why This Project Exists
31
+
32
+ AI coding assistants forget user preferences, architectural decisions, investigations, and project context when a session ends. They also tend to mix very different kinds of information into one oversized prompt.
29
33
 
30
- Standard AI coding assistants lose context as soon as a chat session closes or a conversation is reset. You end up repeatedly re-explaining your preferences, architectural decisions, coding style, or project conventions.
34
+ `@lotargo/memory_plugin` separates persistent knowledge into the right storage class:
35
+
36
+ | What you want to preserve | Tool | Storage behavior |
37
+ | :--- | :--- | :--- |
38
+ | Concise facts, preferences, constraints, conventions, and persona settings | `remember` | **Hot Notebook memory**; available during session initialization |
39
+ | Detailed decisions, research, investigations, experiments, and handoffs | `remember_note` | **Cold RAG Memory Note**; searchable but not injected into every session |
40
+ | Files, URLs, documentation, reports, specifications, and code | `ingest_document` | **Curated external knowledge** in the RAG index |
31
41
 
32
- `@lotargo/memory_plugin` gives your AI tools durable, **persistent**, local-first long-term memory and document retrieval capabilities that persist across restarts and work seamlessly across all supported coding environments. Any LLM-based coding agent (OpenCode, Claude Code, Codex, Antigravity / Gemini CLI) can query its own memory and hybrid knowledge base via the **Model Context Protocol (MCP)**.
42
+ The same engine adds Git-based project isolation, semantic search, full raw-source expansion, explicit fact-to-document links, optional Turso synchronization, and native OpenCode auto-injection.
33
43
 
34
- > **Project Scope & Runtime Notes**:
35
- > `@lotargo/memory_plugin` is designed primarily as a practical plugin to expand capabilities and streamline daily interaction with AI coding tools. Benchmark scores in this repository represent internal synthetic evaluation runs and are not intended as generalized RAG benchmarks.
36
- >
37
- > **Hardware Acceleration**: GPU execution mode is an experimental feature and may vary in stability across different operating systems or models. For optimal stability and consistent runtime performance, using standard CPU mode with `multilingual-e5-small` or `multilingual-e5-base` is recommended.
44
+ ### Highlights
38
45
 
39
- ### Practical Use Cases
46
+ - Human-readable Markdown Notebook facts with stable IDs, TTL, protection, tags, superseding, and explicit `fact` / `directive` semantics.
47
+ - Agent-authored long-form RAG Memory Notes for cold or episodic context.
48
+ - Hybrid SQLite FTS5 BM25 + local ONNX vector retrieval with RSF/RRF fusion.
49
+ - Compact semantic TOC discovery through `resultMode: "index"`, followed by deliberate full-source expansion.
50
+ - PDF, DOCX, XLSX/XLS/CSV, Markdown, text, HTML/URL, and source-code ingestion.
51
+ - Three-tier document hierarchy, retrieval-policy expansion for tables/code, and GraphRAG Lite symbol extraction.
52
+ - Git-identity project scopes that follow a repository across directories, machines, and operating systems.
53
+ - Active persona overlays shared across OpenCode, Codex, Claude Code, Gemini CLI, and Antigravity.
54
+ - Local-only, cloud-only, and bidirectional hybrid-sync modes, including portable raw RAG blobs and deletion tombstones.
55
+ - No Docker, external vector database, hosted embedding API, or telemetry.
40
56
 
41
- - **Architectural Decisions**: _"In this project, we use Fastify instead of Express and strict schema validation via Zod."_
42
- - **Coding Conventions**: _"Place all helper utilities inside `src/utils/` and cover new functions with Vitest tests."_
43
- - **Environment Constraints**: _"Our target deployment environment is Node.js 20 on AWS Lambda."_
44
- - **User Profile & Tone**: _"My name is Alex. I prefer concise, direct answers without conversational filler."_
57
+ > This is a practical agent-memory system, not a claim of generalized benchmark superiority. Repository benchmark results describe the included evaluation corpus and configuration.
45
58
 
46
59
  ---
47
60
 
48
61
  ## Quick Start
49
62
 
50
- ### Minimum System Requirements
63
+ ### Requirements
51
64
 
52
- - **Node.js**: `22.5.0` or higher (required by the built-in `node:sqlite` module)
53
- - **Package Manager**: `npm` / `npx` (included with Node.js)
54
- - **Supported Environment**: OpenCode, Antigravity / Gemini CLI, Claude Code, Codex, or Google Jules
65
+ - Node.js `22.5.0` or newer; the project uses the built-in `node:sqlite` module.
66
+ - npm/npx.
67
+ - OpenCode, Codex, Claude Code, Gemini CLI, Antigravity, Google Jules, or another MCP-capable client.
55
68
 
56
- ### Installation & Auto-Setup
69
+ CPU execution with `Xenova/multilingual-e5-small` is the recommended stable default. WebGPU execution is experimental.
57
70
 
58
- Run the setup command to configure all detected AI environments automatically:
71
+ ### Install and Configure
72
+
73
+ Configure every supported client location:
59
74
 
60
75
  ```bash
61
- # Recommended: Global installation & auto-setup across all environments
62
- npm install -g @lotargo/memory_plugin && memory_plugin setup
76
+ npm install -g @lotargo/memory_plugin
77
+ memory_plugin setup
78
+ ```
79
+
80
+ Or run setup without a permanent global installation:
63
81
 
64
- # Or via npx
82
+ ```bash
65
83
  npx @lotargo/memory_plugin setup
66
84
  ```
67
85
 
68
- To target a specific environment:
86
+ Target one client when needed:
69
87
 
70
88
  ```bash
71
- # Antigravity / Gemini CLI
89
+ memory_plugin setup --opencode
90
+ memory_plugin setup --codex
91
+ memory_plugin setup --claude
72
92
  memory_plugin setup --antigravity
93
+ memory_plugin setup --gemini # Gemini CLI (~/.gemini/settings.json)
94
+ ```
73
95
 
74
- # OpenCode
75
- memory_plugin setup --opencode
96
+ Use `--local` with Antigravity setup to create the workspace-local `.agents/mcp_config.json` even when `.agents/` does not yet exist.
76
97
 
77
- # Claude Code
78
- memory_plugin setup --claude
98
+ Claude Code, Gemini CLI, and Codex setup/uninstall use their native MCP lifecycle commands when available. An ownership-checked config edit is retained as a compatibility fallback for missing, older, or non-functional client CLIs. Antigravity remains a separate integration because it uses a different config layout.
99
+
100
+ Setup also installs the bundled `using-memory` skill and managed memory instructions for the selected clients. Existing unrelated configuration is preserved.
101
+
102
+ ### Uninstall
103
+
104
+ Remove the plugin from one or all clients without deleting Notebook/RAG data:
105
+
106
+ ```bash
107
+ memory_plugin uninstall --dry-run # preview
108
+ memory_plugin uninstall # remove all clients, keep data
109
+ memory_plugin uninstall --purge --yes # also delete local data (MEMORY_DIR, prompt state)
110
+ memory_plugin uninstall --opencode --purge-cache # explicitly remove this plugin's OpenCode cache
111
+ memory_plugin uninstall --opencode --claude # only selected clients
112
+ npx @lotargo/memory_plugin uninstall --dry-run
113
+ memory_plugin setup --uninstall --purge # alias
114
+ ```
115
+
116
+ What `uninstall` removes by default (without `--purge`):
117
+
118
+ - `~/.config/opencode/opencode.json` — plugin entry (including `file://` dev link)
119
+ - `~/.claude.json` — `mcpServers.memory-agent`
120
+ - `~/.gemini/settings.json` — Gemini CLI `mcpServers.memory-agent`
121
+ - `~/.gemini/config/mcp_config.json` and `.agents/mcp_config.json` — Antigravity `mcpServers.memory-agent`
122
+ - `~/.codex/config.toml` — `[mcp_servers.memory-agent]` (only if owned by this plugin)
123
+ - Managed prompt blocks from `~/.codex/AGENTS.md`, `~/.claude/CLAUDE.md`, `~/.gemini/GEMINI.md`, and `~/.gemini/config/AGENTS.md`
124
+ - `using-memory` skill from each client's `skills/` directory
125
+
126
+ Existing user content outside the managed prompt/persona markers is preserved. Foreign `memory-agent` registrations, modified/non-owned `using-memory` skills, unrelated file plugins, and other packages in the `@lotargo` OpenCode cache namespace are left untouched.
127
+
128
+ Normal uninstall keeps OpenCode's package cache, matching the host lifecycle. `--purge-cache` removes only exact cache directories owned by this package; unrelated packages, including other packages in the `@lotargo` namespace, remain untouched.
129
+
130
+ With `--purge` it also deletes `MEMORY_DIR` (`~/.config/opencode/memory` by default) and the memory-agent prompt state. Purge resolves and validates every target before changing client configuration, rejects filesystem roots, home/workspace/config roots and broad top-level paths, follows symlinks for validation, and prints the exact targets before interactive confirmation. The npm package itself is removed separately with `npm uninstall -g @lotargo/memory_plugin`. Restart clients after uninstall.
131
+
132
+ On Linux/macOS, `XDG_CONFIG_HOME` and `XDG_CACHE_HOME` are respected for OpenCode configuration, prompt state, and package-cache cleanup. `OPENCODE_CONFIG_DIR` and `MEMORY_DIR` remain explicit overrides on every platform.
133
+
134
+ ### Verify Codex
135
+
136
+ Codex uses a direct executable chain (`node` -> `mcp-server/boot.js`) instead of an `npx`/`.cmd` launcher, avoiding Windows stdio handshake failures. Setup safely migrates legacy registrations in `~/.codex/config.toml`.
79
137
 
80
- # Codex
81
- memory_plugin setup --codex
82
- ```
83
-
84
- Codex is configured with a direct executable chain (`node` `mcp-server/boot.js`),
85
- not `npx`. This avoids Windows stdio handshake failures caused by `.cmd` launchers.
86
- Running setup again safely migrates legacy `npx` entries and preserves unrelated
87
- sections in `~/.codex/config.toml`.
88
-
89
- `memory_plugin setup --codex` updates only the Codex MCP registration, Codex prompt,
90
- and the Codex-compatible skill locations (`~/.codex/skills` and the shared
91
- `~/.agents/skills`). It does not modify Claude Code, OpenCode, or Antigravity files.
92
-
93
- To verify registration, the Node runtime, MCP initialization, tool discovery, and
94
- real `memory_info` / `recall(scope="all")` calls:
95
-
96
- ```bash
97
- memory_plugin doctor --codex
98
- ```
99
-
100
- The doctor checks the server process itself. If it passes but a fresh Codex Desktop
101
- task still does not expose the tools, the remaining fault is in Desktop tool
102
- exposure rather than the memory MCP launcher.
103
-
104
- `setup` also accepts `--gemini` (alias for Antigravity) and `--local` (registers the MCP server in the project-local `.agents/` directory). Without a specific flag, all detected environments are configured.
105
-
106
- ### Headless & Cloud Setup (CI / Docker / Cloud Workspaces)
107
-
108
- For headless environments (e.g., Google Jules, VPS, CI/CD pipelines), configure auth and sync mode in a single non-interactive command:
138
+ ```bash
139
+ memory_plugin doctor --codex
140
+ ```
141
+
142
+ The doctor validates the configured Node runtime, MCP initialization, tool discovery, and real `memory_info` and `recall(scope: "all")` calls.
143
+
144
+ ### Headless / CI Setup
109
145
 
110
146
  ```bash
111
- # Authenticate via Turso API token and set hybrid sync mode
147
+ # Authenticate with a Turso account token and enable hybrid sync
112
148
  memory_plugin setup --api-key <TURSO_API_TOKEN> --mode hybrid-sync
113
149
 
114
- # Or set sync mode if already authorized
150
+ # Or change mode when credentials already exist
115
151
  memory_plugin setup --mode only-cloud
116
152
  ```
117
153
 
118
- ---
154
+ Prefer `TURSO_API_TOKEN`, `TURSO_DB_URL`, and `TURSO_DB_TOKEN` environment variables over command-line secrets because shell arguments may appear in process lists and history.
119
155
 
120
- ## Multi-Layer Architecture
156
+ ### Local Repository Development
121
157
 
122
- 1. **Layer 1: Notebook Store (Durable Facts)**
123
- - **Tools**: `remember`, `recall`, `get_fact`, `update_fact`, `forget`, `memory_info`
124
- - **Scope**: User preferences, identity, project conventions, system rules.
125
- - **Storage**: Human-readable Markdown format (`global` and per-project stores).
126
- - **Fact Schema**: Every fact is formatted as `**Title** — body` with inline metadata badges (`[id]`, `[ttl]`, `[keep]`, `[tags]`, `[supersedes]`, `[inject]`).
127
- - **Project Identity**: Project stores are bound to a **Git-based project identity** — the normalized remote URL (`git:github.com/owner/repo`) or `git:local:<repo basename>` — never to a directory path. Memories follow the repository across machines, OSes, and subdirectories. Legacy path/basename stores can be linked and merged via `link_project_memory`.
158
+ ```bash
159
+ npm install
160
+ npm run dev:link
161
+ ```
128
162
 
129
- 2. **Layer 2: RAG Knowledge Base (Technical Documents & Codebases)**
130
- - **Tools**: `ingest_document`, `query_knowledge_base`, `batch_query_knowledge_base`, `manage_knowledge_base`, `reindex_knowledge_base`
131
- - **Capabilities**: Ingests raw text files, Markdown, HTML, Web URLs, office documents (PDF, DOCX, XLSX, CSV), and codebases.
132
- - **Curation Model**: Stores only project-relevant sources likely to be reused—for example important web findings and current library/framework documentation that may be newer than model training. Ingest the useful document or excerpt, then link it to the project memory it supports; do not archive everything the agent encounters.
133
- - **Scope Isolation**: New documents default to the current linked Git project. `scope: "all"` searches global sources plus the current project's sources; outside a Git repository it searches global sources only. Use `scope: "global"` only for genuinely cross-project material.
134
- - **Stable Shared Sources**: Ingesting the same path or URL in another scope reuses one document and adds a scope association. Re-ingesting updated content preserves the document ID and its fact links; removing one scope does not delete a document still used by another scope.
135
- - **Engine Components**: 3-tier hierarchy chunking (Big / Medium / Small), SQLite FTS5 BM25 search, ONNX dense vector embeddings (`multilingual-e5-small`), Reciprocal Rank Fusion (RRF / RSF), cross-encoder reranking (optional), and GraphRAG Lite code symbol extraction.
163
+ `dev:link` performs an npm global link for the `memory_plugin`, `memory-agent`, and `memory-cli` binaries; rewrites only this plugin's OpenCode entry to an absolute `file://` URL for `opencode-plugin/main.js`; creates `opencode.json.memory-dev-backup` on first use; synchronizes managed prompts; and copies the current skill to all client skill locations.
136
164
 
137
- 3. **Layer 3: Agent-Driven Knowledge Graph**
138
- - **Tools**: `link_knowledge` (plus `docId`, `startLine`, `endLine` in `remember`)
139
- - **Capabilities**: Connects Layer 1 notebook facts directly to Layer 2 documents, sections, or exact line ranges with semantic edge relations (`RULES_FOR`, `IMPLEMENTS`, `EXPLAINS`, `REFERENCES`).
140
- - **Surfacing**: Linked facts automatically highlight target documents and line ranges in `recall` output (`🔗 [Linked Docs: ...]`).
165
+ After code changes, restart OpenCode to reload the module. Codex, Claude Code, Gemini CLI, and Antigravity load prompt and skill files at session start, so open a new task/session after synchronization. Publishing to npm is not required for local testing.
141
166
 
142
167
  ---
143
168
 
144
- ## Cloud Synchronization & Database Modes (Turso / LibSQL)
169
+ ## Memory Architecture
145
170
 
146
- The plugin provides local-first SQLite persistence with optional cloud database synchronization powered by Turso (LibSQL):
171
+ ### 1. Hot Notebook Memory
147
172
 
148
- ### 3 Storage Sync Modes
173
+ Notebook memory stores concise, high-signal context in Markdown:
149
174
 
150
- | Mode | Command / Flag | Description |
151
- | :--- | :------------- | :---------- |
152
- | **`only-local`** (default) | `--mode only-local` | 100% local SQLite database. No external network traffic for data storage. |
153
- | **`only-cloud`** | `--mode only-cloud` | Direct LibSQL connection to a remote Turso database instance. |
154
- | **`hybrid-sync`** | `--mode hybrid-sync` | Local SQLite performance with background asynchronous synchronization to Turso Cloud, featuring automatic reverse-sync and conflict resolution. |
175
+ ```text
176
+ - [2026-08-22 10:00] **API Convention** Use Fastify and Zod for new services <!-- id:a1b2c3, keep:1, tags:arch, kind:fact -->
177
+ ```
155
178
 
156
- ### Cloud Failover & Circuit Breaker
179
+ Supported metadata includes:
157
180
 
158
- When operating in cloud modes (`only-cloud` or `hybrid-sync`), the database engine incorporates a built-in **Circuit Breaker**:
159
- - If the primary cloud database endpoint is unreachable or encounters network failure, queries fail over to the secondary cloud endpoint configured in `failoverUrl`. Failover is disabled when `failoverUrl` is empty (the default).
160
- - In `hybrid-sync` the local SQLite copy keeps serving reads regardless; in `only-cloud` no local database is opened, so an outage with no `failoverUrl` surfaces as an error.
161
- - Prevents agent blocking or crash loops during internet outages or cloud service degradation.
181
+ - `id`: stable short identifier used by `get_fact`, `update_fact`, and `forget`.
182
+ - `kind`: `fact` for descriptive context or `directive` for active personalization/working instructions.
183
+ - `ttl`: `90d`, `2w`, `24h`, `12m`, or a bare day count. Expired entries are retained and marked `[EXPIRED]`.
184
+ - `keep`: protects an entry from ordinary deletion.
185
+ - `tags`: recall filters and legacy classification metadata.
186
+ - `supersedes` / `supersededBy`: preserves version history while excluding obsolete facts from active recall.
162
187
 
163
- ### Secure Credential Storage
188
+ `recall(scope: "all")` returns global facts plus only the current Git-linked project's facts. Full bodies are the default and should be used for session initialization; `mode: "headers"` is only for compact inventories.
164
189
 
165
- Cloud authentication tokens are never written to `config.json`. They are stored in `auth_secrets.enc`, encrypted with **AES-256-GCM** using a key derived via **PBKDF2-HMAC-SHA256 (600,000 iterations)** from a stable machine fingerprint (OS machine ID + platform + architecture). The file is written with owner-only permissions (`0600`).
190
+ ### 2. Cold RAG Memory Notes
166
191
 
167
- > **Note:** this is not an OS keychain (DPAPI / Keychain / Secret Service). The fingerprint components are readable by other processes running as the same user, so the encryption protects against file exfiltration and casual inspection, not against a compromised local account. Secrets are bound to the machine copying `auth_secrets.enc` to another computer will not decrypt.
168
- >
169
- > **Exception:** the headless fallback via `MEMORY_DIR/.env` (`TURSO_DB_URL`, `TURSO_DB_TOKEN`, `TURSO_API_TOKEN`) stores credentials in **plain text** by design, for Docker/CI deployments.
192
+ Use `remember_note` when the reusable value is in the detailed record itself:
170
193
 
171
- ---
194
+ ```text
195
+ remember_note(
196
+ title: "Authentication Investigation",
197
+ content: "Detailed symptoms, experiments, rejected explanations, and final cause...",
198
+ kind: "research",
199
+ tags: "auth,incident",
200
+ scope: "project"
201
+ )
202
+ ```
203
+
204
+ Supported note kinds are `decision`, `research`, `context`, `handoff`, and `note`. Notes are represented as virtual RAG documents with stable `docId` and content-addressed `blobHash`. They are searchable with the same engine as external sources but are not injected into every session.
205
+
206
+ Recommended discovery flow:
207
+
208
+ ```text
209
+ query_knowledge_base(query: "authentication token decryption investigation", resultMode: "index")
210
+ -> inspect compact candidates and stable doc_id values
211
+ manage_knowledge_base(action: "read_document", docId: "selected-id")
212
+ -> expand the complete raw note only when needed
213
+ ```
172
214
 
173
- ## Available Tools
174
-
175
- The package currently exposes **17 unique tool names** across its two integration surfaces:
176
-
177
- | Integration surface | Tool count | Composition |
178
- | :------------------ | ---------: | :---------- |
179
- | **MCP server** (Codex, Claude Code, Antigravity / Gemini CLI and other MCP clients) | **15** | 6 Notebook + 4 identity/graph + 5 RAG tools |
180
- | **Native OpenCode plugin** | **17** | 15 shared memory/identity/RAG tools + 2 OpenCode-only helpers |
181
-
182
- The two surfaces are intentionally counted separately. The OpenCode plugin exposes
183
- all 15 shared tools, including `batch_query_knowledge_base`, and adds the native
184
- `list-mcp-tools` and `mcp-reminder` helpers.
185
-
186
- ### MCP Server Tools (15)
187
-
188
- #### 1. Memory Notebook Tools (Layer 1)
189
-
190
- | Tool | Scope / Target | Key Parameters | Description |
191
- | :--- | :------------- | :------------- | :---------- |
192
- | `remember` | `project` / `global` | `fact`, `title`, `scope`, `docId`, `startLine`, `endLine`, `relationType`, `ttl`, `keep`, `tags`, `supersedes` | Save a durable fact or preference. Supports optional title, document linking, TTL, keep protection, tags, and version superseding. |
193
- | `recall` | `all`, `project`, `global`, `list_projects` | `scope`, `project`, `query`, `tags`, `since`, `until`, `mode`, `offset`, `limit`, `includeSuperseded` | Display saved facts with metadata badges and linked docs. Superseded facts are hidden by default; opt into history with `includeSuperseded: true`. Filtered results retain stable storage indices for safe `forget` operations. |
194
- | `get_fact` | `all`, `project`, `global` | `id`, `scope` | Retrieve full text, raw line, and metadata of a single fact by its metadata ID (e.g. `"8f3a2c"`). |
195
- | `update_fact` | `project` / `global` | `id`, `newText`, `title`, `scope` | Rewrite a fact (and optionally its `**Title**`) while preserving its original creation date, metadata, and knowledge links. |
196
- | `forget` | `project` / `global` | `id` / `range` / `query`, `scope`, `force` | Remove a fact by index number, ID, range (e.g. `"3-30"`), or query. Requires `force: true` for protected (`[KEEP]`) facts. |
197
- | `memory_info` | - | - | Show storage paths, fact counts, RAG statistics, git identity bindings, and package version. |
198
-
199
- #### 2. Project Identity Tools
200
-
201
- | Tool | Key Parameters | Description |
202
- | :--- | :------------- | :---------- |
203
- | `link_project_memory` | `directory`, `remote` | Link a directory path to a Git-based project identity key, register aliases, and migrate legacy path/basename stores with deduplication. |
204
- | `unlink_project_memory` | `directory`, `purge` | Remove a path alias binding for a directory. Optionally purge the project identity entry if `purge: true`. |
205
- | `relink_project_memory` | `directory`, `remote` | Switch a project's primary identity to a new remote URL and merge all stored facts into the target store with fact-text deduplication. |
206
-
207
- #### 3. RAG Knowledge Base & Graph Tools (Layers 2 & 3)
208
-
209
- | Tool | Key Parameters | Description |
210
- | :--- | :------------- | :---------- |
211
- | `ingest_document` | `content`, `type`, `title`, `path`, `scope`, `generateEmbeddings` | Ingest local files, URLs, or raw text into the 3-tier index. Defaults to the current linked Git project; use `scope: "global"` for intentionally shared knowledge. |
212
- | `query_knowledge_base` | `query`, `scope`, `limit`, `instruction`, `generateEmbeddings` | Perform hybrid search (RSF/RRF BM25 + dense vectors). `all` means global plus the current project, while `project` and `global` restrict retrieval explicitly. |
213
- | `batch_query_knowledge_base` | `queries` (array), `scope`, `limit`, `instruction`, `generateEmbeddings` | Execute multiple scoped queries in one call. All embeddings are computed in one ONNX pass, making this the preferred API for comparisons and multi-part research. |
214
- | `manage_knowledge_base` | `action`, `scope`, `docId`, `snapshotPath` | Inspect, list, read, or unlink documents within the selected scope, or export/import complete snapshots. Delete defaults to the current project (global outside Git); broader removal requires explicit `global` or `all`. |
215
- | `reindex_knowledge_base` | `model`, `dimension` | Re-embed all stored vectors with the active (or specified) embedding model and vector dimension. Use after switching the embedding model or vector dimension so previously indexed documents remain retrievable. Preserves documents, FTS index, graph edges, and fact links. |
216
- | `link_knowledge` | `action`, `factText`, `docId`, `scope`, `startLine`, `endLine`, `relationType` | Create, list, or retrieve semantic graph links connecting Notebook facts to Knowledge Base documents, sections, or line ranges. Actions: `link`, `list_links`, `get_doc_links`. |
217
-
218
- ### Native OpenCode Plugin Tools (17)
219
-
220
- | Group | Count | Tools |
221
- | :---- | ----: | :---- |
222
- | **Memory Notebook** | 6 | `remember`, `recall`, `get_fact`, `forget`, `update_fact`, `memory_info` |
223
- | **Project Identity & Knowledge Graph** | 4 | `link_knowledge`, `link_project_memory`, `unlink_project_memory`, `relink_project_memory` |
224
- | **RAG Knowledge Base** | 5 | `ingest_document`, `query_knowledge_base`, `batch_query_knowledge_base`, `manage_knowledge_base`, `reindex_knowledge_base` |
225
- | **OpenCode-only helpers** | 2 | `list-mcp-tools`, `mcp-reminder` |
226
-
227
- The OpenCode-only helpers have the following purpose:
228
-
229
- | Tool | Key Parameters | Description |
230
- | :--- | :------------- | :---------- |
231
- | `list-mcp-tools` | - | Discover connected MCP servers and their intended use cases. |
232
- | `mcp-reminder` | `task` | Recommend the appropriate MCP tool or server for a developer task. |
215
+ Use `resultMode: "snippet"` when retrieved passages are immediately useful. Use `resultMode: "index"` when first identifying the correct source; index mode intentionally omits bodies and disables large policy expansion.
216
+
217
+ ### 3. Curated External Knowledge
218
+
219
+ `ingest_document` accepts:
220
+
221
+ - Raw text or Markdown (`type: "text"`).
222
+ - Local files (`type: "file"`), including PDF, DOCX, XLSX, XLS, CSV, text, Markdown, and source code.
223
+ - Web pages (`type: "url"`), which are fetched and normalized instead of indexing the URL string.
224
+
225
+ RAG is a curated library, not an automatic archive. Ingest reliable sources likely to matter again, particularly current documentation or project specifications. Project scope is the default; use global scope only for intentionally reusable cross-project knowledge.
226
+
227
+ ### Hot + Cold Linking
228
+
229
+ When a decision needs both quick orientation and detailed history:
230
+
231
+ 1. Save the concise conclusion with `remember`.
232
+ 2. Save the rationale or investigation with `remember_note`.
233
+ 3. Connect them with `link_knowledge`, using the note's returned `docId`.
234
+
235
+ This keeps startup context small while preserving the complete reasoning trail without duplicating the note body into Notebook memory.
233
236
 
234
237
  ---
235
238
 
236
- ## CLI Command Reference
239
+ ## Persona and Agent Personalization
237
240
 
238
- The plugin provides both direct non-interactive CLI commands and an interactive terminal UI (TUI):
241
+ Notebook entries have explicit semantics:
239
242
 
240
- ```bash
241
- # Executable commands (available globally or via npx)
242
- memory_plugin <command> [options]
243
- # or
244
- memory-cli <command> [options]
243
+ ```text
244
+ kind: "fact" # descriptive context
245
+ kind: "directive" # active user-approved personality or working configuration
245
246
  ```
246
247
 
247
- Both binaries accept the same commands. `memory_plugin` with **no** command starts the MCP server on stdio; `memory-cli` with no command opens the interactive TUI. Use `--help` on either for the full usage text.
248
+ Use `kind: "directive"` for personality, behavior, tone, communication style, preferences, or working conventions the agent should actively apply. Explicit `kind` is authoritative; persuasive wording alone does not turn a fact into an instruction.
249
+
250
+ ### OpenCode
248
251
 
249
- > **Secrets:** prefer the environment variables `TURSO_API_TOKEN`, `TURSO_DB_URL` and `TURSO_DB_TOKEN` over `--api-key` / `--db-token` flags — arguments passed on the command line are visible in the process list and shell history. Without a flag or env var, `login` prompts for the token on stdin with echo disabled.
252
+ The native plugin performs complete session initialization automatically:
250
253
 
251
- ### Direct Non-Interactive Commands
254
+ - Global and current-project descriptive entries are injected into `<MEMORY_FACTS>`.
255
+ - Active global directives are separated into `<PERSONAL_AGENT_OVERLAY>`.
256
+ - Directives are promoted through OpenCode's system-prompt transform.
257
+ - Agents are instructed not to perform a redundant startup `recall`; manual or filtered recall remains available.
252
258
 
253
- | Command | Options / Flags | Description |
254
- | :------ | :-------------- | :---------- |
255
- | **`setup`** | `--antigravity`, `--opencode`, `--claude`, `--codex`, `--local`, `--api-key <TOKEN>`, `--mode <MODE>` | Configures MCP server registrations across detected environments and sets initial cloud auth/sync mode. |
256
- | **`link`** | `--dir <path>`, `--remote <url>` | Links a directory to a Git project identity or remote URL. |
257
- | **`unlink`** | `--dir <path>`, `--purge` | Unlinks a directory path alias. `--purge` removes the identity record. |
258
- | **`relink`** | `--remote <url>`, `--dir <path>` | Relinks project identity to a new remote URL and merges facts. |
259
- | **`identity`** | `--dir <path>` | Inspects Git project identity key, primary remote, name, and toplevel path for a directory. |
260
- | **`migrate_titles`** | `--key <key>` | Auto-generates `**Title**` prefixes for legacy facts without titles. |
261
- | **`enable-prompt`** | - | Injects memory agent instructions into client agent files (`AGENTS.md`, `CLAUDE.md`). |
262
- | **`disable-prompt`** | - | Removes memory agent instructions from client agent files. |
263
- | **`doctor`** | `--codex` | Validates Codex config, direct Node runtime, MCP initialize/tools/list, and live `memory_info` + `recall` calls. |
264
- | **`login`** | `--api-token`, `--from-env`, `--db-url <URL> --db-token`, `$TURSO_API_TOKEN`, `$TURSO_DB_TOKEN` | Authenticates with Turso Cloud via API token, direct DB token, or environment variables. Token values are read from the environment or a hidden stdin prompt. |
265
- | **`logout`** | `--api-key` | Signs out of Turso Cloud or removes stored API key while retaining DB session. |
266
- | **`auth-status`** | - | Displays authentication source, endpoint URL, username, organization, database, and sync mode. |
259
+ ### Codex, Claude Code, Gemini CLI, and Antigravity
267
260
 
268
- ### Interactive TUI (CLI Menu)
261
+ These clients receive plugin-owned instruction and persona blocks in:
269
262
 
270
- Launch the interactive terminal UI to manage engine settings, tune retrieval algorithms, inspect databases, and run diagnostics:
263
+ - `~/.codex/AGENTS.md`
264
+ - `~/.claude/CLAUDE.md`
265
+ - `~/.gemini/GEMINI.md`
266
+ - `~/.gemini/config/AGENTS.md`
267
+
268
+ The global Notebook is the source of truth. Managed prompt blocks are generated views and update automatically after global directive changes, relevant cloud pulls, setup, or `dev:link`.
269
+
270
+ Manual synchronization:
271
271
 
272
272
  ```bash
273
- memory_plugin cli
274
- # or
275
- memory-cli
273
+ memory-cli sync-persona
274
+ npm run persona:sync # from the repository
276
275
  ```
277
276
 
278
- #### TUI Menu Navigation
277
+ Legacy entries using `persona`, `behavior`, `speech`, `style`, `tone`, `preference(s)`, `instruction(s)`, `directive`, or `inject:1` metadata remain compatible. Permanently classify them as explicit directives with the idempotent migration:
279
278
 
280
- Use **Up / Down** arrows to navigate, **ENTER** to select, and **BACKSPACE** to go back.
279
+ ```bash
280
+ memory-cli migrate-persona --dry-run
281
+ memory-cli migrate-persona
282
+ npm run persona:migrate # from the repository
283
+ ```
281
284
 
282
- - **Engine & Hybrid Search Settings**: Switch fusion algorithms (`rsf`, `rrf`, `semantic_only`, `lexical_only`), adjust RSF $\alpha$ balance, select ONNX embedding models, set a fixed embedding vector dimension, toggle Cross-Encoder rerankers, configure GPU attention budget, and set WASM threads.
283
- - **Knowledge Base & Storage Management**: Browse Layer 1 facts, manage Layer 2 RAG docs, re-embed all vectors after switching model/dimension (`[REINDEX]`), export/import JSON snapshots, purge model cache, or perform a hard reset.
284
- - **Global Prompt & Integration**: Toggle memory instruction sync across client configurations (`~/.gemini/config/AGENTS.md`, `~/.codex/AGENTS.md`, `~/.claude/CLAUDE.md`).
285
- - **Diagnostics & System Actions**: Execute a hybrid search verification query, run the graph & notebook linking check, and reset config to factory defaults.
285
+ Higher-priority platform and safety instructions remain authoritative.
286
286
 
287
287
  ---
288
288
 
289
- ## Agent Skill & System Prompt Integration
289
+ ## Project Identity and Scope Isolation
290
290
 
291
- ### Built-in Agent Skill (`using-memory`)
291
+ Project memory is Git-first:
292
292
 
293
- The plugin bundles a pre-configured Agent Skill located at [`skills/using-memory/SKILL.md`](./skills/using-memory/SKILL.md). When installed in supported environments (such as Antigravity / Gemini CLI or OpenCode), coding agents automatically read this skill to:
294
- 1. **Initialize Sessions**: Invoke full-body `recall(scope: "all")` first, loading global memory plus only the current Git project's memory (or global-only outside Git).
295
- 2. **Register Git Projects**: Inspect `memory_info` after recall and automatically call `link_project_memory` when the current Git identity reports `Registry: unlinked`.
296
- 3. **Proactively Save Context**: Automatically call `remember` whenever you share durable facts, tech stack choices, or coding guidelines.
297
- 4. **Curate and Use RAG Deliberately**: Preserve important web findings and current technical documentation only when they are likely to matter again. Store project-specific sources in the current project scope, reserve global scope for reusable cross-project material, query with concept-dense searches, and avoid low-value bulk ingestion.
298
- 5. **Architect Knowledge Graphs**: Use `link_knowledge` or `remember(docId, startLine, endLine)` to connect concise project memories to their supporting technical sources.
293
+ - Repositories with a remote use `git:<normalized-host-and-path>`, for example `git:github.com/owner/repo`.
294
+ - Repositories without a remote use `git:local:<repository-name>`.
295
+ - Every subdirectory of the same repository resolves to the same identity.
296
+ - Outside Git, project memory is not created; global memory remains available.
299
297
 
300
- ### Global System Prompt Synchronization
298
+ The SQLite identity registry stores remote, path, and basename aliases. It supports moving a repository between directories or operating systems without changing its logical memory identity.
301
299
 
302
- Run `memory_plugin enable-prompt` to automatically inject memory agent guidance into your global LLM configuration files:
303
- - `~/.gemini/config/AGENTS.md` (Antigravity / Gemini CLI)
304
- - `~/.codex/AGENTS.md` (Codex)
305
- - `~/.claude/CLAUDE.md` (Claude Code)
300
+ | Tool | Purpose |
301
+ | :--- | :--- |
302
+ | `link_project_memory` | Register the current Git identity and merge compatible legacy path/basename facts and RAG scope data. |
303
+ | `unlink_project_memory` | Remove a path alias; optionally purge the identity record. |
304
+ | `relink_project_memory` | Move/merge facts and RAG scope data to a new normalized remote identity. |
306
305
 
307
- This ensures your coding assistant is always aware of its memory capabilities even in fresh workspace sessions.
306
+ For both Notebook and RAG retrieval, `all` means **global + current project**, never all known projects. Unrelated project memories and documents are isolated.
308
307
 
309
308
  ---
310
309
 
311
- ## GraphRAG Lite
310
+ ## Retrieval and Knowledge Graph
311
+
312
+ ### Hybrid Retrieval
313
+
314
+ The local retrieval pipeline combines:
312
315
 
313
- The RAG engine includes a lightweight graph layer built on SQLite. It combines code symbol extraction, hierarchy edges, and explicit memory-to-document links without requiring external graph databases or LLM calls at ingest time.
316
+ - SQLite FTS5 BM25 lexical search.
317
+ - Local ONNX dense embeddings (`Xenova/multilingual-e5-small` by default).
318
+ - RSF (default), RRF, semantic-only, or lexical-only ranking.
319
+ - Optional cross-encoder reranking.
320
+ - Batched query embeddings through `batch_query_knowledge_base`.
321
+ - Optional fixed vector dimensions and an experimental WebGPU execution mode.
314
322
 
315
- ### Multilingual Code Symbol Parsing
323
+ Queries should be short, concept-dense phrases. For multi-part research or comparisons, use `batch_query_knowledge_base`; all query embeddings are computed in one ONNX pass.
316
324
 
317
- During `ingest_document`, code symbols are extracted from code blocks using fast regex heuristics across the following language families:
325
+ ### Three-Tier Chunking and Policy Expansion
318
326
 
319
- - **JavaScript / TypeScript**: `function`, `class`, `interface`, `type`, `enum`, `const`, `let`, `var`
320
- - **Python**: `def`, `class`
321
- - **Go**: `struct`, `interface`, `func` (including methods with receivers)
322
- - **Rust**: `struct`, `enum`, `trait`, `fn` (including async/pub)
323
- - **C++**: `class`, `struct`, `namespace`, functions and methods
324
- - **Java & Kotlin**: `class`, `interface`, `record`, `enum`, `fun`, synchronized methods
325
- - **C#**: `class`, `interface`, `struct`, `record`, methods (properties without a parameter list are not captured)
326
- - **PHP**: `class`, `interface`, `trait`, functions
327
- - **Ruby**: `module`, `class`, methods
327
+ Each document is partitioned into three retrieval levels: section-level big chunks, medium blocks, and micro chunks. Tables receive compact summaries and code blocks receive signature chunks. With `policyExpansion: true` (default), matching summaries/signatures expand to their full source blocks for content-rich retrieval. Set the configuration to `false` when pure micro-chunk precision is preferred.
328
328
 
329
- ### Graph Edges
329
+ Re-ingesting an updated path/URL preserves its stable document ID and knowledge links while rebuilding chunks, vectors, policies, and structural edges. Ingesting the same source in another scope adds a scope association without duplicating the document.
330
330
 
331
- | Relation Type | Direction / Example |
331
+ ### GraphRAG Lite
332
+
333
+ The SQLite graph layer requires no external graph database or ingestion-time LLM:
334
+
335
+ | Relation | Meaning |
332
336
  | :--- | :--- |
333
- | `CONTAINS` | Document -> Section -> Micro-Chunk (3-tier hierarchy) |
334
- | `DEFINES_SYMBOL` | Section -> `symbol:<name>` (extracted code symbol) |
335
- | `LINKS_TO` (default) | Memory fact -> Document or line range (via `link_knowledge`) |
337
+ | `CONTAINS` | Document -> Section -> Micro Chunk graph hierarchy |
338
+ | `DEFINES_SYMBOL` | A document section defines an extracted code symbol |
339
+ | `LINKS_TO` and custom relations | A Notebook fact points to a document, note, section, or line range |
340
+
341
+ Code-symbol extraction covers JavaScript/TypeScript, Python, Go, Rust, C++, Java/Kotlin, C#, PHP, and Ruby patterns.
336
342
 
337
343
  ---
338
344
 
339
- ## Supported Platforms
345
+ ## Cloud Synchronization
346
+
347
+ Cloud support uses Turso / LibSQL and is optional.
348
+
349
+ | Mode | Behavior |
350
+ | :--- | :--- |
351
+ | `only-local` (default) | Markdown notebooks, SQLite index, CAS blobs, and models remain local. |
352
+ | `only-cloud` | Notebook and database operations use Turso directly; raw RAG blobs are materialized into a verified local cache when read. |
353
+ | `hybrid-sync` | Local-first reads/writes with background push, reverse synchronization, and conflict resolution. |
354
+
355
+ Hybrid synchronization covers Notebook stores and complete RAG state: documents, scopes, sections, chunks, vectors, retrieval policies, graph edges, fact links, compressed raw CAS blobs, and deletion tombstones. Raw notes/documents can therefore be expanded on another device rather than returning metadata without source content.
356
+
357
+ Notebook conflict strategies:
358
+
359
+ - `merge` (default): union fact lines with local order first and deduplication.
360
+ - `cloud-wins`.
361
+ - `local-wins`.
362
+
363
+ Cloud operations retry with timeouts and can switch to `failoverUrl` after repeated primary failures. In `hybrid-sync`, local SQLite continues serving reads during an outage. In `only-cloud`, an unavailable primary with no failover surfaces as an error.
340
364
 
341
- | Platform | Status | Configuration Mechanism |
365
+ ### Authentication
366
+
367
+ ```bash
368
+ memory-cli login
369
+ memory-cli login --api-token # hidden prompt if value omitted
370
+ memory-cli login --from-env
371
+ memory-cli login --db-url <URL> # token from prompt or TURSO_DB_TOKEN
372
+ memory-cli auth-status
373
+ memory-cli logout
374
+ ```
375
+
376
+ Stored tokens live in `auth_secrets.enc`, not `config.json`. They are encrypted with AES-256-GCM using PBKDF2-HMAC-SHA256 (600,000 iterations) over a stable machine fingerprint and written with owner-only permissions where supported.
377
+
378
+ This is not an OS keychain. It protects against casual inspection/file-only exfiltration, not a compromised local user account. Encrypted secrets are machine-bound. The headless `.env` fallback stores credentials in plaintext by design.
379
+
380
+ ---
381
+
382
+ ## Tool Reference
383
+
384
+ The MCP server exposes **16 tools**. The native OpenCode plugin exposes the same 16 plus two OpenCode-specific helpers, for **18 total**.
385
+
386
+ ### Notebook and Cold Memory
387
+
388
+ | Tool | Important parameters | Purpose |
342
389
  | :--- | :--- | :--- |
343
- | **Antigravity / Gemini CLI** | Supported | MCP Server (`~/.gemini/config/mcp_config.json` & `.agents/mcp_config.json`) |
344
- | **OpenCode** | Native | Native plugin with 16 tools (`~/.config/opencode/opencode.json`) |
345
- | **Claude Code** | Supported | MCP Server (`~/.claude.json`) |
346
- | **Codex** | Supported | MCP Server (`~/.codex/config.toml`) |
347
- | **Google Jules** | Supported | MCP Server via global install + setup (`memory_plugin setup`) |
390
+ | `remember` | `fact`, `title`, `kind`, `scope`, `directory`, `ttl`, `keep`, `tags`, `supersedes`, optional link fields | Save a concise hot fact or directive. |
391
+ | `recall` | `scope`, `directory`, `query`, `tags`, `since`, `until`, `mode`, `offset`, `limit`, `includeSuperseded` | Load/filter Notebook facts and linked-document references. |
392
+ | `get_fact` | `id`, `scope`, `directory` | Read one fact and all metadata by stable ID. |
393
+ | `update_fact` | `id`, `newText`, `title`, `kind`, `scope`, `directory` | Update/reclassify a fact while preserving date, metadata, and links. |
394
+ | `forget` | `query`, `scope`, `directory`, `force` | Delete by index, range, ID, or text; `force` overrides `[KEEP]`. |
395
+ | `memory_info` | `directory` | Show version, storage paths/counts, Git identity/registry state, and RAG statistics. |
396
+ | `remember_note` | `title`, `content`, `kind`, `tags`, `scope`, `directory`, `generateEmbeddings` | Save a detailed cold/episodic note into RAG. |
397
+
398
+ ### Identity and Knowledge Graph
399
+
400
+ | Tool | Important parameters | Purpose |
401
+ | :--- | :--- | :--- |
402
+ | `link_project_memory` | `directory`, `remote` | Register Git identity and migrate compatible legacy data. |
403
+ | `unlink_project_memory` | `directory`, `purge` | Remove an alias or purge its registry identity. |
404
+ | `relink_project_memory` | `directory`, `remote` | Move/merge memory into a new normalized remote identity. |
405
+ | `link_knowledge` | `action`, `factText`, `docId`, `scope`, `startLine`, `endLine`, `relationType` | Link facts to documents/notes or inspect graph links. |
406
+
407
+ ### RAG Knowledge Base
408
+
409
+ | Tool | Important parameters | Purpose |
410
+ | :--- | :--- | :--- |
411
+ | `ingest_document` | `content`, `type`, `title`, `path`, `scope`, `directory`, `generateEmbeddings` | Ingest raw text, a local file, or a URL. |
412
+ | `query_knowledge_base` | `query`, `scope`, `limit`, `instruction`, `resultMode`, `generateEmbeddings`, `directory` | Run one hybrid query in snippet or compact index mode. |
413
+ | `batch_query_knowledge_base` | `queries`, `scope`, `limit`, `instruction`, `resultMode`, `generateEmbeddings`, `directory` | Run several queries with one embedding batch. |
414
+ | `manage_knowledge_base` | `action`, `scope`, `docId`, `snapshotPath`, `directory` | Stats, list, full raw read, scoped delete/unlink, snapshot export/import. |
415
+ | `reindex_knowledge_base` | `model`, `dimension` | Rebuild vectors after changing model/dimension while preserving source and graph data. |
416
+
417
+ ### OpenCode-Only Helpers
418
+
419
+ | Tool | Purpose |
420
+ | :--- | :--- |
421
+ | `list-mcp-tools` | Show connected MCP servers and their intended roles. |
422
+ | `mcp-reminder` | Suggest a connected MCP/tool family for a described task. |
423
+
424
+ ---
425
+
426
+ ## CLI Reference
427
+
428
+ `memory_plugin` and `memory-agent` are MCP stdio entry points. `memory_plugin setup` performs client installation, while `memory_plugin cli` or `memory-cli` opens the interactive control panel. Direct administration commands should use `memory-cli`.
429
+
430
+ | Command | Purpose |
431
+ | :--- | :--- |
432
+ | `memory_plugin setup [client flags] [--mode <mode>]` | Configure clients, skills, prompts, and optional cloud mode/auth. |
433
+ | `memory_plugin doctor --codex` | Validate Codex configuration and live MCP behavior. |
434
+ | `memory-cli` | Open the interactive TUI. |
435
+ | `memory-cli login ...` / `logout` / `auth-status` | Manage Turso authentication. |
436
+ | `memory-cli link --dir <path> [--remote <url>]` | Link a Git project identity. |
437
+ | `memory-cli unlink --dir <path> [--purge]` | Remove an alias or registry identity. |
438
+ | `memory-cli relink --dir <path> --remote <url>` | Move/merge into a new remote identity. |
439
+ | `memory-cli identity --dir <path>` | Inspect resolved Git identity. |
440
+ | `memory-cli migrate_titles [--key <key>]` | Add titles to legacy Notebook entries. |
441
+ | `memory-cli enable-prompt` / `disable-prompt` | Add/remove only plugin-owned memory instruction blocks. |
442
+ | `memory-cli sync-persona` | Regenerate managed persona blocks from global directives. |
443
+ | `memory-cli migrate-persona [--dry-run]` | Convert legacy persona metadata to explicit `kind:directive`. |
444
+ | `memory-cli dev-link` | Link the installed binaries/OpenCode plugin to the working repository. |
445
+ | `memory-cli uninstall [--purge] [--purge-cache] [--dry-run] [--yes] [client flags]` | Remove plugin, MCP entries, prompts and skills; `--purge` deletes local data, while `--purge-cache` explicitly removes only this plugin's OpenCode cache. |
446
+
447
+ The TUI provides retrieval configuration, model management, Notebook/RAG browsing, reindexing, snapshots, cloud settings, prompt integration, diagnostics, and reset actions. Use Up/Down, Enter, and Backspace to navigate.
448
+
449
+ ---
450
+
451
+ ## Client Integration
452
+
453
+ | Client | Integration | Session initialization | Tool count |
454
+ | :--- | :--- | :--- | ---: |
455
+ | OpenCode | Native plugin in `~/.config/opencode/opencode.json` | Full memory auto-injection + system persona transform | 18 |
456
+ | Codex | MCP server in `~/.codex/config.toml` | Managed prompt requires full `recall(scope: "all")` | 16 |
457
+ | Claude Code | MCP server in `~/.claude.json` | Managed prompt requires full `recall(scope: "all")` | 16 |
458
+ | Gemini CLI | MCP server in `~/.gemini/settings.json` | Managed `~/.gemini/GEMINI.md` prompt requires full `recall(scope: "all")` | 16 |
459
+ | Antigravity | MCP server in `~/.gemini/config/mcp_config.json` and optional `.agents/mcp_config.json` | Managed prompt requires full `recall(scope: "all")` | 16 |
460
+ | Google Jules / generic MCP | MCP stdio server | Client instructions should initialize with full recall | 16 |
461
+
462
+ The bundled [`using-memory` skill](./skills/using-memory/SKILL.md) teaches agents to:
463
+
464
+ 1. Avoid duplicate recall when OpenCode already auto-injected memory.
465
+ 2. Perform full unfiltered recall first in clients without auto-injection.
466
+ 3. Apply `kind:directive` entries as active configuration.
467
+ 4. Register unlinked Git identities with `link_project_memory`.
468
+ 5. Route concise facts, long internal notes, and external sources to the correct store.
469
+ 6. Use semantic index discovery before expanding a full note/document.
470
+ 7. Save high-signal knowledge proactively and avoid transient noise.
348
471
 
349
472
  ---
350
473
 
351
474
  ## Configuration
352
475
 
353
- The engine is configured through `<memory-dir>/config.json` (created with defaults on first run):
476
+ Configuration is stored in `<memory-dir>/config.json`.
354
477
 
355
- | Key | Default | Description |
478
+ | Key | Default | Meaning |
356
479
  | :--- | :--- | :--- |
357
- | `mode` | `only-local` | Storage sync mode: `only-local`, `only-cloud`, or `hybrid-sync` |
480
+ | `mode` | `only-local` | `only-local`, `only-cloud`, or `hybrid-sync` |
481
+ | `conflictStrategy` | `merge` | Notebook conflict policy: `merge`, `cloud-wins`, `local-wins` |
358
482
  | `fusionAlgorithm` | `rsf` | `rsf`, `rrf`, `semantic_only`, or `lexical_only` |
359
- | `alpha` | `0.5` | Vector vs BM25 weight in RSF `[0.0 - 1.0]` |
360
- | `embeddingModel` | `Xenova/multilingual-e5-small` | ONNX dense embedding model (E5 / BGE families supported) |
361
- | `vectorDimension` | `0` | Fixed embedding vector dimension; `0` = auto-detect from the model |
362
- | `rerankerModel` | `none` | Cross-encoder reranker model (e.g. `Xenova/bge-reranker-base`) |
363
- | `rerankerEnabled` | `false` | Enable cross-encoder re-ranking |
364
- | `batchSize` | `12` | Ingestion vector batch size `[1 - 256]` |
365
- | `gpuAttentionBudget` | `2000000` | GPU micro-batch attention budget `[1M - 16M]` |
366
- | `onnxThreads` | `0` | ONNX WASM threads: `0` auto-detect, or `1-16` |
367
- | `executionDevice` | `cpu` | `cpu` or `webgpu` (experimental) |
368
- | `vectorScanLimit` | `50000` | Max micro-chunks scanned per vector query (`0` = unlimited) |
369
- | `policyExpansion` | `true` | Expand table_summary/code_signature policy chunks for better recall (slight MRR trade-off). Disable for pure micro_chunk precision. |
370
- | `conflictStrategy` | `merge` | Hybrid-sync conflict resolution: `merge`, `cloud-wins`, or `local-wins` |
371
- | `tursoUrl` | `""` | Primary Turso endpoint URL (set by `login`) |
372
- | `failoverUrl` | `""` | Secondary cloud endpoint for the circuit breaker; empty = failover disabled |
373
- | `authorized` | `false` | Set to `true` once a cloud login completed |
374
- | `username` | `""` | Account username from the Turso profile |
375
- | `ingestAllowedPaths` | `[]` | Extra directories `ingest_document(type: "file")` may read from |
376
- | `ingestAllowAnyPath` | `false` | Escape hatch: allow reading **any** path from disk (unsafe) |
377
-
378
- > `ingest_document(type: "file")` reads only from the current working directory and the plugin data directory by default. This prevents a prompt-injected agent from pulling `~/.ssh/id_rsa` or `.env` into the knowledge base (and, in `hybrid-sync`, into the cloud). Widen it deliberately via `ingestAllowedPaths`.
483
+ | `alpha` | `0.5` | Dense-vector weight for RSF |
484
+ | `embeddingModel` | `Xenova/multilingual-e5-small` | Local Hugging Face/ONNX embedding model |
485
+ | `vectorDimension` | `0` | Fixed vector size; `0` auto-detects model output |
486
+ | `vectorScanLimit` | `50000` | Maximum vector candidates; `0` is unlimited |
487
+ | `rerankerModel` | `none` | Optional cross-encoder model |
488
+ | `rerankerEnabled` | `false` | Enable cross-encoder reranking |
489
+ | `batchSize` | `12` | Ingestion embedding batch size |
490
+ | `policyExpansion` | `true` | Expand matched table summaries/code signatures |
491
+ | `executionDevice` | `cpu` | `cpu` or experimental `webgpu` |
492
+ | `gpuAttentionBudget` | `2000000` | Experimental GPU micro-batch budget |
493
+ | `onnxThreads` | `0` | WASM thread count; `0` auto-detects |
494
+ | `tursoUrl` | `""` | Primary LibSQL endpoint populated by login |
495
+ | `failoverUrl` | `""` | Optional secondary cloud endpoint |
496
+ | `authorized` | `false` | Whether cloud authorization completed |
497
+ | `username` | `""` | Authenticated Turso username |
498
+ | `ingestAllowedPaths` | `[]` | Additional directories allowed for local-file ingestion |
499
+ | `ingestAllowAnyPath` | `false` | Unsafe escape hatch allowing arbitrary file reads |
500
+
501
+ `ingest_document(type: "file")` is restricted to the current working directory, the plugin data directory, and explicitly allowed paths. This prevents a prompt-injected agent from silently indexing unrelated secrets such as SSH keys or `.env` files.
379
502
 
380
503
  ---
381
504
 
382
- ## Testing & Benchmarking
505
+ ## Storage, Privacy, and Security
383
506
 
384
- To run the automated test suite and benchmarks locally, from the repository root:
507
+ The data-directory resolution order is:
385
508
 
386
- ```bash
387
- # Unit + integration + cloud suites (18 files) — fast and fully offline
388
- npm test
509
+ 1. `MEMORY_DIR`.
510
+ 2. `$OPENCODE_CONFIG_DIR/memory`.
511
+ 3. Existing legacy `~/.config/opencode/memory`.
512
+ 4. `%LOCALAPPDATA%/opencode/memory` on Windows.
513
+ 5. `$XDG_CONFIG_HOME/opencode/memory` or `~/.config/opencode/memory` elsewhere.
389
514
 
390
- # End-to-end smoke test with REAL ONNX embeddings — run before a release
391
- npm run smoke
515
+ Important paths inside it:
392
516
 
393
- # Search quality & ingestion benchmarks
394
- npm run benchmark
517
+ ```text
518
+ global.md global Notebook facts/directives
519
+ git_<identity>.md per-project Notebook facts
520
+ config.json non-secret configuration
521
+ auth_secrets.enc encrypted cloud credentials
522
+ storage/memory.sqlite RAG, graph, identity registry, sync state
523
+ storage/blobs/ content-addressed compressed raw sources
524
+ storage/models/ cached ONNX models
525
+ exports/ snapshots/exports
395
526
  ```
396
527
 
397
- ### Two testing modes, and why both exist
528
+ - No telemetry or analytics are sent.
529
+ - Model weights download from Hugging Face on first use and remain cached afterward.
530
+ - Network access is otherwise limited to explicit URL ingestion and configured Turso cloud modes.
531
+ - Snapshot path validation and local ingestion allowlists restrict arbitrary filesystem access.
532
+ - SQLite uses foreign keys, migrations, transactions, and a busy timeout for concurrent access.
398
533
 
399
- `npm test` runs every suite with `generateEmbeddings: false`. That keeps it fast
400
- and offline (no model download, no network), but it means the **dense-vector half
401
- of the engine is never exercised** — retrieval falls back to BM25-only.
534
+ ### Dependency Advisories
402
535
 
403
- `npm run smoke` covers exactly that blind spot: it ingests a document with real
404
- ONNX vectors and asserts that hybrid retrieval returns a non-zero cosine
405
- similarity, plus that a Russian query still reaches an English document
406
- (something BM25 cannot do). It also walks the full user journey — remember →
407
- recall → ingest → query → link → update → get → forget — and checks the ingest
408
- path guard.
536
+ Spreadsheet ingestion uses SheetJS CE `0.20.3` from the official SheetJS CDN rather than the stale `xlsx@0.18.5` package in the public npm registry. This version is outside the affected ranges for the known [prototype pollution](https://github.com/advisories/GHSA-4r6h-8v6p-xvw6) and [ReDoS](https://github.com/advisories/GHSA-5pgg-2g8v-p4x9) advisories.
409
537
 
410
- This split is not academic: a regression in `v1.5.3+` disabled vector search
411
- entirely (`node:sqlite` returns BLOBs as `Uint8Array`, and a `Buffer.isBuffer()`
412
- guard discarded every stored vector) while all offline suites stayed green. The
413
- smoke test exists so that class of failure cannot ship unnoticed again.
538
+ `npm audit` may still report the high-severity `sharp` / libvips advisory inherited through `@huggingface/transformers`. The project uses Transformers only for text feature extraction and explicitly sets `env.sharp = false`; it does not pass images through the Transformers image-decoding path. The upstream dependency currently constrains `sharp` below the patched `0.35.x` line, so this warning remains transitive until Transformers updates its dependency. Advisory: [GHSA-f88m-g3jw-g9cj](https://github.com/advisories/GHSA-f88m-g3jw-g9cj).
414
539
 
415
- The smoke test reuses the model weights already cached in your data directory, so
416
- it does not re-download them. Point `MEMORY_MODEL_CACHE` at a cache directory to
417
- override the lookup; without any cache the weights are fetched once.
540
+ ---
541
+
542
+ ## Testing and Benchmarks
418
543
 
419
- For complete methodology details and search quality evaluation metrics, see [`docs/BENCHMARKS.md`](./docs/BENCHMARKS.md).
544
+ ```bash
545
+ npm test # unified unit, integration, and simulated-cloud suites
546
+ npm run smoke # real ONNX vectors and end-to-end memory journey
547
+ npm run test:rag # retrieval quality evaluation
548
+ npm run benchmark # full search benchmark report
549
+ npm run benchmark:table-code
550
+ ```
420
551
 
421
- ### Empirical Search Quality Results
552
+ The fast suites use `generateEmbeddings: false` in retrieval paths for deterministic offline coverage. `npm run smoke` covers the dense-vector path with real cached/downloaded model weights and checks multilingual semantic retrieval. Both modes are needed: lexical-only tests cannot catch a broken vector serialization or ONNX execution path.
422
553
 
423
- Evaluated across a 32-document technical corpus (21 queries) using Mean Reciprocal Rank (MRR@5), Recall@5, and Normalized Discounted Cumulative Gain (NDCG@5):
554
+ The unified suites cover fact formatting, typed directives, persona migration/synchronization, client prompt safety, Codex launcher compatibility, Git identity isolation, RAG scopes, policy expansion, RAG Memory Notes, semantic index output, raw blob portability, reverse sync, tombstones, snapshots, MCP contracts, and cloud authentication workflows.
424
555
 
425
- | Retrieval Strategy | MRR@5 | Recall@5 | NDCG@5 |
426
- | :---------------------------- | :--------: | :---------: | :--------: |
427
- | BM25 Lexical Search Only | 0.6706 | 76.19% | 0.6934 |
428
- | Dense ONNX Vector Only | 0.8135 | 100.00% | 0.8612 |
429
- | Hybrid RRF ($k=60$) | 0.8810 | 95.24% | 0.8997 |
430
- | **Hybrid RSF ($\alpha=0.5$)** | **0.9286** | **100.00%** | **0.9473** |
556
+ See [`docs/BENCHMARKS.md`](./docs/BENCHMARKS.md) for methodology and detailed reports.
431
557
 
432
- ---
558
+ ### Included Search Evaluation
433
559
 
434
- ## Storage & Privacy
560
+ The stored 32-document / 21-query technical corpus produced:
435
561
 
436
- - **Local-First Storage**: All SQLite indexes, ONNX models, CAS blobs, and Markdown notebooks are stored locally in the memory directory. Resolution order: `$MEMORY_DIR` → `$OPENCODE_CONFIG_DIR/memory` → the legacy `~/.config/opencode/memory` directory when it already exists (this takes precedence on Windows too) → `%LOCALAPPDATA%\opencode\memory`.
437
- - **Model Weights**: ONNX weights are downloaded on first use from `https://huggingface.co` and cached locally; later runs are fully offline.
438
- - **Zero Telemetry**: No third-party analytics or telemetry calls are made. The only outbound traffic is the one-off model download, plus Turso requests in the cloud sync modes.
562
+ | Strategy | MRR@5 | Recall@5 | NDCG@5 |
563
+ | :--- | :---: | :---: | :---: |
564
+ | BM25 lexical only | 0.6706 | 76.19% | 0.6934 |
565
+ | Dense ONNX only | 0.8135 | 100.00% | 0.8612 |
566
+ | Hybrid RRF (`k=60`) | 0.8810 | 95.24% | 0.8997 |
567
+ | **Hybrid RSF (`alpha=0.5`)** | **0.9286** | **100.00%** | **0.9473** |
439
568
 
440
- ### Known Dependency Advisories
569
+ ---
441
570
 
442
- `npm audit` reports three high-severity advisories with no upstream fix available. Both affected packages are only reachable through explicit user action:
571
+ ## Troubleshooting
443
572
 
444
- | Package | Advisory | Reachability | Mitigation |
445
- | :--- | :--- | :--- | :--- |
446
- | `xlsx` (SheetJS) | Prototype Pollution ([GHSA-4r6h-8v6p-xvw6](https://github.com/advisories/GHSA-4r6h-8v6p-xvw6)), ReDoS ([GHSA-5pgg-2g8v-p4x9](https://github.com/advisories/GHSA-5pgg-2g8v-p4x9)) | Only when you ingest a `.xlsx` / `.xls` / `.csv` file | Do not ingest untrusted spreadsheets. A migration to `exceljs` is under consideration. |
447
- | `sharp` `<0.35.0` (via `@huggingface/transformers`) | libvips CVE-2026-33327 / 33328 / 35590 / 35591 ([GHSA-f88m-g3jw-g9cj](https://github.com/advisories/GHSA-f88m-g3jw-g9cj)) | Image decoding path only; this plugin runs text embedding models exclusively and never feeds images to `sharp` | Not reachable in normal use; will clear once `@huggingface/transformers` bumps `sharp`. |
573
+ - **`No such built-in module: node:sqlite`**: install Node.js `22.5.0` or newer.
574
+ - **Codex tools are missing**: run `memory_plugin setup --codex`, then `memory_plugin doctor --codex`, and open a new Codex task.
575
+ - **OpenCode still runs old code**: restart OpenCode. For repository development, confirm `npm run dev:link` points its plugin entry to `opencode-plugin/main.js`.
576
+ - **Persona changes are not visible**: run `memory-cli sync-persona`, then start a new CLI session/task. Use `memory-cli migrate-persona --dry-run` for legacy entries.
577
+ - **Project recall is empty**: call `memory_info`; if a Git identity is `Registry: unlinked`, run `link_project_memory` or `memory-cli link --dir <repo>`.
578
+ - **A raw note/document exists only in cloud**: `manage_knowledge_base(action: "read_document")` automatically materializes and verifies its CAS blob locally when cloud credentials are available.
579
+ - **Embedding model changed**: run `reindex_knowledge_base` or use the TUI `[REINDEX]` action.
448
580
 
449
581
  ---
450
582