@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.
- package/LICENSE +190 -0
- package/README.md +136 -2
- package/bin/hindsight-project-index +530 -0
- package/cli/coding-agent/access-policy.mjs +38 -0
- package/cli/coding-agent/agents.mjs +34 -0
- package/cli/coding-agent/bank-from-cwd.mjs +140 -0
- package/cli/coding-agent/capabilities.mjs +23 -0
- package/cli/coding-agent/hook-harnesses.mjs +87 -0
- package/cli/coding-agent/hook-runner.mjs +260 -0
- package/cli/coding-agent/install-access.mjs +93 -0
- package/cli/coding-agent/install-shim.mjs +97 -0
- package/cli/coding-agent/opencode-config.mjs +91 -0
- package/cli/coding-agent/opencode-plugin.mjs +96 -0
- package/cli/coding-agent/runtime.mjs +39 -0
- package/cli/coding-agent/session-facade.mjs +62 -0
- package/cli/cognee-mcp.mjs +260 -0
- package/cli/feed-sync.mjs +11 -0
- package/cli/install-coding-agent.mjs +165 -0
- package/cli/install-memory-mcp.mjs +426 -0
- package/cli/is-main.mjs +18 -0
- package/cli/mcp/context.mjs +61 -0
- package/cli/mcp/export/cognee-dataset-name.mjs +12 -0
- package/cli/mcp/export/cognee.mjs +119 -0
- package/cli/mcp/export/hindsight.mjs +48 -0
- package/cli/mcp/export/index.mjs +26 -0
- package/cli/mcp/export/mem0.mjs +31 -0
- package/cli/mcp/llm-synthesize.mjs +50 -0
- package/cli/mcp/mem0-scope-id.mjs +22 -0
- package/cli/mcp/memory-facade.mjs +455 -0
- package/cli/mcp/memory-reflect-consolidate.mjs +120 -0
- package/cli/mcp/notebooklm-banks.mjs +21 -0
- package/cli/mcp/notebooklm-hindsight-rest.mjs +45 -0
- package/cli/mcp/notebooklm-provider.mjs +225 -0
- package/cli/mcp/pmm-records.mjs +23 -0
- package/cli/mcp/portability.mjs +158 -0
- package/cli/mcp/stdio.mjs +65 -0
- package/cli/mcp/unified-mcp-install.mjs +65 -0
- package/cli/mem0-mcp.mjs +108 -0
- package/cli/notebooklm-mcp.mjs +236 -0
- package/cli/openmem-mcp.mjs +35 -0
- package/cli/openmem.mjs +205 -0
- package/cli/roots.mjs +85 -0
- package/cli/stack.mjs +436 -0
- package/cli/switch-memory-provider.mjs +358 -0
- package/cli/wiring-report.mjs +125 -0
- package/compose.bench.yaml +12 -0
- package/compose.yaml +164 -0
- package/config/coding-agent.json +13 -0
- package/config/hindsight.env.example +24 -0
- package/config/index.yml +54 -0
- package/config/litellm.lemond.yaml +40 -0
- package/config/litellm.ollama.yaml +33 -0
- package/config/notebooklm.yml +33 -0
- package/config/openmem.toml.example +62 -0
- package/docs/OPENMEM.md +23 -0
- package/docs/architecture.md +219 -0
- package/docs/assets/README.md +10 -0
- package/docs/assets/setup-demo.gif +0 -0
- package/docs/coding-agent-hooks.md +51 -0
- package/docs/coding-agent-scopes.md +22 -0
- package/docs/coding-agents.md +51 -0
- package/docs/cognee.md +37 -0
- package/docs/concepts.md +112 -0
- package/docs/hindsight.md +74 -0
- package/docs/index-sources-roadmap.md +38 -0
- package/docs/index-sources.md +39 -0
- package/docs/indexer-sinks.md +122 -0
- package/docs/indexing.md +57 -0
- package/docs/manual-stack-setup.md +74 -0
- package/docs/mcp-install-guide.md +4 -0
- package/docs/mcp-setup.md +101 -0
- package/docs/mem0.md +103 -0
- package/docs/memory-portability.md +73 -0
- package/docs/memory-providers.md +246 -0
- package/docs/model-configuration.md +84 -0
- package/docs/notebooklm.md +83 -0
- package/docs/npx-install.md +170 -0
- package/docs/openmem-config.md +194 -0
- package/docs/provider-wizard-hooks.md +222 -0
- package/docs/quickstart.md +101 -0
- package/docs/setup-wizard.md +116 -0
- package/docs/sources-feeds.md +52 -0
- package/docs/sources-readwise.md +23 -0
- package/docs/sources-zotero.md +22 -0
- package/glama.json +4 -0
- package/indexer/Dockerfile +38 -0
- package/indexer/code_outline.py +146 -0
- package/indexer/feed_sync.py +107 -0
- package/indexer/index_config.py +290 -0
- package/indexer/pytest.ini +5 -0
- package/indexer/sinks/__init__.py +148 -0
- package/indexer/sinks/_http.py +44 -0
- package/indexer/sinks/cognee.py +329 -0
- package/indexer/sinks/hindsight.py +107 -0
- package/indexer/sinks/mem0.py +247 -0
- package/indexer/watch.py +240 -0
- package/package.json +95 -4
- package/providers/_template/compose.yaml +52 -0
- package/providers/cognee/OPERATOR.md +82 -0
- package/providers/cognee/compose.yaml +89 -0
- package/providers/cognee/lib/clack.mjs +157 -0
- package/providers/cognee/lib/coding-agent.mjs +26 -0
- package/providers/cognee/lib/cognee-mcp-install.mjs +153 -0
- package/providers/cognee/lib/config.mjs +98 -0
- package/providers/cognee/lib/env-file.mjs +194 -0
- package/providers/cognee/lib/env-setup.mjs +83 -0
- package/providers/cognee/lib/llm-env.mjs +382 -0
- package/providers/cognee/lib/ports.mjs +25 -0
- package/providers/cognee/lib/smoke.mjs +246 -0
- package/providers/cognee/lib/stack-env.mjs +134 -0
- package/providers/cognee/lib/state.mjs +101 -0
- package/providers/cognee/lib/summary.mjs +56 -0
- package/providers/cognee/lib/validate.mjs +97 -0
- package/providers/cognee/manifest.json +56 -0
- package/providers/cognee/wizard.mjs +134 -0
- package/providers/graphiti/manifest.json +15 -0
- package/providers/hindsight/lib/clack.mjs +245 -0
- package/providers/hindsight/lib/coding-agent.mjs +204 -0
- package/providers/hindsight/lib/config.mjs +73 -0
- package/providers/hindsight/lib/env-setup.mjs +71 -0
- package/providers/hindsight/lib/litellm-routes.mjs +187 -0
- package/providers/hindsight/lib/model-backend.mjs +214 -0
- package/providers/hindsight/lib/notebooklm-mcp-install.mjs +127 -0
- package/providers/hindsight/lib/ollama-compose.mjs +51 -0
- package/providers/hindsight/lib/ports.mjs +30 -0
- package/providers/hindsight/lib/probe.mjs +33 -0
- package/providers/hindsight/lib/stack-env.mjs +132 -0
- package/providers/hindsight/lib/state.mjs +75 -0
- package/providers/hindsight/lib/summary.mjs +43 -0
- package/providers/hindsight/lib/validate.mjs +75 -0
- package/providers/hindsight/manifest.json +58 -0
- package/providers/hindsight/wizard.mjs +149 -0
- package/providers/letta/manifest.json +29 -0
- package/providers/mem0/OPERATOR.md +124 -0
- package/providers/mem0/compose.yaml +57 -0
- package/providers/mem0/lib/coding-agent.mjs +58 -0
- package/providers/mem0/lib/config.mjs +45 -0
- package/providers/mem0/lib/configure.mjs +135 -0
- package/providers/mem0/lib/dotenv.mjs +71 -0
- package/providers/mem0/lib/env-file.mjs +110 -0
- package/providers/mem0/lib/http.mjs +69 -0
- package/providers/mem0/lib/mcp-install.mjs +165 -0
- package/providers/mem0/lib/secret.mjs +30 -0
- package/providers/mem0/lib/smoke.mjs +179 -0
- package/providers/mem0/lib/stack-env.mjs +216 -0
- package/providers/mem0/lib/state.mjs +67 -0
- package/providers/mem0/lib/summary.mjs +60 -0
- package/providers/mem0/lib/url.mjs +106 -0
- package/providers/mem0/lib/validate.mjs +158 -0
- package/providers/mem0/manifest.json +47 -0
- package/providers/mem0/wizard.mjs +133 -0
- package/providers/zep/manifest.json +29 -0
- package/scripts/check-pack.mjs +218 -0
- package/scripts/gen-masks.mjs +83 -0
- package/scripts/gen-masks.sh +4 -0
- package/scripts/promotion-provider-smoke.mjs +34 -0
- package/scripts/run-setup.sh +30 -0
- package/scripts/setup.mjs +94 -0
- package/scripts/setup.sh +5 -0
- package/scripts/spin-up.sh +45 -0
- package/scripts/wizard.sh +5 -0
- package/server.json +34 -0
- package/skills/openmem/SKILL.md +29 -0
- package/sync/Dockerfile +27 -0
- package/sync/memory_backend.py +87 -0
- package/sync/notebooklm_sync.py +664 -0
- package/wizard/bin/pm.mjs +97 -0
- package/wizard/bin/setup.mjs +33 -0
- package/wizard/lib/compose-version.mjs +32 -0
- package/wizard/lib/compose.mjs +70 -0
- package/wizard/lib/curl.mjs +103 -0
- package/wizard/lib/docker-build.mjs +148 -0
- package/wizard/lib/exec.mjs +41 -0
- package/wizard/lib/indexer.mjs +6 -0
- package/wizard/lib/load-machine-env.mjs +4 -0
- package/wizard/lib/log.mjs +32 -0
- package/wizard/lib/notebooklm-agent-access.mjs +92 -0
- package/wizard/lib/notebooklm.mjs +214 -0
- package/wizard/lib/parse-args.mjs +87 -0
- package/wizard/lib/paths.mjs +39 -0
- package/wizard/lib/pm-config.mjs +163 -0
- package/wizard/lib/ports.mjs +94 -0
- package/wizard/lib/prompts.mjs +57 -0
- package/wizard/lib/provider-wizard/helpers.mjs +98 -0
- package/wizard/lib/provider-wizard/run-steps.mjs +129 -0
- package/wizard/lib/providers/registry.mjs +262 -0
- package/wizard/lib/run-clack.mjs +108 -0
- package/wizard/lib/run-wizard.mjs +755 -0
- package/wizard/lib/validate-setup.mjs +62 -0
- package/wizard/lib/wizard-action.mjs +34 -0
- 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).
|
package/docs/concepts.md
ADDED
|
@@ -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
|
package/docs/indexing.md
ADDED
|
@@ -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,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)
|