@bcmyguest/openmem 0.6.3 → 0.8.0

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 (102) hide show
  1. package/{skills → .agents/skills}/openmem/SKILL.md +5 -0
  2. package/README.md +80 -76
  3. package/cli/coding-agent/capabilities.mjs +14 -3
  4. package/cli/coding-agent/context-store.mjs +81 -0
  5. package/cli/coding-agent/context-trim.mjs +897 -0
  6. package/cli/coding-agent/file-io.mjs +72 -0
  7. package/cli/coding-agent/hook-harnesses.mjs +2 -1
  8. package/cli/coding-agent/hook-runner.mjs +28 -4
  9. package/cli/coding-agent/install-access.mjs +43 -17
  10. package/cli/coding-agent/install-context-proxy.mjs +333 -0
  11. package/cli/coding-agent/install-rtk.mjs +60 -0
  12. package/cli/coding-agent/install-shim.mjs +119 -15
  13. package/cli/coding-agent/opencode-config.mjs +21 -5
  14. package/cli/coding-agent/opencode-plugin.mjs +39 -3
  15. package/cli/coding-agent/opencode2-plugin/index.js +299 -0
  16. package/cli/coding-agent/recall-frame.mjs +29 -0
  17. package/cli/coding-agent/remove-upstream-access.mjs +122 -0
  18. package/cli/coding-agent/runtime.mjs +2 -1
  19. package/cli/coding-agent/session-db.mjs +626 -0
  20. package/cli/coding-agent/session-facade.mjs +30 -6
  21. package/cli/coding-agent/toml-edit.mjs +161 -0
  22. package/cli/context-management.mjs +254 -0
  23. package/cli/feed-sync.mjs +18 -2
  24. package/cli/install-coding-agent.mjs +173 -40
  25. package/cli/mcp/context-sql-runner.mjs +58 -0
  26. package/cli/mcp/context-store.mjs +670 -0
  27. package/cli/mcp/knowledge.mjs +333 -0
  28. package/cli/mcp/memory-facade.mjs +99 -33
  29. package/cli/openmem-mcp.mjs +3 -0
  30. package/cli/openmem.mjs +18 -1
  31. package/cli/schedule.mjs +176 -0
  32. package/cli/stack.mjs +2 -0
  33. package/cli/switch-memory-provider.mjs +1 -1
  34. package/compose.yaml +67 -4
  35. package/config/hindsight.env.example +2 -0
  36. package/config/openmem.toml.example +64 -2
  37. package/docs/architecture.md +35 -9
  38. package/docs/coding-agent-hooks.md +26 -2
  39. package/docs/coding-agents.md +27 -7
  40. package/docs/compatibility.md +80 -0
  41. package/docs/concepts.md +30 -7
  42. package/docs/context-management.md +255 -0
  43. package/docs/context-proxy.md +115 -0
  44. package/docs/context-research.md +215 -0
  45. package/docs/context-store.md +277 -0
  46. package/docs/hindsight.md +5 -2
  47. package/docs/mcp-setup.md +5 -2
  48. package/docs/mem0.md +39 -1
  49. package/docs/memory-providers.md +2 -2
  50. package/docs/meridian-litellm.md +198 -0
  51. package/docs/model-configuration.md +22 -0
  52. package/docs/npx-install.md +6 -4
  53. package/docs/openmem-config.md +2 -2
  54. package/docs/quickstart.md +12 -6
  55. package/docs/setup-wizard.md +5 -4
  56. package/docs/sources-feeds.md +9 -22
  57. package/package.json +5 -4
  58. package/providers/cognee/OPERATOR.md +2 -2
  59. package/providers/hindsight/lib/clack.mjs +122 -20
  60. package/providers/hindsight/lib/coding-agent.mjs +1 -1
  61. package/providers/hindsight/lib/config.mjs +6 -0
  62. package/providers/hindsight/lib/env-setup.mjs +2 -1
  63. package/providers/hindsight/lib/litellm-routes.mjs +21 -12
  64. package/providers/hindsight/lib/meridian.mjs +307 -0
  65. package/providers/hindsight/lib/model-backend.mjs +38 -9
  66. package/providers/hindsight/lib/probe.mjs +21 -0
  67. package/providers/hindsight/lib/stack-env.mjs +5 -12
  68. package/providers/hindsight/lib/state.mjs +6 -1
  69. package/providers/hindsight/lib/summary.mjs +16 -2
  70. package/providers/hindsight/lib/validate.mjs +6 -0
  71. package/providers/hindsight/wizard.mjs +3 -2
  72. package/providers/mem0/OPERATOR.md +21 -2
  73. package/providers/mem0/compose.yaml +24 -2
  74. package/providers/mem0/lib/coding-agent.mjs +1 -1
  75. package/providers/mem0/lib/configure.mjs +66 -0
  76. package/providers/mem0/lib/litellm.mjs +457 -0
  77. package/providers/mem0/lib/stack-env.mjs +40 -1
  78. package/providers/mem0/lib/summary.mjs +30 -2
  79. package/providers/mem0/manifest.json +1 -1
  80. package/providers/mem0/wizard.mjs +15 -2
  81. package/proxy/config.yaml +33 -0
  82. package/proxy/openmem_context/__init__.py +6 -0
  83. package/proxy/openmem_context/adapters.py +504 -0
  84. package/proxy/openmem_context/compress.py +53 -0
  85. package/proxy/openmem_context/core.py +606 -0
  86. package/proxy/openmem_context/embed.py +212 -0
  87. package/proxy/openmem_context/recall.py +49 -0
  88. package/proxy/openmem_context/session.py +70 -0
  89. package/proxy/openmem_context/sessiondb.py +276 -0
  90. package/proxy/openmem_context/settings.py +134 -0
  91. package/proxy/openmem_context/store.py +129 -0
  92. package/proxy/openmem_context/tokens.py +123 -0
  93. package/proxy/openmem_context/ttl.py +78 -0
  94. package/proxy/openmem_context_hook.py +34 -0
  95. package/scripts/check-pack.mjs +2 -1
  96. package/scripts/setup.mjs +14 -1
  97. package/server.json +2 -2
  98. package/wizard/lib/context-step.mjs +140 -0
  99. package/wizard/lib/litellm-env.mjs +55 -0
  100. package/wizard/lib/pm-config.mjs +212 -4
  101. package/wizard/lib/prompts.mjs +28 -0
  102. package/wizard/lib/run-wizard.mjs +26 -31
@@ -15,12 +15,17 @@ For project work, pass the project bank explicitly so memories do not land in th
15
15
 
16
16
  - For past decisions or project context, call `memory_recall` with a focused query and the project bank. `memory_search` is also available for direct search.
17
17
  - Use `memory_reflect` when a question needs a synthesized answer across several memories. Check the returned evidence before treating it as current truth.
18
+ - Before fixing a bug or changing a convention, call `memory_pages_search` (then `memory_pages_read`; `memory_pages_list` shows what exists) for curated decision and convention pages. Hindsight only.
19
+ - When an `[openmem: continuing session <sid>; …]` pointer says earlier messages are not in your context, call `smart_compact_search` with that `session_id` and a query to recover the detail. Pass `pattern` (a JavaScript regex, `ignore_case` optional) instead of `query` for exact strings, and `context` (0–5) for neighbouring rows; `role` defaults to user and tool rows (`"all"` adds assistant text) and `in_context: false` keeps only trimmed rows; `line_matches` is an exact count of matching lines across the whole session (use it for "how many" questions). For counts, groupings or joins, call `smart_compact_sql` with the `session_id` and one read-only `SELECT` over the session database (`messages`, `lines`, `messages_fts`, `lines_fts`; the tool description lists the schema). For a compressed tool result, call `smart_compact_get` with its `id` (page with `offset`). All three read local files and work with every provider.
20
+ - To check whether context management is working, call `context_status` (or run `openmem context status`), not docker logs. It reports trims, estimated tokens saved and fail-opens. A fail-open means the request still succeeded but went to the model untrimmed; `proxy_stale: true` means the proxy runs older code than the checkout and needs a restart.
18
21
  - If the tools are unavailable, say that memory was unavailable. Do not claim to have searched it.
19
22
 
20
23
  ## Store and correct
21
24
 
22
25
  - Session hooks capture supported conversations. When the user explicitly asks to remember a durable fact, external note, or decision now, call `memory_add` with a concise, self-contained record and the project bank. On Hindsight, `memory_add` defaults to **async** ingest (omit `async` or pass `async: true`) so MCP clients do not time out; use `async: false` only when you must wait for extraction.
23
26
  - When verified code or current documentation contradicts a memory, call `memory_add` with a correction that states the old claim, the current fact, and the evidence. Do not silently leave a known false record to resurface.
27
+ - After the user approves a plan for a new feature, call `memory_capture_initiative` before writing code; skip bug fixes and small tweaks.
28
+ - Call `memory_status` before relying on recall of just-stored content; it reports whether async ingest has drained.
24
29
  - `memory_forget` can delete an entire Hindsight bank. Confirm the exact scope before using it for bulk deletion.
25
30
 
26
31
  Use `memory_provider_status` to identify the active provider when that matters. The provider can change without changing this skill or the tool names.
package/README.md CHANGED
@@ -2,18 +2,45 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@bcmyguest/openmem.svg)](https://www.npmjs.com/package/@bcmyguest/openmem)
4
4
  [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
5
- [![openmem-mcp](https://glama.ai/mcp/servers/@bcmyguest/openmem-mcp/badges/score.svg)](https://glama.ai/mcp/servers/@bcmyguest/openmem)
5
+ [![openmem-mcp](https://glama.ai/mcp/servers/bcmyguest/openmem/badges/score.svg)](https://glama.ai/mcp/servers/bcmyguest/openmem/score)
6
6
  [![GitHub](https://img.shields.io/badge/github-bcmyguest%2Fopenmem-blue)](https://github.com/bcmyguest/openmem)
7
7
 
8
- [![openmem-mcp](https://glama.ai/mcp/servers/@bcmyguest/openmem-mcp/badges/card.svg)](https://glama.ai/mcp/servers/@bcmyguest/openmem)
8
+ [![openmem-mcp](https://glama.ai/mcp/servers/bcmyguest/openmem/badges/card.svg)](https://glama.ai/mcp/servers/bcmyguest/openmem)
9
9
 
10
- **Docs:** [bcmyguest.github.io/openmem/](https://bcmyguest.github.io/openmem/) · **npm:** [@bcmyguest/openmem](https://www.npmjs.com/package/@bcmyguest/openmem) · **MCP:** `npx -y -p @bcmyguest/openmem openmem-mcp` · **Repo:** [github.com/bcmyguest/openmem](https://github.com/bcmyguest/openmem)
10
+ **OpenMem.** Memory and context management for coding agents: smart compaction that keeps every turn searchable, pluggable [memory providers](https://bcmyguest.github.io/openmem/docs/provider-status/) (Hindsight, mem0, Cognee), one setup wizard.
11
11
 
12
- **OpenMem** is a **memory interface for coding agents**: a stable `memory_*` API and ops surface over pluggable backends (Hindsight, mem0, Cognee, …), with shared wizard, indexer, and import/export formats (PMM first).
12
+ **A. Memory**: your sources become memory any agent can query.
13
13
 
14
- > Formerly **personal-memory**. Use the `openmem` CLI and MCP server name; installers drop the old `personal-memory` MCP entry.
14
+ <p align="center">
15
+ <picture>
16
+ <source media="(prefers-color-scheme: dark)" srcset="https://bcmyguest.github.io/openmem/media/overview-memory-wide-dark.png" />
17
+ <img src="https://bcmyguest.github.io/openmem/media/overview-memory-wide.png" alt="A, memory: sources (Git repos, Obsidian vaults, notes, papers, bookmarks, feeds), OpenMem indexer, one active provider (Hindsight default, mem0, Cognee), OpenMem MCP tools, coding agents with session hooks" />
18
+ </picture>
19
+ </p>
20
+
21
+ **B. Context management**: long sessions stay under the limit; nothing is summarized away.
22
+
23
+ <p align="center">
24
+ <picture>
25
+ <source media="(prefers-color-scheme: dark)" srcset="https://bcmyguest.github.io/openmem/media/overview-context-wide-dark.png" />
26
+ <img src="https://bcmyguest.github.io/openmem/media/overview-context-wide.png" alt="B, context management: coding agent, context proxy trimming at 120k tokens with no LLM call, model API, SQLite session store read back with smart_compact_search and smart_compact_sql; OpenCode 2 uses a native plugin" />
27
+ </picture>
28
+ </p>
29
+
30
+ **Benchmarks:** [smart compaction against Claude Code's native compaction and keep-everything](https://bcmyguest.github.io/openmem/docs/context-management/#benchmarks) on [ContextBench](https://github.com/RulinShao/ContextBench) synthetic tasks (Claude Haiku 5.5). Compact-Bench real-coding results are in progress.
31
+
32
+ <p align="center">
33
+ <picture>
34
+ <source media="(prefers-color-scheme: dark)" srcset="https://bcmyguest.github.io/openmem/media/contextbench-quality-compact-dark.png" />
35
+ <img src="https://bcmyguest.github.io/openmem/media/contextbench-quality-compact.png" alt="Line charts of ContextBench score by task size, kv-store and log-triage: OpenMem smart compaction stays at 0.90 to 1.00; native compaction and keep everything fall as tasks grow" width="480" />
36
+ </picture>
37
+ </p>
15
38
 
16
- **Start here:** [Concepts](https://bcmyguest.github.io/openmem/docs/concepts/) · [Quickstart](https://bcmyguest.github.io/openmem/docs/getting-started/)
39
+ **Docs:** [bcmyguest.github.io/openmem/](https://bcmyguest.github.io/openmem/)
40
+
41
+ **MCP:** `npx -y -p @bcmyguest/openmem openmem-mcp` (after the wizard — it needs a running provider)
42
+
43
+ **Start here:** [Concepts](https://bcmyguest.github.io/openmem/docs/concepts/) · [Quickstart](https://bcmyguest.github.io/openmem/docs/getting-started/) · [Compatibility](https://bcmyguest.github.io/openmem/docs/compatibility/)
17
44
 
18
45
  ## Quickstart
19
46
 
@@ -27,91 +54,61 @@
27
54
 
28
55
  ```sh
29
56
  git clone https://github.com/bcmyguest/openmem.git && cd openmem
30
- npm install && npx . setup
57
+ npm install && npm run setup
31
58
  ```
32
59
 
33
- **Needs:** Docker Compose v2, Node ≥ 20.12, and an LLM route if you use Hindsight (lemond, Ollama, or OpenAI-compatible — set in the wizard).
60
+ Other commands from a checkout: `node cli/openmem.mjs <command>`.
34
61
 
35
- ### Day-2
62
+ **Needs:** Docker Compose v2, Node ≥ 24 (built-in `node:sqlite` with FTS5), and an LLM route if you use Hindsight (lemond, Ollama, OpenAI-compatible, or a Claude subscription through Meridian — set in the wizard).
36
63
 
37
- ```sh
38
- npx @bcmyguest/openmem up
39
- npx @bcmyguest/openmem down
40
- npx @bcmyguest/openmem switch mem0 --yes
41
- npx @bcmyguest/openmem doctor
42
- ```
64
+ Later: `npx @bcmyguest/openmem up` / `down` / `switch <provider> --yes` / `doctor`.
43
65
 
44
66
  Wizard dry-run (what first setup plans — no writes):
45
67
 
46
- ![Setup dry-run: npx @bcmyguest/openmem setup --dry-run](https://bcmyguest.github.io/openmem/setup-demo.gif)
68
+ <p align="center">
69
+ <img src="https://bcmyguest.github.io/openmem/setup-demo.gif" alt="Terminal recording of the setup wizard dry run: preflight checks, memory provider, model backend, secrets, sources and stack steps, each planned write printed as a [dry-run] line" width="720" />
70
+ </p>
47
71
 
48
72
  Full guide: [Quickstart](https://bcmyguest.github.io/openmem/docs/getting-started/) · [Concepts](https://bcmyguest.github.io/openmem/docs/concepts/) · [Architecture](https://bcmyguest.github.io/openmem/docs/architecture/)
49
73
 
50
74
  ## Architecture
51
75
 
76
+ The two diagrams at the top show memory (A) and context management (B).
77
+
78
+ <details>
79
+ <summary>Same diagrams as Mermaid</summary>
80
+
52
81
  ```mermaid
53
- flowchart TB
54
- subgraph disk["Sources on disk"]
55
- GIT[Git repos]
56
- OBS[Obsidian vaults]
57
- MD[notes · papers · bookmarks]
58
- FEED[Feed cache]
59
- end
60
-
61
- subgraph compose["Docker Compose — one active provider"]
62
- IDX[indexer]
63
- PROV[(Provider API)]
64
- IDX -->|retain / update| PROV
65
- LIT[LiteLLM]
66
- NLM[NotebookLM sync]
67
- LIT -.->|Hindsight stack + optional reflect synth| PROV
68
- NLM -.->|opt-in profile| PROV
69
- end
70
-
71
- LIT --> LLM[(lemond · Ollama · OpenAI-compatible)]
72
-
73
- subgraph host["Host — coding agents"]
74
- AG[Claude Code · Codex · Cursor Agent · OpenCode]
75
- UMCP["OpenMem MCP\n(memory_*)"]
76
- SHIM["Session hooks"]
77
- PLG["Hindsight plugin\n(optional)"]
78
- SKILL["openmem skill"]
79
- PMCP[Provider MCP optional]
80
- NLMCP[NotebookLM MCP optional]
81
- end
82
-
83
- GIT --> IDX
84
- OBS --> IDX
85
- MD --> IDX
86
- FEED --> IDX
87
- AG <-->|stdio| UMCP
88
- AG <-->|hooks| SHIM
89
- AG --> SKILL
90
- AG <-->|optional| PLG
91
- SHIM --> UMCP
92
- AG <-->|stdio| PMCP
93
- AG <-->|stdio| NLMCP
94
- UMCP -->|loopback HTTP| PROV
95
- PLG -->|loopback HTTP| PROV
96
- PMCP -->|loopback HTTP| PROV
97
- NLMCP -->|loopback HTTP| PROV
98
-
99
- W["npx @bcmyguest/openmem\nsetup · install-mcp"] -.->|configure| compose
100
- W -.->|mcp.json| UMCP
82
+ flowchart LR
83
+ S["<b>Sources</b><br/>Git repos: docs, code outlines<br/>Obsidian vaults · notes · papers · bookmarks<br/>RSS · OpenAlex feeds"] -->|index| I["<b>OpenMem indexer</b><br/>polls repos, watches folders"]
84
+ I -->|retain| P[("<b>Memory provider</b><br/>one active, swappable<br/>Hindsight (default) · mem0 · Cognee · …")]
85
+ P <--> M["<b>OpenMem MCP</b><br/>memory_recall · memory_add<br/>memory_search · memory_reflect<br/>memory_pages_* + export/import, status…"]
86
+ M <-->|tools| A["<b>Coding agents</b><br/>Claude Code · Codex · Cursor · OpenCode"]
87
+ A -.->|"session hooks: recall at start · retain at stop"| M
88
+ classDef om fill:#e8eaf9,stroke:#4651a6,color:#1b1d2a
89
+ class I,M om
101
90
  ```
102
91
 
103
- | Connection | What it is |
104
- | --- | --- |
105
- | Sources → indexer → provider | Shared watcher; sink from active manifest (`MEMORY_SINK`) |
106
- | Agents → MCP / hooks → provider | `install-coding-agent` installs the shared skill, unified `memory_*` MCP, and session hooks for Claude Code, Codex, Cursor Agent, and OpenCode |
107
- | Wizard (dashed) | Writes env, starts compose, registers MCP — not on the hot indexing path |
92
+ ```mermaid
93
+ flowchart LR
94
+ A["<b>Coding agent</b><br/>Claude Code · Codex · OpenCode 1"] -->|requests| X["<b>Context proxy</b><br/>LiteLLM pre-call hook<br/>trims at 120k tokens · no LLM call"]
95
+ X -->|trimmed request| API["<b>Model API</b><br/>Anthropic · ChatGPT (Codex)"]
96
+ X -->|every turn| S[("<b>Session store</b><br/>SQLite · every turn, verbatim")]
97
+ S -->|"MCP: smart_compact_search · smart_compact_sql"| A
98
+ O["<b>OpenCode 2</b><br/>native plugin, no proxy"] -.->|same store| S
99
+ classDef om fill:#e8eaf9,stroke:#4651a6,color:#1b1d2a
100
+ class X,S om
101
+ ```
108
102
 
109
- On Hindsight stacks, `memory_reflect` uses Hindsight's native reflect API and returns its answer with source evidence. On mem0 and Cognee, it searches first and uses the configured LiteLLM route for synthesis when available; otherwise it returns the search hits. See [Architecture](https://bcmyguest.github.io/openmem/docs/architecture/) for MCP and hooks limits.
103
+ </details>
104
+
105
+ Native compaction replaces history with an LLM summary, so exact values can be lost; OpenMem keeps every turn verbatim and searchable. The optional [context proxy](https://bcmyguest.github.io/openmem/docs/context-proxy/) trims long agent sessions without an LLM summary. See the [full architecture](https://bcmyguest.github.io/openmem/docs/architecture/) for setup, optional integrations, and provider-specific behavior.
110
106
 
111
107
  ## Providers and portability
112
108
 
113
- - **Providers** — manifests under `providers/` ([Hindsight](https://bcmyguest.github.io/openmem/docs/hindsight/), [mem0](https://bcmyguest.github.io/openmem/docs/mem0/), [Cognee](https://bcmyguest.github.io/openmem/docs/cognee/)). Add another with a compose fragment, indexer sink, and wizard hooks.
109
+ - **Providers** — [Provider status](https://bcmyguest.github.io/openmem/docs/provider-status/) lists every provider and its support level from the manifests. Contributor details: [adding a provider](https://github.com/bcmyguest/openmem/blob/main/docs/memory-providers.md).
114
110
  - **MCP** — unified `memory_*` plus optional native/NotebookLM servers: [MCP setup](https://bcmyguest.github.io/openmem/docs/mcp-setup/).
111
+ - **Context management** — smart compaction on/off, per-agent support, tools and config: [Context management](https://bcmyguest.github.io/openmem/docs/context-management/).
115
112
  - **Portable memory** — `memory_export` / `memory_import` speak **PMM**: [Portable memory](https://bcmyguest.github.io/openmem/docs/memory-portability/).
116
113
  - **Switch** — `npx @bcmyguest/openmem switch <provider>` does not migrate data by itself; export/import (or re-index) moves content.
117
114
 
@@ -125,12 +122,19 @@ OpenMem is not affiliated with these projects; they shape the problem or the pat
125
122
  | --- | --- |
126
123
  | **[OpenFeature](https://openfeature.dev/)** | Inspiration for a vendor-agnostic interface + pluggable providers (there: feature flags; here: coding-agent memory). |
127
124
  | **[mise](https://mise.jdx.dev/) / [asdf](https://asdf-vm.com/)** | One CLI over many backends; declarative config and tasks without replacing each tool’s own settings. |
128
- | **[Hindsight](https://github.com/vectorize-io/hindsight)** | Default memory provider in this repo. |
129
- | **[mem0](https://github.com/mem0ai/mem0)** | Supported memory provider. |
130
- | **[Cognee](https://github.com/topoteretes/cognee)** | Supported memory provider. |
131
- | **[LiteLLM](https://github.com/BerriAI/litellm)** | Model proxy used on Hindsight stacks. |
125
+ | **[LiteLLM](https://github.com/BerriAI/litellm)** | Model proxy used on Hindsight stacks; its pre-call hook hosts the context proxy. |
126
+ | **[Hindsight coding agents](https://www.npmjs.com/package/@vectorize-io/hindsight-coding-agents)** | Reference implementation for knowledge pages, initiative capture and ingest status; OpenMem's hooks replace it in `openmem` mode. |
127
+ | **[Mainplane](https://github.com/mainplane-ai/mainplane)** | Inspiration for smart compaction: continue in a fresh context with a pointer to the saved transcript and retrieve as you go, instead of an LLM summary. |
128
+ | **[rtk](https://github.com/rtk-ai/rtk)** | Compresses shell command output before the agent sees it; `install-coding-agent` runs `rtk init` when it is installed. Inspired the context proxy's compression of large tool results (reimplemented, not bundled). |
129
+ | **[opencode-clm](https://github.com/bcmyguest/opencode-clm)** | OpenCode plugin for [Context Language Models](https://arxiv.org/abs/2609.37725): the model edits a file mirror of its own context. Same goal as smart compaction, with the model doing the trimming ([comparison](https://bcmyguest.github.io/openmem/docs/context-research/)). |
130
+ | **[Meridian](https://github.com/rynfar/meridian)** | Bridges a Claude subscription to an Anthropic-compatible API; optional Hindsight model backend ([guide](https://bcmyguest.github.io/openmem/docs/model-configuration/)). |
131
+ | **[OpenCode](https://opencode.ai/)** / **[Claude Code hooks](https://code.claude.com/docs/en/hooks)** / **[Codex hooks](https://developers.openai.com/codex/hooks)** | The agent hook and plugin APIs OpenMem translates between ([compatibility](https://bcmyguest.github.io/openmem/docs/compatibility/)). |
132
+
133
+ Research notes and benchmark results for the context proxy: [Context research](https://bcmyguest.github.io/openmem/docs/context-research/).
132
134
 
133
- More setup analogues (Chezmoi, Home Assistant integrations, …): [Provider status](https://bcmyguest.github.io/openmem/docs/provider-status/).
135
+ More setup analogues: [Pluggable memory providers](https://github.com/bcmyguest/openmem/blob/main/docs/memory-providers.md).
136
+
137
+ > Formerly **personal-memory**. Use the `openmem` CLI and MCP server name; installers drop the old `personal-memory` MCP entry.
134
138
 
135
139
  ## License
136
140
 
@@ -5,12 +5,23 @@ import { CODING_AGENTS, DEFAULT_AGENT_IDS } from "./agents.mjs";
5
5
  export const AGENT_IDS = Object.freeze(CODING_AGENTS.map((a) => a.id));
6
6
  export { DEFAULT_AGENT_IDS };
7
7
 
8
- /** @typedef {"retain" | "recall" | "reflect" | "consolidate" | "bank_scope"} Feature */
8
+ /**
9
+ * @typedef {"retain" | "recall" | "reflect" | "consolidate" | "bank_scope" | "knowledge_pages" | "initiatives" | "ingest_status"} Feature
10
+ */
9
11
 
10
12
  /** @type {Record<string, Partial<Record<Feature, boolean>>>} */
11
13
  export const PROVIDER_CAPABILITIES = {
12
- hindsight: { retain: true, recall: true, reflect: true, consolidate: true, bank_scope: true },
13
- mem0: { retain: true, recall: true, reflect: true, consolidate: false, bank_scope: true },
14
+ hindsight: {
15
+ retain: true,
16
+ recall: true,
17
+ reflect: true,
18
+ consolidate: true,
19
+ bank_scope: true,
20
+ knowledge_pages: true,
21
+ initiatives: true,
22
+ ingest_status: true,
23
+ },
24
+ mem0: { retain: true, recall: true, reflect: true, consolidate: false, bank_scope: true, ingest_status: true },
14
25
  cognee: { retain: true, recall: true, reflect: true, consolidate: true, bank_scope: true },
15
26
  };
16
27
 
@@ -0,0 +1,81 @@
1
+ /** Hook side of the context store contract (docs/context-store.md). */
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+
5
+ /** Marker in the installed smart-compact command body; survives command expansion. */
6
+ export const SMART_COMPACT_MARKER = "openmem:smart-compact";
7
+ /** Prompt that `/smart-compact` sends in every agent (Claude Code command file, OpenCode 2 command). */
8
+ export const SMART_COMPACT_BODY = `<!-- ${SMART_COMPACT_MARKER} -->
9
+ OpenMem will trim this session's earlier context on the next request. Reply with one short line acknowledging this; do not summarize the conversation. After the trim, use \`smart_compact_search\` with this session's id to look up anything earlier.`;
10
+ /** Claude Code command file (`~/.claude/commands/smart-compact.md`): frontmatter plus SMART_COMPACT_BODY. */
11
+ export const SMART_COMPACT_COMMAND = `---
12
+ description: Trim this session's context on the next request (OpenMem)
13
+ ---
14
+ ${SMART_COMPACT_BODY}
15
+ `;
16
+ const SMART_COMPACT_PREFIX = /^\s*\/smart-compact(?:\s|$)/;
17
+ const SMART_COMPACT_TAG = "<command-name>/smart-compact</command-name>";
18
+ /** ASCII whitespace only, so the hooks and the proxy trim the same characters (session ids, OPENMEM_STATE_DIR). */
19
+ const ASCII_TRIM_RE = /^[ \t\n\v\f\r]+|[ \t\n\v\f\r]+$/g;
20
+ const SID_UNSAFE_RE = /[^A-Za-z0-9._-]/gu;
21
+
22
+ /** `$OPENMEM_STATE_DIR/context` (value trimmed), default `~/.local/share/openmem/context`. */
23
+ export function contextRoot(home, env = process.env) {
24
+ const state = String(env.OPENMEM_STATE_DIR || "").replace(ASCII_TRIM_RE, "") || path.join(home, ".local", "share", "openmem");
25
+ return path.join(state, "context");
26
+ }
27
+
28
+ /**
29
+ * Contract sanitizer (docs/context-store.md): trim surrounding ASCII whitespace, replace every character
30
+ * outside `[A-Za-z0-9._-]` with `_`, throw on an empty result.
31
+ */
32
+ export function sanitizeSessionId(sessionId) {
33
+ const sid = String(sessionId ?? "").replace(ASCII_TRIM_RE, "").replace(SID_UNSAFE_RE, "_");
34
+ if (!sid) throw new Error("empty session id");
35
+ return sid;
36
+ }
37
+
38
+ function sessionsDir(home, env) {
39
+ const root = contextRoot(home, env);
40
+ const dir = path.join(root, "sessions");
41
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
42
+ fs.chmodSync(root, 0o700);
43
+ fs.chmodSync(dir, 0o700);
44
+ return dir;
45
+ }
46
+
47
+ function writePrivate(file, text) {
48
+ const temporary = `${file}.${process.pid}.tmp`;
49
+ fs.writeFileSync(temporary, text, { mode: 0o600 });
50
+ fs.renameSync(temporary, file);
51
+ }
52
+
53
+ /** Write `sessions/<sid>.json`. Returns the path, or null without a session id. */
54
+ export function registerSession({ home, env, sessionId, agent, cwd, bank, now = new Date() }) {
55
+ if (!sessionId) return null;
56
+ const sid = sanitizeSessionId(sessionId);
57
+ const file = path.join(sessionsDir(home, env), `${sid}.json`);
58
+ const registration = {
59
+ session_id: sid,
60
+ agent,
61
+ cwd,
62
+ bank,
63
+ registered_at: now.toISOString().replace(/\.\d{3}Z$/, "Z"),
64
+ };
65
+ writePrivate(file, `${JSON.stringify(registration)}\n`);
66
+ return file;
67
+ }
68
+
69
+ /** Write the empty `sessions/<sid>.force` flag. Returns the path, or null without a session id. */
70
+ export function writeForceFlag({ home, env, sessionId }) {
71
+ if (!sessionId) return null;
72
+ const file = path.join(sessionsDir(home, env), `${sanitizeSessionId(sessionId)}.force`);
73
+ writePrivate(file, "");
74
+ return file;
75
+ }
76
+
77
+ /** True for `/smart-compact …`, Claude Code's command tag, or the expanded command body. */
78
+ export function isSmartCompactPrompt(prompt) {
79
+ const text = String(prompt || "");
80
+ return SMART_COMPACT_PREFIX.test(text) || text.includes(SMART_COMPACT_TAG) || text.includes(SMART_COMPACT_MARKER);
81
+ }