memento-mcp 0.3.17 → 0.3.18

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memento-mcp",
3
- "version": "0.3.17",
3
+ "version": "0.3.18",
4
4
  "mcpName": "io.github.myrakrusemark/memento-protocol",
5
5
  "description": "The Memento Protocol — persistent memory for AI agents",
6
6
  "type": "module",
@@ -0,0 +1,55 @@
1
+ #!/bin/bash
2
+ # SessionStart hook (Memento) — inject MCP tool reference into every session.
3
+ # Independent of identity/items injection — always runs.
4
+ # Output: JSON with hookSpecificOutput.additionalContext.
5
+
6
+ # Consume stdin (SessionStart sends JSON we don't need)
7
+ cat > /dev/null
8
+
9
+ read -r -d '' INSTRUCTIONS << 'MEMENTO_EOF'
10
+ # Memento MCP (`mcp__memento__*`)
11
+
12
+ **Load tools:** `ToolSearch query="+memento" max_results=20` — then READ the tool descriptions. They explain when and how to use each one.
13
+
14
+ **Primary system:** Memento SaaS API (`https://memento-api.myrakrusemark.workers.dev`)
15
+ **Dashboard:** `hifathom.com/dashboard`
16
+
17
+ | Tool | What it does |
18
+ |------|-------------|
19
+ | `memento_init` | Initialize workspace (one-time setup) |
20
+ | `memento_health` | System health — item/memory/skip counts, last updated |
21
+ | `memento_read` / `memento_update` | Legacy markdown working memory (sections: active_work, standing_decisions, skip_list, session_notes) |
22
+ | `memento_remember` | Store a memory (fact/decision/observation/instruction) with tags + expiration |
23
+ | `memento_recall` | Search memories by keyword/tag/type — ranked by relevance |
24
+ | `memento_consolidate` | Merge 3+ overlapping memories into one sharper representation |
25
+ | `memento_skip_add` / `memento_skip_check` | Anti-memory: things to NOT investigate right now (with expiration) |
26
+ | `memento_item_create` | Create structured item (active_work/standing_decision/skip_list/waiting_for/session_note) |
27
+ | `memento_item_update` | Update item fields (status, next_action, priority, category, tags) |
28
+ | `memento_item_delete` | Delete item (prefer archiving via status=archived) |
29
+ | `memento_item_list` | List items with filters (category, status, query) |
30
+ | `memento_identity` | Read identity crystal |
31
+ | `memento_identity_update` | Write/replace identity crystal |
32
+
33
+ **Memory discipline — notes are instructions, not logs.**
34
+ Write: "Skip X until condition Y" — not "checked X, it was quiet."
35
+ Every memory must answer: could a future agent with zero context read this and know exactly what to do?
36
+
37
+ Use `memento_remember` when you learn something worth keeping.
38
+ Use `memento_skip_add` for things to explicitly not re-investigate.
39
+ Use `memento_recall` to search memories by keyword or tag.
40
+ Hooks run automatically — recall before responses, distillation before compaction. Trust the hooks. Focus on writing good memories.
41
+
42
+ REMINDER: If Memento MCP tools are not loaded, run: ToolSearch query="+memento" max_results=20
43
+ MEMENTO_EOF
44
+
45
+ python3 -c "
46
+ import json, sys
47
+ print(json.dumps({
48
+ 'hookSpecificOutput': {
49
+ 'hookEventName': 'SessionStart',
50
+ 'additionalContext': sys.argv[1]
51
+ }
52
+ }))
53
+ " "$INSTRUCTIONS"
54
+
55
+ exit 0
package/src/cli.js CHANGED
@@ -92,51 +92,6 @@ function httpsPost(url, body) {
92
92
  });
93
93
  }
94
94
 
95
- // ---------------------------------------------------------------------------
96
- // Instructions blob — appended to CLAUDE.md during init
97
- // ---------------------------------------------------------------------------
98
-
99
- const INSTRUCTIONS_BLOB = `## Memento Protocol
100
-
101
- Working memory is managed by Memento. MCP tools available:
102
- \`memento_remember\`, \`memento_recall\`, \`memento_item_list\`,
103
- \`memento_skip_add\`, \`memento_skip_check\`.
104
-
105
- **Memory discipline — notes are instructions, not logs.**
106
- Write: "Skip X until condition Y" — not "checked X, it was quiet."
107
- Every memory must answer: could a future agent with zero context
108
- read this and know exactly what to do?
109
-
110
- Use \`memento_remember\` when you learn something worth keeping.
111
- Use \`memento_skip_add\` for things to explicitly not re-investigate.
112
- Use \`memento_recall\` to search memories by keyword or tag.
113
- Hooks run automatically — recall before responses, distillation
114
- before compaction. Trust the hooks. Focus on writing good memories.`;
115
-
116
- // ---------------------------------------------------------------------------
117
- // CLAUDE.md integration
118
- // ---------------------------------------------------------------------------
119
-
120
- function appendToClaudeMd(cwd, sectionHeading, blob) {
121
- const mdPath = path.join(cwd, "CLAUDE.md");
122
- let content = "";
123
- try { content = fs.readFileSync(mdPath, "utf-8"); } catch { /* new file */ }
124
-
125
- const headingEscaped = sectionHeading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
126
- const sectionRe = new RegExp(
127
- `(^|\\n)(#{1,3} ${headingEscaped}[^\\n]*\\n)([\\s\\S]*?)(?=\\n#{1,3} |$)`,
128
- );
129
-
130
- if (sectionRe.test(content)) {
131
- content = content.replace(sectionRe, `$1${blob}`);
132
- } else {
133
- content = content.trimEnd() + "\n\n" + blob + "\n";
134
- }
135
-
136
- fs.writeFileSync(mdPath, content, "utf-8");
137
- return mdPath;
138
- }
139
-
140
95
  // ---------------------------------------------------------------------------
141
96
  // CLI flag parsing
142
97
  // ---------------------------------------------------------------------------
@@ -474,11 +429,9 @@ async function runInit(flags = {}) {
474
429
  writeJsonFile(configPath, config);
475
430
  created.push(".memento.json");
476
431
 
477
- // 7. Copy hook scripts — gated on any hook-supporting agent
478
- const anyHookEnabled =
479
- enableUserPrompt || enableStop || enablePreCompact || enableSessionStart;
480
-
481
- if (hasHookAgent && anyHookEnabled) {
432
+ // 7. Copy hook scripts — gated on hook-supporting agent
433
+ // Instructions script is always copied; other hooks are gated on user selection
434
+ if (hasHookAgent) {
482
435
  const pkgScriptsDir = path.resolve(__dirname, "..", "scripts");
483
436
  const localScriptsDir = path.join(cwd, ".memento", "scripts");
484
437
  if (!fs.existsSync(localScriptsDir))
@@ -486,6 +439,7 @@ async function runInit(flags = {}) {
486
439
 
487
440
  const scriptFiles = [
488
441
  "hook-toast.sh",
442
+ "memento-instructions.sh",
489
443
  enableUserPrompt && "memento-userprompt-recall.sh",
490
444
  enableStop && "memento-stop-recall.sh",
491
445
  enablePreCompact && "memento-precompact-distill.sh",
@@ -508,6 +462,7 @@ async function runInit(flags = {}) {
508
462
  fs.writeFileSync(versionPath, pkgVersion + "\n");
509
463
 
510
464
  // Hook script commands (absolute paths)
465
+ const instructionsCmd = path.join(localScriptsDir, "memento-instructions.sh");
511
466
  const recallCmd = path.join(localScriptsDir, "memento-userprompt-recall.sh");
512
467
  const stopCmd = path.join(localScriptsDir, "memento-stop-recall.sh");
513
468
  const precompactCmd = path.join(localScriptsDir, "memento-precompact-distill.sh");
@@ -518,6 +473,8 @@ async function runInit(flags = {}) {
518
473
  const settingsPath = path.join(cwd, ".claude", "settings.local.json");
519
474
  const settings = readJsonFile(settingsPath) || {};
520
475
  let changed = false;
476
+ // Instructions hook always registered (not gated by enableSessionStart)
477
+ changed = ensureHook(settings, "SessionStart", instructionsCmd, 5000) || changed;
521
478
  if (enableUserPrompt) changed = ensureHook(settings, "UserPromptSubmit", recallCmd, 5000) || changed;
522
479
  if (enableStop) changed = ensureHook(settings, "Stop", stopCmd, 5000) || changed;
523
480
  if (enablePreCompact) changed = ensureHook(settings, "PreCompact", precompactCmd, 30000) || changed;
@@ -533,6 +490,8 @@ async function runInit(flags = {}) {
533
490
  const settingsPath = path.join(cwd, ".gemini", "settings.json");
534
491
  const settings = readJsonFile(settingsPath) || {};
535
492
  let changed = false;
493
+ // Instructions hook always registered
494
+ changed = ensureHook(settings, "SessionStart", instructionsCmd, 5000) || changed;
536
495
  if (enableUserPrompt) changed = ensureHook(settings, "BeforeAgent", recallCmd, 5000) || changed;
537
496
  if (enableStop) changed = ensureHook(settings, "SessionEnd", stopCmd, 5000) || changed;
538
497
  if (enablePreCompact) changed = ensureHook(settings, "PreCompress", precompactCmd, 30000) || changed;
@@ -592,27 +551,6 @@ async function runInit(flags = {}) {
592
551
  console.log(` Non-interactive equivalent:\n ${parts.join(" ")}\n`);
593
552
  }
594
553
 
595
- // 12. Append instructions to CLAUDE.md
596
- if (nonInteractive) {
597
- const mdPath = appendToClaudeMd(cwd, "Memento Protocol", INSTRUCTIONS_BLOB);
598
- console.log(`\n ✓ Instructions written to ${path.relative(cwd, mdPath)}\n`);
599
- } else {
600
- const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
601
- console.log("─".repeat(60));
602
- const integrate = await askYesNo(
603
- rl2,
604
- "\n Append Memento instructions to CLAUDE.md?",
605
- true,
606
- );
607
- rl2.close();
608
-
609
- if (integrate) {
610
- const mdPath = appendToClaudeMd(cwd, "Memento Protocol", INSTRUCTIONS_BLOB);
611
- console.log(`\n ✓ Instructions written to ${path.relative(cwd, mdPath)}\n`);
612
- } else {
613
- printInstructionsFallback(selectedAgents);
614
- }
615
- }
616
554
  }
617
555
 
618
556
  // ---------------------------------------------------------------------------
@@ -659,10 +597,11 @@ async function runUpdate() {
659
597
  const versionPath = path.join(cwd, ".memento", "version");
660
598
  fs.writeFileSync(versionPath, pkgVersion + "\n");
661
599
 
662
- // Ensure SessionStart hook is registered for agents that support hooks
600
+ // Ensure SessionStart hooks are registered for agents that support hooks
663
601
  // Detect by config agents field or directory presence (older configs may lack agents)
664
602
  const config = readJsonFile(configPath) || {};
665
603
  const agents = config.agents || [];
604
+ const instructionsCmd = path.join(localScriptsDir, "memento-instructions.sh");
666
605
  const sessionStartCmd = path.join(localScriptsDir, "memento-sessionstart-identity.sh");
667
606
  const registeredHooks = [];
668
607
 
@@ -672,7 +611,9 @@ async function runUpdate() {
672
611
  if (hasClaude) {
673
612
  const settingsPath = path.join(cwd, ".claude", "settings.local.json");
674
613
  const settings = readJsonFile(settingsPath) || {};
675
- if (ensureHook(settings, "SessionStart", sessionStartCmd, 10000)) {
614
+ let changed = ensureHook(settings, "SessionStart", instructionsCmd, 5000);
615
+ changed = ensureHook(settings, "SessionStart", sessionStartCmd, 10000) || changed;
616
+ if (changed) {
676
617
  writeJsonFile(settingsPath, settings);
677
618
  registeredHooks.push("Claude Code → .claude/settings.local.json");
678
619
  }
@@ -684,7 +625,9 @@ async function runUpdate() {
684
625
  if (hasGemini) {
685
626
  const settingsPath = path.join(cwd, ".gemini", "settings.json");
686
627
  const settings = readJsonFile(settingsPath) || {};
687
- if (ensureHook(settings, "SessionStart", sessionStartCmd, 10000)) {
628
+ let changed = ensureHook(settings, "SessionStart", instructionsCmd, 5000);
629
+ changed = ensureHook(settings, "SessionStart", sessionStartCmd, 10000) || changed;
630
+ if (changed) {
688
631
  writeJsonFile(settingsPath, settings);
689
632
  registeredHooks.push("Gemini CLI → .gemini/settings.json");
690
633
  }
@@ -705,26 +648,6 @@ async function runUpdate() {
705
648
  console.log(" Restart your agent session to pick up changes.\n");
706
649
  }
707
650
 
708
- function printInstructionsFallback(selectedAgents) {
709
- const hasNonClaude = selectedAgents.some((k) => k !== "claude-code");
710
- const docTarget = hasNonClaude
711
- ? "your CLAUDE.md, AGENTS.md, or equivalent"
712
- : "your CLAUDE.md";
713
-
714
- console.log("─".repeat(60));
715
- console.log(`
716
- One more step: paste the following into ${docTarget},
717
- or hand it to your agent and ask it to add it. This teaches
718
- your agent the memory discipline Memento expects.
719
-
720
- ── paste below this line ──────────────────────────────
721
-
722
- ${INSTRUCTIONS_BLOB}
723
-
724
- ── paste above this line ──────────────────────────────
725
- `);
726
- }
727
-
728
651
  // ---------------------------------------------------------------------------
729
652
  // Entrypoint — only run when this module is the entry point (not imported)
730
653
  // ---------------------------------------------------------------------------