nexusmem 0.3.0 → 0.3.2
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/CHANGELOG.md +260 -182
- package/LICENSE +21 -21
- package/README.md +95 -27
- package/dist/cli/index.js +448 -17
- package/dist/cli/index.js.map +1 -1
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# NexusMem
|
|
2
2
|
|
|
3
|
+
[](https://github.com/yaminbkk/NexusMem/actions/workflows/ci.yml)
|
|
3
4
|
[](https://www.npmjs.com/package/nexusmem)
|
|
5
|
+
[](https://www.npmjs.com/package/nexusmem)
|
|
4
6
|
[](LICENSE)
|
|
5
7
|

|
|
6
8
|
|
|
@@ -70,6 +72,55 @@ Requirements: Node 22 or newer, and git. Node 20 will not work, because `better-
|
|
|
70
72
|
prebuilt binary for it and Node 20 went end-of-life in April 2026. Ollama is optional and only
|
|
71
73
|
affects semantic search (see below).
|
|
72
74
|
|
|
75
|
+
## Optional: exact shell capture
|
|
76
|
+
|
|
77
|
+
Scraped history files (PSReadLine, `.bash_history`, `.zsh_history`) give you command text and not
|
|
78
|
+
much else. The hook gives you working directory, exit code and a real timestamp:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
nexusmem hook install
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
It wraps your existing PowerShell prompt rather than replacing it, is idempotent, and
|
|
85
|
+
`nexusmem hook remove` undoes it cleanly.
|
|
86
|
+
|
|
87
|
+
Exit codes are what make this worth installing. A failed command is a stronger signal than a
|
|
88
|
+
successful one, and without the hook there is no way to tell them apart.
|
|
89
|
+
|
|
90
|
+
## Failure → fix chains (opt-in)
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
nexusmem sync --link-failures
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
After a normal sync, this walks every failed `shell_command` (non-zero exit code) and looks for
|
|
97
|
+
whatever later resolved it, using two independent heuristics: a later command in the same project
|
|
98
|
+
and working directory, exact same normalized text, that exited `0` within 24h (**same-command
|
|
99
|
+
retry**); and, separately, the best full-text match among nearby conversation turns or session
|
|
100
|
+
summaries, requiring every significant word of the failing command to appear, not just one
|
|
101
|
+
(**conversation bridge**). A failure can be linked by either, both, or neither.
|
|
102
|
+
|
|
103
|
+
Both links are surfaced in query results. The conversation-bridge heuristic originally matched on
|
|
104
|
+
any shared word, and dogfooding against this repo's own real history found it wrong on roughly half
|
|
105
|
+
its links — a shared word as generic as "npm" was enough to link an unrelated discussion. Requiring
|
|
106
|
+
every significant word fixed that: re-dogfooded against the same corpus, every resulting link (the
|
|
107
|
+
full set produced, not a sample) checked out correct on manual review of the full text, not just the
|
|
108
|
+
summary.
|
|
109
|
+
|
|
110
|
+
When a linked failure appears in a result set, its fix rides along immediately after it, inheriting
|
|
111
|
+
the failure's own relevance score rather than needing to match the query on its own merits. That is
|
|
112
|
+
the point: a query about why something failed shouldn't need to separately guess the words used in
|
|
113
|
+
whatever fixed it. This works across projects too — `query --all-projects` chains a failure to its
|
|
114
|
+
fix using whichever project's own database recorded the link, since links are always local to the
|
|
115
|
+
project they were found in.
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
$ nexusmem query "why did npm whoami fail"
|
|
119
|
+
|
|
120
|
+
- 2026-08-12 shell: npm whoami (exit 1)
|
|
121
|
+
- 2026-08-12 shell: npm login (exit 0) -- linked as the fix
|
|
122
|
+
```
|
|
123
|
+
|
|
73
124
|
## How retrieval works
|
|
74
125
|
|
|
75
126
|
Every source normalizes to the same `MemoryNode` shape, so a commit, a shell command and a docs
|
|
@@ -155,21 +206,6 @@ Three tools over stdio: `search_memory` returns the packed context block, `sync_
|
|
|
155
206
|
MCP tool call carries no shell working directory. `sync_project` runs `init` for you if the
|
|
156
207
|
repository has not been set up.
|
|
157
208
|
|
|
158
|
-
## Optional: exact shell capture
|
|
159
|
-
|
|
160
|
-
Scraped history files (PSReadLine, `.bash_history`, `.zsh_history`) give you command text and not
|
|
161
|
-
much else. The hook gives you working directory, exit code and a real timestamp:
|
|
162
|
-
|
|
163
|
-
```bash
|
|
164
|
-
nexusmem hook install
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
It wraps your existing PowerShell prompt rather than replacing it, is idempotent, and
|
|
168
|
-
`nexusmem hook remove` undoes it cleanly.
|
|
169
|
-
|
|
170
|
-
Exit codes are what make this worth installing. A failed command is a stronger signal than a
|
|
171
|
-
successful one, and without the hook there is no way to tell them apart.
|
|
172
|
-
|
|
173
209
|
## What it costs you
|
|
174
210
|
|
|
175
211
|
Two numbers get conflated in tools like this, so they are kept apart here.
|
|
@@ -179,14 +215,40 @@ corpus it runs 81–84%. It is useful for tuning the ranker and useless as a cla
|
|
|
179
215
|
because the baseline is hypothetical: without NexusMem those candidates were never going into your
|
|
180
216
|
context window in the first place.
|
|
181
217
|
|
|
182
|
-
**End-to-end saving** compares packed context
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
218
|
+
**End-to-end saving** compares the packed context NexusMem actually sends against reading, in full,
|
|
219
|
+
the same files its own ranking identified as relevant to the query. Measured with
|
|
220
|
+
[`scripts/benchmark.ts`](scripts/benchmark.ts) (`npm run bench`), which anyone who clones this repo
|
|
221
|
+
and points it at a synced corpus can re-run from scratch:
|
|
222
|
+
|
|
223
|
+
| Corpus | Commits | Query set | vs. full file content | vs. `git log -p` on those files |
|
|
224
|
+
| --- | --- | --- | --- | --- |
|
|
225
|
+
| This repo | 62 | 16 real prompts, verbatim from this project's own history | 95% (median 94%) | 98% (median 97%) |
|
|
226
|
+
| [`vitejs/vite`](https://github.com/vitejs/vite) | 9,567 | 16, mechanically sampled — see below | 99% (median 98%) | ~100% (median ~100%) — see caveat |
|
|
227
|
+
|
|
228
|
+
Both clear the original >70% target ("cut API token spend versus sending full context"), and the vite
|
|
229
|
+
run is the first measurement at the scale that target was always described as applying to.
|
|
230
|
+
|
|
231
|
+
**Read the methodology before quoting either number, because it is a narrower claim than it looks:**
|
|
232
|
+
|
|
233
|
+
- The file set each query is graded against comes from NexusMem's *own* ranking — whichever files the
|
|
234
|
+
packed nodes for that query touch, not an outside judge's idea of the right answer. This isolates
|
|
235
|
+
what the pack step (rank → budget → excerpt) saves once retrieval has already picked a candidate
|
|
236
|
+
set; it does not independently verify that the candidate set was the right one to pick.
|
|
237
|
+
- The vite query set is not hand-picked: an even sample, across the full commit history, of
|
|
238
|
+
well-explained `fix`/`feat`/`perf`/`refactor` commits turned into "why does vite `<description>`"
|
|
239
|
+
from the commit's own conventional-commit text, plus rationale-bearing doc section headings. This
|
|
240
|
+
repo's own query set instead reuses real historical prompts verbatim from `conversation_turn`
|
|
241
|
+
nodes — several are broad task instructions rather than narrow questions, which pulls a wider file
|
|
242
|
+
set into scope and is part of why its number, while still high, sits below vite's. Both derivations
|
|
243
|
+
are mechanical and disclosed in `scripts/benchmark.ts`, neither is cherry-picked per-query.
|
|
244
|
+
- `git log -p` on a file touched by thousands of commits is enormous — one vite query's baseline hit
|
|
245
|
+
7.5M tokens because a file in its resolved set has that much history. That is itself a finding, not
|
|
246
|
+
noise: at this scale, "just read the file's history instead" stops being a viable alternative at
|
|
247
|
+
all, which is a big part of why that column rounds to ~100%.
|
|
248
|
+
- **This supersedes the previous ~40% figure**, which was hand-tallied from two hand-picked queries
|
|
249
|
+
against this repo alone, never instrumented, and used an unstated baseline. It was not wrong so much
|
|
250
|
+
as underspecified — this number replaces it with a stated method and a script that reproduces it,
|
|
251
|
+
rather than being a claim that the product got better.
|
|
190
252
|
|
|
191
253
|
One thing that is not a percentage: shell commands and conversation turns have no cheap `grep`
|
|
192
254
|
equivalent. Without something recording them, they are gone, not merely more expensive to find.
|
|
@@ -241,6 +303,11 @@ optimizing, and it is somebody else's process.
|
|
|
241
303
|
unmounted drive is not a deleted project.
|
|
242
304
|
- **Conversation chunking is unevaluated.** Splitting long replies at heading boundaries measurably
|
|
243
305
|
helped, but it has never been tested systematically.
|
|
306
|
+
- **A chunked node's sibling count in one result is capped, not tuned.** `conversation_turn` and
|
|
307
|
+
`doc_section` both split one reply or file into several nodes; at most 2 of them may appear
|
|
308
|
+
together in a packed result. Found live: a query for "token" returned 9 of its top 12 hits as
|
|
309
|
+
different pieces of one heavily-sectioned reply, crowding out the node that actually answered it.
|
|
310
|
+
The cap of 2 is a judgement call, not a measured optimum, same as the ranking priors' budget above.
|
|
244
311
|
- **The size of the prior budget is a judgement call, not a measured optimum.** Priors are now
|
|
245
312
|
bounded jointly rather than one at a time, which closed a real 4× hole (see the ranking section),
|
|
246
313
|
but the 2× budget itself has never been tuned against a labelled relevance set — there isn't one.
|
|
@@ -260,8 +327,9 @@ is the intended way to tune scoring against a real repository before committing
|
|
|
260
327
|
`--json` to pipe them somewhere.
|
|
261
328
|
|
|
262
329
|
Every command takes `-C <path>` to target another repository. On `sync`, `--conversation` opts the
|
|
263
|
-
transcript source in for one run without persisting it, `--no-embed` skips the vector pass,
|
|
264
|
-
`--
|
|
330
|
+
transcript source in for one run without persisting it, `--no-embed` skips the vector pass,
|
|
331
|
+
`--link-failures` builds the failure → fix chains described above, and `--rebuild` drops the
|
|
332
|
+
project's nodes and re-ingests from scratch.
|
|
265
333
|
|
|
266
334
|
## Recall across projects
|
|
267
335
|
|
|
@@ -315,8 +383,8 @@ Deleting `.nexusmem/` loses nothing that `sync` cannot rebuild.
|
|
|
315
383
|
|
|
316
384
|
## Status
|
|
317
385
|
|
|
318
|
-
Ingestion, hybrid retrieval, budgeted packing and the MCP server all work and are covered by
|
|
319
|
-
tests running on Linux and Windows across Node 22 and 24.
|
|
386
|
+
Ingestion, hybrid retrieval, budgeted packing and the MCP server all work and are covered by 342
|
|
387
|
+
tests running on Linux and Windows across Node 22 and 24.
|
|
320
388
|
|
|
321
389
|
## Development
|
|
322
390
|
|