linksee-memory 0.11.0 → 0.11.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/README.md +81 -41
- package/dist/bin/map-import.js +31 -0
- package/dist/bin/setup.js +11 -9
- package/dist/bin/stats.js +5 -4
- package/dist/mcp/server.js +44 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
>
|
|
7
7
|
> Underneath sits a local-first cross-LLM memory MCP — one SQLite file that **Claude Code, Cursor, Windsurf, OpenAI Codex, and Gemini CLI** all read from. Not just "what happened" but **WHY**: 6-layer structured memory with precision recall and an AST-aware diff cache (50–99% token savings on re-reads).
|
|
8
8
|
>
|
|
9
|
-
> `npx linksee-memory
|
|
9
|
+
> `npx -y linksee-memory setup` — one command, done.
|
|
10
10
|
|
|
11
11
|
[](https://www.npmjs.com/package/linksee-memory)
|
|
12
12
|
[](./LICENSE)
|
|
@@ -14,17 +14,34 @@
|
|
|
14
14
|
[](https://glama.ai/mcp/servers/michielinksee/linksee-memory)
|
|
15
15
|
|
|
16
16
|
🌐 **Landing page**: [linksee-site.vercel.app](https://linksee-site.vercel.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 all 11 tools
|
|
17
18
|
|
|
18
19
|
## 🪄 Three spells to remember
|
|
19
20
|
|
|
20
21
|
| Say this | What happens |
|
|
21
22
|
|---|---|
|
|
22
|
-
| **"use linksee"**
|
|
23
|
-
| **"linksee this"**
|
|
24
|
-
| **"what's drifting?"**
|
|
23
|
+
| **"use linksee"** | Recalls relevant memories before acting |
|
|
24
|
+
| **"linksee this"** | Saves the decision / lesson right now |
|
|
25
|
+
| **"what's drifting?"** | Reconciles reality against your locked decisions |
|
|
25
26
|
|
|
26
27
|
> Make it automatic: add **"Use Linksee Memory"** to your system prompt / `CLAUDE.md`.
|
|
27
28
|
|
|
29
|
+
## 🗺️ Not just memory — a product map
|
|
30
|
+
|
|
31
|
+
Memory is the entry point. Tie it to a `map.yaml` of how your product fits together, and the `linksee-memory map` CLI catches drift with file:line evidence:
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+
|
|
35
|
+
**The 30-second demo above:** the README says `--export`. The code doesn't. Linksee catches it — and shows what else a change would touch.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx -y linksee-memory map where README.md # this file belongs to the README node — and what it touches
|
|
39
|
+
npx -y linksee-memory map explain readme # README promises --export; the code doesn't implement it — drift, with evidence
|
|
40
|
+
npx -y linksee-memory map affects readme # changing the README also touches docs, the CLI help, and the npm listing
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
→ see [The Map](#the-map) for the full flow.
|
|
44
|
+
|
|
28
45
|
## 📣 As featured on
|
|
29
46
|
|
|
30
47
|
- **Zenn**: [あなたの Claude Code、 実は前回のセッションを完全に忘れている](https://zenn.dev/kanseilink/articles/linksee-memory-claude-code-recall-20260508) — 73 ♡ on Zenn, **165+ users on Hatena Bookmark**, picked up by tech blogs + YouTube shorts (May 2026)
|
|
@@ -121,7 +138,7 @@ Anchors are classified into four species with different display formats:
|
|
|
121
138
|
|
|
122
139
|
<a id="the-map"></a>
|
|
123
140
|
|
|
124
|
-
## 🗺️ The Map — `linksee-memory
|
|
141
|
+
## 🗺️ The Map — `linksee-memory map`
|
|
125
142
|
|
|
126
143
|
Drift detection (above) checks individual anchors. The **Map** lifts it to the whole product: a `map.yaml` describing how value reaches your user (`discover → understand → try → adopt → retain → monetize → expand`), with typed dependencies between the pieces — README, npm listing, onboarding, the engine that powers them. The reconciler checks that map against your real code, and the CLI answers the question an engineer actually has:
|
|
127
144
|
|
|
@@ -130,7 +147,7 @@ Drift detection (above) checks individual anchors. The **Map** lifts it to the w
|
|
|
130
147
|
**1. Where am I?** — locate a file (or, with no argument, infer from your recent edits):
|
|
131
148
|
|
|
132
149
|
```
|
|
133
|
-
$ linksee-memory
|
|
150
|
+
$ npx -y linksee-memory map where README.md
|
|
134
151
|
"README.md" belongs to this Map node:
|
|
135
152
|
|
|
136
153
|
readme [understand] convergence
|
|
@@ -145,7 +162,7 @@ The blast radius is **graded** — `must fix together` vs `should align` vs `fyi
|
|
|
145
162
|
**2. Why is it in this state?** — the diagnosis, with file:line evidence:
|
|
146
163
|
|
|
147
164
|
```
|
|
148
|
-
$ linksee-memory
|
|
165
|
+
$ npx -y linksee-memory map explain readme
|
|
149
166
|
|
|
150
167
|
STATUS
|
|
151
168
|
declared: healthy (active)
|
|
@@ -159,7 +176,7 @@ EVIDENCE
|
|
|
159
176
|
|
|
160
177
|
Declared state and the reality verdict are shown **separately** — a hand-declared `suspect` the scanner refutes reads as *"declared suspect, refuted by reality (→ convergence)"*, not a confusing mix.
|
|
161
178
|
|
|
162
|
-
**3. Whole-project triage:** `linksee-memory
|
|
179
|
+
**3. Whole-project triage:** `npx -y linksee-memory map status` — a health %, what is *fixable now in code* vs *external checks*, and any deferral with no expiry (so "accounted-for" can't quietly become a drift graveyard).
|
|
163
180
|
|
|
164
181
|
**How it works**
|
|
165
182
|
- **`map.yaml`** (repo root) is the desired-state source of truth: a journey spine × surface/implementation layers × typed edges (`must-stay-consistent-with` / `should-align-with` / `realizes`).
|
|
@@ -187,7 +204,7 @@ It is **fail-open by construction**: any parse / DB / logic error surfaces nothi
|
|
|
187
204
|
|
|
188
205
|
### Enable it
|
|
189
206
|
|
|
190
|
-
`npx linksee-memory
|
|
207
|
+
`npx -y linksee-memory setup` offers to wire this into your **project's** `.claude/settings.json` (Step 4). To do it by hand, drop this block into `.claude/settings.json` at your project root — it points at the globally-installed `linksee-memory-guard` bin, so no build step is needed:
|
|
191
208
|
|
|
192
209
|
```json
|
|
193
210
|
{
|
|
@@ -196,7 +213,7 @@ It is **fail-open by construction**: any parse / DB / logic error surfaces nothi
|
|
|
196
213
|
{
|
|
197
214
|
"matcher": "startup|resume|compact",
|
|
198
215
|
"hooks": [
|
|
199
|
-
{ "type": "command", "command": "npx -y linksee-memory
|
|
216
|
+
{ "type": "command", "command": "npx -y linksee-memory guard", "timeout": 15 }
|
|
200
217
|
]
|
|
201
218
|
}
|
|
202
219
|
],
|
|
@@ -204,7 +221,7 @@ It is **fail-open by construction**: any parse / DB / logic error surfaces nothi
|
|
|
204
221
|
{
|
|
205
222
|
"matcher": "Edit|Write|Bash",
|
|
206
223
|
"hooks": [
|
|
207
|
-
{ "type": "command", "command": "npx -y linksee-memory
|
|
224
|
+
{ "type": "command", "command": "npx -y linksee-memory guard", "timeout": 8 }
|
|
208
225
|
]
|
|
209
226
|
}
|
|
210
227
|
]
|
|
@@ -214,7 +231,7 @@ It is **fail-open by construction**: any parse / DB / logic error surfaces nothi
|
|
|
214
231
|
|
|
215
232
|
It's **project-scoped on purpose** — the guard enforces *this* repo's decisions, and you opt in per project rather than letting it deny tool calls everywhere (the Stop hook from setup, by contrast, is user-global). 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.
|
|
216
233
|
|
|
217
|
-
> 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
|
|
234
|
+
> 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.
|
|
218
235
|
|
|
219
236
|
---
|
|
220
237
|
|
|
@@ -270,7 +287,7 @@ Every memory is tagged with **exactly one layer**. `caveat`-layer entries are pr
|
|
|
270
287
|
## Quick Start — One Command
|
|
271
288
|
|
|
272
289
|
```bash
|
|
273
|
-
npx linksee-memory
|
|
290
|
+
npx -y linksee-memory setup
|
|
274
291
|
```
|
|
275
292
|
|
|
276
293
|
This does everything:
|
|
@@ -297,7 +314,7 @@ Tools appear as `mcp__linksee__remember`, `mcp__linksee__recall`, `mcp__linksee_
|
|
|
297
314
|
**Install the skill (auto-invocation):**
|
|
298
315
|
|
|
299
316
|
```bash
|
|
300
|
-
npx -y linksee-memory
|
|
317
|
+
npx -y linksee-memory install-skill
|
|
301
318
|
```
|
|
302
319
|
|
|
303
320
|
Copies `SKILL.md` to `~/.claude/skills/linksee-memory/`. Agent auto-fires on phrases like "前に…", "また同じエラー", "覚えておいて", new task starts, file edits, etc.
|
|
@@ -313,7 +330,7 @@ Add to `~/.claude/settings.json`:
|
|
|
313
330
|
{
|
|
314
331
|
"matcher": "",
|
|
315
332
|
"hooks": [
|
|
316
|
-
{ "type": "command", "command": "npx -y linksee-memory
|
|
333
|
+
{ "type": "command", "command": "npx -y linksee-memory sync" }
|
|
317
334
|
]
|
|
318
335
|
}
|
|
319
336
|
]
|
|
@@ -371,20 +388,15 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
371
388
|
<summary><strong>OpenAI Codex CLI</strong></summary>
|
|
372
389
|
|
|
373
390
|
```bash
|
|
374
|
-
codex
|
|
391
|
+
codex mcp add linksee -- npx -y linksee-memory
|
|
375
392
|
```
|
|
376
393
|
|
|
377
|
-
Or add to `~/.codex/config.
|
|
394
|
+
Or add to `~/.codex/config.toml`:
|
|
378
395
|
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
"command": "npx",
|
|
384
|
-
"args": ["-y", "linksee-memory"]
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
396
|
+
```toml
|
|
397
|
+
[mcp_servers.linksee]
|
|
398
|
+
command = "npx"
|
|
399
|
+
args = ["-y", "linksee-memory"]
|
|
388
400
|
```
|
|
389
401
|
|
|
390
402
|
</details>
|
|
@@ -413,6 +425,23 @@ All editors share the same `~/.linksee-memory/memory.db`. A decision made in Cla
|
|
|
413
425
|
|
|
414
426
|
Default: `~/.linksee-memory/memory.db`. Override with `LINKSEE_MEMORY_DIR` env var.
|
|
415
427
|
|
|
428
|
+
### Uninstall
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
# 1. Remove the MCP server registration
|
|
432
|
+
claude mcp remove linksee
|
|
433
|
+
|
|
434
|
+
# 2. Remove the hooks from settings.json (edit the file, delete the linksee entries):
|
|
435
|
+
# ~/.claude/settings.json → the Stop hook running "npx -y linksee-memory sync"
|
|
436
|
+
# <project>/.claude/settings.json → the SessionStart/PreToolUse hooks running "npx -y linksee-memory guard"
|
|
437
|
+
|
|
438
|
+
# 3. Remove the installed skill and all local memory (optional)
|
|
439
|
+
rm -rf ~/.claude/skills/linksee-memory
|
|
440
|
+
rm -rf ~/.linksee-memory # deletes all stored memory — nothing is kept anywhere else
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Nothing ever leaves your machine, so step 3 fully erases everything Linksee stored.
|
|
444
|
+
|
|
416
445
|
## What's new in v0.9
|
|
417
446
|
|
|
418
447
|
| Feature | Detail |
|
|
@@ -447,7 +476,7 @@ Default: `~/.linksee-memory/memory.db`. Override with `LINKSEE_MEMORY_DIR` env v
|
|
|
447
476
|
|
|
448
477
|
| Feature | Detail |
|
|
449
478
|
|---|---|
|
|
450
|
-
| **One-command setup** | `npx linksee-memory
|
|
479
|
+
| **One-command setup** | `npx -y linksee-memory setup` — registers MCP server, installs skill, configures auto-capture hook. One command instead of three. |
|
|
451
480
|
| **Structured memory v2** | 3-axis classification (altitude × type × state) for every memory. Auto-extraction from sessions produces machine-scannable JSON, not raw chat dumps. |
|
|
452
481
|
| **Precision recall guide** | SKILL.md now teaches agents HOW to write effective queries, WHEN to recall vs skip, and WHEN to proactively surface caveats before risky actions. |
|
|
453
482
|
| **Five MCP Blocks** | Tools + Resources + Prompts + Sampling + Roots + Elicitation. Most MCP servers expose only Tools; linksee-memory implements all five primitives. |
|
|
@@ -488,13 +517,13 @@ Previous versions exposed 3 tools — v0.8.0 added 4 drift tools that let agents
|
|
|
488
517
|
|
|
489
518
|
| Command | Purpose |
|
|
490
519
|
|---|---|
|
|
491
|
-
| `npx linksee-memory
|
|
520
|
+
| `npx -y linksee-memory setup` | One-command setup: MCP server + skill + Stop hook, then offers to wire the re-injection guard into this project. Idempotent — skips what's already done. |
|
|
492
521
|
| `npx linksee-memory` | MCP server (stdio) |
|
|
493
|
-
| `npx linksee-memory
|
|
494
|
-
| `npx linksee-memory
|
|
495
|
-
| `npx linksee-memory
|
|
496
|
-
| `npx linksee-memory
|
|
497
|
-
| `npx linksee-memory
|
|
522
|
+
| `npx -y linksee-memory sync` | Claude Code Stop-hook entry point |
|
|
523
|
+
| `npx -y linksee-memory guard` | Re-injection guard hook: `PreToolUse` gate (`Edit`/`Write`/`Bash`) + `SessionStart` boot digest. Wired per-project (see [Re-injection Guard](#reinjection-guard)); fail-open. |
|
|
524
|
+
| `npx -y linksee-memory import` | Batch-import Claude Code session JSONL history |
|
|
525
|
+
| `npx -y linksee-memory install-skill` | Install the Claude Code Skill that teaches the agent when to call recall/remember/read_smart |
|
|
526
|
+
| `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. |
|
|
498
527
|
|
|
499
528
|
## The 6 memory layers
|
|
500
529
|
|
|
@@ -544,7 +573,7 @@ The conversation↔file linkage is the key. Every file edit captured by the Stop
|
|
|
544
573
|
- ✅ Five MCP Blocks (Tools + Resources + Prompts + Sampling + Roots + Elicitation)
|
|
545
574
|
- ✅ Stop-hook auto-capture for Claude Code
|
|
546
575
|
- ✅ JP/EN trigram FTS5
|
|
547
|
-
- ✅ One-command setup (`npx linksee-memory
|
|
576
|
+
- ✅ One-command setup (`npx -y linksee-memory setup`)
|
|
548
577
|
- ✅ Structured memory v2 (3-axis classification: altitude × type × state)
|
|
549
578
|
- ✅ Cross-LLM: Claude Code, Cursor, Windsurf, OpenAI Codex, Gemini CLI
|
|
550
579
|
- ✅ Landing page ([linksee-site.vercel.app](https://linksee-site.vercel.app))
|
|
@@ -621,7 +650,7 @@ No account, no credit card, no API key. Just install and use.
|
|
|
621
650
|
```bash
|
|
622
651
|
ls ~/.claude/skills/linksee-memory/SKILL.md
|
|
623
652
|
```
|
|
624
|
-
If absent, run `npx -y linksee-memory
|
|
653
|
+
If absent, run `npx -y linksee-memory install-skill`.
|
|
625
654
|
2. Restart Claude Code. Skills are indexed on session start.
|
|
626
655
|
3. Check that the MCP is registered under the name `linksee` (the skill expects `mcp__linksee__*` tool names):
|
|
627
656
|
```bash
|
|
@@ -636,9 +665,9 @@ No account, no credit card, no API key. Just install and use.
|
|
|
636
665
|
1. Check the hook log: `cat ~/.linksee-memory/hook.log`
|
|
637
666
|
2. Run a manual test:
|
|
638
667
|
```bash
|
|
639
|
-
echo '{"session_id":"test","transcript_path":"/path/to/some.jsonl"}' | npx linksee-memory
|
|
668
|
+
echo '{"session_id":"test","transcript_path":"/path/to/some.jsonl"}' | npx -y linksee-memory sync
|
|
640
669
|
```
|
|
641
|
-
3. Make sure the `Stop` hook in `~/.claude/settings.json` points to `npx -y linksee-memory
|
|
670
|
+
3. Make sure the `Stop` hook in `~/.claude/settings.json` points to `npx -y linksee-memory sync` (not the old `-import`).
|
|
642
671
|
</details>
|
|
643
672
|
|
|
644
673
|
<details>
|
|
@@ -647,7 +676,7 @@ No account, no credit card, no API key. Just install and use.
|
|
|
647
676
|
v0.0.6+ fixed the entity detection bug that collapsed all memories into the session's starting cwd. To re-index existing history with correct project attribution, run:
|
|
648
677
|
|
|
649
678
|
```bash
|
|
650
|
-
npx linksee-memory
|
|
679
|
+
npx -y linksee-memory import --all
|
|
651
680
|
```
|
|
652
681
|
|
|
653
682
|
The importer is idempotent (wipes existing session data before re-inserting). Typical runtime: a few minutes for hundreds of sessions. Expect a dramatic improvement in `recall` precision afterward.
|
|
@@ -775,12 +804,23 @@ After install, in a new Claude session ask: *"Can you remember that I prefer Typ
|
|
|
775
804
|
|
|
776
805
|
## Changelog
|
|
777
806
|
|
|
778
|
-
### v0.11.
|
|
807
|
+
### v0.11.2 — More cold-start hardening (2026-06-16)
|
|
808
|
+
|
|
809
|
+
- **`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).
|
|
810
|
+
- **`map --help`** prints usage instead of trying to import a map.
|
|
811
|
+
|
|
812
|
+
### v0.11.1 — Cold-start fixes (2026-06-16)
|
|
813
|
+
|
|
814
|
+
- **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.
|
|
815
|
+
- **`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).
|
|
816
|
+
- **serverInfo** now reports the real package version (was pinned to an old string).
|
|
817
|
+
|
|
818
|
+
### v0.11.0 — The Map: `where_am_i` + `linksee-memory map` (2026-06-15)
|
|
779
819
|
|
|
780
820
|
**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.
|
|
781
821
|
|
|
782
822
|
- **`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.
|
|
783
|
-
- **`linksee-memory
|
|
823
|
+
- **`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`.
|
|
784
824
|
- Graded blast radius (`must fix together` / `should align` / `fyi`), declared-vs-reality verdicts, and an anti-graveyard guard for accounted-for drift.
|
|
785
825
|
- Per-project keys so the Map handles many projects at once.
|
|
786
826
|
|
|
@@ -884,7 +924,7 @@ Based on one week of dogfooding, here's what changed:
|
|
|
884
924
|
**New tools**
|
|
885
925
|
- `update_memory` — atomic edit with preserved `memory_id`. Solves the "forget+remember breaks session_file_edits links" bug.
|
|
886
926
|
- `list_entities` — fast "what do I know about?" primitive for session init. Supports `kind`/`min_memories` filters and returns layer breakdown.
|
|
887
|
-
- `npx linksee-memory
|
|
927
|
+
- `npx -y linksee-memory stats` — local DB summary CLI.
|
|
888
928
|
|
|
889
929
|
**`recall` enhancements**
|
|
890
930
|
- `match_reasons` array on each memory: e.g. `["content_match_fts", "heat:hot", "pinned"]`.
|
package/dist/bin/map-import.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
// linksee-memory-map blueprint # stage×node board (colors reflect the live verdict)
|
|
16
16
|
// linksee-memory-map [--file map.yaml] [--root <repo>]
|
|
17
17
|
import { join } from 'node:path';
|
|
18
|
+
import { existsSync } from 'node:fs';
|
|
18
19
|
import { openDb, runMigrations } from '../db/migrate.js';
|
|
19
20
|
import { parseMapFile, importMap } from '../lib/map-import.js';
|
|
20
21
|
import { blastRadius, getSuspects, getBlueprint, getNode, getProjectMeta, whereAmI } from '../lib/map-view.js';
|
|
@@ -38,8 +39,38 @@ for (let i = 0; i < argv.length; i++) {
|
|
|
38
39
|
const sub = positionals[0] ?? 'import';
|
|
39
40
|
const arg1 = positionals[1]; // the node-id / file / topic for explain|blast|affects|where
|
|
40
41
|
const mapPath = flagValue(argv, 'file', join(process.cwd(), 'map.yaml'));
|
|
42
|
+
if (argv.includes('--help') || argv.includes('-h') || sub === 'help') {
|
|
43
|
+
process.stdout.write(`linksee-memory map — navigate your product map (map.yaml) and catch drift\n\n` +
|
|
44
|
+
`Usage: npx -y linksee-memory map <command> [args]\n\n` +
|
|
45
|
+
` where [<file>] where am I? (no arg = infer from recent edits) → node + what it affects\n` +
|
|
46
|
+
` explain <node> why this status? — declared vs reality + file:line evidence + fix\n` +
|
|
47
|
+
` affects <node> what to change together if you touch this node\n` +
|
|
48
|
+
` status whole-project health % + what needs attention\n` +
|
|
49
|
+
` next the prioritized next fix candidate(s)\n` +
|
|
50
|
+
` reconcile re-check the map against the real code/files\n` +
|
|
51
|
+
` inspect --json machine-readable dump (CI / tooling)\n` +
|
|
52
|
+
` blueprint stage x node board (colors = live verdict)\n\n` +
|
|
53
|
+
`Flags: --file <map.yaml> --root <repo> --lang ja\n`);
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
41
56
|
const db = openDb();
|
|
42
57
|
runMigrations(db);
|
|
58
|
+
// Graceful exit when there's no map yet (the cold-user state) — never a raw stack trace.
|
|
59
|
+
if (!existsSync(mapPath)) {
|
|
60
|
+
const ja = flagValue(argv, 'lang', 'en') === 'ja';
|
|
61
|
+
process.stderr.write(ja
|
|
62
|
+
? `map.yaml が見つかりません(探した場所: ${mapPath})\n\n` +
|
|
63
|
+
`プロダクトMapは手書き(またはスキャン生成)の map.yaml で、git が正本です。\n` +
|
|
64
|
+
`リポジトリのルートに作成してから、もう一度実行してください:\n` +
|
|
65
|
+
` npx -y linksee-memory map status\n\n` +
|
|
66
|
+
`書式と例: https://docs.linksee.app/concepts/product-map\n`
|
|
67
|
+
: `No map.yaml found (looked in: ${mapPath})\n\n` +
|
|
68
|
+
`The product map is a map.yaml you hand-write (or scan-generate); git is the source of truth.\n` +
|
|
69
|
+
`Create one in your repo root, then run:\n` +
|
|
70
|
+
` npx -y linksee-memory map status\n\n` +
|
|
71
|
+
`Format & examples: https://docs.linksee.app/concepts/product-map\n`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
43
74
|
const map = parseMapFile(mapPath);
|
|
44
75
|
// Always (re)import first so reads reflect the file — map.yaml is authoritative.
|
|
45
76
|
const res = importMap(db, map);
|
package/dist/bin/setup.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// setup: One-command setup for Linksee Memory — the "Use Linksee" installer.
|
|
3
3
|
//
|
|
4
4
|
// Usage:
|
|
5
|
-
// npx linksee-memory
|
|
6
|
-
// npx linksee-memory
|
|
7
|
-
// npx linksee-memory
|
|
5
|
+
// npx linksee-memory setup (interactive setup)
|
|
6
|
+
// npx linksee-memory setup --yes (accept all defaults, no prompts)
|
|
7
|
+
// npx linksee-memory setup --dry-run
|
|
8
8
|
//
|
|
9
9
|
// Does four things:
|
|
10
10
|
// 1. Registers the MCP server with Claude Code
|
|
@@ -35,9 +35,9 @@ if (showHelp) {
|
|
|
35
35
|
console.log(`linksee-memory-setup — One-command setup for Linksee Memory
|
|
36
36
|
|
|
37
37
|
Usage:
|
|
38
|
-
npx linksee-memory
|
|
39
|
-
npx linksee-memory
|
|
40
|
-
npx linksee-memory
|
|
38
|
+
npx linksee-memory setup Interactive setup
|
|
39
|
+
npx linksee-memory setup --yes Accept all defaults, no prompts
|
|
40
|
+
npx linksee-memory setup --dry-run Show what would happen
|
|
41
41
|
|
|
42
42
|
What it does:
|
|
43
43
|
1. Registers linksee-memory MCP server with Claude Code
|
|
@@ -59,12 +59,14 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
59
59
|
const SKILL_SRC = join(dirname(__filename), '..', 'skill', 'SKILL.md');
|
|
60
60
|
const SERVER_NAME = 'linksee';
|
|
61
61
|
const MCP_COMMAND = `claude mcp add -s user ${SERVER_NAME} -- npx -y linksee-memory`;
|
|
62
|
-
|
|
62
|
+
// Subcommand form (npx -y linksee-memory <sub>) so the hooks resolve for a cold user —
|
|
63
|
+
// npx can resolve the package name, but not sibling bin names like linksee-memory-sync.
|
|
64
|
+
const HOOK_COMMAND = 'npx -y linksee-memory sync';
|
|
63
65
|
// Re-injection guard — wired into the PROJECT (not user-global) settings, because it enforces THIS
|
|
64
66
|
// project's accepted decisions. Mirrors the dogfood wiring's ${CLAUDE_PROJECT_DIR}/dist/bin path, but
|
|
65
67
|
// points at the globally-installed `linksee-memory-guard` bin so it ships without a build step. Shell
|
|
66
68
|
// form (resolved at run time) survives npx-cache eviction; a baked dist path would not.
|
|
67
|
-
const GUARD_COMMAND = 'npx -y linksee-memory
|
|
69
|
+
const GUARD_COMMAND = 'npx -y linksee-memory guard';
|
|
68
70
|
const PROJECT_DIR = process.cwd();
|
|
69
71
|
const PROJECT_CLAUDE_DIR = join(PROJECT_DIR, '.claude');
|
|
70
72
|
const PROJECT_SETTINGS_PATH = join(PROJECT_CLAUDE_DIR, 'settings.json');
|
|
@@ -293,7 +295,7 @@ console.log('How it works:');
|
|
|
293
295
|
console.log(` ${DIM}• Every session is auto-captured (decisions, caveats, learnings)${RESET}`);
|
|
294
296
|
console.log(` ${DIM}• Agent auto-recalls past context when starting a task${RESET}`);
|
|
295
297
|
console.log(` ${DIM}• Memory is local-first (nothing leaves your machine)${RESET}`);
|
|
296
|
-
console.log(` ${DIM}• Works across Claude Code, Cursor,
|
|
298
|
+
console.log(` ${DIM}• Works across Claude Code, Cursor, Windsurf, Codex, Gemini (cross-agent)${RESET}`);
|
|
297
299
|
if (guardConfigured) {
|
|
298
300
|
console.log(` ${DIM}• Re-injection guard re-surfaces this project's accepted decisions before edits${RESET}`);
|
|
299
301
|
}
|
package/dist/bin/stats.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// linksee-memory-stats — summary of the local memory DB.
|
|
3
3
|
// Usage:
|
|
4
|
-
// npx linksee-memory
|
|
5
|
-
// npx linksee-memory
|
|
6
|
-
// npx linksee-memory
|
|
4
|
+
// npx -y linksee-memory stats
|
|
5
|
+
// npx -y linksee-memory stats --json
|
|
6
|
+
// npx -y linksee-memory stats --per-entity 10
|
|
7
7
|
//
|
|
8
8
|
// Safe to run anytime (read-only).
|
|
9
9
|
import { statSync } from 'node:fs';
|
|
10
|
-
import { openDb, getDbPath } from '../db/migrate.js';
|
|
10
|
+
import { openDb, runMigrations, getDbPath } from '../db/migrate.js';
|
|
11
11
|
function parseArgs() {
|
|
12
12
|
const argv = process.argv.slice(2);
|
|
13
13
|
const a = { json: false, perEntity: 5, help: false };
|
|
@@ -68,6 +68,7 @@ function main() {
|
|
|
68
68
|
}
|
|
69
69
|
catch { /* no db yet */ }
|
|
70
70
|
const db = openDb();
|
|
71
|
+
runMigrations(db); // ensure schema exists — `stats` may be the first command a fresh user runs
|
|
71
72
|
const counts = {
|
|
72
73
|
entities: db.prepare('SELECT COUNT(*) as c FROM entities').get().c,
|
|
73
74
|
memories: db.prepare('SELECT COUNT(*) as c FROM memories').get().c,
|
package/dist/mcp/server.js
CHANGED
|
@@ -24,7 +24,49 @@ import { getTruthView, getDecisionDetail, resolveDrift } from '../lib/truth-engi
|
|
|
24
24
|
import { declareAnchor, setNodeFields } from '../lib/drift-anchors.js';
|
|
25
25
|
import { getReinjectionFriction, setGateMode } from '../lib/guard.js';
|
|
26
26
|
import { whereAmI } from '../lib/map-view.js';
|
|
27
|
-
|
|
27
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
28
|
+
import { fileURLToPath } from 'node:url';
|
|
29
|
+
import { dirname, join } from 'node:path';
|
|
30
|
+
import { spawnSync } from 'node:child_process';
|
|
31
|
+
// Single source of truth: read our own version from package.json so the MCP
|
|
32
|
+
// serverInfo can never drift from the published package version. (We catch
|
|
33
|
+
// doc/code drift for a living — our own version string shouldn't drift.)
|
|
34
|
+
function readServerVersion() {
|
|
35
|
+
try {
|
|
36
|
+
const here = fileURLToPath(import.meta.url);
|
|
37
|
+
// dist/mcp/server.js → ../../package.json
|
|
38
|
+
const pkgPath = join(dirname(dirname(dirname(here))), 'package.json');
|
|
39
|
+
if (existsSync(pkgPath)) {
|
|
40
|
+
return String(JSON.parse(readFileSync(pkgPath, 'utf8')).version || '0.0.0');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch { /* fall through */ }
|
|
44
|
+
return '0.0.0';
|
|
45
|
+
}
|
|
46
|
+
const SERVER_VERSION = readServerVersion();
|
|
47
|
+
// ── Subcommand dispatch ───────────────────────────────────────────────────────
|
|
48
|
+
// Each CLI ships as its own bin (linksee-memory-setup, …) AND as a subcommand of
|
|
49
|
+
// the main bin, so `npx -y linksee-memory <sub>` works for a cold user: npx can
|
|
50
|
+
// only resolve the package name (linksee-memory), not sibling bin names like
|
|
51
|
+
// linksee-memory-setup. Run as the MCP server (no subcommand / stdio) → skip this.
|
|
52
|
+
const SUBCOMMANDS = {
|
|
53
|
+
setup: 'setup.js',
|
|
54
|
+
map: 'map-import.js',
|
|
55
|
+
sync: 'sync-session.js',
|
|
56
|
+
guard: 'guard-hook.js',
|
|
57
|
+
stats: 'stats.js',
|
|
58
|
+
import: 'import-sessions.js',
|
|
59
|
+
'install-skill': 'install-skill.js',
|
|
60
|
+
declare: 'declare-anchor.js',
|
|
61
|
+
detect: 'detect-drift.js',
|
|
62
|
+
};
|
|
63
|
+
const subcommand = process.argv[2];
|
|
64
|
+
if (subcommand && Object.prototype.hasOwnProperty.call(SUBCOMMANDS, subcommand)) {
|
|
65
|
+
// Spawn the target bin as a child (shebang-safe, argv/stdio correct) and exit with its code.
|
|
66
|
+
const binPath = join(dirname(fileURLToPath(import.meta.url)), '..', 'bin', SUBCOMMANDS[subcommand]);
|
|
67
|
+
const r = spawnSync(process.execPath, [binPath, ...process.argv.slice(3)], { stdio: 'inherit' });
|
|
68
|
+
process.exit(r.status ?? (r.signal ? 1 : 0));
|
|
69
|
+
}
|
|
28
70
|
const db = openDb();
|
|
29
71
|
runMigrations(db);
|
|
30
72
|
// Auto-maintenance: consolidate stale memories on startup (non-blocking)
|
|
@@ -161,7 +203,7 @@ const TOOLS = [
|
|
|
161
203
|
},
|
|
162
204
|
{
|
|
163
205
|
name: 'where_am_i',
|
|
164
|
-
description: 'Locate the current topic on the Current Truth Map and report "you are here" + blast radius — the per-turn re-anchor.\n\nReturns the matching Map node(s) + journey stage (
|
|
206
|
+
description: 'Locate the current topic on the Current Truth Map and report "you are here" + blast radius — the per-turn re-anchor.\n\nReturns the matching Map node(s) + journey stage (discover → … → expand), the BLAST RADIUS (what becomes suspect if you change this — the must-stay-consistent-with / should-align-with / realizes dependents; e.g. editing the README implicates the LP), and the decision behind the node (linked anchor), if any.\n\nThree ways to call:\n• NO ARGS → auto-locates from the files you JUST edited this session (the zero-effort re-anchor — call it freely as you work).\n• query: "<topic>" → lexical locate by topic.\n• node_id: "<id>" → exact node.\n\nThis is how you avoid optimizing one node while silently breaking its neighbors (change the spec → npm/Docs/LP must move too). Matching is lexical (no embeddings).\n\nWHEN TO CALL:\n• Right after editing files — call with no args to see what you just touched + its blast radius.\n• When the topic shifts — re-anchor to the new node.\n• When the user asks "what does changing X affect?" / "where does this fit?"',
|
|
165
207
|
inputSchema: {
|
|
166
208
|
type: 'object',
|
|
167
209
|
properties: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "linksee-memory",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"mcpName": "io.github.michielinksee/linksee-memory",
|
|
5
5
|
"description": "Local-first agent memory MCP — cross-agent brain with drift detection, 6-layer structured memory + token-saving file diff cache",
|
|
6
6
|
"type": "module",
|