memory-boost 0.1.1__tar.gz → 0.2.0__tar.gz

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 (68) hide show
  1. {memory_boost-0.1.1 → memory_boost-0.2.0}/.claude-plugin/plugin.json +4 -4
  2. {memory_boost-0.1.1 → memory_boost-0.2.0}/CHANGELOG.md +24 -0
  3. memory_boost-0.2.0/CONTRIBUTING.md +16 -0
  4. {memory_boost-0.1.1 → memory_boost-0.2.0}/PKG-INFO +65 -13
  5. {memory_boost-0.1.1 → memory_boost-0.2.0}/README.md +61 -11
  6. memory_boost-0.2.0/docs/logo-400.png +0 -0
  7. memory_boost-0.2.0/llms-install.md +144 -0
  8. {memory_boost-0.1.1 → memory_boost-0.2.0}/pyproject.toml +5 -2
  9. memory_boost-0.2.0/scripts/eval_recall.py +61 -0
  10. memory_boost-0.2.0/scripts/render-logo.py +25 -0
  11. {memory_boost-0.1.1 → memory_boost-0.2.0}/scripts/smoke.sh +1 -1
  12. {memory_boost-0.1.1 → memory_boost-0.2.0}/server.json +2 -2
  13. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/__init__.py +1 -1
  14. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/cli.py +44 -5
  15. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/core.py +126 -12
  16. memory_boost-0.2.0/src/memory_boost/semantic.py +150 -0
  17. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/server.py +22 -5
  18. {memory_boost-0.1.1 → memory_boost-0.2.0}/tests/test_cli.py +9 -0
  19. {memory_boost-0.1.1 → memory_boost-0.2.0}/tests/test_core.py +54 -4
  20. {memory_boost-0.1.1 → memory_boost-0.2.0}/tests/test_mcp.py +50 -3
  21. memory_boost-0.2.0/tests/test_packaging.py +104 -0
  22. memory_boost-0.2.0/tests/test_semantic.py +152 -0
  23. memory_boost-0.1.1/CONTRIBUTING.md +0 -11
  24. memory_boost-0.1.1/tests/test_packaging.py +0 -58
  25. {memory_boost-0.1.1 → memory_boost-0.2.0}/.claude-plugin/marketplace.json +0 -0
  26. {memory_boost-0.1.1 → memory_boost-0.2.0}/.github/ISSUE_TEMPLATE/bug.md +0 -0
  27. {memory_boost-0.1.1 → memory_boost-0.2.0}/.github/ISSUE_TEMPLATE/harness.md +0 -0
  28. {memory_boost-0.1.1 → memory_boost-0.2.0}/.github/pull_request_template.md +0 -0
  29. {memory_boost-0.1.1 → memory_boost-0.2.0}/.github/workflows/ci.yml +0 -0
  30. {memory_boost-0.1.1 → memory_boost-0.2.0}/.github/workflows/release.yml +0 -0
  31. {memory_boost-0.1.1 → memory_boost-0.2.0}/.gitignore +0 -0
  32. {memory_boost-0.1.1 → memory_boost-0.2.0}/CODE_OF_CONDUCT.md +0 -0
  33. {memory_boost-0.1.1 → memory_boost-0.2.0}/LICENSE +0 -0
  34. {memory_boost-0.1.1 → memory_boost-0.2.0}/SECURITY.md +0 -0
  35. {memory_boost-0.1.1 → memory_boost-0.2.0}/docs/architecture.mmd +0 -0
  36. {memory_boost-0.1.1 → memory_boost-0.2.0}/docs/architecture.png +0 -0
  37. {memory_boost-0.1.1 → memory_boost-0.2.0}/docs/demo.gif +0 -0
  38. {memory_boost-0.1.1 → memory_boost-0.2.0}/docs/demo.tape +0 -0
  39. {memory_boost-0.1.1 → memory_boost-0.2.0}/docs/social.html +0 -0
  40. {memory_boost-0.1.1 → memory_boost-0.2.0}/docs/social.png +0 -0
  41. {memory_boost-0.1.1 → memory_boost-0.2.0}/scripts/render-demo.sh +0 -0
  42. {memory_boost-0.1.1 → memory_boost-0.2.0}/skills/memory-boost/SKILL.md +0 -0
  43. {memory_boost-0.1.1 → memory_boost-0.2.0}/skills/restore-session/SKILL.md +0 -0
  44. {memory_boost-0.1.1 → memory_boost-0.2.0}/skills/retro/SKILL.md +0 -0
  45. {memory_boost-0.1.1 → memory_boost-0.2.0}/skills/save-session/SKILL.md +0 -0
  46. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/drift.py +0 -0
  47. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_transcripts/-work-acme-api/0a1b2c3d-1111-4aaa-8bbb-000000000001.jsonl +0 -0
  48. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_transcripts/-work-acme-api/0a1b2c3d-3333-4aaa-8bbb-000000000003.jsonl +0 -0
  49. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_transcripts/-work-acme-api/0a1b2c3d-4444-4aaa-8bbb-000000000004.jsonl +0 -0
  50. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_transcripts/-work-pixel-notes/0a1b2c3d-2222-4aaa-8bbb-000000000002.jsonl +0 -0
  51. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/concepts/money-as-integer-cents.md +0 -0
  52. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/concepts/retry-jobs-idempotently.md +0 -0
  53. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/context/preferences.md +0 -0
  54. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/decisions/cors-allow-all.md +0 -0
  55. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/decisions/float-money.md +0 -0
  56. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/decisions/pin-postgres-15.md +0 -0
  57. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/decisions/queue-in-postgres.md +0 -0
  58. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/decisions/sessions-in-redis.md +0 -0
  59. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/log.md +0 -0
  60. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/projects/acme-api.md +0 -0
  61. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/projects/legacy-dashboard.md +0 -0
  62. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/example_wiki/projects/pixel-notes.md +0 -0
  63. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/lessons.py +0 -0
  64. {memory_boost-0.1.1 → memory_boost-0.2.0}/src/memory_boost/mine.py +0 -0
  65. {memory_boost-0.1.1 → memory_boost-0.2.0}/tests/conftest.py +0 -0
  66. {memory_boost-0.1.1 → memory_boost-0.2.0}/tests/test_drift.py +0 -0
  67. {memory_boost-0.1.1 → memory_boost-0.2.0}/tests/test_lessons.py +0 -0
  68. {memory_boost-0.1.1 → memory_boost-0.2.0}/tests/test_mine.py +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memory-boost",
3
- "version": "0.1.1",
4
- "description": "Memory that reviews itself: a markdown wiki your agents read and write over MCP, plus drift reports on that memory and local digests of your own sessions.",
3
+ "version": "0.2.0",
4
+ "description": "Markdown memory your coding agent reads and writes over MCP, with drift reports that flag stale decisions and local digests of your own sessions. Everything stays in a local folder.",
5
5
  "author": { "name": "Arnau González", "url": "https://github.com/arnaugonzalez" },
6
6
  "homepage": "https://github.com/arnaugonzalez/memory-boost",
7
7
  "repository": "https://github.com/arnaugonzalez/memory-boost",
@@ -10,7 +10,7 @@
10
10
  "mcpServers": {
11
11
  "memory": {
12
12
  "command": "uvx",
13
- "args": ["--quiet", "--from", "${CLAUDE_PLUGIN_ROOT}", "memory-boost", "serve"]
13
+ "args": ["--quiet", "memory-boost==0.2.0", "serve"]
14
14
  }
15
15
  },
16
16
  "hooks": {
@@ -19,7 +19,7 @@
19
19
  "hooks": [
20
20
  {
21
21
  "type": "command",
22
- "command": "uvx --quiet --from \"${CLAUDE_PLUGIN_ROOT}\" memory-boost hook session-start",
22
+ "command": "uvx --quiet memory-boost==0.2.0 hook session-start",
23
23
  "timeout": 120
24
24
  }
25
25
  ]
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0 — 2026-10-18
4
+
5
+ - recall: freshness is now a down-weight on the bm25 score instead of a hard sort, so a strong match is no longer buried under fresher weak ones.
6
+ - Optional semantic recall: `pip install "memory-boost[semantic]"` plus `MEMORY_BOOST_SEMANTIC=1` and a local
7
+ `embeddinggemma` (Ollama) adds vector search via sqlite-vec. Default mode when on is `hybrid`; `recall --mode`
8
+ and `MEMORY_BOOST_RECALL_MODE` select `fts`, `semantic` or `hybrid`. Falls back to full-text if Ollama is down.
9
+ The base install is unchanged.
10
+ While embedding, `memory-boost index` and `recall` report `embedding N/M chunks…` on stderr (one
11
+ rewritten line on a terminal, a line every 128 chunks otherwise); stdout and the MCP server stay quiet.
12
+ - `shelf`: park a one-line idea in a wiki page (default `concepts/idea-shelf.md`) from the CLI
13
+ (`memory-boost shelf "..."`) or the new `memory_shelf` MCP tool, without reading the page.
14
+ - `serve --http [--host 127.0.0.1] [--port 8765]`: the MCP server over streamable HTTP (stateless,
15
+ JSON responses) at `http://HOST:PORT/mcp`, for one long-lived local server shared by several
16
+ sessions. stdio stays the default. Requires `mcp>=1.10`.
17
+ - MCP `initialize` reports `serverInfo` as `memory-boost` and its own version (it reported the mcp
18
+ library's version).
19
+ - Plugin: the MCP server and the session-start hook run the exact release (`uvx memory-boost==0.2.0`)
20
+ instead of the plugin checkout, as the Claude plugin directory requires pinned launchers. A test
21
+ fails if any pinned install (plugin, README, `llms-install.md`) drifts from `__version__`.
22
+ - `llms-install.md`: steps an agent (Claude Code, Codex, Cline, Cursor) can follow to install the CLI
23
+ and register the MCP server over stdio or `serve --http`, with a harness-independent check. The
24
+ README gains an "Install from your agent" prompt and pins its install commands.
25
+ - `docs/logo-400.png` (400×400, for MCP directories), rendered by `scripts/render-logo.py`.
26
+
3
27
  ## 0.1.1 — 2026-09-26
4
28
 
5
29
  - README renders on PyPI and in the MCP registry: the demo GIF, the architecture diagram (now an
@@ -0,0 +1,16 @@
1
+ # Contributing
2
+
3
+ ```bash
4
+ uv sync
5
+ uv run pytest
6
+ uvx ruff check .
7
+ ```
8
+
9
+ Keep the core stdlib-only (the `mcp` package is the single runtime dependency) and keep
10
+ the hook path fast: `memory-boost hook` must not import `mcp`. Open an issue before
11
+ large changes.
12
+
13
+ Releasing: the version lives in `pyproject.toml`, `src/memory_boost/__init__.py`,
14
+ `.claude-plugin/plugin.json` (`version` and both `memory-boost==X` launchers), `server.json`,
15
+ the `memory-boost==X` pins in `README.md` and `llms-install.md`, and a dated `CHANGELOG.md`
16
+ heading. `tests/test_packaging.py` fails until all of them agree.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: memory-boost
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Summary: Memory that reviews itself: a markdown wiki for coding agents over MCP, plus drift reports on the wiki and digests of your own sessions.
5
5
  Project-URL: Repository, https://github.com/arnaugonzalez/memory-boost
6
6
  Project-URL: Issues, https://github.com/arnaugonzalez/memory-boost/issues
@@ -17,7 +17,9 @@ Classifier: Operating System :: POSIX :: Linux
17
17
  Classifier: Programming Language :: Python :: 3
18
18
  Classifier: Topic :: Software Development
19
19
  Requires-Python: >=3.11
20
- Requires-Dist: mcp<2,>=1.2
20
+ Requires-Dist: mcp<2,>=1.10
21
+ Provides-Extra: semantic
22
+ Requires-Dist: sqlite-vec>=0.1.6; extra == 'semantic'
21
23
  Description-Content-Type: text/markdown
22
24
 
23
25
  <!-- mcp-name: io.github.arnaugonzalez/memory-boost -->
@@ -71,9 +73,9 @@ times.
71
73
  No install needed; the wiki lands in `~/.local/share/memory-boost`:
72
74
 
73
75
  ```bash
74
- uvx memory-boost init --example # sample wiki with five kinds of rot + four synthetic transcripts
75
- uvx memory-boost drift # what in that memory is stale, orphaned or never written down
76
- uvx memory-boost mine # now on your real ~/.claude/projects: aggregates only
76
+ uvx memory-boost==0.2.0 init --example # sample wiki with five kinds of rot + four synthetic transcripts
77
+ uvx memory-boost==0.2.0 drift # what in that memory is stale, orphaned or never written down
78
+ uvx memory-boost==0.2.0 mine # now on your real ~/.claude/projects: aggregates only
77
79
  ```
78
80
 
79
81
  To keep it in Claude Code, install the plugin. It brings the MCP server, the session-start
@@ -84,7 +86,22 @@ brief and the skills in one step; it only needs [uv](https://docs.astral.sh/uv/)
84
86
  /plugin install memory-boost@memory-boost
85
87
  ```
86
88
 
87
- Other agents, or the CLI on its own: `uv tool install memory-boost` (or `pipx install memory-boost`).
89
+ Other agents, or the CLI on its own: `uv tool install memory-boost==0.2.0` (or
90
+ `pipx install memory-boost==0.2.0`). Or let your agent do it: see [Install from your agent](#install-from-your-agent).
91
+
92
+ ## Install from your agent
93
+
94
+ Paste this into Claude Code, Codex, Cline or Cursor:
95
+
96
+ > Install memory-boost 0.2.0 by following
97
+ > https://github.com/arnaugonzalez/memory-boost/blob/main/llms-install.md : install the CLI with
98
+ > `uv tool install memory-boost==0.2.0`, run `memory-boost init`, register `memory-boost serve`
99
+ > as a stdio MCP server named `memory`, check that it answers with nine `memory_*` tools, then run
100
+ > `memory-boost drift` and show me the output. Ask me before writing outside the memory home
101
+ > (`~/.local/share/memory-boost`) or editing any global agent config.
102
+
103
+ The agent-oriented steps (stdio and `serve --http`, per harness, with checks) are in
104
+ [llms-install.md](https://github.com/arnaugonzalez/memory-boost/blob/main/llms-install.md).
88
105
 
89
106
  ## On a real machine
90
107
 
@@ -123,9 +140,11 @@ it needed a new tool: the data was already on disk. It needed a reader.
123
140
  ## What it is
124
141
 
125
142
  1. **A wiki you own.** `projects/*.md`, `decisions/*.md`, `concepts/*.md`, `log.md`. Plain
126
- markdown; edit by hand, keep it in git. SQLite FTS5 index as a disposable cache. Eight MCP
143
+ markdown; edit by hand, keep it in git. SQLite FTS5 index as a disposable cache. Nine MCP
127
144
  tools for any harness: `memory_brief`, `memory_recall`, `memory_page`, `memory_save`,
128
- `memory_checkpoint`, `memory_resume`, `memory_drift`, `memory_lesson`.
145
+ `memory_checkpoint`, `memory_resume`, `memory_drift`, `memory_lesson`, `memory_shelf`.
146
+ `memory_shelf` (CLI: `memory-boost shelf "idea"`) appends a dated one-line idea to
147
+ `concepts/idea-shelf.md` without the agent reading the page back.
129
148
  2. **Freshness as data.** Decisions carry `status:` and `review_by:`. Search results are tagged
130
149
  `current / unclassified / review / historic / superseded`, current first.
131
150
  3. **Session checkpoints** that survive `/compact`, with one line per *other* active session on
@@ -143,6 +162,16 @@ it needed a new tool: the data was already on disk. It needed a reader.
143
162
 
144
163
  MCP server (all harnesses): command `memory-boost`, args `["serve"]`.
145
164
 
165
+ To share one server between several sessions, run it over streamable HTTP (stateless, JSON
166
+ responses) and point each harness at `http://127.0.0.1:8765/mcp`:
167
+
168
+ ```bash
169
+ memory-boost serve --http # --host 127.0.0.1 --port 8765 are the defaults
170
+ claude mcp add --transport http memory -s user http://127.0.0.1:8765/mcp
171
+ ```
172
+
173
+ It binds to loopback by default and has no authentication: keep it there.
174
+
146
175
  | Harness | MCP registration | Context at session start |
147
176
  |---|---|---|
148
177
  | Claude Code (plugin) | `/plugin install memory-boost@memory-boost` | Included: hook, MCP server, skills |
@@ -163,7 +192,8 @@ checkpoint. It never blocks session start: on any error it prints nothing.
163
192
  Skills: `/memory-boost` (router: when to run what), `/save-session`, `/restore-session`,
164
193
  `/retro`. The plugin installs them as `/memory-boost:retro` and so on; without it, copy
165
194
  `skills/*` into `~/.claude/skills/`. The first session after installing the plugin takes a few
166
- extra seconds while uv fetches the package; later sessions start in about 0.2 s.
195
+ extra seconds while uv fetches `memory-boost==0.2.0` and its dependencies from PyPI (the only
196
+ network access the plugin makes); later sessions start in about 0.2 s.
167
197
 
168
198
  CLI contract for agents: data on stdout, errors on stderr with a `fix:` line, `--json` on every
169
199
  reading command (with a `version` field), exit 0 = trust stdout, 1 = not found, 2 = bad input.
@@ -176,8 +206,30 @@ Reports end with a `next:` line naming the exact command to run.
176
206
  <sub>Source: [docs/architecture.mmd](https://github.com/arnaugonzalez/memory-boost/blob/main/docs/architecture.mmd)</sub>
177
207
 
178
208
  The project is resolved from the working directory name (`~/work/acme-api` → `projects/acme-api.md`);
179
- map other names in `aliases.json`. Under 1,600 lines of Python, one dependency (`mcp`), no
180
- embeddings, no daemon.
209
+ map other names in `aliases.json`. Under 1,900 lines of Python, one dependency (`mcp`), no
210
+ embeddings unless you opt into semantic recall, no daemon unless you run `serve --http`.
211
+
212
+ ## Semantic recall (optional)
213
+
214
+ Off by default: `memory_recall` is full-text only and the base install stays one dependency.
215
+ To also match paraphrases and other languages, run a local embedding model:
216
+
217
+ ```bash
218
+ pip install "memory-boost[semantic]==0.2.0" # adds sqlite-vec
219
+ ollama pull embeddinggemma
220
+ export MEMORY_BOOST_SEMANTIC=1
221
+ memory-boost index # embeds the wiki once; later runs embed only changes
222
+ ```
223
+
224
+ The first index of a large wiki on CPU can take minutes: as a rough guide, about 15 minutes for some
225
+ 850 documents on a laptop without a GPU (one measurement, not a benchmark). `memory-boost index` and
226
+ `recall` show `embedding N/M chunks…` on stderr while it runs; later runs re-embed only what changed.
227
+
228
+ Default mode when on is `hybrid` (full-text and vectors fused by weighted reciprocal rank); override
229
+ with `MEMORY_BOOST_RECALL_MODE=fts|semantic|hybrid` or `memory-boost recall --mode`. If Ollama is down,
230
+ recall falls back to full-text and logs a warning. On a private 64-query set (39 literal, 25 paraphrase)
231
+ with a warm index on CPU: paraphrase nDCG@10 0.46 to 0.76, literal 0.80 to 0.85, p50 about 110 ms per query.
232
+ The query set is not published.
181
233
 
182
234
  ## Configuration
183
235
 
@@ -195,7 +247,7 @@ embeddings, no daemon.
195
247
  | | memory-boost | [basic-memory](https://github.com/basicmachines-co/basic-memory) | [claude-mem](https://github.com/thedotmack/claude-mem) | [agent-retro](https://github.com/giannimassi/agent-retro) |
196
248
  |---|---|---|---|---|
197
249
  | Store | Markdown wiki you edit | Markdown | Captured observations | None (prompt skill) |
198
- | Search | FTS5 | FTS + vectors | FTS + vectors | — |
250
+ | Search | FTS5 (+ optional local vectors) | FTS + vectors | FTS + vectors | — |
199
251
  | Freshness / review dates | Yes | No | No | — |
200
252
  | Drift report over memory | Yes | No | No | No |
201
253
  | Session analytics | Yes (aggregates, local) | No | No | LLM reads the conversation |
@@ -208,7 +260,7 @@ agents already wrote down.
208
260
 
209
261
  ## Limits / non-goals
210
262
 
211
- - Keyword search only; no embeddings.
263
+ - Full-text search by default; embeddings only with the optional `[semantic]` extra and a local Ollama.
212
264
  - `mine` understands Claude Code transcripts today. Codex is on the roadmap.
213
265
  - Reports are as good as the wiki: an empty wiki yields an empty `drift`.
214
266
  - Single user, local files. Linux and macOS; Windows untested.
@@ -49,9 +49,9 @@ times.
49
49
  No install needed; the wiki lands in `~/.local/share/memory-boost`:
50
50
 
51
51
  ```bash
52
- uvx memory-boost init --example # sample wiki with five kinds of rot + four synthetic transcripts
53
- uvx memory-boost drift # what in that memory is stale, orphaned or never written down
54
- uvx memory-boost mine # now on your real ~/.claude/projects: aggregates only
52
+ uvx memory-boost==0.2.0 init --example # sample wiki with five kinds of rot + four synthetic transcripts
53
+ uvx memory-boost==0.2.0 drift # what in that memory is stale, orphaned or never written down
54
+ uvx memory-boost==0.2.0 mine # now on your real ~/.claude/projects: aggregates only
55
55
  ```
56
56
 
57
57
  To keep it in Claude Code, install the plugin. It brings the MCP server, the session-start
@@ -62,7 +62,22 @@ brief and the skills in one step; it only needs [uv](https://docs.astral.sh/uv/)
62
62
  /plugin install memory-boost@memory-boost
63
63
  ```
64
64
 
65
- Other agents, or the CLI on its own: `uv tool install memory-boost` (or `pipx install memory-boost`).
65
+ Other agents, or the CLI on its own: `uv tool install memory-boost==0.2.0` (or
66
+ `pipx install memory-boost==0.2.0`). Or let your agent do it: see [Install from your agent](#install-from-your-agent).
67
+
68
+ ## Install from your agent
69
+
70
+ Paste this into Claude Code, Codex, Cline or Cursor:
71
+
72
+ > Install memory-boost 0.2.0 by following
73
+ > https://github.com/arnaugonzalez/memory-boost/blob/main/llms-install.md : install the CLI with
74
+ > `uv tool install memory-boost==0.2.0`, run `memory-boost init`, register `memory-boost serve`
75
+ > as a stdio MCP server named `memory`, check that it answers with nine `memory_*` tools, then run
76
+ > `memory-boost drift` and show me the output. Ask me before writing outside the memory home
77
+ > (`~/.local/share/memory-boost`) or editing any global agent config.
78
+
79
+ The agent-oriented steps (stdio and `serve --http`, per harness, with checks) are in
80
+ [llms-install.md](https://github.com/arnaugonzalez/memory-boost/blob/main/llms-install.md).
66
81
 
67
82
  ## On a real machine
68
83
 
@@ -101,9 +116,11 @@ it needed a new tool: the data was already on disk. It needed a reader.
101
116
  ## What it is
102
117
 
103
118
  1. **A wiki you own.** `projects/*.md`, `decisions/*.md`, `concepts/*.md`, `log.md`. Plain
104
- markdown; edit by hand, keep it in git. SQLite FTS5 index as a disposable cache. Eight MCP
119
+ markdown; edit by hand, keep it in git. SQLite FTS5 index as a disposable cache. Nine MCP
105
120
  tools for any harness: `memory_brief`, `memory_recall`, `memory_page`, `memory_save`,
106
- `memory_checkpoint`, `memory_resume`, `memory_drift`, `memory_lesson`.
121
+ `memory_checkpoint`, `memory_resume`, `memory_drift`, `memory_lesson`, `memory_shelf`.
122
+ `memory_shelf` (CLI: `memory-boost shelf "idea"`) appends a dated one-line idea to
123
+ `concepts/idea-shelf.md` without the agent reading the page back.
107
124
  2. **Freshness as data.** Decisions carry `status:` and `review_by:`. Search results are tagged
108
125
  `current / unclassified / review / historic / superseded`, current first.
109
126
  3. **Session checkpoints** that survive `/compact`, with one line per *other* active session on
@@ -121,6 +138,16 @@ it needed a new tool: the data was already on disk. It needed a reader.
121
138
 
122
139
  MCP server (all harnesses): command `memory-boost`, args `["serve"]`.
123
140
 
141
+ To share one server between several sessions, run it over streamable HTTP (stateless, JSON
142
+ responses) and point each harness at `http://127.0.0.1:8765/mcp`:
143
+
144
+ ```bash
145
+ memory-boost serve --http # --host 127.0.0.1 --port 8765 are the defaults
146
+ claude mcp add --transport http memory -s user http://127.0.0.1:8765/mcp
147
+ ```
148
+
149
+ It binds to loopback by default and has no authentication: keep it there.
150
+
124
151
  | Harness | MCP registration | Context at session start |
125
152
  |---|---|---|
126
153
  | Claude Code (plugin) | `/plugin install memory-boost@memory-boost` | Included: hook, MCP server, skills |
@@ -141,7 +168,8 @@ checkpoint. It never blocks session start: on any error it prints nothing.
141
168
  Skills: `/memory-boost` (router: when to run what), `/save-session`, `/restore-session`,
142
169
  `/retro`. The plugin installs them as `/memory-boost:retro` and so on; without it, copy
143
170
  `skills/*` into `~/.claude/skills/`. The first session after installing the plugin takes a few
144
- extra seconds while uv fetches the package; later sessions start in about 0.2 s.
171
+ extra seconds while uv fetches `memory-boost==0.2.0` and its dependencies from PyPI (the only
172
+ network access the plugin makes); later sessions start in about 0.2 s.
145
173
 
146
174
  CLI contract for agents: data on stdout, errors on stderr with a `fix:` line, `--json` on every
147
175
  reading command (with a `version` field), exit 0 = trust stdout, 1 = not found, 2 = bad input.
@@ -154,8 +182,30 @@ Reports end with a `next:` line naming the exact command to run.
154
182
  <sub>Source: [docs/architecture.mmd](https://github.com/arnaugonzalez/memory-boost/blob/main/docs/architecture.mmd)</sub>
155
183
 
156
184
  The project is resolved from the working directory name (`~/work/acme-api` → `projects/acme-api.md`);
157
- map other names in `aliases.json`. Under 1,600 lines of Python, one dependency (`mcp`), no
158
- embeddings, no daemon.
185
+ map other names in `aliases.json`. Under 1,900 lines of Python, one dependency (`mcp`), no
186
+ embeddings unless you opt into semantic recall, no daemon unless you run `serve --http`.
187
+
188
+ ## Semantic recall (optional)
189
+
190
+ Off by default: `memory_recall` is full-text only and the base install stays one dependency.
191
+ To also match paraphrases and other languages, run a local embedding model:
192
+
193
+ ```bash
194
+ pip install "memory-boost[semantic]==0.2.0" # adds sqlite-vec
195
+ ollama pull embeddinggemma
196
+ export MEMORY_BOOST_SEMANTIC=1
197
+ memory-boost index # embeds the wiki once; later runs embed only changes
198
+ ```
199
+
200
+ The first index of a large wiki on CPU can take minutes: as a rough guide, about 15 minutes for some
201
+ 850 documents on a laptop without a GPU (one measurement, not a benchmark). `memory-boost index` and
202
+ `recall` show `embedding N/M chunks…` on stderr while it runs; later runs re-embed only what changed.
203
+
204
+ Default mode when on is `hybrid` (full-text and vectors fused by weighted reciprocal rank); override
205
+ with `MEMORY_BOOST_RECALL_MODE=fts|semantic|hybrid` or `memory-boost recall --mode`. If Ollama is down,
206
+ recall falls back to full-text and logs a warning. On a private 64-query set (39 literal, 25 paraphrase)
207
+ with a warm index on CPU: paraphrase nDCG@10 0.46 to 0.76, literal 0.80 to 0.85, p50 about 110 ms per query.
208
+ The query set is not published.
159
209
 
160
210
  ## Configuration
161
211
 
@@ -173,7 +223,7 @@ embeddings, no daemon.
173
223
  | | memory-boost | [basic-memory](https://github.com/basicmachines-co/basic-memory) | [claude-mem](https://github.com/thedotmack/claude-mem) | [agent-retro](https://github.com/giannimassi/agent-retro) |
174
224
  |---|---|---|---|---|
175
225
  | Store | Markdown wiki you edit | Markdown | Captured observations | None (prompt skill) |
176
- | Search | FTS5 | FTS + vectors | FTS + vectors | — |
226
+ | Search | FTS5 (+ optional local vectors) | FTS + vectors | FTS + vectors | — |
177
227
  | Freshness / review dates | Yes | No | No | — |
178
228
  | Drift report over memory | Yes | No | No | No |
179
229
  | Session analytics | Yes (aggregates, local) | No | No | LLM reads the conversation |
@@ -186,7 +236,7 @@ agents already wrote down.
186
236
 
187
237
  ## Limits / non-goals
188
238
 
189
- - Keyword search only; no embeddings.
239
+ - Full-text search by default; embeddings only with the optional `[semantic]` extra and a local Ollama.
190
240
  - `mine` understands Claude Code transcripts today. Codex is on the roadmap.
191
241
  - Reports are as good as the wiki: an empty wiki yields an empty `drift`.
192
242
  - Single user, local files. Linux and macOS; Windows untested.
Binary file
@@ -0,0 +1,144 @@
1
+ # Installing memory-boost (instructions for AI agents)
2
+
3
+ You are an AI coding agent (Claude Code, Codex, Cline, Cursor or similar) asked to install
4
+ memory-boost and register it as an MCP server. Follow these steps in order. Run each check; if one
5
+ fails, stop and report the command and its stderr. Ask the user before you edit a global config
6
+ file (anything under `~`) or write outside the memory home.
7
+
8
+ What it is: a markdown wiki that agents read and write over MCP (nine `memory_*` tools), plus
9
+ `drift` reports on that memory and `mine` digests of local Claude Code transcripts. Everything is
10
+ local files; nothing is sent anywhere. The optional semantic recall talks only to a local Ollama.
11
+
12
+ ## 1. Requirements
13
+
14
+ - Python 3.11+ and [uv](https://docs.astral.sh/uv/) (`uv --version`). If uv is missing, ask the
15
+ user before installing it. `pipx` works too: replace `uv tool install` with `pipx install`.
16
+ - Linux or macOS. Windows is untested.
17
+
18
+ ## 2. Install the CLI (pinned)
19
+
20
+ ```bash
21
+ uv tool install memory-boost==0.2.0
22
+ memory-boost --version # expect: memory-boost 0.2.0
23
+ ```
24
+
25
+ Check which binary the harness will run: `command -v memory-boost` must be inside `uv tool dir --bin`
26
+ and `memory-boost --version` must print 0.2.0. If it is not found, or another `memory-boost` comes
27
+ first on PATH, put the absolute path `$(uv tool dir --bin)/memory-boost` in the MCP config below
28
+ instead of `memory-boost` (or ask the user before running `uv tool update-shell`).
29
+
30
+ Without installing anything permanently, use `uvx memory-boost==0.2.0 <command>` instead of
31
+ `memory-boost <command>` everywhere below (MCP config: command `uvx`, args
32
+ `["--quiet", "memory-boost==0.2.0", "serve"]`).
33
+
34
+ ## 3. Create the memory home
35
+
36
+ ```bash
37
+ memory-boost init # creates the wiki in $MEMORY_BOOST_HOME (default ~/.local/share/memory-boost)
38
+ memory-boost drift # exit 0; an empty wiki gives an empty report
39
+ ```
40
+
41
+ To see what it does on sample data first: `memory-boost init --example` (only into an empty home).
42
+ To use an existing markdown wiki, set `MEMORY_BOOST_WIKI=/path/to/wiki` in the MCP server's `env`.
43
+
44
+ ## 4. Register the MCP server
45
+
46
+ Server name: `memory`. Transport: stdio (default). Command: `memory-boost`, args: `["serve"]`.
47
+ If a server named `memory` is already configured (`claude mcp list`, `codex mcp list` or the JSON
48
+ file), ask the user whether to replace it or use another name such as `memory-boost`.
49
+ Pick the block for your harness.
50
+
51
+ **Claude Code.** If the user wants the full setup (MCP server, session-start hook, skills), tell
52
+ them to run `/plugin marketplace add arnaugonzalez/memory-boost` and then
53
+ `/plugin install memory-boost@memory-boost` themselves, and skip the rest of this step.
54
+ MCP server only:
55
+
56
+ ```bash
57
+ claude mcp add memory -s user -- memory-boost serve # all projects (global: ask first)
58
+ claude mcp add memory -s project -- memory-boost serve # this repo only: writes ./.mcp.json
59
+ claude mcp list # expect: memory: memory-boost serve - ✓ Connected
60
+ ```
61
+
62
+ **Codex CLI**:
63
+
64
+ ```bash
65
+ codex mcp add memory -- memory-boost serve
66
+ ```
67
+
68
+ or in `~/.codex/config.toml`:
69
+
70
+ ```toml
71
+ [mcp_servers.memory]
72
+ command = "memory-boost"
73
+ args = ["serve"]
74
+ ```
75
+
76
+ **Cline** (`cline_mcp_settings.json`), **Cursor** (`.cursor/mcp.json`), **VS Code, Gemini CLI and
77
+ other JSON configs**:
78
+
79
+ ```json
80
+ {
81
+ "mcpServers": {
82
+ "memory": { "command": "memory-boost", "args": ["serve"] }
83
+ }
84
+ }
85
+ ```
86
+
87
+ ### Optional: one shared server over HTTP
88
+
89
+ For several sessions sharing one long-lived server, run streamable HTTP (stateless, JSON responses).
90
+ It binds to 127.0.0.1 and has no authentication: never expose it on another interface.
91
+
92
+ ```bash
93
+ memory-boost serve --http # defaults: --host 127.0.0.1 --port 8765, endpoint /mcp
94
+ claude mcp add --transport http memory -s user http://127.0.0.1:8765/mcp
95
+ ```
96
+
97
+ JSON configs: `{"mcpServers": {"memory": {"type": "streamableHttp", "url": "http://127.0.0.1:8765/mcp"}}}`
98
+ (Cline uses `streamableHttp`; Claude Code's `.mcp.json` uses `"type": "http"`). Codex:
99
+ `url = "http://127.0.0.1:8765/mcp"` under `[mcp_servers.memory]`. The server must already be
100
+ running (a user service or a terminal); this step does not start it for the user.
101
+
102
+ ## 5. Check that the server answers
103
+
104
+ This talks to the server directly, independent of any harness. Expect `9`:
105
+
106
+ ```bash
107
+ printf '%s\n' \
108
+ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"check","version":"0"}}}' \
109
+ '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
110
+ '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
111
+ | memory-boost serve 2>/dev/null | grep -o '"name":"memory_[a-z]*"' | sort -u | wc -l
112
+ ```
113
+
114
+ For the HTTP server: `curl -s -X POST http://127.0.0.1:8765/mcp -H 'Content-Type: application/json'
115
+ -H 'Accept: application/json, text/event-stream' -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"check","version":"0"}}}'`
116
+ returns `"serverInfo":{"name":"memory-boost","version":"0.2.0"}`.
117
+
118
+ The MCP tools: `memory_brief`, `memory_recall`, `memory_page`, `memory_save`, `memory_checkpoint`,
119
+ `memory_resume`, `memory_drift`, `memory_lesson`, `memory_shelf`.
120
+
121
+ ## 6. Tell the agent to use it
122
+
123
+ Add one line to the project's agent instructions (`AGENTS.md`, `CLAUDE.md`, `.clinerules`, Cursor
124
+ rules), after asking the user:
125
+
126
+ > At session start call `memory_brief` (MCP server `memory`) and follow it. Record decisions with
127
+ > `memory_save`; before `/compact` or a long pause, call `memory_checkpoint`.
128
+
129
+ Claude Code without the plugin can also inject the brief automatically with a SessionStart hook in
130
+ `~/.claude/settings.json` (global: ask first):
131
+
132
+ ```json
133
+ { "hooks": { "SessionStart": [ { "hooks": [ { "type": "command", "command": "memory-boost hook session-start" } ] } ] } }
134
+ ```
135
+
136
+ ## 7. Report back
137
+
138
+ Tell the user: the installed version, where the memory home is, which config file you changed and
139
+ the exact entry, the result of the check in step 5, and the first lines of `memory-boost drift`.
140
+
141
+ ## Uninstall
142
+
143
+ `uv tool uninstall memory-boost`, remove the `memory` entry from the MCP config, and delete the
144
+ memory home only if the user asks (it holds their notes).
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "memory-boost"
3
- version = "0.1.1"
3
+ version = "0.2.0"
4
4
  description = "Memory that reviews itself: a markdown wiki for coding agents over MCP, plus drift reports on the wiki and digests of your own sessions."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -17,7 +17,10 @@ classifiers = [
17
17
  "Programming Language :: Python :: 3",
18
18
  "Topic :: Software Development",
19
19
  ]
20
- dependencies = ["mcp>=1.2,<2"]
20
+ dependencies = ["mcp>=1.10,<2"]
21
+
22
+ [project.optional-dependencies]
23
+ semantic = ["sqlite-vec>=0.1.6"]
21
24
 
22
25
  [project.scripts]
23
26
  memory-boost = "memory_boost.cli:main"
@@ -0,0 +1,61 @@
1
+ """Measure recall quality (nDCG@10, hit@5, MRR) and latency (p50) per query split.
2
+
3
+ --queries points to JSON shaped as {"<split>": [{"q": str, "gold": [key, ...]}]}.
4
+ A key is a page stem (decisions/foo.md -> "foo") or the project name for log.md entries.
5
+ The queries file is supplied by the user and is not versioned in this repo.
6
+ Run with MEMORY_BOOST_HOME pointing at the wiki to evaluate; --mode picks fts|semantic|hybrid.
7
+ """
8
+ import argparse
9
+ import json
10
+ import math
11
+ import statistics
12
+ import time
13
+ from pathlib import Path
14
+
15
+ from memory_boost import core
16
+
17
+
18
+ def recall_keys(query: str, historic: bool, mode: str | None) -> list[str]:
19
+ keys: list[str] = []
20
+ for r in core.recall(query, limit=10, include_historic=historic, mode=mode):
21
+ key = r["project"] if r["kind"] == "log" else Path(r["path"]).stem
22
+ if key not in keys:
23
+ keys.append(key)
24
+ return keys[:10]
25
+
26
+
27
+ def score(keys: list[str], gold: list[str]) -> dict[str, float]:
28
+ gold_set = set(gold)
29
+ rank = next((i + 1 for i, k in enumerate(keys) if k in gold_set), None)
30
+ dcg = sum(1 / math.log2(i + 2) for i, k in enumerate(keys) if k in gold_set)
31
+ idcg = sum(1 / math.log2(i + 2) for i in range(min(len(gold_set), 10)))
32
+ return {
33
+ "ndcg": dcg / idcg if idcg else 0.0,
34
+ "hit5": float(rank is not None and rank <= 5),
35
+ "mrr": 1 / rank if rank else 0.0,
36
+ }
37
+
38
+
39
+ def main() -> None:
40
+ ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
41
+ ap.add_argument("--queries", type=Path, required=True, help="JSON file with query splits")
42
+ ap.add_argument("--historic", action="store_true", help="include historic pages")
43
+ ap.add_argument("--mode", choices=core.RECALL_MODES, default=None, help="recall mode to evaluate")
44
+ args = ap.parse_args()
45
+ splits = json.loads(args.queries.read_text(encoding="utf-8"))
46
+ for split, items in splits.items():
47
+ scores, times = [], []
48
+ for it in items:
49
+ t0 = time.perf_counter()
50
+ keys = recall_keys(it["q"], args.historic, args.mode)
51
+ times.append((time.perf_counter() - t0) * 1000)
52
+ scores.append(score(keys, it["gold"]))
53
+ n = len(scores) or 1
54
+ mean = {m: sum(s[m] for s in scores) / n for m in ("ndcg", "hit5", "mrr")}
55
+ p50 = statistics.median(times) if times else 0.0
56
+ print(f"{split}: nDCG@10 {mean['ndcg']:.3f} hit@5 {mean['hit5']:.3f} MRR {mean['mrr']:.3f} "
57
+ f"p50 {p50:.0f} ms")
58
+
59
+
60
+ if __name__ == "__main__":
61
+ main()
@@ -0,0 +1,25 @@
1
+ """Render docs/logo-400.png (Cline / Glama logo) in the docs/social.png palette.
2
+
3
+ uv run --no-project --with pillow python scripts/render-logo.py docs/logo-400.png
4
+ """
5
+ import sys
6
+
7
+ from PIL import Image, ImageDraw, ImageFont
8
+
9
+ out = sys.argv[1]
10
+ S = 4 # supersample
11
+ W = 400 * S
12
+ img = Image.new("RGB", (W, W), "#1e1e2e")
13
+ d = ImageDraw.Draw(img)
14
+ bold = "/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf"
15
+ reg = "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf"
16
+ pad = 40 * S
17
+ d.rounded_rectangle([pad - 4*S, 92*S, W - pad + 4*S, 300*S], radius=18*S,
18
+ fill="#181825", outline="#313244", width=2*S)
19
+ f_big = ImageFont.truetype(bold, 78 * S)
20
+ f_small = ImageFont.truetype(reg, 24 * S)
21
+ d.text((pad + 16*S, 110*S), "memory", font=f_big, fill="#f5e0dc")
22
+ d.text((pad + 16*S, 195*S), "-boost", font=f_big, fill="#f5e0dc")
23
+ d.text((pad + 16*S, 48*S), "$ drift", font=f_small, fill="#89b4fa")
24
+ d.text((pad + 16*S, 318*S), "reads it back.", font=f_small, fill="#a6e3a1")
25
+ img.resize((400, 400), Image.LANCZOS).save(out, optimize=True)
@@ -43,7 +43,7 @@ assert init["result"]["serverInfo"]["name"], init
43
43
  call({"jsonrpc": "2.0", "method": "notifications/initialized"}, reply=False)
44
44
  tools = {t["name"] for t in call({"jsonrpc": "2.0", "id": 2, "method": "tools/list"})["result"]["tools"]}
45
45
  p.terminate()
46
- assert len(tools) == 8 and "memory_drift" in tools, tools
46
+ assert len(tools) == 9 and {"memory_drift", "memory_shelf"} <= tools, tools
47
47
  print("mcp tools:", ", ".join(sorted(tools)))
48
48
  EOF
49
49
  step OK
@@ -8,12 +8,12 @@
8
8
  "source": "github"
9
9
  },
10
10
  "websiteUrl": "https://github.com/arnaugonzalez/memory-boost",
11
- "version": "0.1.1",
11
+ "version": "0.2.0",
12
12
  "packages": [
13
13
  {
14
14
  "registryType": "pypi",
15
15
  "identifier": "memory-boost",
16
- "version": "0.1.1",
16
+ "version": "0.2.0",
17
17
  "runtimeHint": "uvx",
18
18
  "packageArguments": [{ "type": "positional", "value": "serve" }],
19
19
  "transport": { "type": "stdio" }
@@ -1,3 +1,3 @@
1
1
  """Shared, file-based memory for coding agents (MCP server + CLI + hooks)."""
2
2
 
3
- __version__ = "0.1.1"
3
+ __version__ = "0.2.0"