@bcmyguest/openmem 0.0.0-stage → 0.6.3

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 (191) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +136 -2
  3. package/bin/hindsight-project-index +530 -0
  4. package/cli/coding-agent/access-policy.mjs +38 -0
  5. package/cli/coding-agent/agents.mjs +34 -0
  6. package/cli/coding-agent/bank-from-cwd.mjs +140 -0
  7. package/cli/coding-agent/capabilities.mjs +23 -0
  8. package/cli/coding-agent/hook-harnesses.mjs +87 -0
  9. package/cli/coding-agent/hook-runner.mjs +260 -0
  10. package/cli/coding-agent/install-access.mjs +93 -0
  11. package/cli/coding-agent/install-shim.mjs +97 -0
  12. package/cli/coding-agent/opencode-config.mjs +91 -0
  13. package/cli/coding-agent/opencode-plugin.mjs +96 -0
  14. package/cli/coding-agent/runtime.mjs +39 -0
  15. package/cli/coding-agent/session-facade.mjs +62 -0
  16. package/cli/cognee-mcp.mjs +260 -0
  17. package/cli/feed-sync.mjs +11 -0
  18. package/cli/install-coding-agent.mjs +165 -0
  19. package/cli/install-memory-mcp.mjs +426 -0
  20. package/cli/is-main.mjs +18 -0
  21. package/cli/mcp/context.mjs +61 -0
  22. package/cli/mcp/export/cognee-dataset-name.mjs +12 -0
  23. package/cli/mcp/export/cognee.mjs +119 -0
  24. package/cli/mcp/export/hindsight.mjs +48 -0
  25. package/cli/mcp/export/index.mjs +26 -0
  26. package/cli/mcp/export/mem0.mjs +31 -0
  27. package/cli/mcp/llm-synthesize.mjs +50 -0
  28. package/cli/mcp/mem0-scope-id.mjs +22 -0
  29. package/cli/mcp/memory-facade.mjs +455 -0
  30. package/cli/mcp/memory-reflect-consolidate.mjs +120 -0
  31. package/cli/mcp/notebooklm-banks.mjs +21 -0
  32. package/cli/mcp/notebooklm-hindsight-rest.mjs +45 -0
  33. package/cli/mcp/notebooklm-provider.mjs +225 -0
  34. package/cli/mcp/pmm-records.mjs +23 -0
  35. package/cli/mcp/portability.mjs +158 -0
  36. package/cli/mcp/stdio.mjs +65 -0
  37. package/cli/mcp/unified-mcp-install.mjs +65 -0
  38. package/cli/mem0-mcp.mjs +108 -0
  39. package/cli/notebooklm-mcp.mjs +236 -0
  40. package/cli/openmem-mcp.mjs +35 -0
  41. package/cli/openmem.mjs +205 -0
  42. package/cli/roots.mjs +85 -0
  43. package/cli/stack.mjs +436 -0
  44. package/cli/switch-memory-provider.mjs +358 -0
  45. package/cli/wiring-report.mjs +125 -0
  46. package/compose.bench.yaml +12 -0
  47. package/compose.yaml +164 -0
  48. package/config/coding-agent.json +13 -0
  49. package/config/hindsight.env.example +24 -0
  50. package/config/index.yml +54 -0
  51. package/config/litellm.lemond.yaml +40 -0
  52. package/config/litellm.ollama.yaml +33 -0
  53. package/config/notebooklm.yml +33 -0
  54. package/config/openmem.toml.example +62 -0
  55. package/docs/OPENMEM.md +23 -0
  56. package/docs/architecture.md +219 -0
  57. package/docs/assets/README.md +10 -0
  58. package/docs/assets/setup-demo.gif +0 -0
  59. package/docs/coding-agent-hooks.md +51 -0
  60. package/docs/coding-agent-scopes.md +22 -0
  61. package/docs/coding-agents.md +51 -0
  62. package/docs/cognee.md +37 -0
  63. package/docs/concepts.md +112 -0
  64. package/docs/hindsight.md +74 -0
  65. package/docs/index-sources-roadmap.md +38 -0
  66. package/docs/index-sources.md +39 -0
  67. package/docs/indexer-sinks.md +122 -0
  68. package/docs/indexing.md +57 -0
  69. package/docs/manual-stack-setup.md +74 -0
  70. package/docs/mcp-install-guide.md +4 -0
  71. package/docs/mcp-setup.md +101 -0
  72. package/docs/mem0.md +103 -0
  73. package/docs/memory-portability.md +73 -0
  74. package/docs/memory-providers.md +246 -0
  75. package/docs/model-configuration.md +84 -0
  76. package/docs/notebooklm.md +83 -0
  77. package/docs/npx-install.md +170 -0
  78. package/docs/openmem-config.md +194 -0
  79. package/docs/provider-wizard-hooks.md +222 -0
  80. package/docs/quickstart.md +101 -0
  81. package/docs/setup-wizard.md +116 -0
  82. package/docs/sources-feeds.md +52 -0
  83. package/docs/sources-readwise.md +23 -0
  84. package/docs/sources-zotero.md +22 -0
  85. package/glama.json +4 -0
  86. package/indexer/Dockerfile +38 -0
  87. package/indexer/code_outline.py +146 -0
  88. package/indexer/feed_sync.py +107 -0
  89. package/indexer/index_config.py +290 -0
  90. package/indexer/pytest.ini +5 -0
  91. package/indexer/sinks/__init__.py +148 -0
  92. package/indexer/sinks/_http.py +44 -0
  93. package/indexer/sinks/cognee.py +329 -0
  94. package/indexer/sinks/hindsight.py +107 -0
  95. package/indexer/sinks/mem0.py +247 -0
  96. package/indexer/watch.py +240 -0
  97. package/package.json +95 -4
  98. package/providers/_template/compose.yaml +52 -0
  99. package/providers/cognee/OPERATOR.md +82 -0
  100. package/providers/cognee/compose.yaml +89 -0
  101. package/providers/cognee/lib/clack.mjs +157 -0
  102. package/providers/cognee/lib/coding-agent.mjs +26 -0
  103. package/providers/cognee/lib/cognee-mcp-install.mjs +153 -0
  104. package/providers/cognee/lib/config.mjs +98 -0
  105. package/providers/cognee/lib/env-file.mjs +194 -0
  106. package/providers/cognee/lib/env-setup.mjs +83 -0
  107. package/providers/cognee/lib/llm-env.mjs +382 -0
  108. package/providers/cognee/lib/ports.mjs +25 -0
  109. package/providers/cognee/lib/smoke.mjs +246 -0
  110. package/providers/cognee/lib/stack-env.mjs +134 -0
  111. package/providers/cognee/lib/state.mjs +101 -0
  112. package/providers/cognee/lib/summary.mjs +56 -0
  113. package/providers/cognee/lib/validate.mjs +97 -0
  114. package/providers/cognee/manifest.json +56 -0
  115. package/providers/cognee/wizard.mjs +134 -0
  116. package/providers/graphiti/manifest.json +15 -0
  117. package/providers/hindsight/lib/clack.mjs +245 -0
  118. package/providers/hindsight/lib/coding-agent.mjs +204 -0
  119. package/providers/hindsight/lib/config.mjs +73 -0
  120. package/providers/hindsight/lib/env-setup.mjs +71 -0
  121. package/providers/hindsight/lib/litellm-routes.mjs +187 -0
  122. package/providers/hindsight/lib/model-backend.mjs +214 -0
  123. package/providers/hindsight/lib/notebooklm-mcp-install.mjs +127 -0
  124. package/providers/hindsight/lib/ollama-compose.mjs +51 -0
  125. package/providers/hindsight/lib/ports.mjs +30 -0
  126. package/providers/hindsight/lib/probe.mjs +33 -0
  127. package/providers/hindsight/lib/stack-env.mjs +132 -0
  128. package/providers/hindsight/lib/state.mjs +75 -0
  129. package/providers/hindsight/lib/summary.mjs +43 -0
  130. package/providers/hindsight/lib/validate.mjs +75 -0
  131. package/providers/hindsight/manifest.json +58 -0
  132. package/providers/hindsight/wizard.mjs +149 -0
  133. package/providers/letta/manifest.json +29 -0
  134. package/providers/mem0/OPERATOR.md +124 -0
  135. package/providers/mem0/compose.yaml +57 -0
  136. package/providers/mem0/lib/coding-agent.mjs +58 -0
  137. package/providers/mem0/lib/config.mjs +45 -0
  138. package/providers/mem0/lib/configure.mjs +135 -0
  139. package/providers/mem0/lib/dotenv.mjs +71 -0
  140. package/providers/mem0/lib/env-file.mjs +110 -0
  141. package/providers/mem0/lib/http.mjs +69 -0
  142. package/providers/mem0/lib/mcp-install.mjs +165 -0
  143. package/providers/mem0/lib/secret.mjs +30 -0
  144. package/providers/mem0/lib/smoke.mjs +179 -0
  145. package/providers/mem0/lib/stack-env.mjs +216 -0
  146. package/providers/mem0/lib/state.mjs +67 -0
  147. package/providers/mem0/lib/summary.mjs +60 -0
  148. package/providers/mem0/lib/url.mjs +106 -0
  149. package/providers/mem0/lib/validate.mjs +158 -0
  150. package/providers/mem0/manifest.json +47 -0
  151. package/providers/mem0/wizard.mjs +133 -0
  152. package/providers/zep/manifest.json +29 -0
  153. package/scripts/check-pack.mjs +218 -0
  154. package/scripts/gen-masks.mjs +83 -0
  155. package/scripts/gen-masks.sh +4 -0
  156. package/scripts/promotion-provider-smoke.mjs +34 -0
  157. package/scripts/run-setup.sh +30 -0
  158. package/scripts/setup.mjs +94 -0
  159. package/scripts/setup.sh +5 -0
  160. package/scripts/spin-up.sh +45 -0
  161. package/scripts/wizard.sh +5 -0
  162. package/server.json +34 -0
  163. package/skills/openmem/SKILL.md +29 -0
  164. package/sync/Dockerfile +27 -0
  165. package/sync/memory_backend.py +87 -0
  166. package/sync/notebooklm_sync.py +664 -0
  167. package/wizard/bin/pm.mjs +97 -0
  168. package/wizard/bin/setup.mjs +33 -0
  169. package/wizard/lib/compose-version.mjs +32 -0
  170. package/wizard/lib/compose.mjs +70 -0
  171. package/wizard/lib/curl.mjs +103 -0
  172. package/wizard/lib/docker-build.mjs +148 -0
  173. package/wizard/lib/exec.mjs +41 -0
  174. package/wizard/lib/indexer.mjs +6 -0
  175. package/wizard/lib/load-machine-env.mjs +4 -0
  176. package/wizard/lib/log.mjs +32 -0
  177. package/wizard/lib/notebooklm-agent-access.mjs +92 -0
  178. package/wizard/lib/notebooklm.mjs +214 -0
  179. package/wizard/lib/parse-args.mjs +87 -0
  180. package/wizard/lib/paths.mjs +39 -0
  181. package/wizard/lib/pm-config.mjs +163 -0
  182. package/wizard/lib/ports.mjs +94 -0
  183. package/wizard/lib/prompts.mjs +57 -0
  184. package/wizard/lib/provider-wizard/helpers.mjs +98 -0
  185. package/wizard/lib/provider-wizard/run-steps.mjs +129 -0
  186. package/wizard/lib/providers/registry.mjs +262 -0
  187. package/wizard/lib/run-clack.mjs +108 -0
  188. package/wizard/lib/run-wizard.mjs +755 -0
  189. package/wizard/lib/validate-setup.mjs +62 -0
  190. package/wizard/lib/wizard-action.mjs +34 -0
  191. package/wizard/lib/wizard-conf.mjs +71 -0
package/docs/cognee.md ADDED
@@ -0,0 +1,37 @@
1
+ # Cognee (loopback container)
2
+
3
+ Self-hosted graph/RAG memory via a pinned `cognee/cognee` image on a loopback port (`COGNEE_PORT`, default **8766**). Auth is off in this stack. Cognify defaults to local GLiNER + FastEmbed (no API key); optional LLM keys live in env files under `~/.config/personal-memory/`, not in stack `.env` or `mcp.json`.
4
+
5
+ ## Coding agents
6
+
7
+ No plugin package. Agents use REST (`/docs`, `/health`, `/api/v1/add`, `/cognify`, `/search`) or the **read-only** MCP in this repo.
8
+
9
+ ### Cursor MCP
10
+
11
+ When `MEMORY_PROVIDER=cognee`:
12
+
13
+ ```sh
14
+ npx @bcmyguest/openmem install-mcp --yes --provider-only
15
+ ```
16
+
17
+ Registers `cli/cognee-mcp.mjs` with `COGNEE_API_URL` only — **never** `COGNEE_API_KEY` in `mcp.json`. If you enable auth, export the key in the agent environment.
18
+
19
+ | Tool | Purpose |
20
+ | --- | --- |
21
+ | `cognee_health` | `GET /health` |
22
+ | `cognee_search` | `POST /api/v1/search` |
23
+
24
+ Ingest and cognify stay with the indexer or direct API calls; the MCP is search/health only.
25
+
26
+ Restart Cursor Agent after install.
27
+
28
+ ## Switch provider
29
+
30
+ ```sh
31
+ npx @bcmyguest/openmem switch cognee --yes
32
+ # later: npx @bcmyguest/openmem switch hindsight --yes
33
+ ```
34
+
35
+ Updates active provider config, restarts the stack (unless `--no-stack`), runs MCP install (unless `--no-mcp`). Does **not** migrate memories.
36
+
37
+ See also [Architecture](architecture.md), [Hindsight](hindsight.md), and [Provider status](provider-status.md).
@@ -0,0 +1,112 @@
1
+ # Concepts
2
+
3
+ OpenMem is a **memory interface for coding agents**: a stable API and operator surface, with pluggable backends underneath.
4
+
5
+ ## What’s coding-agent memory?
6
+
7
+ Coding agents forget between sessions. A memory system stores durable facts, decisions, and project context so the next turn (or agent) can recall them without re-deriving everything from the repo.
8
+
9
+ In practice that means:
10
+
11
+ - **Write** — retain notes, session transcripts, indexed sources
12
+ - **Read** — search, recall, or synthesize an answer from stored memories
13
+ - **Scope** — keep personal notes, vaults, and per-repo banks from colliding
14
+ - **Operate** — run a backend locally (or point at one), keep secrets off the wire you did not choose
15
+
16
+ Full use of memory needs a **memory system**: an API (or library) plus storage, extraction, and usually an admin or ops path. Hindsight, mem0, Cognee, and in-house stores are examples. Each has its own API, deploy story, and agent wiring.
17
+
18
+ ## What’s OpenMem?
19
+
20
+ OpenMem is **not** a memory engine. It is the layer that sits between coding agents and whichever engine you run:
21
+
22
+ | Layer | Role |
23
+ | --- | --- |
24
+ | **Agents** | Claude Code, Codex, Cursor Agent, OpenCode — call stable `memory_*` tools and share one skill |
25
+ | **OpenMem** | Wizard, Compose, indexer, unified MCP, session hooks, import/export formats |
26
+ | **Provider** | Hindsight, mem0, Cognee, or the next manifest — owns semantics, storage, and native APIs |
27
+
28
+ One active provider at a time. `openmem switch` rewires the stack; it does not pretend to migrate your data. Portability is explicit through the format layer (PMM today).
29
+
30
+ ```mermaid
31
+ flowchart TB
32
+ AG[Coding agents]
33
+ OM["OpenMem surface<br/>memory_* · skill · session hooks · wizard · indexer"]
34
+ AG --> OM
35
+ OM --> HS[Hindsight]
36
+ OM --> M0[mem0]
37
+ OM --> CG[Cognee]
38
+ OM --> NX["…next provider manifest"]
39
+ ```
40
+
41
+ ## Why an interface layer?
42
+
43
+ Without a shared front door, every agent and indexer hard-codes one vendor’s SDK or HTTP shape. Switching backends means rewriting hooks, MCP entries, and indexing. Trying a second system means a second install path.
44
+
45
+ Standardizing the **agent and ops surface** means:
46
+
47
+ - Keep using your current memory product
48
+ - Try another backend without rewriting agent prompts and MCP tool names
49
+ - Share indexer, wizard, and install plumbing across backends
50
+ - Grow a community of providers behind one contract
51
+
52
+ OpenMem owns machine plumbing. Providers own memory quality.
53
+
54
+ ## Core pieces
55
+
56
+ ### Providers
57
+
58
+ A **provider** is the translation layer between OpenMem and a memory backend. It maps manifests, Compose fragments, wizard hooks, and an indexer sink onto that product’s API so agents and the indexer stay backend-agnostic.
59
+
60
+ Ship a provider as `providers/<id>/` (manifest + hooks + compose). Status (`supported` / `experimental` / `planned`) comes from the manifest. See [Provider status](provider-status.md) and [Pluggable memory providers](memory-providers.md).
61
+
62
+ Only one provider is registered as active (`MEMORY_PROVIDER`). Switching replaces the active backend for Compose, the indexer sink, and unified MCP.
63
+
64
+ ### Evaluation API (`memory_*`)
65
+
66
+ Agents do not call Hindsight or mem0 tool names by default. They call a **stable tool set** on the `openmem` MCP server:
67
+
68
+ | Tool | Intent |
69
+ | --- | --- |
70
+ | `memory_add` | Store a durable record |
71
+ | `memory_search` / `memory_recall` | Retrieve |
72
+ | `memory_reflect` / `memory_consolidate` | Synthesize (provider-dependent) |
73
+ | `memory_forget` | Delete (scoped; confirm before bulk) |
74
+ | `memory_export` / `memory_import` | Portability (PMM) |
75
+ | `memory_provider_status` / `memory_project_scope` | Ops / bank resolution |
76
+
77
+ The facade (`cli/mcp/memory-facade.mjs`) maps each call onto the active provider’s HTTP API. Native provider MCP (`install-mcp --provider-only`) remains available when you want vendor tools.
78
+
79
+ ### Context and banks
80
+
81
+ **Bank** (or provider-equivalent `user_id` / dataset) is the scope key for a write or read. Default MCP scope is `openmem-mcp`. Project work should pass the resolved project bank so session noise does not land in the default.
82
+
83
+ Resolution order: longest matching `index.yml` bank prefix → `~/.config/personal-memory/coding-agent.json` `mapPathToBank` → legacy Hindsight mapping → `coding-agent::<repo-directory-name>`. Details: [Coding-agent scopes](coding-agent-scopes.md).
84
+
85
+ ### Formats
86
+
87
+ Import/export goes through a **format layer**, not a provider-specific dump. **PMM** (Personal Memory Manifest) is the first format; more formats plug into the same orchestrator. See [Portable memory (PMM)](memory-portability.md).
88
+
89
+ ### Session hooks and skill
90
+
91
+ OpenMem installs one **skill** and **session hooks** (SessionStart / prompt / Stop) so agents recall and retain without remembering a vendor SDK. Optional: upstream Hindsight plugin via `--hindsight-plugin`.
92
+
93
+ ### Indexer
94
+
95
+ A shared **indexer** watches git repos, Obsidian vaults, notes trees, and feed caches, then writes through the active provider’s sink. Sources are provider-agnostic; only the sink changes with `MEMORY_PROVIDER`.
96
+
97
+ ## What OpenMem is not
98
+
99
+ - A replacement for Hindsight, mem0, or Cognee product UIs
100
+ - A guarantee that memories move losslessly between backends (export/import is explicit)
101
+ - A multi-provider fan-out in one process (one active provider; switch to change)
102
+
103
+ ## Next
104
+
105
+ | Doc | Use when |
106
+ | --- | --- |
107
+ | [Quickstart](quickstart.md) | First install |
108
+ | [MCP setup](mcp-setup.md) | Unified `memory_*` MCP, native mem0/Cognee, NotebookLM |
109
+ | [Portable memory (PMM)](memory-portability.md) | Export/import between providers |
110
+ | [Architecture](architecture.md) | Runtime data paths |
111
+ | [Provider status](provider-status.md) | Which backends ship |
112
+ | [mem0](mem0.md) · [Hindsight](hindsight.md) · [Cognee](cognee.md) | Provider operator guides |
@@ -0,0 +1,74 @@
1
+ # Hindsight (default stack)
2
+
3
+ **Hindsight** is the default memory provider: Docker Compose runs **LiteLLM**, the **Hindsight API**, and the shared **indexer** on loopback. Retain, recall, reflect, and consolidate go through Hindsight’s HTTP API; LiteLLM routes model calls to lemond, Ollama, or another OpenAI-compatible backend.
4
+
5
+ Upstream project: [vectorize-io/hindsight](https://github.com/vectorize-io/hindsight).
6
+
7
+ ## What openmem runs
8
+
9
+ | Service | Role |
10
+ | --- | --- |
11
+ | `litellm` | Proxy for Hindsight aliases `memory-retain`, `memory-reflect`, `memory-consolidate` |
12
+ | `hindsight` | Memory API (default host port **8888**, `HINDSIGHT_PORT`) |
13
+ | `indexer` | Git, Obsidian, markdown trees, feed cache → Hindsight banks via `MEMORY_SINK=hindsight` |
14
+
15
+ Health check after setup:
16
+
17
+ ```sh
18
+ curl -fsS http://127.0.0.1:8888/health
19
+ ```
20
+
21
+ Control plane URL is printed by the wizard (separate from the API port).
22
+
23
+ ## Secrets and config (never in the repo)
24
+
25
+ | Path | Purpose |
26
+ | --- | --- |
27
+ | `~/.config/hindsight/hindsight.env` | Hindsight API settings |
28
+ | `~/.config/hindsight/litellm.yaml` | Optional full LiteLLM route override |
29
+ | `~/.config/hindsight/index.yml` | Index sources ([index-sources.md](index-sources.md)) |
30
+ | `~/.config/hindsight/wizard.conf` | Active provider and wizard choices |
31
+ | `~/.hindsight/coding-agent.json` | **Real file on disk** — repo maps, opt-in paths, NotebookLM access |
32
+
33
+ Shipped route templates live in `config/litellm.lemond.yaml` and `config/litellm.ollama.yaml`. Details: [Model configuration](model-configuration.md).
34
+
35
+ ## Coding agents and MCP
36
+
37
+ **Default (all providers):** unified `memory_*` MCP plus in-repo session hooks:
38
+
39
+ ```sh
40
+ npx @bcmyguest/openmem install-coding-agent --yes
41
+ ```
42
+
43
+ **Optional:** also install the upstream Hindsight plugin hooks:
44
+
45
+ ```sh
46
+ npx @bcmyguest/openmem install-coding-agent --yes --hindsight-plugin
47
+ ```
48
+
49
+ MCP without session hooks:
50
+
51
+ ```sh
52
+ npx @bcmyguest/openmem install-mcp --yes
53
+ ```
54
+
55
+ Restart Cursor Agent after MCP changes.
56
+
57
+ ## Switch provider
58
+
59
+ ```sh
60
+ npx @bcmyguest/openmem switch mem0 --yes
61
+ # return: npx @bcmyguest/openmem switch hindsight --yes
62
+ ```
63
+
64
+ Updates compose profile, env, and MCP wiring. Does **not** migrate memories between backends.
65
+
66
+ ## NotebookLM (opt-in)
67
+
68
+ NotebookLM sync and MCP are provider-agnostic but were built for Hindsight-first workflows. See [docs/notebooklm.md](notebooklm.md).
69
+
70
+ ## See also
71
+
72
+ - [Architecture](architecture.md) — indexing and MCP paths
73
+ - [Model configuration](model-configuration.md) — LiteLLM aliases and backends
74
+ - [Provider status](provider-status.md)
@@ -0,0 +1,38 @@
1
+ # Index sources — roadmap
2
+
3
+ Today the indexer **ships** git repos, Obsidian vaults, markdown directory trees (`notes`, `papers`, `bookmarks` in `index.yml`), and a **feed cache** (`feeds` + `feed-sync`). Everything else below is **planned** or **bring-your-own-export** (point a folder at an export until a native connector exists).
4
+
5
+ ## Shipped (filesystem)
6
+
7
+ | Kind | Config | Typical content |
8
+ | --- | --- | --- |
9
+ | Git repo | `roots`, `repos` | Code + tracked docs |
10
+ | Obsidian vault | `vaults` | Notes with `.obsidian` |
11
+ | Notes | `notes.paths` | Plain markdown trees |
12
+ | Papers | `papers.paths` | Paper notes, Zotero md export, reading notes |
13
+ | Bookmarks | `bookmarks.paths` | Saved links as markdown/HTML exports |
14
+ | Feed cache | `feeds.out_dir` + `feed-sync` | RSS / OpenAlex markdown under a watched dir |
15
+
16
+ ## Planned connectors (API / sync jobs)
17
+
18
+ | Source | Idea | Likely bank prefix | Notes |
19
+ | --- | --- | --- | --- |
20
+ | **Zotero** | API or periodic export dir | `papers::zotero` | Prefer export-to-`papers.paths` first |
21
+ | **OpenAlex / OpenResearch** | Metadata + abstract pull | `openresearch::` | Read-only citeable snippets, not full PDF hosting |
22
+ | **Semantic Scholar** | Library sync | `papers::s2` | Same pattern as OpenAlex |
23
+ | **Readwise** | Reader / highlight export | `readwise::` | Official export → markdown dir |
24
+ | **Hypothesis** | Annotation export | `hypothesis::` | Web annotation JSON → indexer adapter |
25
+ | **Pinboard / Linkwarden / Karakeep** | Bookmark API or export | `bookmarks::` | Overlap with `bookmarks.paths` |
26
+ | **RSS / arXiv feed** | `npx @bcmyguest/openmem feed-sync` | `feed::*` | Shipped; see [sources-feeds.md](sources-feeds.md) |
27
+ | **Email** | mbox / selective forward | `mail::` | High privacy risk; opt-in only |
28
+ | **Slack / Discord export** | JSON dump dirs | `chat::` | Enterprise exports only |
29
+ | **NotebookLM** | Already optional Hindsight profile | `notebooklm::*` | Not a generic source type |
30
+
31
+ ## Design rules for new sources
32
+
33
+ 1. **One sink** — all sources retain into the active provider via the same indexer process.
34
+ 2. **Stable bank ids** — prefix + slug; override with `banks:` in `index.yml`.
35
+ 3. **Filesystem first** — if the tool can export to a directory, use `*.paths` before building OAuth sync.
36
+ 4. **No secrets in repo** — API keys in `~/.config/personal-memory/`, not index.yml.
37
+
38
+ Contributing a connector: add a row here, then either a new `*.paths` kind (markdown) or an indexer sidecar script that writes retains through the existing sink.
@@ -0,0 +1,39 @@
1
+ # Index sources
2
+
3
+ The shared indexer reads `~/.config/hindsight/index.yml` (or `config/index.yml` defaults). One active provider sink receives retains from every source.
4
+
5
+ | Source kind | Config | Detection | Default bank prefix |
6
+ | --- | --- | --- | --- |
7
+ | **Git repo** | `roots`, `repos` | Poll `git` fingerprint | `coding-agent::<repo>` |
8
+ | **Obsidian vault** | `roots` + `vaults.auto`, `vaults.paths` | inotify after quiet period | `obsidian::<slug>` |
9
+ | **Notes** | `notes.paths` | inotify | `notes::<slug>` |
10
+ | **Papers** | `papers.paths` | inotify | `papers::<slug>` |
11
+ | **Bookmarks** | `bookmarks.paths` | inotify (.md, .html, .txt) | `bookmarks::<slug>` |
12
+ | **Feed cache** | `feeds` + `feed-sync` | inotify on `feeds.out_dir` | `feed::<slug>` |
13
+
14
+ Markdown trees index `.md` (and Obsidian-style structure) the same way; use separate keys so banks stay readable in Hindsight/mem0 scopes.
15
+
16
+ Override banks with the `banks:` map (longest prefix wins).
17
+
18
+ ```yaml
19
+ notes:
20
+ paths:
21
+ - ~/Documents/plain-markdown
22
+ papers:
23
+ paths:
24
+ - ~/Zotero/storage/export-md
25
+ bookmarks:
26
+ paths:
27
+ - ~/Exports/linkwarden-markdown
28
+ repos:
29
+ - ~/src/my-fork
30
+ vaults:
31
+ paths:
32
+ - ~/Obsidian/Main
33
+ ```
34
+
35
+ Exclude paths with `exclude:` globs. Tune `poll_seconds`, `vault_quiet_seconds`, and `relist_seconds` for watcher behavior.
36
+
37
+ **Guides:** [Feed sync](sources-feeds.md) (RSS / OpenAlex → `feed::*`) · [Zotero exports](sources-zotero.md) · [Readwise exports](sources-readwise.md). Native API connectors and more kinds: [index-sources-roadmap.md](index-sources-roadmap.md).
38
+
39
+ See [indexer sinks](indexer-sinks.md) for how banks map to mem0/Cognee/Hindsight scopes.
@@ -0,0 +1,122 @@
1
+ # Indexer sink drivers
2
+
3
+ The shared indexer (`bin/hindsight-project-index`, watcher, compose `indexer` service) turns
4
+ git repos, Obsidian vaults, markdown trees (`notes` / `papers` / `bookmarks`), and feed-cache
5
+ folders into documents and writes them through a **sink**: a Python module
6
+ under `indexer/sinks/<name>.py`. Provider manifests declare how compose and the wizard wire that
7
+ sink; see [Pluggable memory providers](memory-providers.md) for manifests and wizard ownership.
8
+
9
+ ## Manifest fields vs runtime ids
10
+
11
+ | Concept | Where it lives | Role |
12
+ | --- | --- | --- |
13
+ | **`indexer.sink`** | `providers/<id>/manifest.json` | Module name: `indexer/sinks/<sink>.py`. Becomes `MEMORY_SINK` in compose and `--sink` on the CLI. |
14
+ | **`indexer.sinkDriver`** | same | Human-readable wire-dialect label only (for docs and status pages). **Does not** select a module. |
15
+ | **`indexer.apiUrlEnv`** | same | Name of the env var the wizard documents for the provider API base URL on the host. |
16
+
17
+ Registered providers today:
18
+
19
+ | Provider | `sink` (module) | `sinkDriver` | `apiUrlEnv` |
20
+ | --- | --- | --- | --- |
21
+ | Hindsight (`supported`) | `hindsight` | `hindsight-rest-v1` | `HINDSIGHT_URL` |
22
+ | mem0 | `mem0` | `mem0-rest` | `MEM0_API_URL` |
23
+ | Cognee | `cognee` | `cognee-rest` | `COGNEE_API_URL` |
24
+
25
+ Contract tests: `indexer/tests/sink_contract.py`, provider-specific tests under `indexer/tests/`.
26
+
27
+ ## Choosing a sink and API URL
28
+
29
+ | Input | Meaning |
30
+ | --- | --- |
31
+ | `--sink NAME` | Sink module name. Default: `$MEMORY_SINK`, then `hindsight`. |
32
+ | `MEMORY_SINK` | Set in compose fragments for mem0/Cognee (`providers/*/compose.yaml`). |
33
+ | `--url URL` | Overrides all URL env vars for this run. |
34
+ | `HINDSIGHT_URL` | API base for the **hindsight** sink only (default `http://127.0.0.1:8888`). |
35
+ | `MEMORY_API_URL` | API base for **every non-Hindsight** sink (mem0, Cognee). Required for those sinks when `--url` is omitted. |
36
+
37
+ Resolution order in the CLI: `--url` → `HINDSIGHT_URL` (hindsight sink) or `MEMORY_API_URL` (other
38
+ sinks) → sink-specific default (Hindsight only). Credentials are read inside each sink’s `create()`
39
+ from provider-specific env vars, never from indexed file paths.
40
+
41
+ Provider secret files (mode `600`, outside the repo):
42
+
43
+ | Provider | Typical file | Indexer-relevant keys |
44
+ | --- | --- | --- |
45
+ | mem0 | `~/.config/personal-memory/mem0.env` | `MEM0_API_KEY` → `X-API-Key` on API calls (not on `GET /docs` health) |
46
+ | Cognee | `~/.config/personal-memory/cognee-indexer.env` | `COGNEE_API_KEY` when the server requires auth (default single-user image does not) |
47
+
48
+ Stack `.env` holds host ports and derived URLs (for example `MEM0_INDEXER_URL` for the indexer
49
+ container’s view of mem0). LLM keys for Cognee cognify live in `cognee.env`, not in the indexer env
50
+ file — see [Cognee](cognee.md).
51
+
52
+ ## Indexer `bank` → provider namespace
53
+
54
+ The indexer uses **`bank`** for the logical scope of a source (repo, vault, or `index.yml` override).
55
+ Examples: `coding-agent::my-repo`, `obsidian::my-vault`, `notebooklm::work-notes` (when synced into
56
+ Hindsight). **`doc_id`** is a stable per-document id (`project-index:v1:…`). Each sink maps `bank` /
57
+ `doc_id` to its backend’s scoping model.
58
+
59
+ ### Hindsight (`hindsight-rest-v1`)
60
+
61
+ | Indexer field | Hindsight API |
62
+ | --- | --- |
63
+ | `bank` | Bank id in the path: `/v1/default/banks/{bank}/…` (URL-encoded) |
64
+ | `doc_id` | Carried in retain payload / document identity for updates and deletes |
65
+
66
+ Behavior:
67
+
68
+ - `prepare(bank)` ensures the bank exists, sets retain strategy `project-index`, disables auto-consolidation for indexed banks.
69
+ - Retains are **synchronous** (`async: false`); no `flush()` hook.
70
+ - Default URL when unset: `http://127.0.0.1:8888`. Compose sets `HINDSIGHT_URL: http://hindsight:8888` on the indexer service.
71
+
72
+ NotebookLM sync writes into Hindsight banks `notebooklm::<slug>`; that path is separate from sink
73
+ selection (still the hindsight sink when `MEMORY_PROVIDER=hindsight`).
74
+
75
+ ### mem0 (`mem0-rest`)
76
+
77
+ | Indexer field | mem0 REST field |
78
+ | --- | --- |
79
+ | `bank` | `user_id` (via `scope_id()` — see below) |
80
+ | `doc_id` | `run_id` (same `scope_id` rules) |
81
+ | (fixed) | `agent_id` = `openmem-indexer` (provenance only; lookups use `user_id` + `run_id`) |
82
+
83
+ **`scope_id`:** If the id has no whitespace, it is used as-is. Otherwise whitespace runs become `_`,
84
+ and `~` plus the first 8 hex digits of SHA-256(original) are appended so ids that differ only in
85
+ whitespace stay distinct (for example `obsidian::My Vault` → `obsidian::My_Vault~<8 hex>`).
86
+
87
+ Documents are chunked (max 3000 characters per chunk, `infer: false`). Updates list existing memories
88
+ for `(user_id, run_id)`, write new chunks, then delete old ids. There is no mem0 “bank” to create;
89
+ `prepare` is a no-op.
90
+
91
+ Compose: `MEMORY_SINK=mem0`, `MEMORY_API_URL=${MEM0_INDEXER_URL}` (wizard derives this from host
92
+ `MEM0_API_URL`). Operator runbook: `providers/mem0/OPERATOR.md`, [mem0](mem0.md).
93
+
94
+ ### Cognee (`cognee-rest`)
95
+
96
+ | Indexer field | Cognee concept |
97
+ | --- | --- |
98
+ | `bank` | **Dataset name** derived from `bank` (not the raw string) |
99
+ | `doc_id` | Stored in upload `external_metadata` as `doc_id` (plus `bank`); used to replace/delete rows |
100
+
101
+ **Dataset name:** `<slug>_<8 hex of sha256(bank)>` where `slug` is `bank` lowercased, non-`[a-z0-9]`
102
+ collapsed to `_`, trimmed, max 40 chars (empty → `bank`). Two banks that slug identically still differ
103
+ by hash suffix.
104
+
105
+ Ingestion is **asynchronous**: `retain`/`delete` call REST add/delete; the sink implements **`flush(bank)`**
106
+ to trigger `POST /api/v1/cognify` for that dataset after each changed batch (and retries pending flushes
107
+ from indexer state). Search lags until cognify completes.
108
+
109
+ Compose: `MEMORY_SINK=cognee`, `MEMORY_API_URL: http://cognee:8000`, optional
110
+ `cognee-indexer.env` for `COGNEE_API_KEY`. Operator notes: [Cognee](cognee.md).
111
+
112
+ ## Optional `flush()` (Cognee)
113
+
114
+ Sinks with `capabilities.async_ingest=True` may define `flush(bank)`. The indexer calls it on
115
+ `--apply` after retains/deletes for that bank, and persists `::flush-pending` in state when a flush
116
+ fails. Hindsight has no flush. Details: [Pluggable memory providers — Optional flush](memory-providers.md#optional-flush).
117
+
118
+ ## Related
119
+
120
+ - [Indexing](indexing.md) — sources, `index.yml`, watcher timings
121
+ - [Architecture](architecture.md) — unified MCP mapping to the same backends
122
+ - [MCP setup](mcp-setup.md) — Cursor servers vs indexer sinks
@@ -0,0 +1,57 @@
1
+ # Indexing
2
+
3
+ The indexer indexes each source once at startup, then keeps it current:
4
+
5
+ - **Git repositories:** the outermost repositories under each `roots` entry, plus `repos`. The indexer polls each one every `poll_seconds` (default 60). A poll fingerprints `HEAD` and the tracked-file status (`git status --porcelain -uno`). After one poll with an unchanged fingerprint, the repository is re-indexed. Edits to an already-modified tracked file change no fingerprint until `HEAD` or the status changes. Repositories with a persistent error re-run on each poll. Banks default to `coding-agent::<repo>` unless `banks` maps the path.
6
+ - **Obsidian vaults:** any folder containing `.obsidian/` within a root's depth, plus `vaults.paths`. Each uses the bank `obsidian::<slug>` unless `banks` maps it. Changes are watched with inotify. A vault is re-indexed after `vault_quiet_seconds` (default 30) without changes. Dot-prefixed paths are ignored.
7
+ - **Markdown trees:** `notes.paths`, `papers.paths`, and `bookmarks.paths` (plain folders without `.obsidian/`). Watched with inotify; banks default to `notes::`, `papers::`, and `bookmarks::` slugs. Bookmarks also index `.html` and `.txt` exports. Use `papers.paths` for Zotero markdown export dirs; see [sources-zotero.md](sources-zotero.md) and [sources-readwise.md](sources-readwise.md).
8
+ - **Feed cache:** when `feeds.rss` or `feeds.openalex_queries` is set in `index.yml`, run `npx @bcmyguest/openmem feed-sync` to refresh markdown under `feeds.out_dir`; the indexer watches that directory as kind `feed` (`feed::<slug>` banks). See [sources-feeds.md](sources-feeds.md).
9
+ - **Source discovery:** sources are re-listed every `relist_seconds` (default 600), so new repos, vaults, and configured paths are picked up without a restart.
10
+
11
+ Operator overview: [index-sources.md](index-sources.md).
12
+ - Code files get a tree-sitter outline (signatures, doc comments, imports) instead of a CodeGraph run. Parsing runs in-process; grammars are prefetched into the image at `/opt/tree-sitter-grammars`, so indexing needs no network. Supported languages: Python, JavaScript, TypeScript, TSX, Go, Rust, Java, C, C++, C#, Ruby, Lua, Bash, PHP. Known gaps: Go type declarations and TypeScript type aliases are not captured, and files with syntax errors give partial outlines. Outlines are re-retained once after this change, and the old CodeGraph-based code documents are deleted as stale.
13
+ - `optInPaths` filters sources. A missing file means no filter; an empty list means nothing is indexed.
14
+ - Automatic consolidation is disabled for the whole indexed bank, not only for indexed documents.
15
+ - Document IDs include the absolute source path. The first run after this change re-retains every document, which costs extraction time on the model server.
16
+ - Concurrent `--apply` runs (the watcher and a manual run) serialize through a lock on `state.json.lock`.
17
+
18
+ Set `INDEXER_DRY_RUN=1` to log the commands the watcher would run without executing them. The environment variables `POLL_SECONDS`, `VAULT_QUIET_SECONDS`, and `RELIST_SECONDS` override the timings in `index.yml`.
19
+
20
+ ### Source config: `index.yml`
21
+
22
+ `config/index.yml` in the repository is the default. The indexer reads the first of these that exists:
23
+
24
+ 1. `--config PATH` (manual runs and `--list`)
25
+ 2. `$HINDSIGHT_INDEX_CONFIG`
26
+ 3. `~/.config/hindsight/index.yml` (per machine; the container sees it through `scripts/setup.mjs`'s mount)
27
+ 4. `config/index.yml` (baked into the image at `/opt/config/index.yml`; rebuild after changing it)
28
+
29
+ A file found this way replaces the default entirely. Keys it omits take the built-in values, which match `config/index.yml`. Unknown keys and wrong types fail at startup with the file, key, and reason. `~` expands; a bare `~` in YAML is null, which means home under `roots[].path`.
30
+
31
+ | Key | Meaning |
32
+ | --- | --- |
33
+ | `roots` | `[{path, depth}]`. Repositories are the outermost git repositories found within `depth` levels (default 3). |
34
+ | `repos` | Extra repositories, outside the roots or not. Each must be a git repository. |
35
+ | `vaults.auto` | `true` (default) finds any folder with `.obsidian/` within a root's depth. |
36
+ | `vaults.paths` | Extra vault folders. |
37
+ | `notes.paths`, `papers.paths`, `bookmarks.paths` | Markdown (and bookmark export) directories; see [index-sources.md](index-sources.md). |
38
+ | `feeds.out_dir`, `feeds.rss`, `feeds.openalex_queries` | Feed sync output; requires `npx @bcmyguest/openmem feed-sync`. |
39
+ | `exclude` | Glob patterns on absolute paths. A matching source is skipped. |
40
+ | `banks` | Absolute path prefix to bank id; the longest prefix wins. Applies to all source kinds. Unmatched repos fall back to `~/.config/personal-memory/coding-agent.json` `mapPathToBank`, then legacy `~/.hindsight/coding-agent.json`, then `coding-agent::<repository-name>`. |
41
+ | `max_file_kb` | Largest indexed file, in kilobytes (1 KB = 1000 bytes). Default 128. |
42
+ | `skip_dirs` | Directory names not descended into. Dot-prefixed directories are always skipped. |
43
+ | `poll_seconds`, `vault_quiet_seconds`, `relist_seconds` | Watcher timings. |
44
+
45
+ `optInPaths` in `~/.hindsight/coding-agent.json` still filters sources after discovery.
46
+
47
+ Check the result with `--list` before a first `--apply`. Excluded sources are reported on stderr.
48
+
49
+ Manual runs. The script defaults to a dry run; `--apply` writes:
50
+
51
+ ```sh
52
+ docker compose run --rm --no-deps indexer hindsight-project-index --list
53
+ docker compose run --rm --no-deps indexer hindsight-project-index --repo PATH --apply
54
+ docker compose run --rm --no-deps indexer hindsight-project-index --vault PATH --apply
55
+ ```
56
+
57
+ `--no-deps` avoids starting the `hindsight` service, which the indexer depends on. `PATH` is the host path, which the container also sees.
@@ -0,0 +1,74 @@
1
+ # Manual stack setup
2
+
3
+ Use this when you are not running the [setup wizard](setup-wizard.md). Commands assume your **stack root** is the current directory (git checkout or `PM_STACK_ROOT`).
4
+
5
+ ## Hindsight: minimal path
6
+
7
+ ```sh
8
+ mkdir -p ~/.config/hindsight
9
+ cp config/hindsight.env.example ~/.config/hindsight/hindsight.env
10
+ chmod 600 ~/.config/hindsight/hindsight.env
11
+ node scripts/setup.mjs
12
+ node scripts/setup.mjs --migrate-env # only if hindsight.env still points at lemond/Ollama directly
13
+ docker compose up -d
14
+ curl -fsS http://127.0.0.1:8888/health
15
+ ```
16
+
17
+ `scripts/setup.mjs` must run before any `docker compose` command (including `logs` and `down`). It writes stack `.env`, `compose.override.yaml`, and related files.
18
+
19
+ ## Compose profiles
20
+
21
+ | Profile | Services |
22
+ | --- | --- |
23
+ | `hindsight` | LiteLLM + Hindsight API (default after wizard) |
24
+ | `ollama` | In-compose Ollama for LiteLLM |
25
+ | `notebooklm` | NotebookLM → Hindsight sync |
26
+
27
+ Plain `docker compose up` without profiles starts only the indexer unless `.env` sets `COMPOSE_PROFILES`. The wizard passes every needed `--profile` on each compose invocation.
28
+
29
+ NotebookLM is started **after** the smoke test so sync does not compete with smoke on the LLM.
30
+
31
+ ## Indexer sinks
32
+
33
+ | Variable | Meaning |
34
+ | --- | --- |
35
+ | `MEMORY_SINK` / `--sink` | `hindsight` (default), `mem0`, `cognee`, … |
36
+ | `HINDSIGHT_URL` | Hindsight API from indexer container |
37
+ | `MEMORY_API_URL` | Non-Hindsight memory API |
38
+
39
+ Entrypoint: `bin/hindsight-project-index` via `indexer/sinks/`.
40
+
41
+ ## What setup.mjs generates
42
+
43
+ | Output | Role |
44
+ | --- | --- |
45
+ | `.env` | `HOST_UID`, `HOST_GID`, `LITELLM_CONFIG`, `COMPOSE_PROFILES`, … |
46
+ | `compose.override.yaml` | Masks `~/.ssh`, `~/.gnupg`, `~/.config/hindsight`, agent credential dirs from the indexer; optional mount for `index.yml` |
47
+ | `~/.config/hindsight/litellm.env` | LiteLLM master key (mode 600) if missing |
48
+
49
+ The indexer runs as your UID (`user: "${HOST_UID}:${HOST_GID}"`). Writable state is only the named volume `indexer-state` (mounted at `$HOME/.cache/hindsight-project-index` inside the container); `$HOME` is read-only.
50
+
51
+ Rerun `node scripts/setup.mjs` after UID changes or when new secret directories appear (masks are generated only for paths that exist).
52
+
53
+ ## Seed indexer state volume
54
+
55
+ When moving from a host `state.json` to the volume:
56
+
57
+ ```bash
58
+ docker compose stop indexer
59
+ docker compose run --rm --no-deps indexer-state-init
60
+ docker run --rm --user "$HOST_UID:$HOST_GID" \
61
+ -v "$HOME/.cache/hindsight-project-index:/src:ro" \
62
+ -v personal-memory_indexer-state:/dst openmem-indexer:local \
63
+ cp /src/state.json /dst/
64
+ ```
65
+
66
+ Adjust the volume name with `docker volume ls` if the compose project name differs.
67
+
68
+ ## Bench overlay (optional)
69
+
70
+ `compose.bench.yaml` also publishes Hindsight on the Docker bridge gateway for sandboxes (see the file for the bind address). Keep `compose.override.yaml` in the `-f` list when you add `-f compose.bench.yaml`.
71
+
72
+ ```bash
73
+ docker compose -f compose.yaml -f compose.override.yaml -f compose.bench.yaml up -d hindsight
74
+ ```
@@ -0,0 +1,4 @@
1
+ # MCP install guide
2
+
3
+ This page moved to **[MCP setup](mcp-setup.md)** (published on the docs site).
4
+
@@ -0,0 +1,101 @@
1
+ # MCP setup
2
+
3
+ OpenMem registers **stdio MCP servers** in `~/.cursor/mcp.json` (and wires session hooks via `install-coding-agent`). Day-to-day you want the **unified** `openmem` server (`memory_*` tools). Provider-native and NotebookLM servers are optional add-ons.
4
+
5
+ For why this exists, see [Concepts](concepts.md). Install path: [Quickstart § Wire your coding agent](quickstart.md#3-wire-your-coding-agent-optional).
6
+
7
+ ## Quick path (recommended)
8
+
9
+ ```sh
10
+ npx @bcmyguest/openmem install-coding-agent --yes
11
+ ```
12
+
13
+ That installs:
14
+
15
+ 1. Unified MCP (`openmem`) — `memory_add`, `memory_search`, `memory_recall`, `memory_reflect`, `memory_consolidate`, `memory_forget`, `memory_export` / `memory_import`, ops tools
16
+ 2. OpenMem skill + session hooks (Claude Code, Codex, OpenCode, Cursor CLI)
17
+
18
+ MCP only (no session hooks):
19
+
20
+ ```sh
21
+ npx @bcmyguest/openmem install-mcp --yes
22
+ ```
23
+
24
+ Restart **Cursor Agent** (or your agent’s MCP host) after changes.
25
+
26
+ ## Server families
27
+
28
+ | Server key | How to install | Tools | Backend |
29
+ | --- | --- | --- | --- |
30
+ | **`openmem`** | Default `install-mcp` / `install-coding-agent` | Stable `memory_*` | Active provider (`MEMORY_PROVIDER`): Hindsight, mem0, or Cognee |
31
+ | **Provider-native** (`mem0`, `cognee`) | `install-mcp --provider-only` | Upstream / repo-specific names | Same HTTP API, different tool surface |
32
+ | **`notebooklm`** | When NotebookLM sync is on, or `--notebooklm` | `notebooklm_list_banks`, `notebooklm_search` | Search over synced notebooks on the **active** provider — not a memory engine |
33
+
34
+ Hindsight’s optional in-editor plugin (`--hindsight-plugin`) is **not** an MCP entry; it complements unified MCP on Hindsight stacks. See [Hindsight](hindsight.md).
35
+
36
+ ## When to use which
37
+
38
+ ### Default: unified `memory_*`
39
+
40
+ Use when you want one tool contract that survives `npx @bcmyguest/openmem switch <provider>` without rewriting prompts.
41
+
42
+ ```sh
43
+ npx @bcmyguest/openmem install-mcp --yes
44
+ npx @bcmyguest/openmem install-mcp --yes --notebooklm # also force NotebookLM MCP
45
+ ```
46
+
47
+ ### Provider-native (optional)
48
+
49
+ Use when you already have prompts for upstream tool names:
50
+
51
+ ```sh
52
+ MEMORY_PROVIDER=mem0 npx @bcmyguest/openmem install-mcp --yes --provider-only
53
+ npx @bcmyguest/openmem install-mcp --yes --provider-only # Cognee when active
54
+ ```
55
+
56
+ - **mem0:** `cli/mem0-mcp.mjs` → `@yeyuan98/mem0-mcp` (URL + path to `mem0.env` in JSON — never the key). Details: [mem0](mem0.md).
57
+ - **Cognee:** `cli/cognee-mcp.mjs` (`cognee_health`, `cognee_search`; `COGNEE_API_URL` only). Details: [Cognee](cognee.md).
58
+
59
+ `install-mcp --provider-only` still merges unified `openmem` unless you also pass `--no-unified-mcp`. Both can coexist in `mcp.json`.
60
+
61
+ ### NotebookLM only
62
+
63
+ ```sh
64
+ npx @bcmyguest/openmem install-mcp --yes --notebooklm-only
65
+ ```
66
+
67
+ Mutually exclusive with `--provider-only`. Read-only search over synced notebooks — not a substitute for project indexing or `memory_*`.
68
+
69
+ ## Flags
70
+
71
+ ```sh
72
+ npx @bcmyguest/openmem install-mcp --yes
73
+ npx @bcmyguest/openmem install-mcp --yes --notebooklm
74
+ npx @bcmyguest/openmem install-mcp --yes --notebooklm-only
75
+ MEMORY_PROVIDER=mem0 npx @bcmyguest/openmem install-mcp --yes --provider-only
76
+ npx @bcmyguest/openmem install-mcp --yes --no-unified-mcp
77
+ npx @bcmyguest/openmem install-mcp --dry-run
78
+ ```
79
+
80
+ | Flag | Effect |
81
+ | --- | --- |
82
+ | `--yes` | No confirmation prompt |
83
+ | `--dry-run` | Print plan; do not write configs |
84
+ | `--notebooklm` | Enable NotebookLM agent access + merge `notebooklm` MCP |
85
+ | `--notebooklm-only` | Only NotebookLM step |
86
+ | `--provider-only` | Native mem0/Cognee MCP for active provider; skip NotebookLM |
87
+ | `--no-unified-mcp` | Do not merge the `openmem` server |
88
+
89
+ **Provider resolution:** `MEMORY_PROVIDER` → `~/.config/hindsight/wizard.conf` → `hindsight`.
90
+
91
+ **Merge behavior:** Existing `hindsight`, `codegraph`, and `notebooklm` entries are preserved; mem0/Cognee entries are updated for the active provider.
92
+
93
+ ## Portability tools
94
+
95
+ On the unified server, `memory_export` / `memory_import` speak **PMM** (Personal Memory Manifest). See [Portable memory (PMM)](memory-portability.md).
96
+
97
+ ## Related
98
+
99
+ - [mem0](mem0.md) · [Cognee](cognee.md) · [Hindsight](hindsight.md)
100
+ - [Architecture](architecture.md) — how `memory_*` maps to provider HTTP
101
+ - [Quickstart](quickstart.md)