linksee-memory 0.1.4 → 0.3.0

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 CHANGED
@@ -2,10 +2,74 @@
2
2
 
3
3
  > Local-first agent memory MCP. A cross-agent brain for Claude Code, Cursor, and ChatGPT Desktop — with a token-saving file diff cache that nobody else does.
4
4
  >
5
- > **v0.1.0** adds `update_memory`, `list_entities`, `match_reasons` on recall, pagination, pin-via-importance, layer aliases, consolidate dry-run, `linksee-memory-stats` CLI, and a momentum-refresh fix. See [CHANGELOG](#changelog).
5
+ > **v0.3.0** ships the **Five Blocks**: Tools + Resources + Prompts + Sampling + Roots, plus the newer **Elicitation** primitive. Most public MCP servers expose only Tools; v0.3.0 moves linksee-memory into the differentiated tier. Backward compatible — all 8 v0.2.x tools keep their signatures. See [CHANGELOG.md](./CHANGELOG.md).
6
6
 
7
7
  [![npm](https://img.shields.io/npm/v/linksee-memory.svg)](https://www.npmjs.com/package/linksee-memory)
8
8
  [![license](https://img.shields.io/npm/l/linksee-memory.svg)](./LICENSE)
9
+ [![mcp-registry](https://img.shields.io/badge/MCP-Official_Registry-6366f1)](https://registry.modelcontextprotocol.io/)
10
+ [![glama-score](https://glama.ai/mcp/servers/michielinksee/linksee-memory/badges/score.svg)](https://glama.ai/mcp/servers/michielinksee/linksee-memory)
11
+
12
+ 🌐 **Landing page**: [linksee-site.vercel.app](https://linksee-site.vercel.app) (includes non-developer onboarding for Claude Desktop / Cursor / Claude Code)
13
+
14
+ ---
15
+
16
+ ## 🎬 See it in action
17
+
18
+ **Without linksee-memory** — Monday morning, new Claude session:
19
+
20
+ ```
21
+ You: We deployed last week but it crashed. How did we fix it?
22
+ Claude: I don't have access to previous sessions. Can you describe
23
+ what happened and walk me through the problem?
24
+
25
+ [30 minutes of log-spelunking and re-explanation]
26
+ ```
27
+
28
+ **With linksee-memory** — Same question, different outcome:
29
+
30
+ ```
31
+ You: We deployed last week but it crashed. How did we fix it?
32
+ Claude: Let me check my caveats...
33
+
34
+ 🧠 [caveat] NextAuth sessions invalidate when JWT_SECRET
35
+ rotates — redeploy all affected projects in parallel.
36
+ (from session 2026-04-13, importance: 0.9)
37
+
38
+ Is this the deploy you're asking about? We hit it when
39
+ we rotated secrets mid-flow.
40
+
41
+ You: Yes, exactly. Let's not repeat that.
42
+ ```
43
+
44
+ That single `caveat` memory is what separates "flat fact storage" from "the agent actually remembers the WHY". linksee-memory stores it across **six explicit layers** so retrieval stays explainable.
45
+
46
+ ---
47
+
48
+ ## 🧠 The 6-layer structure
49
+
50
+ ```
51
+ ┌─────────────────────────────────────────────────────────────┐
52
+ │ 🎯 goal ← what the user is working toward │
53
+ ├─────────────────────────────────────────────────────────────┤
54
+ │ 🧭 context ← why this, why now — constraints, people │
55
+ ├─────────────────────────────────────────────────────────────┤
56
+ │ 💗 emotion ← user tone signals (frustration, etc.) │
57
+ ├─────────────────────────────────────────────────────────────┤
58
+ │ 🛠 implementation ← how it was done (+ what failed) │
59
+ ├─────────────────────────────────────────────────────────────┤
60
+ │ ⚠️ caveat ← "never do this again" · auto-protected │
61
+ ├─────────────────────────────────────────────────────────────┤
62
+ │ 🌱 learning ← patterns distilled from cold memories │
63
+ └─────────────────────────────────────────────────────────────┘
64
+
65
+
66
+ Ranked recall via relevance × heat × momentum × importance
67
+ Returns match_reasons explaining each hit
68
+ ```
69
+
70
+ Every memory is tagged with **exactly one layer**. `caveat`-layer entries are protected from auto-forgetting. Cold low-importance memories get compressed into `learning` entries via `consolidate()`.
71
+
72
+ ---
9
73
 
10
74
  ## What it does
11
75
 
@@ -83,18 +147,29 @@ Add to `~/.claude/settings.json` to record every Claude Code session to your loc
83
147
 
84
148
  Each turn end takes ~100 ms. Failures are silent (Claude Code never blocks). Logs at `~/.linksee-memory/hook.log`.
85
149
 
150
+ ## v0.3.0 — Five Blocks at a glance
151
+
152
+ | MCP Block | Surface |
153
+ |---|---|
154
+ | **Tools** | 8 tools (unchanged signatures since v0.2). |
155
+ | **Resources** | 4 static URIs (`memory://stats`, `memory://hot`, `memory://recent`, `memory://caveats`) + 3 templates (`memory://entity/{name}`, `memory://layer/{layer}`, `memory://memory/{id}`). Browseable via `@-mention` in clients that support it. |
156
+ | **Prompts** | 5 reusable templates: `summarize-session`, `extract-caveats`, `weekly-consolidation`, `recall-and-write`, `entity-handoff`. |
157
+ | **Sampling** *(client opt-in)* | `consolidate{use_llm:true}` asks the client LLM to rewrite consolidated cluster summaries into prose. Falls back to the heuristic when the client declines. |
158
+ | **Roots** *(client opt-in)* | `recall_file{scope_to_roots:true}` filters path matches to files inside any client-provided working root. |
159
+ | **Elicitation** *(client opt-in, newer primitive)* | `forget{interactive:true, memory_id:N}` asks the user to confirm via the client UI before deleting. |
160
+
86
161
  ## Tools
87
162
 
88
163
  | Tool | Purpose |
89
164
  |---|---|
90
165
  | `remember` | Store memory in 1 of 6 layers for an entity. Rejects pasted assistant output / CI logs unless `force=true`. Set `importance=1.0` to pin (survives auto-forget). |
91
166
  | `recall` | FTS5 + heat × momentum × importance composite ranking with `match_reasons` explaining WHY each row matched. Supports pagination (`offset`/`has_more`), `band` filter, layer aliases (`decisions`/`warnings`/`how`/...), and `mark_accessed=false` for passive previews. |
92
- | `recall_file` | Complete edit history of a file across all sessions, with per-edit user-intent context. |
167
+ | `recall_file` | Complete edit history of a file across all sessions, with per-edit user-intent context. **v0.3.0** `scope_to_roots` flag filters by client roots. |
93
168
  | `update_memory` | **v0.1.0** Atomic edit of an existing memory. Preserves `memory_id` (session_file_edits links stay intact). Prefer over forget+remember. |
94
169
  | `list_entities` | **v0.1.0** List what the memory knows about — cheapest "what do I know?" primitive. Filter by `kind`/`min_memories`; returns layer breakdown per entity. |
95
170
  | `read_smart` | Diff-only file read. Returns full content on first read, ~50 tokens on unchanged re-reads, only changed chunks on real edits. |
96
- | `forget` | Explicit delete OR auto-sweep based on `forgettingRisk`. Pinned (`importance>=1.0`) and caveat-layer memories are always preserved. |
97
- | `consolidate` | Sleep-mode compression: cluster cold low-importance memories → protected learning-layer summary. Supports `dry_run` preview. |
171
+ | `forget` | Explicit delete OR auto-sweep based on `forgettingRisk`. Pinned (`importance>=1.0`) and caveat-layer memories are always preserved. **v0.3.0** `interactive` flag asks the user via Elicitation before deleting a specific memory_id. |
172
+ | `consolidate` | Sleep-mode compression: cluster cold low-importance memories → protected learning-layer summary. Supports `dry_run` preview. **v0.3.0** `use_llm` flag asks the client LLM (Sampling) to rewrite cluster summaries into prose. |
98
173
 
99
174
  ### CLI utilities
100
175
 
@@ -287,6 +362,76 @@ consolidate({ scope: "all", min_age_days: 7 })
287
362
  Caveat and active-goal layers are always preserved. Consider scheduling a weekly run via cron / Task Scheduler.
288
363
  </details>
289
364
 
365
+ ## FAQ
366
+
367
+ <details>
368
+ <summary><strong>How is this different from Mem0 / Letta / Zep?</strong></summary>
369
+
370
+ Three axes:
371
+ 1. **Local-first**: those tools require cloud accounts and send your data to their servers. linksee-memory runs entirely on your machine — one SQLite file, no network calls by default.
372
+ 2. **WHY-layered**: they store flat facts or knowledge-graph nodes. linksee-memory has 6 explicit layers (`goal`/`context`/`emotion`/`implementation`/`caveat`/`learning`) so retrieval returns structured reasoning, not just data.
373
+ 3. **File diff cache**: `read_smart` tool saves 86–99% of tokens on file re-reads via AST-aware chunking. None of the memory services do this — it's a feature usually shipped in IDEs.
374
+ </details>
375
+
376
+ <details>
377
+ <summary><strong>Why not just use Claude's built-in auto-memory?</strong></summary>
378
+
379
+ Claude Code's auto-memory is Claude-only (doesn't help if you switch to Cursor or ChatGPT Desktop) and stores flat markdown with no structure. linksee-memory is the same local-first principle but:
380
+ - Works across Claude Code, Cursor, ChatGPT Desktop (shared SQLite)
381
+ - Structured 6-layer format makes recall explainable
382
+ - Provides explicit forget/consolidate primitives rather than the agent guessing
383
+ </details>
384
+
385
+ <details>
386
+ <summary><strong>Is 86% token savings real? Where does it come from?</strong></summary>
387
+
388
+ Yes — see `tools/bench-read-smart.ts` in the repo. The `read_smart` tool:
389
+ 1. Hashes file content on first read, returns full content + chunk metadata (AST/heading/indent boundaries).
390
+ 2. On re-read with unchanged mtime+sha256, returns `~50 tokens` of "unchanged" confirmation instead of re-sending the file.
391
+ 3. On real edits, returns only the changed chunks as full content + unchanged chunks as metadata-only references.
392
+
393
+ For a typical TypeScript file edit in an agentic loop, this cuts round-trip token costs by ~86%. On pure re-reads (user navigating back to a previously-read file), savings exceed 99%.
394
+ </details>
395
+
396
+ <details>
397
+ <summary><strong>Does "local-first" mean no way to sync across my machines?</strong></summary>
398
+
399
+ The default is no sync — the SQLite file lives at `~/.linksee-memory/memory.db` and stays there. If you want multi-machine sync, put that directory under Syncthing / iCloud Drive / Dropbox / Google Drive — it's a single file, so any file-sync tool works. (Avoid simultaneous edits from two machines while the MCP server is running on both; SQLite's WAL mode handles single-writer well but multi-writer conflicts can corrupt.)
400
+ </details>
401
+
402
+ <details>
403
+ <summary><strong>What happens when the DB gets huge?</strong></summary>
404
+
405
+ Two mechanisms:
406
+ 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.
407
+ 2. **`consolidate()`**: compresses clusters of cold low-importance memories by entity into a single `learning`-layer summary, then deletes the originals. Run via `linksee-memory-consolidate` CLI (or schedule weekly).
408
+
409
+ 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.
410
+ </details>
411
+
412
+ <details>
413
+ <summary><strong>Can I use this without Claude Code?</strong></summary>
414
+
415
+ Yes — any MCP-compatible client works:
416
+ - **Claude Code**: `claude mcp add -s user linksee -- npx -y linksee-memory`
417
+ - **Claude Desktop**: add to `claude_desktop_config.json` (see [onboarding on the LP](https://linksee-site.vercel.app))
418
+ - **Cursor**: add to MCP settings in Cursor
419
+ - **ChatGPT Desktop**: same pattern once MCP support ships
420
+ - **Custom agent**: the MCP stdio protocol is documented at modelcontextprotocol.io
421
+ </details>
422
+
423
+ <details>
424
+ <summary><strong>What telemetry does it send?</strong></summary>
425
+
426
+ **By default: zero network calls, zero telemetry.** There's an optional Level-1 telemetry mode you can enable that sends anonymized aggregate metrics (tool call counts, error rates, latency percentiles — never memory content, never file paths, never queries). The exact payload schema is documented in the [Telemetry section](#telemetry-opt-in-off-by-default) and you see every byte before opting in.
427
+ </details>
428
+
429
+ <details>
430
+ <summary><strong>How do I verify it's actually working?</strong></summary>
431
+
432
+ After install, in a new Claude session ask: *"Can you remember that I prefer TypeScript over JavaScript?"* Claude should confirm it called `mcp__linksee__remember` and stored this. Then in a **different session** ask: *"What languages do I prefer?"* It should recall via `mcp__linksee__recall` and return the preference with `match_reasons` showing why.
433
+ </details>
434
+
290
435
  ## Support
291
436
 
292
437
  - **Issues & bug reports**: [github.com/michielinksee/linksee-memory/issues](https://github.com/michielinksee/linksee-memory/issues)
@@ -296,6 +441,19 @@ Caveat and active-goal layers are always preserved. Consider scheduling a weekly
296
441
 
297
442
  ## Changelog
298
443
 
444
+ ### v0.2.0 — English-first launch readiness (2026-04-20)
445
+
446
+ Prepares the package for a broader (primarily English-speaking) audience on Reddit, Hacker News, and Anthropic Discord. No breaking API changes.
447
+
448
+ - **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.
449
+ - **Install-skill CLI output is bilingual**: example test phrases shown after installation include both English and Japanese.
450
+ - **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`.
451
+ - **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.
452
+ - **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.
453
+ - Internal: SKILL.md now documents pairing with KanseiLink skill as an English workflow example.
454
+
455
+ No code changes to the MCP protocol surface; all existing MCP clients continue to work unchanged.
456
+
299
457
  ### v0.1.1 — Pin threshold tweak (2026-04-19)
300
458
 
301
459
  Based on real-world feedback that `importance=0.95` memories were not
@@ -8,8 +8,9 @@
8
8
  // npx linksee-memory-install-skill --dry-run (show what would happen)
9
9
  //
10
10
  // Why: installing the MCP server alone doesn't teach Claude Code WHEN to call
11
- // recall/remember/read_smart/etc. The skill provides trigger phrases ("前に...",
12
- // "また同じエラー", new task start, file edits, etc.) so the agent auto-fires
11
+ // recall/remember/read_smart/etc. The skill provides trigger phrases (EN:
12
+ // "before", "last time", "same error again"; JP: "前に", "また同じエラー";
13
+ // new task start, file edits, etc.) so the agent auto-fires
13
14
  // without the user having to type "use linksee-memory".
14
15
  import { mkdirSync, existsSync, copyFileSync, readFileSync } from 'node:fs';
15
16
  import { join, dirname } from 'node:path';
@@ -85,9 +86,12 @@ console.log('');
85
86
  console.log(' 2. Restart Claude Code (the skill auto-loads on next turn).');
86
87
  console.log('');
87
88
  console.log(' 3. Test by saying something like:');
88
- console.log(' "前にこの問題どう解決したっけ"');
89
- console.log(' "また同じエラーが出た"');
90
- console.log(' "覚えておいて: ..."');
89
+ console.log(' "How did we solve this before?"');
90
+ console.log(' "Same error again"');
91
+ console.log(' "Remember: I prefer TypeScript over JavaScript"');
92
+ console.log(' or in Japanese:');
93
+ console.log(' 「前にこの問題どう解決したっけ」');
94
+ console.log(' 「覚えておいて: ...」');
91
95
  console.log('');
92
96
  console.log('The skill will trigger and call recall/remember automatically.');
93
97
  //# sourceMappingURL=install-skill.js.map
@@ -25,11 +25,11 @@ function findFirstIntent(session) {
25
25
  // ============================================================
26
26
  const DECISION_PATTERNS = [
27
27
  /決めた|採用|確定|これで(いい|進め)|OK進めて|やろう|行こう/,
28
- /learn(ed)?|decide|chose|picked|going with/i,
28
+ /learn(ed)?|decid(?:e|ed|ing)|chose|picked|going with|let'?s\s+go|pivot(?:ing|ed)?|switch(?:ing)?\s+to|settled\s+on|approved|we'?ll\s+use|commit(?:ting)?\s+to/i,
29
29
  ];
30
30
  const FAILURE_PATTERNS = [
31
- /失敗|バグ|エラー|直して|修正|戻して/,
32
- /error|bug|fail|broken|revert|rollback/i,
31
+ /失敗|バグ|エラー|直して|修正|戻して|うまくいかない|ハマった/,
32
+ /error|bug|fail(?:ed|ing|ure)?|broken|broke|revert|rollback|doesn'?t\s+work|not\s+working|stuck|same\s+error\s+again|hit\s+(?:an?\s+|the\s+)?(?:error|bug|issue)|debug/i,
33
33
  ];
34
34
  // Caveats must be EXPLICIT warnings/prohibitions the user wants preserved.
35
35
  // Previous bare patterns (/注意/ /やらない/ /避けて/) caught descriptive usage
@@ -0,0 +1,24 @@
1
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ interface ElicitResult {
3
+ action: 'accept' | 'decline' | 'cancel' | 'unsupported';
4
+ content?: Record<string, unknown>;
5
+ reason?: string;
6
+ }
7
+ interface ElicitParams {
8
+ message: string;
9
+ requestedSchema: {
10
+ type: 'object';
11
+ properties: Record<string, unknown>;
12
+ required?: string[];
13
+ };
14
+ }
15
+ export declare function elicit(server: Server, p: ElicitParams): Promise<ElicitResult>;
16
+ export declare function confirmForget(server: Server, candidate: {
17
+ id: number;
18
+ entity: string;
19
+ layer: string;
20
+ importance: number;
21
+ preview: string;
22
+ }): Promise<boolean>;
23
+ export declare function confirmPin(server: Server, memoryId: number, preview: string, newImportance: number): Promise<boolean>;
24
+ export {};
@@ -0,0 +1,58 @@
1
+ // Elicitation block — server asks the client (and ultimately the user) a structured question.
2
+ //
3
+ // MCP semantics: server.request({method: 'elicitation/create', params: {message, requestedSchema}})
4
+ // The user responds via the client UI. Used by:
5
+ // - Stale-memory cleanup (forget candidates require confirmation)
6
+ // - Pin/unpin confirmation when importance crosses 0.9
7
+ //
8
+ // Clients without elicitation support fail gracefully — caller falls back to "decline = skip".
9
+ import { ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js';
10
+ export async function elicit(server, p) {
11
+ try {
12
+ const res = await server.request({ method: 'elicitation/create', params: p }, ElicitRequestSchema);
13
+ return {
14
+ action: res?.action ?? 'decline',
15
+ content: res?.content,
16
+ };
17
+ }
18
+ catch (err) {
19
+ return { action: 'unsupported', reason: err?.message ?? String(err) };
20
+ }
21
+ }
22
+ export async function confirmForget(server, candidate) {
23
+ const res = await elicit(server, {
24
+ message: `Forget memory #${candidate.id} for "${candidate.entity}"?\n\nLayer: ${candidate.layer} Importance: ${candidate.importance.toFixed(2)}\nPreview: ${candidate.preview.slice(0, 200)}`,
25
+ requestedSchema: {
26
+ type: 'object',
27
+ properties: {
28
+ confirm: {
29
+ type: 'boolean',
30
+ title: 'Forget this memory',
31
+ description: 'Yes = delete permanently. No = keep.',
32
+ },
33
+ },
34
+ required: ['confirm'],
35
+ },
36
+ });
37
+ if (res.action === 'accept' && res.content && typeof res.content.confirm === 'boolean') {
38
+ return res.content.confirm;
39
+ }
40
+ return false;
41
+ }
42
+ export async function confirmPin(server, memoryId, preview, newImportance) {
43
+ const res = await elicit(server, {
44
+ message: `Pin memory #${memoryId}? (importance ${newImportance.toFixed(2)})\n\nPreview: ${preview.slice(0, 200)}\n\nPinned memories survive forget-sweeps and consolidation.`,
45
+ requestedSchema: {
46
+ type: 'object',
47
+ properties: {
48
+ confirm: { type: 'boolean', title: 'Pin this memory', description: 'Yes = pin. No = save without pinning.' },
49
+ },
50
+ required: ['confirm'],
51
+ },
52
+ });
53
+ if (res.action === 'accept' && res.content && typeof res.content.confirm === 'boolean') {
54
+ return res.content.confirm;
55
+ }
56
+ return false;
57
+ }
58
+ //# sourceMappingURL=elicitation.js.map
@@ -0,0 +1,21 @@
1
+ export declare const PROMPTS: {
2
+ name: string;
3
+ description: string;
4
+ arguments: {
5
+ name: string;
6
+ description: string;
7
+ required: boolean;
8
+ }[];
9
+ }[];
10
+ interface PromptMessage {
11
+ role: 'user' | 'assistant';
12
+ content: {
13
+ type: 'text';
14
+ text: string;
15
+ };
16
+ }
17
+ export declare function getPrompt(name: string, args: Record<string, string> | undefined): {
18
+ description?: string;
19
+ messages: PromptMessage[];
20
+ };
21
+ export {};
@@ -0,0 +1,201 @@
1
+ // Prompts block — reusable prompt templates that agents can pull from the server.
2
+ //
3
+ // Templates:
4
+ // summarize-session — turn a chat transcript into structured memories (1 per layer)
5
+ // extract-caveats — read text and produce caveat-layer entries (pain lessons)
6
+ // weekly-consolidation — sleep-mode summary of the past week's memories
7
+ // recall-and-write — recall first, then write — anti-pattern guard
8
+ // entity-handoff — produce a handoff doc for an entity (name + memories + next steps)
9
+ //
10
+ // Each prompt accepts arguments and returns a list of messages the client can feed to its LLM.
11
+ export const PROMPTS = [
12
+ {
13
+ name: 'summarize-session',
14
+ description: 'Turn a chat session transcript into structured memories. Produces up to 6 memories (one per layer) capturing goal/context/emotion/implementation/caveat/learning. Use at session end.',
15
+ arguments: [
16
+ { name: 'transcript', description: 'The session transcript text. Free-form.', required: true },
17
+ { name: 'entity_hint', description: 'Optional canonical entity name to attach the memories to.', required: false },
18
+ ],
19
+ },
20
+ {
21
+ name: 'extract-caveats',
22
+ description: 'Scan a body of text (post-mortem, error log, decision doc) and propose caveat-layer memories — concise pain lessons starting with verbs ("Never", "Always", "Watch out"). Returns JSON list of caveats.',
23
+ arguments: [
24
+ { name: 'text', description: 'Source text (post-mortem, debug session, retro). Free-form.', required: true },
25
+ { name: 'entity_hint', description: 'Optional canonical entity name for the caveats.', required: false },
26
+ ],
27
+ },
28
+ {
29
+ name: 'weekly-consolidation',
30
+ description: 'Sleep-mode summary of the past week\'s memories for an entity. Produces a single learning-layer entry that captures the trajectory. Use as input to the consolidate tool, or to write a Friday digest.',
31
+ arguments: [
32
+ { name: 'entity_name', description: 'The entity to consolidate.', required: true },
33
+ { name: 'week_offset', description: 'Weeks-ago offset (0 = this week, 1 = last week). Default 0.', required: false },
34
+ ],
35
+ },
36
+ {
37
+ name: 'recall-and-write',
38
+ description: 'Anti-pattern guard. Before writing code, draft a doc, or making a decision: recall relevant memories first, then produce the answer with explicit citations to the recalled memory_ids. Forces "memory before action" discipline.',
39
+ arguments: [
40
+ { name: 'task', description: 'What you are about to do (code task, decision, doc draft). One sentence.', required: true },
41
+ { name: 'entity_hint', description: 'Optional entity to focus recall on.', required: false },
42
+ ],
43
+ },
44
+ {
45
+ name: 'entity-handoff',
46
+ description: 'Produce a handoff document for an entity: name, kind, key memories per layer, current open questions, and next steps. Use when transferring context to a new session, a new agent, or a new collaborator.',
47
+ arguments: [
48
+ { name: 'entity_name', description: 'The entity to hand off.', required: true },
49
+ { name: 'audience', description: 'Who receives the handoff (e.g. "new claude session", "human teammate"). Default "new claude session".', required: false },
50
+ ],
51
+ },
52
+ ];
53
+ export function getPrompt(name, args) {
54
+ const a = args ?? {};
55
+ switch (name) {
56
+ case 'summarize-session': {
57
+ const transcript = a.transcript ?? '';
58
+ const entityHint = a.entity_hint ? `\n\nFocus entity: ${a.entity_hint}` : '';
59
+ return {
60
+ description: 'Summarize the session into 6-layer structured memories.',
61
+ messages: [
62
+ {
63
+ role: 'user',
64
+ content: {
65
+ type: 'text',
66
+ text: `You are an agent-memory writer. Read the session transcript below and propose memories to save. Output a JSON array; each item has {entity_name, entity_kind, layer, content, importance}.
67
+
68
+ Layers (use exactly one per memory):
69
+ - goal: WHY this work exists, target outcome
70
+ - context: WHY THIS NOW, situation, timing
71
+ - emotion: USER tone, feelings expressed
72
+ - implementation: HOW it was done, what worked, what failed
73
+ - caveat: PAIN lesson, "never X" / "always Y" — these are protected from forgetting
74
+ - learning: GROWTH, decisions made, insights
75
+
76
+ Rules:
77
+ - Max 6 entries (one per layer). Skip layers with nothing worth saving.
78
+ - Importance 0-1. Set 0.9+ to pin (use sparingly).
79
+ - Caveats must be 1 sentence and start with a verb.
80
+ - Quote nothing verbatim; summarize.
81
+
82
+ Transcript:
83
+ ${transcript}${entityHint}`,
84
+ },
85
+ },
86
+ ],
87
+ };
88
+ }
89
+ case 'extract-caveats': {
90
+ const text = a.text ?? '';
91
+ const entityHint = a.entity_hint ? `\n\nFocus entity: ${a.entity_hint}` : '';
92
+ return {
93
+ description: 'Extract caveat-layer pain lessons.',
94
+ messages: [
95
+ {
96
+ role: 'user',
97
+ content: {
98
+ type: 'text',
99
+ text: `You are a caveat extractor. Read the source text below and output a JSON list of caveats. Each caveat:
100
+ - Starts with a verb ("Never", "Always", "Watch out", "Reject", "Confirm")
101
+ - Is one sentence
102
+ - Is concrete (a specific failure mode, not abstract advice)
103
+ - Captures something the reader does NOT want to relearn the hard way
104
+
105
+ Output format: [{"content": "Never X when Y, because Z", "importance": 0.7-1.0}]
106
+
107
+ Source text:
108
+ ${text}${entityHint}`,
109
+ },
110
+ },
111
+ ],
112
+ };
113
+ }
114
+ case 'weekly-consolidation': {
115
+ const entityName = a.entity_name ?? '<entity>';
116
+ const weekOffset = a.week_offset ?? '0';
117
+ return {
118
+ description: `Consolidate the last week of memories for ${entityName}.`,
119
+ messages: [
120
+ {
121
+ role: 'user',
122
+ content: {
123
+ type: 'text',
124
+ text: `Consolidate the past week's memories for entity "${entityName}" (week_offset=${weekOffset}).
125
+
126
+ Step 1: Call recall(query="${entityName}", entity_name="${entityName}", max_tokens=4000) to retrieve recent memories.
127
+ Step 2: Read the returned memories and produce ONE learning-layer summary that captures:
128
+ - What we set out to do (goal trajectory)
129
+ - What actually happened (implementation summary)
130
+ - What we learned (1-3 insights)
131
+ - Any caveats we should never forget (preserve these — do NOT consolidate them away)
132
+
133
+ Step 3: Output a JSON object {entity_name, layer:"learning", content, importance:0.7}.
134
+
135
+ Do not write to memory directly — just return the JSON. The user will choose whether to save.`,
136
+ },
137
+ },
138
+ ],
139
+ };
140
+ }
141
+ case 'recall-and-write': {
142
+ const task = a.task ?? '<task>';
143
+ const entityHint = a.entity_hint ?? '';
144
+ const recallCmd = entityHint
145
+ ? `recall(query="${task}", entity_name="${entityHint}", max_tokens=2000)`
146
+ : `recall(query="${task}", max_tokens=2000)`;
147
+ return {
148
+ description: 'Memory-before-action discipline.',
149
+ messages: [
150
+ {
151
+ role: 'user',
152
+ content: {
153
+ type: 'text',
154
+ text: `Before doing this task, recall first.
155
+
156
+ Task: ${task}
157
+
158
+ Step 1: Call ${recallCmd}.
159
+ Step 2: Skim the returned memories. Identify any caveats that apply.
160
+ Step 3: Produce your output with INLINE citations to relevant memory_ids: e.g. "Use better-sqlite3 v12+ [memory:1234] because v11 breaks on Node 24 [memory:5678]."
161
+ Step 4: If you found NO relevant memories, say so explicitly: "No prior memories on this — proceeding from first principles."
162
+
163
+ Goal: never solve a problem twice without checking.`,
164
+ },
165
+ },
166
+ ],
167
+ };
168
+ }
169
+ case 'entity-handoff': {
170
+ const entityName = a.entity_name ?? '<entity>';
171
+ const audience = a.audience ?? 'new claude session';
172
+ return {
173
+ description: `Produce a handoff document for ${entityName}.`,
174
+ messages: [
175
+ {
176
+ role: 'user',
177
+ content: {
178
+ type: 'text',
179
+ text: `Produce a handoff document for entity "${entityName}", aimed at: ${audience}.
180
+
181
+ Step 1: Call recall(query="${entityName}", entity_name="${entityName}", max_tokens=6000).
182
+ Step 2: Skim memories grouped by layer.
183
+ Step 3: Output a markdown doc with these sections:
184
+ - **Identity**: name, kind, canonical key (if any)
185
+ - **Goal** (from goal-layer memories): what this entity is for
186
+ - **State** (from latest implementation memories): where things stand right now
187
+ - **Caveats** (from caveat-layer memories): what NEVER to do, with memory_id citations
188
+ - **Open questions**: things the prior session left unresolved
189
+ - **Suggested next steps**: 3 concrete actions for the audience
190
+
191
+ Keep it under 1 page. Cite memory_ids inline like [memory:1234].`,
192
+ },
193
+ },
194
+ ],
195
+ };
196
+ }
197
+ default:
198
+ throw new Error(`unknown prompt: ${name}`);
199
+ }
200
+ }
201
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1,18 @@
1
+ import type Database from 'better-sqlite3';
2
+ export declare const STATIC_RESOURCES: {
3
+ uri: string;
4
+ name: string;
5
+ description: string;
6
+ mimeType: string;
7
+ }[];
8
+ export declare const RESOURCE_TEMPLATES: {
9
+ uriTemplate: string;
10
+ name: string;
11
+ description: string;
12
+ mimeType: string;
13
+ }[];
14
+ export declare function readResource(db: Database.Database, uri: string): {
15
+ uri: string;
16
+ mimeType: string;
17
+ text: string;
18
+ };