linksee-memory 0.16.1 → 0.17.1
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/README.md +97 -183
- package/dist/bin/guard-hook.js +19 -4
- package/dist/bin/setup.js +178 -63
- package/dist/bin/share-draft.d.ts +2 -0
- package/dist/bin/share-draft.js +90 -0
- package/dist/bin/sync-session.js +10 -1
- package/dist/db/migrate.d.ts +30 -0
- package/dist/db/migrate.js +150 -9
- package/dist/lib/consolidate.d.ts +9 -0
- package/dist/lib/consolidate.js +14 -0
- package/dist/lib/guard-wiring.d.ts +47 -1
- package/dist/lib/guard-wiring.js +114 -11
- package/dist/lib/hook-runtime.d.ts +41 -0
- package/dist/lib/hook-runtime.js +197 -0
- package/dist/lib/native-hint.d.ts +5 -0
- package/dist/lib/native-hint.js +42 -0
- package/dist/lib/settings-file.d.ts +23 -0
- package/dist/lib/settings-file.js +137 -0
- package/dist/lib/share-draft.d.ts +56 -0
- package/dist/lib/share-draft.js +234 -0
- package/dist/mcp/prompts.js +1 -1
- package/dist/mcp/server.js +93 -26
- package/dist/skill/SKILL.md +6 -14
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
[](https://registry.modelcontextprotocol.io/)
|
|
14
14
|
[](https://glama.ai/mcp/servers/michielinksee/linksee-memory)
|
|
15
15
|
|
|
16
|
-
🌐 **Landing page**: [linksee
|
|
17
|
-
📖 **Docs**: [docs.linksee.app](https://docs.linksee.app) — full reference: the product map & drift, install, and
|
|
16
|
+
🌐 **Landing page**: [linksee.app](https://linksee.app) (includes non-developer onboarding for Claude Desktop / Cursor / Claude Code / OpenAI Codex / Gemini CLI)
|
|
17
|
+
📖 **Docs**: [docs.linksee.app](https://docs.linksee.app) — full reference: the product map & drift, install, and every tool
|
|
18
18
|
|
|
19
19
|
<!-- releases: tag-driven, published from CI via npm trusted publishing (OIDC).
|
|
20
20
|
See .github/workflows/publish.yml — no token, no OTP, provenance attached automatically. -->
|
|
@@ -254,7 +254,7 @@ It is **fail-open by construction**: any parse / DB / logic error surfaces nothi
|
|
|
254
254
|
|
|
255
255
|
Anchors with `affects` globs fire only on matching paths; an unscoped anchor fires on its own `detect_terms` / `violation_signal`. Nothing is ever **blocked** unless you explicitly hardened it (`resolve_drift(action:'harden')`) — everything else re-injects the decision as context.
|
|
256
256
|
|
|
257
|
-
To wire it by hand instead, drop this block into `.claude/settings.json` (project root, or `~/.claude/settings.json` for every repo)
|
|
257
|
+
To wire it by hand instead, drop this block into `.claude/settings.json` (project root, or `~/.claude/settings.json` for every repo). The `npx -y` form below needs no install, but costs several seconds per call (7.4–8.6 s measured on Windows, close to the 8 s `PreToolUse` timeout — a timed-out guard simply does not fire). `setup` writes a direct `node` call instead; you can do the same with `"<path to node>" "<package>/dist/bin/guard-hook.js"` (paths quoted; Claude Code runs hooks through cmd.exe on Windows and sh elsewhere, and a path containing `$`, a backtick, `%` or `"` cannot be quoted safely — setup keeps the npx form for those):
|
|
258
258
|
|
|
259
259
|
```json
|
|
260
260
|
{
|
|
@@ -279,7 +279,7 @@ To wire it by hand instead, drop this block into `.claude/settings.json` (projec
|
|
|
279
279
|
}
|
|
280
280
|
```
|
|
281
281
|
|
|
282
|
-
|
|
282
|
+
Where it applies is the settings file it lives in: `~/.claude/settings.json` (what `setup` writes) covers every repo; a project's `.claude/settings.json` (`setup --project-guard`) covers that repo only. Declare what it should watch with `declare_anchor(...)`; set `card_policy.gate_mode:'hard'` on an anchor to make a contradiction **block** instead of just warn (the soft default only re-injects). Anchors that are stale (`at_risk`), superseded, or card-disabled never gate.
|
|
283
283
|
|
|
284
284
|
> Developing linksee-memory itself? The repo dogfoods the guard via a (gitignored) `.claude/settings.json` that points at the local build (`node ${CLAUDE_PROJECT_DIR}/dist/bin/guard-hook.js`) so it runs against your uncommitted changes. End-user projects should use the published `npx -y linksee-memory guard` form above.
|
|
285
285
|
|
|
@@ -289,7 +289,7 @@ It's **project-scoped on purpose** — the guard enforces *this* repo's decision
|
|
|
289
289
|
|
|
290
290
|
Most "agent memory" services (Mem0, Letta, Zep) save a flat list of facts. Then the agent looks at "edited file X 30 times" and has no idea why. And none of them notice when this week's work contradicts last week's decision. **linksee-memory keeps the WHY — and watches the drift.**
|
|
291
291
|
|
|
292
|
-
It is a Model Context Protocol (MCP) server with **
|
|
292
|
+
It is a Model Context Protocol (MCP) server with **7 tools** (six for memory and drift, plus the optional `share_draft`) that gives any AI agent structured memory + drift detection:
|
|
293
293
|
|
|
294
294
|
| | Mem0 / Letta / Zep | Claude Code auto-memory | linksee-memory |
|
|
295
295
|
|---|---|---|---|
|
|
@@ -329,7 +329,7 @@ It is a Model Context Protocol (MCP) server with **11 tools** that gives any AI
|
|
|
329
329
|
Returns match_reasons explaining each hit
|
|
330
330
|
```
|
|
331
331
|
|
|
332
|
-
Every memory is tagged with **exactly one layer**. `caveat`-layer entries are protected from auto-forgetting. Cold low-importance memories
|
|
332
|
+
Every memory is tagged with **exactly one layer**. `caveat`-layer entries are protected from auto-forgetting. Cold low-importance memories can be consolidated into `learning` entries, but only if you opt in (`LINKSEE_AUTO_CONSOLIDATE=1` on the server — it deletes the originals; off by default since 0.17.1).
|
|
333
333
|
|
|
334
334
|
---
|
|
335
335
|
|
|
@@ -340,13 +340,39 @@ Every memory is tagged with **exactly one layer**. `caveat`-layer entries are pr
|
|
|
340
340
|
npx -y linksee-memory setup
|
|
341
341
|
```
|
|
342
342
|
|
|
343
|
-
This
|
|
344
|
-
1. Registers the MCP server
|
|
343
|
+
This sets up **Claude Code**:
|
|
344
|
+
1. Registers the MCP server (`claude mcp add -s user linksee -- npx -y linksee-memory`)
|
|
345
345
|
2. Installs the agent skill (teaches the agent when to recall/remember)
|
|
346
|
-
3. Configures auto-capture
|
|
347
|
-
4.
|
|
346
|
+
3. Configures auto-capture — a `Stop` hook, so every session is saved to your local memory
|
|
347
|
+
4. Wires the [re-injection guard](#reinjection-guard) for every repo (`--project-guard` for this repo only, `--no-guard` to skip)
|
|
348
348
|
|
|
349
|
-
|
|
349
|
+
**What is shared, and what is Claude Code only.** The memory itself (the MCP tools `remember` / `recall` / …) works from any MCP client — Claude Code, Cursor, Windsurf, OpenAI Codex, Gemini CLI — and they all use the same `~/.linksee-memory/memory.db`. Auto-capture and the guard are Claude Code hooks: other clients save and recall only when the agent calls the tools.
|
|
350
|
+
|
|
351
|
+
**Using Codex too?** One line registers the same memory there:
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
codex mcp add linksee -- npx -y linksee-memory
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
(Cursor, Windsurf and Gemini CLI: see [Other editors / CLIs](#other-editors--clis).)
|
|
358
|
+
|
|
359
|
+
**Try it — one round trip.** A new install has an empty memory, so "how did we solve this before?" has nothing to find yet. Instead:
|
|
360
|
+
1. In Claude Code, say: *"Remember: in this repo we decided to use X, because Y."*
|
|
361
|
+
2. Open a **new** session and ask: *"What did we decide about X?"*
|
|
362
|
+
|
|
363
|
+
Add **"Use Linksee"** to any prompt to force a recall.
|
|
364
|
+
|
|
365
|
+
**What setup writes, and how to undo it.**
|
|
366
|
+
|
|
367
|
+
| File | What |
|
|
368
|
+
|---|---|
|
|
369
|
+
| `~/.claude.json` | the `linksee` MCP server (via `claude mcp add`) — undo with `claude mcp remove linksee` |
|
|
370
|
+
| `~/.claude/skills/linksee-memory/SKILL.md` | the agent skill |
|
|
371
|
+
| `~/.claude/settings.json` | the `Stop` hook (auto-capture) and the `SessionStart` / `PreToolUse` guard hooks. Merged into what is there — other hooks and settings are kept. If the file does not parse, setup leaves it untouched and says so. Before changing it, setup keeps the previous file as `settings.json.bak-<timestamp>`: to undo, copy that file back over `settings.json`. |
|
|
372
|
+
| `~/.linksee-memory/runtime/<version>/` | only when setup was run through `npx`: setup runs `npm install --prefix ~/.linksee-memory/runtime/<version> --no-save --omit=dev linksee-memory@<version>` once (the only network call, shown with its size), because the hooks call `node` on it directly and npx's cache is temporary. Older versions are not removed automatically (about 35 MB each): setup prints the folder, you can delete old ones by hand, and `linksee-memory runtime prune` is planned for 0.17.2. If the install fails, the hooks stay on the npx form. |
|
|
373
|
+
| `~/.linksee-memory/telemetry-consent` | your telemetry answer (`off` unless you said yes) |
|
|
374
|
+
|
|
375
|
+
Running setup again changes nothing that is already in place. It rewrites only hooks it wrote itself: the exact `npx -y linksee-memory sync` / `npx -y linksee-memory guard` from earlier versions, and the direct form it writes now, which ends in `--linksee-managed`. Anything else that runs our scripts — a wrapper, a path you typed — is left alone and listed at the end of setup. With `--no-guard`, the guard hooks are not touched at all. If you later upgrade Node to a new major version, re-run setup (the hooks print one line saying so and let the action through).
|
|
350
376
|
|
|
351
377
|
### Manual setup (if you prefer step-by-step)
|
|
352
378
|
|
|
@@ -388,7 +414,7 @@ Add to `~/.claude/settings.json`:
|
|
|
388
414
|
}
|
|
389
415
|
```
|
|
390
416
|
|
|
391
|
-
|
|
417
|
+
This `npx -y` form works anywhere, but every call starts npm and checks the registry: on the author's Windows machine one call took 7.4–8.6 s (3 runs, warm cache). `setup` writes a direct call instead — `"<path to node>" "<package>/dist/bin/sync-session.js" --linksee-managed` — which took 0.20–0.27 s on the same machine. Your numbers will differ; measure with your own hook log. Failures are silent. Logs at `~/.linksee-memory/hook.log`.
|
|
392
418
|
|
|
393
419
|
</details>
|
|
394
420
|
|
|
@@ -501,9 +527,11 @@ Default: `~/.linksee-memory/memory.db`. Override with `LINKSEE_MEMORY_DIR` env v
|
|
|
501
527
|
# 1. Remove the MCP server registration
|
|
502
528
|
claude mcp remove linksee
|
|
503
529
|
|
|
504
|
-
# 2. Remove the hooks from settings.json (edit the file, delete the linksee entries)
|
|
505
|
-
#
|
|
506
|
-
#
|
|
530
|
+
# 2. Remove the hooks from settings.json (edit the file, delete the linksee entries),
|
|
531
|
+
# or copy back the settings.json.bak-<timestamp> that setup left next to it:
|
|
532
|
+
# ~/.claude/settings.json → the Stop hook (…sync-session.js, or "npx -y linksee-memory sync")
|
|
533
|
+
# and the SessionStart/PreToolUse hooks (…guard-hook.js, or "npx -y linksee-memory guard")
|
|
534
|
+
# <project>/.claude/settings.json → the same guard hooks, if you used --project-guard
|
|
507
535
|
|
|
508
536
|
# 3. Remove the installed skill and all local memory (optional)
|
|
509
537
|
rm -rf ~/.claude/skills/linksee-memory
|
|
@@ -512,6 +540,13 @@ rm -rf ~/.linksee-memory # deletes all stored memory — nothing is kept anywh
|
|
|
512
540
|
|
|
513
541
|
Nothing ever leaves your machine, so step 3 fully erases everything Linksee stored.
|
|
514
542
|
|
|
543
|
+
## What's new in v0.17
|
|
544
|
+
|
|
545
|
+
| Feature | Detail |
|
|
546
|
+
|---|---|
|
|
547
|
+
| **`share_draft` (optional)** | When you ask to share how a SaaS / MCP / API connection got stuck and what fixed it, the agent fills fixed fields and gets back a link to a reviewed draft on KanseiLINK. **Linksee sends nothing** — you read the draft in your browser and only your click sends it. Anything that looks like a key, token, e-mail, tenant URL, IP or local path stops the link. See [Share a fix with other agents](#share-a-fix-with-other-agents-optional). |
|
|
548
|
+
| **MCP SDK 1.32.2** | `@modelcontextprotocol/sdk` raised to `^1.32.2`; `pnpm audit` 46 → 0. |
|
|
549
|
+
|
|
515
550
|
## What's new in v0.9
|
|
516
551
|
|
|
517
552
|
| Feature | Detail |
|
|
@@ -534,7 +569,7 @@ Nothing ever leaves your machine, so step 3 fully erases everything Linksee stor
|
|
|
534
569
|
| Feature | Detail |
|
|
535
570
|
|---|---|
|
|
536
571
|
| **3-tool unified surface** | 8 tools → 3: `remember` (create + update + delete), `recall` (search + file history + overview), `read_smart` (token-saving reads). Fewer tools = better cross-LLM consistency. Follows Context7's proven pattern. |
|
|
537
|
-
| **Auto-consolidate** | Consolidation runs automatically on server startup (non-blocking, 7-day threshold). No manual `consolidate()` calls needed. |
|
|
572
|
+
| **Auto-consolidate** | Consolidation runs automatically on server startup (non-blocking, 7-day threshold). No manual `consolidate()` calls needed. *(Off by default since 0.17.1 — opt in with `LINKSEE_AUTO_CONSOLIDATE=1`.)* |
|
|
538
573
|
| **Deprecation guidance** | Old tool names (`forget`, `recall_file`, etc.) return specific migration examples instead of silent failures. |
|
|
539
574
|
| **"Use Linksee Memory" trigger** | Add "Use Linksee Memory" to any prompt to force memory recall — same adoption pattern as Context7. |
|
|
540
575
|
| **Claude Code Plugin** | `claude plugin add -- linksee-memory` — ships MCP server + auto-invocation skill in one install. |
|
|
@@ -553,7 +588,7 @@ Nothing ever leaves your machine, so step 3 fully erases everything Linksee stor
|
|
|
553
588
|
|
|
554
589
|
</details>
|
|
555
590
|
|
|
556
|
-
##
|
|
591
|
+
## 7 Tools: six for memory and drift, one you ask for
|
|
557
592
|
|
|
558
593
|
Two pillars, one surface. **Memory** and **drift** each get the minimum; nothing else is exposed.
|
|
559
594
|
Eleven tools bled model-dependent behaviour across Claude / GPT / Cursor / Codex / Gemini — six
|
|
@@ -573,6 +608,10 @@ The five earlier names — `where_am_i`, `check_decision`, `flag_proposals`, `dr
|
|
|
573
608
|
answer if called**, so a skill or agent written against an older version keeps working.
|
|
574
609
|
`LINKSEE_LEGACY_TOOLS=1` lists them.
|
|
575
610
|
|
|
611
|
+
One more tool sits outside the memory/drift surface and does nothing unless the user asks:
|
|
612
|
+
`share_draft` — builds a link to a reviewed draft of a fix for other agents. See
|
|
613
|
+
[Share a fix with other agents](#share-a-fix-with-other-agents-optional).
|
|
614
|
+
|
|
576
615
|
### CLI utilities
|
|
577
616
|
|
|
578
617
|
| Command | Purpose |
|
|
@@ -584,6 +623,7 @@ answer if called**, so a skill or agent written against an older version keeps w
|
|
|
584
623
|
| `npx -y linksee-memory import` | Batch-import Claude Code session JSONL history |
|
|
585
624
|
| `npx -y linksee-memory install-skill` | Install the Claude Code Skill that teaches the agent when to call recall/remember/read_smart |
|
|
586
625
|
| `npx -y linksee-memory stats` | Summary of the local DB (entity count / layer breakdown / top entities / top edited files). Add `--json` for machine-readable output. |
|
|
626
|
+
| `npx -y linksee-memory share-draft --help` | Print a link to a reviewed draft of a fix (same checks as the `share_draft` tool). Sends nothing. |
|
|
587
627
|
|
|
588
628
|
## The 6 memory layers
|
|
589
629
|
|
|
@@ -628,7 +668,7 @@ The conversation↔file linkage is the key. Every file edit captured by the Stop
|
|
|
628
668
|
## Roadmap
|
|
629
669
|
|
|
630
670
|
- ✅ 3-tool unified surface (remember / recall / read_smart) — v0.7.0
|
|
631
|
-
- ✅ Auto-consolidate on server startup — v0.7.0
|
|
671
|
+
- ✅ Auto-consolidate on server startup — v0.7.0 (opt-in since 0.17.1)
|
|
632
672
|
- ✅ Claude Code Plugin (`claude plugin add -- linksee-memory`)
|
|
633
673
|
- ✅ Five MCP Blocks (Tools + Resources + Prompts + Sampling + Roots + Elicitation)
|
|
634
674
|
- ✅ Stop-hook auto-capture for Claude Code
|
|
@@ -636,10 +676,11 @@ The conversation↔file linkage is the key. Every file edit captured by the Stop
|
|
|
636
676
|
- ✅ One-command setup (`npx -y linksee-memory setup`)
|
|
637
677
|
- ✅ Structured memory v2 (3-axis classification: altitude × type × state)
|
|
638
678
|
- ✅ Cross-LLM: Claude Code, Cursor, Windsurf, OpenAI Codex, Gemini CLI
|
|
639
|
-
- ✅ Landing page ([linksee
|
|
679
|
+
- ✅ Landing page ([linksee.app](https://linksee.app))
|
|
640
680
|
- ✅ Drift detection engine + 4 MCP drift tools — v0.8.0
|
|
641
681
|
- ✅ 4-species truth map (hypothesis/constraint/commitment/source_of_truth) — v0.8.0
|
|
642
682
|
- ✅ Dashboard with Decision Register visualization
|
|
683
|
+
- ✅ `share_draft`: share a fix as a reviewed link, never a send — v0.17.0
|
|
643
684
|
- 🔮 Obsidian plugin (read truth map in your vault)
|
|
644
685
|
- 🔮 Vector search via `sqlite-vec` (already in deps, embedding backend pending)
|
|
645
686
|
- 🔮 Cross-device cloud sync (Pro tier)
|
|
@@ -653,6 +694,37 @@ Claude Code ships a built-in memory feature at `~/.claude/projects/<path>/memory
|
|
|
653
694
|
|
|
654
695
|
Use both.
|
|
655
696
|
|
|
697
|
+
## Share a fix with other agents (optional)
|
|
698
|
+
|
|
699
|
+
When an agent gets stuck connecting to a SaaS / MCP / API and gets it working (or doesn't), the
|
|
700
|
+
user can choose to share what happened so the next agent does not repeat it.
|
|
701
|
+
|
|
702
|
+
- **What happens:** the agent calls `share_draft` with fixed fields — `service`, `task`, `symptom`,
|
|
703
|
+
`tried`, `result`, optional `conditions`, `kind` (`execution` / `documentation` / `hypothesis`),
|
|
704
|
+
`runtime`. Linksee checks them and returns **a link** to KanseiLINK's draft page
|
|
705
|
+
(`https://kansei-link.com/agents/note/new.html`). The page opens with the fields filled; the user
|
|
706
|
+
reads them, and only their click on that page sends anything.
|
|
707
|
+
- **What never goes in:** free text outside those fields, or anything that looks like a key, token,
|
|
708
|
+
JWT, `Bearer` value, e-mail, tenant URL (`acme.slack.com`), IP address, local path
|
|
709
|
+
(`C:\`, `/Users/`, `/home/`) or a long hex / base64 run. Any of these stops the build and names the
|
|
710
|
+
field — no link is made. The whole URL must fit in 2,000 characters; Linksee asks you to shorten
|
|
711
|
+
rather than cut. The URL passes through KanseiLINK's request logs (Cloudflare), so keep secrets out.
|
|
712
|
+
- **What Linksee keeps:** one row saying a draft was made, with the time — no field text.
|
|
713
|
+
- **How to turn it off:** don't use it. The tool is only called when the user asks to share;
|
|
714
|
+
nothing is sent, suggested or filled from your memory automatically.
|
|
715
|
+
|
|
716
|
+
<details>
|
|
717
|
+
<summary>日本語</summary>
|
|
718
|
+
|
|
719
|
+
SaaS・MCP・API の接続で詰まって直った(または直らなかった)とき、利用者が望めば、次のエージェントが同じ所で詰まらないよう共有できます。
|
|
720
|
+
|
|
721
|
+
- **起きること:** エージェントが決まった欄(`service`・`task`・`symptom`・`tried`・`result`・任意の `conditions`・`kind`・`runtime`)で `share_draft` を呼ぶと、Linksee は欄を検査して、KanseiLINK の下書きページへの **リンクを返すだけ** です。開くと欄が埋まった画面が出て、人が確かめてから、そのページで押した時だけ送られます。
|
|
722
|
+
- **入らない物:** 決まった欄の外の自由文。キー・トークン・JWT・`Bearer` の値・メールアドレス・テナントの URL(`acme.slack.com`)・IP アドレス・PC の中の道(`C:\`・`/Users/`・`/home/`)・長い 16 進や base64 の塊。どれかがあれば、リンクは作らず、どの欄かを返します。URL 全体は 2,000 字まで。超えたら削らずに「短くしてください」と返します。URL の中身は KanseiLINK の通信の記録(Cloudflare)を通るので、秘密は入れないでください。
|
|
723
|
+
- **Linksee に残る物:** 「下書きを作った」ことと時刻だけ。欄の中身は残しません。
|
|
724
|
+
- **止め方:** 使わなければ何も起きません。利用者が共有したいと言った時だけ使う道具で、自動の送信・提案・記憶からの書き込みはありません。
|
|
725
|
+
|
|
726
|
+
</details>
|
|
727
|
+
|
|
656
728
|
## Security & privacy
|
|
657
729
|
|
|
658
730
|
linksee-memory runs locally and is built to read — and send — as little as possible.
|
|
@@ -660,6 +732,7 @@ linksee-memory runs locally and is built to read — and send — as little as p
|
|
|
660
732
|
- **Local-first.** Memory is one SQLite file at `~/.linksee-memory/memory.db`. No account, no cloud, no API key.
|
|
661
733
|
- **Telemetry is opt-in and OFF by default.** `setup` asks once; nothing is sent unless you agree there (or set `LINKSEE_TELEMETRY=basic`). Even then it never sends your source code, file contents, prompts, conversation, entity/project names, or the memory DB — only anonymous counters ([details](#telemetry-opt-in-off-by-default)).
|
|
662
734
|
- **No automatic repo crawling.** linksee reads: memory you explicitly save, your `map.yaml`, the specific files a map reality-check points at, the local SQLite DB, and — when the Stop hook fires — your Claude Code session transcript (locally, to capture what happened). It does **not** crawl your repo, read `.env`/secrets/`node_modules`, or touch your home directory on its own.
|
|
735
|
+
- **`share_draft` makes a link only; Linksee itself never sends it.** The user opens it and decides ([details](#share-a-fix-with-other-agents-optional)).
|
|
663
736
|
- **Clean MCP transport.** The server writes only JSON-RPC to stdout; all logs go to stderr.
|
|
664
737
|
- **Hooks are documented and removable.** `setup` adds a Stop hook (session capture) and an optional guard hook. They make no network calls by default, are time-bounded, fail-open (a hook error never breaks your session), and are listed under [Uninstall](#uninstall).
|
|
665
738
|
- **No shell-injection surface.** Subcommands run via `spawn` with array args and `shell: false`, from a fixed allowlist; `map.yaml` is parsed with the safe `yaml` parser (no arbitrary tag execution).
|
|
@@ -784,9 +857,7 @@ Or delete individual memories via `remember({ forget: true, memory_id: <id> })`.
|
|
|
784
857
|
<details>
|
|
785
858
|
<summary><b>DB is getting large (>100 MB). How do I trim it?</b></summary>
|
|
786
859
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
If you want to force a manual consolidation, restart the MCP server — auto-consolidate triggers on every startup.
|
|
860
|
+
Since 0.17.1 nothing is consolidated automatically: consolidation deletes the original rows (keeping a short summary), so it runs only if you start the server with `LINKSEE_AUTO_CONSOLIDATE=1` (then at most weekly, 7-day threshold). When enabled it clusters old cold memories into compressed learning-layer summaries and deletes the originals; caveat and active-goal layers are always preserved. Back up `~/.linksee-memory/` before turning it on. There is no `consolidate` tool to call.
|
|
790
861
|
</details>
|
|
791
862
|
|
|
792
863
|
## FAQ
|
|
@@ -816,7 +887,7 @@ Three axes:
|
|
|
816
887
|
Claude Code's auto-memory is Claude-only (doesn't help if you switch to Cursor, OpenAI Codex, or Gemini CLI) and stores flat markdown with no structure. linksee-memory is the same local-first principle but:
|
|
817
888
|
- Works across Claude Code, Cursor, OpenAI Codex, Gemini CLI (shared SQLite)
|
|
818
889
|
- Structured 6-layer format makes recall explainable
|
|
819
|
-
-
|
|
890
|
+
- Consolidation of cold memories is opt-in (`LINKSEE_AUTO_CONSOLIDATE=1`, deletes originals); caveats are permanently protected
|
|
820
891
|
</details>
|
|
821
892
|
|
|
822
893
|
<details>
|
|
@@ -841,7 +912,7 @@ The default is no sync — the SQLite file lives at `~/.linksee-memory/memory.db
|
|
|
841
912
|
|
|
842
913
|
Two mechanisms:
|
|
843
914
|
1. **Ebbinghaus forgetting**: cold low-importance memories decay naturally, eligible for auto-forget sweeps. `caveat` layer and memories with `importance ≥ 0.9` are always protected.
|
|
844
|
-
2. **
|
|
915
|
+
2. **Consolidation (opt-in)**: off by default since 0.17.1. With `LINKSEE_AUTO_CONSOLIDATE=1` on the server it runs at start-up at most weekly (7-day threshold), compressing clusters of cold low-importance memories by entity into a single `learning`-layer summary and deleting the originals.
|
|
845
916
|
|
|
846
917
|
In practice a solo developer hits ~100MB after 6 months of heavy use. A year-old DB I tested with 80K memories still recalls in <10ms.
|
|
847
918
|
</details>
|
|
@@ -851,7 +922,7 @@ In practice a solo developer hits ~100MB after 6 months of heavy use. A year-old
|
|
|
851
922
|
|
|
852
923
|
Yes — any MCP-compatible client works:
|
|
853
924
|
- **Claude Code**: `claude mcp add -s user linksee -- npx -y linksee-memory`
|
|
854
|
-
- **Claude Desktop**: add to `claude_desktop_config.json` (see [onboarding on the LP](https://linksee
|
|
925
|
+
- **Claude Desktop**: add to `claude_desktop_config.json` (see [onboarding on the LP](https://linksee.app))
|
|
855
926
|
- **Cursor**: add to MCP settings in Cursor → Settings → Features → Model Context Protocol
|
|
856
927
|
- **OpenAI Codex**: `codex mcp add linksee -- npx -y linksee-memory` (or `~/.codex/config.toml` with `[mcp_servers.linksee]` block)
|
|
857
928
|
- **Gemini CLI**: add to `~/.gemini/settings.json` mcpServers section
|
|
@@ -880,164 +951,7 @@ After install, in a new Claude session ask: *"Can you remember that I prefer Typ
|
|
|
880
951
|
|
|
881
952
|
## Changelog
|
|
882
953
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
- **Corrupt-database recovery:** if `~/.linksee-memory/memory.db` is unreadable, linksee preserves it as `memory.db.corrupt-<timestamp>` and starts a fresh one (with a clear message) instead of crashing with a raw SQLite error. Old memories stay recoverable in the backup.
|
|
886
|
-
- **`recall` tool description** no longer suggests editing your system prompt — cleaner MCP citizenship.
|
|
887
|
-
|
|
888
|
-
### v0.11.2 — More cold-start hardening (2026-06-16)
|
|
889
|
-
|
|
890
|
-
- **`stats` works on a fresh database** instead of crashing with `no such table` — it ensures the schema exists first (it may be the first command a new user runs).
|
|
891
|
-
- **`map --help`** prints usage instead of trying to import a map.
|
|
892
|
-
|
|
893
|
-
### v0.11.1 — Cold-start fixes (2026-06-16)
|
|
894
|
-
|
|
895
|
-
- **Run any CLI through the package name:** `npx -y linksee-memory setup` (and `map`, `sync`, `guard`, `stats`, `import`, `install-skill`). A fresh user couldn't reach the standalone bins (`linksee-memory-setup`, …) via `npx` — npx resolves package names, not sibling bin names — so the one-command install 404'd. The main bin now dispatches subcommands; the standalone bins remain as aliases.
|
|
896
|
-
- **`map` exits gracefully** with a next-step message when there's no `map.yaml` yet (was a raw stack trace — the exact state of a first-time user).
|
|
897
|
-
- **serverInfo** now reports the real package version (was pinned to an old string).
|
|
898
|
-
|
|
899
|
-
### v0.11.0 — The Map: `where_am_i` + `linksee-memory map` (2026-06-15)
|
|
900
|
-
|
|
901
|
-
**Memory is the entry point; the product map is the new surface.** Drift detection grows up from individual anchors into a whole-product map you navigate from the CLI.
|
|
902
|
-
|
|
903
|
-
- **`where_am_i`** (11th MCP tool) — locate the current topic/file on the Current Truth Map and get its blast radius. Call it with no args to auto-locate from your recent edits.
|
|
904
|
-
- **`linksee-memory map`** CLI — `where` · `affects` · `explain` · `status` · `next` · `reconcile` · `inspect --json` · `blueprint`. A `map.yaml` (git source of truth) describes how value reaches your user; the reconciler checks it against your code with file:line evidence. Bilingual: add `--lang ja`.
|
|
905
|
-
- Graded blast radius (`must fix together` / `should align` / `fyi`), declared-vs-reality verdicts, and an anti-graveyard guard for accounted-for drift.
|
|
906
|
-
- Per-project keys so the Map handles many projects at once.
|
|
907
|
-
|
|
908
|
-
### v0.8.0 — Drift Detection MCP Tools (2026-06-08)
|
|
909
|
-
|
|
910
|
-
**3 tools → 7 tools.** The biggest update since launch — agents can now detect, query, and resolve intent ↔ reality drift.
|
|
911
|
-
|
|
912
|
-
**New tools:**
|
|
913
|
-
- **`drift_status`** — returns the truth map with 4-species classification and per-node drift state
|
|
914
|
-
- **`check_decision`** — deep-dive into a single anchor: state, edges, pending candidates
|
|
915
|
-
- **`declare_anchor`** — record a decision/constraint/prohibition as a truth-map node (with v9 ProjectCoreNode fields)
|
|
916
|
-
- **`resolve_drift`** — close the feedback loop: fix / supersede / acknowledge / dismiss
|
|
917
|
-
|
|
918
|
-
**New engine module:**
|
|
919
|
-
- **`truth-engine.ts`** — state derivation logic migrated from the dashboard into the MCP engine. Any MCP client can now query drift status without a dashboard.
|
|
920
|
-
- **Resolution priority fix**: when multiple resolutions reference the same anchor, the most recent one wins (by `resolved_at` timestamp). Prevents a stale acknowledge from shadowing a newer fix.
|
|
921
|
-
- **4-species classification**: nodes classified by `decision_mode` into hypothesis / constraint / commitment / source_of_truth with display format guidance.
|
|
922
|
-
|
|
923
|
-
No breaking changes to existing memory tools. All 3 memory tools (remember, recall, read_smart) are unchanged.
|
|
924
|
-
|
|
925
|
-
### v0.7.2 — Recall ergonomics + auto-edge detection + classifier precision (2026-05-30)
|
|
926
|
-
|
|
927
|
-
Quality pass on v0.7.0 / v0.7.1 — sharper day-to-day agent UX and cleaner data for the dashboard:
|
|
928
|
-
|
|
929
|
-
- **`recall` token discipline**: drops the redundant `content_raw` from the response (parsed `content` was already there — it was a 2× duplicate), and actually enforces `max_tokens` by greedy assembly that measures real serialized size (was a flat ~100 tok/memory estimate). Adds `approx_tokens` to the response so the agent can see its budget usage. The same query that previously returned ~15,800 tokens for a 1200 budget now stays inside it.
|
|
930
|
-
- **`recall` precision**: near-duplicate memories — same entity + near-identical core text, e.g. the same message captured under both `goal` and `learning` — collapse to one in the result set. Composite weights adapt to query specificity: multi-term queries weight relevance higher so off-topic-but-pinned memories don't crowd narrow recalls.
|
|
931
|
-
- **Capture dedup (write side)**: `session-extractor` now produces AT MOST one memory per user turn, with priority `goal[first_intent] > caveat > decision > context`. A first-intent message containing decision words (e.g. "決めた" / "これで進めよう") is no longer double-saved as both `goal` and `learning`.
|
|
932
|
-
- **`memory_edges` auto-detection**: the previously-empty `memory_edges` table is now populated during the sleep-mode consolidation sweep. `detectMemoryEdges()` links a later DECISION memory to the most-recent earlier same-topic decision within an entity (chain, not clique) so the dashboard can render Pivot Chains. The default relation is `extends` — a same-topic later decision builds on, but does NOT deactivate, the earlier one. Explicit reversal markers (やめる / revert / instead of) produce `contradicts`; explicit replacement markers (の代わり / replaces / deprecate) produce `supersedes`. Prevents silent deactivation of still-valid decisions.
|
|
933
|
-
- **`inferType` / `inferState` precision**: chitchat acknowledgements ("そうだね" / "ありがとう"), pasted terminal/git/email content, and meta-noise no longer classify as `decision` — they return `note` / `open` before pattern matching. The learning-layer default → `decision` is gated by this guard. Real decisions (採用 / 決めた, even after an acknowledgement opener) survive.
|
|
934
|
-
|
|
935
|
-
No schema migration, no breaking API changes. Existing rows keep their stored content; the classifier improvements apply to new captures going forward.
|
|
936
|
-
|
|
937
|
-
### v0.7.1 — Review fixes (2026-05-29)
|
|
938
|
-
|
|
939
|
-
Based on Opus 4.7 design review of v0.7.0:
|
|
940
|
-
|
|
941
|
-
- **P0 — Required params guidance**: `remember` tool description now includes "REQUIRED PARAMS BY MODE" section so LLMs know exactly which fields are needed for create vs update vs delete.
|
|
942
|
-
- **P0 — Migration guidance**: Deprecated tool names (`forget`, `recall_file`, etc.) now return specific migration examples instead of generic errors.
|
|
943
|
-
- **P1 — recall path+query merge**: When both `path` and `query` are provided to `recall`, results from file history and memory search are merged into a single response.
|
|
944
|
-
- **P2 — Auto-consolidate safety**: Table existence check via `sqlite_master` before querying `consolidations` table, preventing errors on fresh databases.
|
|
945
|
-
|
|
946
|
-
### v0.7.0 — 3-Tool Unified Surface (2026-05-29)
|
|
947
|
-
|
|
948
|
-
**8 tools → 3 tools.** Following Context7's proven pattern of fewer tools = better cross-LLM consistency.
|
|
949
|
-
|
|
950
|
-
**Breaking change**: The following tools are removed from the MCP surface. Calling them returns a migration guide:
|
|
951
|
-
|
|
952
|
-
| Old tool | New equivalent |
|
|
953
|
-
|---|---|
|
|
954
|
-
| `forget` | `remember({ forget: true, memory_id: <id> })` |
|
|
955
|
-
| `update_memory` | `remember({ memory_id: <id>, content: "..." })` |
|
|
956
|
-
| `recall_file` | `recall({ path: "server.ts" })` |
|
|
957
|
-
| `list_entities` | `recall({})` (no params = entity overview) |
|
|
958
|
-
| `consolidate` | Auto-runs on server startup (7-day threshold) |
|
|
959
|
-
|
|
960
|
-
**New unified tools:**
|
|
961
|
-
- **`remember`** — create + update + delete in one tool. Mode is inferred from params.
|
|
962
|
-
- **`recall`** — search + file history + overview in one tool. Mode is inferred from params.
|
|
963
|
-
- **`read_smart`** — unchanged.
|
|
964
|
-
|
|
965
|
-
**Other changes:**
|
|
966
|
-
- Auto-consolidate on server startup (non-blocking `setTimeout`, 7-day threshold, `sqlite_master` safety check)
|
|
967
|
-
- Claude Code Plugin bundle (`claude plugin add -- linksee-memory`)
|
|
968
|
-
- Deprecation errors include specific migration examples
|
|
969
|
-
|
|
970
|
-
All internal handler functions are preserved — this is a surface change, not a logic rewrite.
|
|
971
|
-
|
|
972
|
-
### v0.2.0 — English-first launch readiness (2026-04-20)
|
|
973
|
-
|
|
974
|
-
Prepares the package for a broader (primarily English-speaking) audience on Reddit, Hacker News, and Anthropic Discord. No breaking API changes.
|
|
975
|
-
|
|
976
|
-
- **Bilingualized `SKILL.md`** (auto-invocation skill). The bundled skill that `linksee-memory-install-skill` copies into `~/.claude/skills/linksee-memory/SKILL.md` was Japanese-first; it is now English-primary with Japanese trigger phrases preserved inline. English speakers now get the skill firing on natural English phrases ("how did we solve this before?", "same error again", "remember this") in addition to the existing JP triggers.
|
|
977
|
-
- **Install-skill CLI output is bilingual**: example test phrases shown after installation include both English and Japanese.
|
|
978
|
-
- **Session-extractor EN coverage** (`linksee-memory-import`): expanded regex patterns for decisions, failures, and caveats so English Claude Code session logs get auto-tagged correctly. Additions include `let's go`, `pivot`, `switch to`, `settled on`, `approved`, `doesn't work`, `stuck`, `same error again`, `hit an error`, `debug`, `broke`, `revert`.
|
|
979
|
-
- **Clearer caveat-forget error hint**: the previous message said "lower importance below 0.9 first, then forget" which was misleading — caveat-layer memories are permanently protected regardless of importance. The hint now correctly distinguishes layer-protection from pin-protection.
|
|
980
|
-
- **README rework** for launch readiness: added a "See it in action" before/after scenario, ASCII 6-layer diagram, MCP Official Registry + Glama score badges, landing-page link, and an 8-item FAQ covering questions that surface during public launches.
|
|
981
|
-
- Internal: SKILL.md now documents pairing with KanseiLink skill as an English workflow example.
|
|
982
|
-
|
|
983
|
-
No code changes to the MCP protocol surface; all existing MCP clients continue to work unchanged.
|
|
984
|
-
|
|
985
|
-
### v0.1.1 — Pin threshold tweak (2026-04-19)
|
|
986
|
-
|
|
987
|
-
Based on real-world feedback that `importance=0.95` memories were not
|
|
988
|
-
being treated as pinned despite intent.
|
|
989
|
-
|
|
990
|
-
- **Pin threshold lowered from `>= 1.0` to `>= 0.9`.** Memories with
|
|
991
|
-
`importance >= 0.9` are now exempt from the auto-forget sweep and
|
|
992
|
-
surface `pinned: true` in `recall` and `remember` responses. This
|
|
993
|
-
matches the natural mental model ("0.9 = high importance = should
|
|
994
|
-
survive cleanup") without requiring exact `1.0`.
|
|
995
|
-
- All existing memories with `importance >= 0.9` (including older ones
|
|
996
|
-
set to `0.9` or `0.95`) become pinned automatically — no migration
|
|
997
|
-
needed.
|
|
998
|
-
- Updated tool descriptions and error messages to reflect the new
|
|
999
|
-
threshold.
|
|
1000
|
-
|
|
1001
|
-
### v0.1.0 — Major UX update (2026-04-18)
|
|
1002
|
-
|
|
1003
|
-
Based on one week of dogfooding, here's what changed:
|
|
1004
|
-
|
|
1005
|
-
**New tools**
|
|
1006
|
-
- `update_memory` — atomic edit with preserved `memory_id`. Solves the "forget+remember breaks session_file_edits links" bug.
|
|
1007
|
-
- `list_entities` — fast "what do I know about?" primitive for session init. Supports `kind`/`min_memories` filters and returns layer breakdown.
|
|
1008
|
-
- `npx -y linksee-memory stats` — local DB summary CLI.
|
|
1009
|
-
|
|
1010
|
-
**`recall` enhancements**
|
|
1011
|
-
- `match_reasons` array on each memory: e.g. `["content_match_fts", "heat:hot", "pinned"]`.
|
|
1012
|
-
- `score_breakdown` with per-dimension scores (relevance / heat / momentum / importance).
|
|
1013
|
-
- Pagination via `offset` / `has_more` / `stopped_by`.
|
|
1014
|
-
- `limit` parameter (hard cap, complements `max_tokens` budget).
|
|
1015
|
-
- `band` filter to request only hot/warm/cold/frozen memories.
|
|
1016
|
-
- `mark_accessed=false` for preview queries that shouldn't bump heat.
|
|
1017
|
-
- **Layer aliases**: `decisions` → `learning`, `warnings` → `caveat`, `how` → `implementation`, etc.
|
|
1018
|
-
- **Fix**: opportunistic refresh of stale entity momentum scores. Entities recalled >1 h after last remember() no longer return stale momentum.
|
|
1019
|
-
|
|
1020
|
-
**`remember` enhancements**
|
|
1021
|
-
- Quality check: rejects pasted assistant output / CI logs / stack traces unless `force=true`.
|
|
1022
|
-
- `importance=1.0` now implicitly pins the memory (survives auto-forget).
|
|
1023
|
-
- Layer aliases accepted.
|
|
1024
|
-
|
|
1025
|
-
**`forget` changes**
|
|
1026
|
-
- Pinned memories (importance=1.0) now preserved alongside caveat-layer memories.
|
|
1027
|
-
- Clear error response when attempting to delete a protected or missing memory.
|
|
1028
|
-
- dry-run now includes `sample_ids_to_drop`.
|
|
1029
|
-
|
|
1030
|
-
**`consolidate` changes**
|
|
1031
|
-
- `dry_run: true` preview mode — reports cluster count + candidates without writing.
|
|
1032
|
-
|
|
1033
|
-
**Infra**
|
|
1034
|
-
- Fixed fresh-DB migration bug (was querying `meta` table before it existed).
|
|
1035
|
-
- Bumped to Node 20+ for structured language feature usage.
|
|
1036
|
-
|
|
1037
|
-
All changes are **backward compatible** — existing integrations continue to work. Server.ts version banner now reports `v0.1.0`.
|
|
1038
|
-
|
|
1039
|
-
### Older versions
|
|
1040
|
-
See [GitHub Releases](https://github.com/michielinksee/linksee-memory/releases).
|
|
954
|
+
See [CHANGELOG.md](./CHANGELOG.md) for every release, and [GitHub Releases](https://github.com/michielinksee/linksee-memory/releases).
|
|
1041
955
|
|
|
1042
956
|
## License
|
|
1043
957
|
|
package/dist/bin/guard-hook.js
CHANGED
|
@@ -14,8 +14,14 @@
|
|
|
14
14
|
// "hooks": [ { "type": "command", "command": "node",
|
|
15
15
|
// "args": ["${CLAUDE_PROJECT_DIR}/dist/bin/guard-hook.js"], "timeout": 8 } ] } ] } }
|
|
16
16
|
import { pathToFileURL } from 'node:url';
|
|
17
|
-
import {
|
|
18
|
-
|
|
17
|
+
import { NATIVE_HINT, isNativeLoadError, hookLog } from '../lib/native-hint.js';
|
|
18
|
+
/** Fail open (exit 0). Native-load failures say so once on stderr; anything else goes to hook.log only. */
|
|
19
|
+
function bail(where, e) {
|
|
20
|
+
if (isNativeLoadError(e))
|
|
21
|
+
process.stderr.write(`${NATIVE_HINT}\n`);
|
|
22
|
+
hookLog(`guard: ${where}: ${String(e?.message ?? e).split('\n')[0]}`);
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
19
25
|
function readStdin() {
|
|
20
26
|
return new Promise((resolve) => {
|
|
21
27
|
const chunks = [];
|
|
@@ -37,14 +43,23 @@ async function main() {
|
|
|
37
43
|
}
|
|
38
44
|
if (!ev || typeof ev !== 'object')
|
|
39
45
|
process.exit(0);
|
|
46
|
+
let openDb, runMigrations;
|
|
47
|
+
let gateAction, buildBootDigest;
|
|
48
|
+
try {
|
|
49
|
+
({ openDb, runMigrations } = await import('../db/migrate.js'));
|
|
50
|
+
({ gateAction, buildBootDigest } = await import('../lib/guard.js'));
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
bail('import', e);
|
|
54
|
+
}
|
|
40
55
|
let db;
|
|
41
56
|
try {
|
|
42
57
|
db = openDb();
|
|
43
58
|
db.pragma('busy_timeout = 2000'); // MCP server may hold a write lock; wait briefly, else fail-open
|
|
44
59
|
runMigrations(db); // ensures injection_log exists even when run standalone
|
|
45
60
|
}
|
|
46
|
-
catch {
|
|
47
|
-
|
|
61
|
+
catch (e) {
|
|
62
|
+
bail('open', e); // can't open DB → never block
|
|
48
63
|
}
|
|
49
64
|
try {
|
|
50
65
|
if (ev.hook_event_name === 'PreToolUse') {
|