linksee-memory 0.15.0 → 0.15.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 +44 -4
- package/dist/lib/truth-engine.d.ts +8 -0
- package/dist/lib/truth-engine.js +10 -5
- package/dist/mcp/server.js +3 -1
- package/package.json +14 -4
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# linksee-memory
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **Claude Code forgets everything when you start a new session. Your successor knows even less.**
|
|
4
4
|
>
|
|
5
|
-
> **Linksee Memory
|
|
5
|
+
> **Linksee Memory lets you hand a project over — to your next session, to Cursor or Codex, to the person after you — with the reasons attached.** Record a decision once (`remember({ content, anchor: {} })`) and it comes back *before* the agent acts on it: re-injected on session start and ahead of every Edit / Write / Bash that touches it. Change your mind on the record and it stops nagging; leave it and it keeps the next agent from repeating last week's mistake.
|
|
6
6
|
>
|
|
7
|
-
> Underneath
|
|
7
|
+
> Underneath: **drift detection** across every project you run in parallel — which ones quietly left their goal (🔴), which were checked and hold (🔵), which nobody has looked at yet (⚫). One local SQLite file that **Claude Code, Cursor, Windsurf, OpenAI Codex and Gemini CLI** all read. Nothing leaves your machine.
|
|
8
8
|
>
|
|
9
|
-
> `npx -y linksee-memory setup` — one command,
|
|
9
|
+
> `npx -y linksee-memory setup` — one command, on in every repo.
|
|
10
10
|
|
|
11
11
|
[](https://www.npmjs.com/package/linksee-memory)
|
|
12
12
|
[](./LICENSE)
|
|
@@ -19,6 +19,46 @@
|
|
|
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. -->
|
|
21
21
|
|
|
22
|
+
## Questions this answers
|
|
23
|
+
|
|
24
|
+
These are the questions people actually type — measured, verbatim (2026-09-04). If yours is here, this is the answer.
|
|
25
|
+
|
|
26
|
+
**Claude Code forgets everything when I start a new session. How do I make it remember decisions across sessions?**
|
|
27
|
+
Run `npx -y linksee-memory setup`. Every new session opens with `recall()` — a brief of what needs attention, where you are, what's unresolved — and your locked decisions are re-injected before the agent acts. Nothing to re-explain.
|
|
28
|
+
|
|
29
|
+
**Claude Codeがセッションをまたぐと過去の経緯を忘れてしまいます。記憶を持たせる方法を教えてください。**
|
|
30
|
+
`npx -y linksee-memory setup` の一回で入ります。新しいセッションは `recall()` の brief(注意すべきこと・いまどこか・未解決)から始まり、固定した決定は行動の直前に再注入されます。説明し直す必要はありません。
|
|
31
|
+
|
|
32
|
+
**What is the best MCP server for persistent memory across AI coding agents?**
|
|
33
|
+
Honest answer: if "remember across sessions" is all you need, a `CLAUDE.md` is enough — we measured it. Linksee is for the three moments it isn't: right before a mistake, when you change your mind, and when you run many projects and need to see which one drifted.
|
|
34
|
+
|
|
35
|
+
**AIコーディングエージェント用の記憶MCPサーバーでおすすめはありますか?**
|
|
36
|
+
正直に言うと、「セッションを跨いで覚える」だけなら `CLAUDE.md` で足ります(実測しました)。Linksee が要るのは、間違いかけたとき・方針を変えたとき・並行案件のどれが外れたかを知りたいとき、の3場面です。
|
|
37
|
+
|
|
38
|
+
**I want one shared memory between Claude Code, Cursor, and OpenAI Codex. What tools exist for that?**
|
|
39
|
+
One SQLite file. Claude Code, Cursor, Windsurf, OpenAI Codex and Gemini CLI all read and write the same memory — a decision made in one shows up in the others.
|
|
40
|
+
|
|
41
|
+
**Claude CodeとCursorとCodexで同じ記憶を共有したいのですが、どうすればいいですか?**
|
|
42
|
+
SQLite ファイル1つを全員で読みます。Claude Code / Cursor / Windsurf / Codex / Gemini CLI のどこで決めた決定も、他のエージェントの行動の直前に出てきます。
|
|
43
|
+
|
|
44
|
+
**My AI agent keeps re-implementing things we already decided against. How can I detect that a codebase has drifted from past decisions?**
|
|
45
|
+
Declare the decision (`remember({ content, anchor: { violation_signal: [...] } })`). The guard then warns — or blocks, if you hardened it — the moment an edit contradicts it, and `drift_status` shows every decision that reality has quietly left.
|
|
46
|
+
|
|
47
|
+
**過去に決めた設計方針とコードがずれていないかを検出できるツールはありますか?**
|
|
48
|
+
決定を宣言しておくと(`remember({ content, anchor: {...} })`)、それに反する編集の直前に警告(hardened なら拒否)が出ます。`drift_status` は「宣言と現実がずれた決定」を証拠つきで一覧します。
|
|
49
|
+
|
|
50
|
+
**Is there a local-first, self-hosted alternative to Mem0 for agent memory?**
|
|
51
|
+
Yes. No account, no API key, no cloud — one local file, MIT licensed. `npx -y linksee-memory setup` and it's on.
|
|
52
|
+
|
|
53
|
+
**Mem0 vs Zep vs Letta for a coding agent's long-term memory — which should I pick?**
|
|
54
|
+
We installed them and ran one scenario across all of them. Storing and recalling a decision: everyone passes. The difference appears *before a mistake* and *when you change your mind* — Linksee is built for those two moments; the others leave them to you.
|
|
55
|
+
|
|
56
|
+
**How do I stop Claude Code from repeating the same mistake it made last week?**
|
|
57
|
+
Record it as a caveat (`remember({ content, layer: 'caveat' })`). Caveats are protected from forgetting and come back when the same ground is touched again — and if you anchor it, the guard stops the repeat before it lands.
|
|
58
|
+
|
|
59
|
+
**開発の意思決定履歴をMCPサーバーで残しておく定番のやり方はありますか?**
|
|
60
|
+
`remember({ content, anchor: {} })` の1回で、記録と強制が同時に入ります。`drift_status` がその台帳で、各決定が いま守られているか(🔵)・ずれているか(🔴)・誰も確かめていないか(⚫)を示します。
|
|
61
|
+
|
|
22
62
|
## 🪄 Three spells to remember
|
|
23
63
|
|
|
24
64
|
| Say this | What happens |
|
|
@@ -95,6 +95,14 @@ export type ResolutionAction = 'fix' | 'supersede' | 'acknowledge' | 'dismiss';
|
|
|
95
95
|
export interface ResolveInput {
|
|
96
96
|
/** For dismiss: silence only this match term. Omitted → silence the anchor at the gate. */
|
|
97
97
|
hit_term?: string;
|
|
98
|
+
/**
|
|
99
|
+
* For dismiss: false = close these drift edges as false positives but leave the gate
|
|
100
|
+
* watching. The default (true) also stops the gate. Two different verdicts hide behind
|
|
101
|
+
* "dismiss": "this detection was wrong" and "stop detecting this". Anchor #2 ("no destructive
|
|
102
|
+
* migrations") had a false positive from migrate.ts — the right answer was to close the edge
|
|
103
|
+
* and keep the gate, since "ALTER TABLE memories DROP" is exactly what it exists to catch.
|
|
104
|
+
*/
|
|
105
|
+
gate?: boolean;
|
|
98
106
|
anchor_id: number;
|
|
99
107
|
action: ResolutionAction;
|
|
100
108
|
rationale?: string;
|
package/dist/lib/truth-engine.js
CHANGED
|
@@ -543,12 +543,17 @@ export function resolveDrift(db, input) {
|
|
|
543
543
|
// real detections survive.
|
|
544
544
|
if (input.action === 'dismiss') {
|
|
545
545
|
db.prepare("UPDATE drift_edges SET status = 'dismissed' WHERE anchor_id = ? AND status = 'open'").run(input.anchor_id);
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
resolution.gate_dismissed = input.hit_term ? input.hit_term.toLowerCase() : 'all matches';
|
|
546
|
+
if (input.gate === false) {
|
|
547
|
+
resolution.gate_dismissed = 'none (edges closed; gate still watching)';
|
|
548
|
+
resolution.gate = false;
|
|
550
549
|
}
|
|
551
|
-
|
|
550
|
+
else
|
|
551
|
+
try {
|
|
552
|
+
db.prepare(`INSERT INTO gate_dismissals (anchor_id, hit_term, rationale) VALUES (?, ?, ?)
|
|
553
|
+
ON CONFLICT(anchor_id, COALESCE(hit_term, '')) DO UPDATE SET rationale = excluded.rationale`).run(input.anchor_id, input.hit_term ? input.hit_term.toLowerCase() : null, input.rationale ?? null);
|
|
554
|
+
resolution.gate_dismissed = input.hit_term ? input.hit_term.toLowerCase() : 'all matches';
|
|
555
|
+
}
|
|
556
|
+
catch { /* pre-v16 DB → edges-only dismiss, as before */ }
|
|
552
557
|
}
|
|
553
558
|
// If action is 'fix', mark open edges as resolved
|
|
554
559
|
if (input.action === 'fix') {
|
package/dist/mcp/server.js
CHANGED
|
@@ -280,13 +280,14 @@ const TOOLS = [
|
|
|
280
280
|
},
|
|
281
281
|
{
|
|
282
282
|
name: 'resolve_drift',
|
|
283
|
-
description: 'Record a resolution for a drifting anchor — the human feedback loop.\n\n6 actions:\n• fix — "we fixed the code/reality to match intent" → state becomes aligned\n• supersede — "intent evolved, this is the new direction" → state becomes aligned\n• acknowledge — "we know, parking it for now" → state becomes held (with optional review date)\n• dismiss — "false positive, not actually drifting" → edges dismissed AND the gate stops firing on it (
|
|
283
|
+
description: 'Record a resolution for a drifting anchor — the human feedback loop.\n\n6 actions:\n• fix — "we fixed the code/reality to match intent" → state becomes aligned\n• supersede — "intent evolved, this is the new direction" → state becomes aligned\n• acknowledge — "we know, parking it for now" → state becomes held (with optional review date)\n• dismiss — "false positive, not actually drifting" → edges dismissed AND the gate stops firing on it (hit_term: just that word; gate:false: close the edges but keep the gate watching)\n• harden — "re-injected but still violated, enforce it" → card_policy.gate_mode=hard (PreToolUse will BLOCK)\n• soften — "back off to a warning" → gate_mode=soft\n\nWHEN TO CALL:\n• After drift_status shows 🔴 drift or 🟡 review items\n• When the user says "that\'s fixed" / "ignore that" / "we changed direction"\n• When acknowledging a known gap with a review date',
|
|
284
284
|
inputSchema: {
|
|
285
285
|
type: 'object',
|
|
286
286
|
properties: {
|
|
287
287
|
anchor_id: { type: 'number', description: 'The drift_anchor ID to resolve' },
|
|
288
288
|
action: { type: 'string', enum: ['fix', 'supersede', 'acknowledge', 'dismiss', 'harden', 'soften', 'surface'], description: "Resolution action. With candidate_id (an orphaned proposal): 'surface' keeps it visible for the human, 'dismiss' retires it." },
|
|
289
289
|
candidate_id: { type: 'number', description: 'Resolve an orphaned proposal (from recall({ dream: true })) instead of an anchor: pass its candidate_id with action surface | dismiss and a rationale that references the North Star. (Absorbs resolve_proposal.)' },
|
|
290
|
+
gate: { type: 'boolean', default: true, description: "For dismiss: false = these detections were false positives, close them, but KEEP the gate watching this anchor (its signals still fire). Use when the anchor's rule is right and only this evidence was wrong — e.g. a lexical hit in a file that is not what the rule is about. Default true also silences the gate (whole anchor, or just hit_term)." },
|
|
290
291
|
rationale: { type: 'string', description: 'Why this resolution (recorded for audit trail)' },
|
|
291
292
|
review_after: { type: 'string', description: 'For acknowledge: ISO date to re-check (e.g. "2026-07-04")' },
|
|
292
293
|
superseded_by: { type: 'number', description: 'For supersede: the new anchor ID that replaces this one' },
|
|
@@ -1751,6 +1752,7 @@ function handleResolveDrift(args) {
|
|
|
1751
1752
|
review_after: args.review_after,
|
|
1752
1753
|
superseded_by: args.superseded_by,
|
|
1753
1754
|
hit_term: args.hit_term,
|
|
1755
|
+
gate: args.gate,
|
|
1754
1756
|
});
|
|
1755
1757
|
return JSON.stringify(result);
|
|
1756
1758
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "linksee-memory",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.2",
|
|
4
4
|
"mcpName": "io.github.michielinksee/linksee-memory",
|
|
5
|
-
"description": "Local-first
|
|
5
|
+
"description": "Hand a project over — to your next session, to Cursor/Codex/Gemini, to your successor — with the reasons attached. Local-first memory MCP for coding agents: decisions re-injected before the agent acts, drift detection across every project you run. One SQLite file, nothing leaves your machine.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"linksee-memory": "dist/mcp/server.js",
|
|
@@ -39,14 +39,24 @@
|
|
|
39
39
|
"mcp",
|
|
40
40
|
"model-context-protocol",
|
|
41
41
|
"memory",
|
|
42
|
-
"agent",
|
|
43
42
|
"agent-memory",
|
|
43
|
+
"persistent-memory",
|
|
44
|
+
"long-term-memory",
|
|
45
|
+
"session-memory",
|
|
46
|
+
"handover",
|
|
47
|
+
"hand-off",
|
|
48
|
+
"decision-log",
|
|
49
|
+
"drift-detection",
|
|
50
|
+
"guardrails",
|
|
44
51
|
"claude",
|
|
45
52
|
"claude-code",
|
|
46
53
|
"cursor",
|
|
54
|
+
"windsurf",
|
|
55
|
+
"codex",
|
|
56
|
+
"gemini-cli",
|
|
47
57
|
"chatgpt",
|
|
48
|
-
"sqlite",
|
|
49
58
|
"local-first",
|
|
59
|
+
"sqlite",
|
|
50
60
|
"token-savings",
|
|
51
61
|
"cross-agent"
|
|
52
62
|
],
|