@mnemo-mcp/cli 1.0.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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +123 -0
  3. package/assets/skill/SKILL.md +52 -0
  4. package/bin/mnemo.js +2 -0
  5. package/dist/commands/doctor.d.ts +3 -0
  6. package/dist/commands/doctor.d.ts.map +1 -0
  7. package/dist/commands/doctor.js +88 -0
  8. package/dist/commands/doctor.js.map +1 -0
  9. package/dist/commands/edit.d.ts +3 -0
  10. package/dist/commands/edit.d.ts.map +1 -0
  11. package/dist/commands/edit.js +88 -0
  12. package/dist/commands/edit.js.map +1 -0
  13. package/dist/commands/export.d.ts +3 -0
  14. package/dist/commands/export.d.ts.map +1 -0
  15. package/dist/commands/export.js +23 -0
  16. package/dist/commands/export.js.map +1 -0
  17. package/dist/commands/forget.d.ts +3 -0
  18. package/dist/commands/forget.d.ts.map +1 -0
  19. package/dist/commands/forget.js +26 -0
  20. package/dist/commands/forget.js.map +1 -0
  21. package/dist/commands/hook.d.ts +3 -0
  22. package/dist/commands/hook.d.ts.map +1 -0
  23. package/dist/commands/hook.js +77 -0
  24. package/dist/commands/hook.js.map +1 -0
  25. package/dist/commands/import.d.ts +3 -0
  26. package/dist/commands/import.d.ts.map +1 -0
  27. package/dist/commands/import.js +23 -0
  28. package/dist/commands/import.js.map +1 -0
  29. package/dist/commands/init.d.ts +3 -0
  30. package/dist/commands/init.d.ts.map +1 -0
  31. package/dist/commands/init.js +153 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/list.d.ts +3 -0
  34. package/dist/commands/list.d.ts.map +1 -0
  35. package/dist/commands/list.js +31 -0
  36. package/dist/commands/list.js.map +1 -0
  37. package/dist/commands/prune.d.ts +3 -0
  38. package/dist/commands/prune.d.ts.map +1 -0
  39. package/dist/commands/prune.js +82 -0
  40. package/dist/commands/prune.js.map +1 -0
  41. package/dist/commands/recall.d.ts +3 -0
  42. package/dist/commands/recall.d.ts.map +1 -0
  43. package/dist/commands/recall.js +50 -0
  44. package/dist/commands/recall.js.map +1 -0
  45. package/dist/commands/remember.d.ts +3 -0
  46. package/dist/commands/remember.d.ts.map +1 -0
  47. package/dist/commands/remember.js +42 -0
  48. package/dist/commands/remember.js.map +1 -0
  49. package/dist/commands/stats.d.ts +3 -0
  50. package/dist/commands/stats.d.ts.map +1 -0
  51. package/dist/commands/stats.js +19 -0
  52. package/dist/commands/stats.js.map +1 -0
  53. package/dist/hooks/capture-rules.d.ts +3 -0
  54. package/dist/hooks/capture-rules.d.ts.map +1 -0
  55. package/dist/hooks/capture-rules.js +18 -0
  56. package/dist/hooks/capture-rules.js.map +1 -0
  57. package/dist/hooks/post-edit.d.ts +18 -0
  58. package/dist/hooks/post-edit.d.ts.map +1 -0
  59. package/dist/hooks/post-edit.js +38 -0
  60. package/dist/hooks/post-edit.js.map +1 -0
  61. package/dist/hooks/pre-task.d.ts +10 -0
  62. package/dist/hooks/pre-task.d.ts.map +1 -0
  63. package/dist/hooks/pre-task.js +22 -0
  64. package/dist/hooks/pre-task.js.map +1 -0
  65. package/dist/hooks/session-start.d.ts +8 -0
  66. package/dist/hooks/session-start.d.ts.map +1 -0
  67. package/dist/hooks/session-start.js +26 -0
  68. package/dist/hooks/session-start.js.map +1 -0
  69. package/dist/hooks/user-prompt-submit.d.ts +12 -0
  70. package/dist/hooks/user-prompt-submit.d.ts.map +1 -0
  71. package/dist/hooks/user-prompt-submit.js +28 -0
  72. package/dist/hooks/user-prompt-submit.js.map +1 -0
  73. package/dist/index.d.ts +2 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +35 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/output.d.ts +5 -0
  78. package/dist/output.d.ts.map +1 -0
  79. package/dist/output.js +37 -0
  80. package/dist/output.js.map +1 -0
  81. package/package.json +47 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Omer Maksuti
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # Mnemo
2
+
3
+ > Persistent memory for Claude Code. Your AI never starts from scratch again.
4
+
5
+ [![CI](https://github.com/omermaksutii/mnemo/actions/workflows/ci.yml/badge.svg)](https://github.com/omermaksutii/mnemo/actions)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ Mnemo gives Claude Code a brain that survives across sessions. It captures decisions, conventions, and preferences — and recalls them by meaning, on demand, with sub-100ms semantic search.
9
+
10
+ ---
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ # install the CLI
16
+ npm install -g @mnemo-mcp/cli
17
+
18
+ # install Mnemo into Claude Code (skill + MCP server)
19
+ mnemo init
20
+
21
+ # (optional) also wire auto-capture hooks
22
+ mnemo init --with-hooks
23
+
24
+ # verify
25
+ mnemo doctor
26
+ ```
27
+
28
+ After `mnemo init`, restart Claude Code. The `/mnemo` skill and the `mnemo_*` MCP tools are now available — Claude will use them automatically when relevant.
29
+
30
+ ## Use it from the terminal too
31
+
32
+ ```bash
33
+ mnemo remember "our API auth uses OAuth2 with refresh tokens every 30min"
34
+ mnemo remember --global "I prefer pnpm over npm"
35
+ mnemo recall "what's our auth pattern?"
36
+ mnemo list
37
+ mnemo stats
38
+ mnemo forget <id>
39
+ mnemo export --out memories.json
40
+ mnemo import memories.json
41
+ ```
42
+
43
+ ## What Mnemo solves
44
+
45
+ Claude Code forgets everything when the session ends. `CLAUDE.md` partially helps — it's a static blob loaded on every turn — but it grows unwieldy fast and can't answer "do we have a precedent for X?"
46
+
47
+ Mnemo gives you semantic, on-demand memory:
48
+
49
+ | | `CLAUDE.md` | Mnemo |
50
+ |---|---|---|
51
+ | Capacity | A handful of paragraphs before token cost hurts | Tens of thousands of memories |
52
+ | Retrieval | Always loaded, every turn | On demand, by meaning |
53
+ | Updates | You edit a file by hand | Captured automatically or via `/teach` |
54
+ | Cross-project | Per-project only | Project + global tiers |
55
+ | Forgetting | Manually delete lines | `mnemo forget <id>` or `/forget` |
56
+
57
+ ## How it works
58
+
59
+ ```
60
+ Claude Code session
61
+ ├── /mnemo skill ← teaches Claude when to call the tools
62
+ ├── @mnemo-mcp/server server ← exposes recall/remember/forget/list/stats
63
+ └── @mnemo-mcp/cli hooks ← session-start, pre-task, post-edit auto-wiring
64
+
65
+
66
+ @mnemo-mcp/core
67
+ ├── ONNX all-MiniLM-L6-v2 (384-dim embeddings, ~25MB, lazy)
68
+ ├── HNSW vector index (sub-100ms recall at 50k memories)
69
+ └── sql.js (WASM SQLite) (~/.mnemo/memory.db)
70
+ ```
71
+
72
+ Everything is local-first. No daemon. No cloud account. No telemetry.
73
+
74
+ ## Auto-capture rules
75
+
76
+ By default the post-edit hook captures any change to:
77
+
78
+ - `CLAUDE.md`, `AGENTS.md`, `GEMINI.md`
79
+ - `*.adr.md`
80
+ - `docs/decisions/**`
81
+ - `docs/adr/**`
82
+
83
+ Anything you write to those files becomes a project memory automatically. Disable with `mnemo init` (no `--with-hooks`).
84
+
85
+ ## Recall scoring
86
+
87
+ ```
88
+ score = 0.7 × cosine_similarity + 0.2 × recency + 0.1 × access_boost
89
+ ```
90
+
91
+ Recency decays with a 30-day half-life. Access boost saturates at 20 reads.
92
+
93
+ ## Layout
94
+
95
+ ```
96
+ @mnemo-mcp/core — pure TS memory engine
97
+ @mnemo-mcp/server — MCP server (drop into Claude Code)
98
+ @mnemo-mcp/cli — terminal commands + hook handlers + init
99
+ ```
100
+
101
+ ## Roadmap
102
+
103
+ - ✅ **v0.1** — core engine + CLI
104
+ - ✅ **v0.2** — MCP server (5 tools)
105
+ - ✅ **v0.3** — hooks (session-start, pre-task, post-edit)
106
+ - ✅ **v0.4** — `/mnemo` skill
107
+ - ✅ **v1.0** — `mnemo init`, beefier doctor, CI, polish
108
+ - ⏳ **v1.1** — team mode (git-synced shared memory)
109
+ - ⏳ **v2.0** — opt-in hosted sync, web UI
110
+
111
+ ## Development
112
+
113
+ ```bash
114
+ npm install
115
+ npm test # fast (44 tests, hash embedder)
116
+ MNEMO_TEST_ONNX=1 MNEMO_E2E=1 npm test # full incl. real ONNX (~5s)
117
+ npm run build
118
+ npm run lint
119
+ ```
120
+
121
+ ## License
122
+
123
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: mnemo
3
+ description: Persistent memory for the current session. Use this skill whenever the user asks you to remember a fact, recall something they told you before, or when starting work where prior context might exist (conventions, decisions, file purposes, preferences).
4
+ ---
5
+
6
+ # Mnemo — persistent memory
7
+
8
+ You have access to a persistent memory layer via these MCP tools:
9
+
10
+ - `mnemo_recall(query, k?, scope?)` — semantic search across stored memories
11
+ - `mnemo_remember(content, scope?, tags?)` — capture a new memory
12
+ - `mnemo_forget(id)` — delete a memory
13
+ - `mnemo_list(scope?, limit?)` — browse recent memories
14
+ - `mnemo_stats()` — show memory engine status
15
+
16
+ ## When to use each
17
+
18
+ **`mnemo_recall`** — call this BEFORE answering anything where prior context might help:
19
+ - "what's our convention for X?"
20
+ - "how did we decide to handle Y?"
21
+ - "why is Z structured this way?"
22
+ - whenever you're starting a task in an unfamiliar area of the codebase
23
+
24
+ Use natural-language queries. Don't try to construct keyword searches — the index is semantic.
25
+
26
+ **`mnemo_remember`** — call this when:
27
+ - The user explicitly asks ("remember this", "save this for later")
28
+ - You make or affirm a non-obvious decision (capture it as `scope: "project"`)
29
+ - The user states a personal preference that applies across projects (capture as `scope: "global"`)
30
+ - You finish a task and notice something worth not having to rediscover
31
+
32
+ Default scope is `"project"` (auto-tied to the current repo).
33
+
34
+ **`mnemo_forget`** — only when the user explicitly asks to forget, OR when you discover a memory contradicts current reality and should be replaced.
35
+
36
+ ## Examples
37
+
38
+ User: "we always use Vitest, never Jest"
39
+ → `mnemo_remember({ content: "we always use Vitest, never Jest", scope: "global" })`
40
+
41
+ User: "what test framework do we use?"
42
+ → `mnemo_recall({ query: "test framework preference", k: 3 })` then synthesize the answer.
43
+
44
+ User: "forget that pnpm thing"
45
+ → `mnemo_list({ limit: 50 })` to find it, then `mnemo_forget({ id: "..." })`.
46
+
47
+ ## Discipline
48
+
49
+ - Don't capture things that are already in CLAUDE.md or other always-loaded files (Mnemo is for the long tail that those files can't carry)
50
+ - Don't capture transient task state — capture lasting facts
51
+ - Prefer global scope for cross-project preferences; default to project scope otherwise
52
+ - When recall returns nothing useful, say so plainly — don't guess or hallucinate from low-similarity hits
package/bin/mnemo.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import('../dist/index.js');
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerDoctor(program: Command): void;
3
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmFrD"}
@@ -0,0 +1,88 @@
1
+ import { Mnemo, paths, resolveDataDir } from '@mnemo-mcp/core';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import chalk from 'chalk';
6
+ export function registerDoctor(program) {
7
+ program
8
+ .command('doctor')
9
+ .description('Diagnose your Mnemo installation and Claude Code integration')
10
+ .option('--data-dir <path>', 'Memory data directory override')
11
+ .option('--scope <scope>', 'user (default) or project', 'user')
12
+ .action(async (opts) => {
13
+ const dataDir = resolveDataDir(opts.dataDir);
14
+ const p = paths(dataDir);
15
+ const claudeDir = process.env.MNEMO_CLAUDE_DIR ??
16
+ (opts.scope === 'project' ? join(process.cwd(), '.claude') : join(homedir(), '.claude'));
17
+ const settingsFile = join(claudeDir, 'settings.json');
18
+ const skillFile = join(claudeDir, 'skills', 'mnemo', 'SKILL.md');
19
+ const checks = [];
20
+ // ---- memory engine ----
21
+ checks.push({ name: 'data dir', ok: existsSync(dataDir), detail: dataDir });
22
+ checks.push({ name: 'database', ok: existsSync(p.dbFile), detail: p.dbFile });
23
+ checks.push({ name: 'vector index', ok: existsSync(p.indexFile), detail: p.indexFile });
24
+ const embedderType = (process.env.MNEMO_EMBEDDER === 'hash' ? 'hash' : 'onnx');
25
+ let openOk = false;
26
+ let total = 0;
27
+ try {
28
+ const m = await Mnemo.open({ dataDir, embedderType });
29
+ const stats = await m.stats();
30
+ total = stats.totalMemories;
31
+ await m.close();
32
+ openOk = true;
33
+ }
34
+ catch (err) {
35
+ checks.push({ name: 'mnemo opens', ok: false, detail: err.message });
36
+ }
37
+ if (openOk) {
38
+ checks.push({ name: 'mnemo opens', ok: true, detail: `${embedderType} embedder, ${total} memories` });
39
+ }
40
+ // ---- claude code integration ----
41
+ checks.push({ name: 'claude config dir', ok: existsSync(claudeDir), detail: claudeDir });
42
+ checks.push({ name: 'mnemo skill', ok: existsSync(skillFile), detail: skillFile });
43
+ let mcpOk = false;
44
+ let hooksOk = false;
45
+ if (existsSync(settingsFile)) {
46
+ try {
47
+ const cfg = JSON.parse(readFileSync(settingsFile, 'utf8'));
48
+ const mcp = cfg.mcpServers?.mnemo;
49
+ mcpOk = !!mcp;
50
+ const hooks = cfg.hooks;
51
+ hooksOk = !!hooks?.SessionStart || !!hooks?.PostToolUse || !!hooks?.PreToolUse;
52
+ }
53
+ catch { }
54
+ }
55
+ checks.push({ name: 'mcp registered', ok: mcpOk, detail: settingsFile });
56
+ checks.push({ name: 'hooks installed', ok: hooksOk, detail: 'optional — run `mnemo init --with-hooks` to enable' });
57
+ let allOk = true;
58
+ let warnings = 0;
59
+ for (const c of checks) {
60
+ let tag;
61
+ if (c.ok) {
62
+ tag = chalk.green('OK ');
63
+ }
64
+ else if (c.name === 'hooks installed') {
65
+ tag = chalk.yellow('WARN');
66
+ warnings++;
67
+ }
68
+ else {
69
+ tag = chalk.red('FAIL');
70
+ allOk = false;
71
+ }
72
+ console.log(`${tag} ${c.name.padEnd(22)} ${chalk.dim(c.detail)}`);
73
+ }
74
+ console.log('');
75
+ if (allOk && warnings === 0) {
76
+ console.log(chalk.green('healthy'));
77
+ }
78
+ else if (allOk) {
79
+ console.log(chalk.yellow(`healthy with ${warnings} warning${warnings === 1 ? '' : 's'}`));
80
+ }
81
+ else {
82
+ console.log(chalk.red('issues detected'));
83
+ console.log(chalk.dim('try `mnemo init` to install missing pieces'));
84
+ process.exitCode = 1;
85
+ }
86
+ });
87
+ }
88
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerEdit(program: Command): void;
3
+ //# sourceMappingURL=edit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/commands/edit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkEnD"}
@@ -0,0 +1,88 @@
1
+ import { Mnemo } from '@mnemo-mcp/core';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { mkdtempSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import chalk from 'chalk';
7
+ export function registerEdit(program) {
8
+ program
9
+ .command('edit <id>')
10
+ .description('Edit a memory in $EDITOR (or pass --content / --tags non-interactively)')
11
+ .option('-c, --content <text>', 'Replace content directly without opening editor')
12
+ .option('-t, --tags <list>', 'Replace tags (comma-separated)')
13
+ .option('--expires-in <duration>', 'Set TTL (e.g. 30d). Pass empty to clear.')
14
+ .option('--data-dir <path>', 'Data directory override')
15
+ .action(async (id, opts) => {
16
+ const embedderType = (process.env.MNEMO_EMBEDDER === 'hash' ? 'hash' : 'onnx');
17
+ const m = await Mnemo.open({ dataDir: opts.dataDir, embedderType });
18
+ try {
19
+ const list = await m.list({ includeExpired: true });
20
+ const match = list.find(r => r.id === id || r.id.startsWith(id));
21
+ if (!match) {
22
+ console.log(chalk.yellow(`no memory matches "${id}"`));
23
+ process.exitCode = 1;
24
+ return;
25
+ }
26
+ let nextContent;
27
+ let nextTags;
28
+ if (opts.content !== undefined) {
29
+ nextContent = opts.content;
30
+ }
31
+ else if (opts.tags === undefined && opts.expiresIn === undefined) {
32
+ // Interactive editor mode
33
+ nextContent = await editInTemp(match.content);
34
+ if (nextContent === null || nextContent.trim() === '') {
35
+ console.log(chalk.dim('aborted (empty or unchanged)'));
36
+ return;
37
+ }
38
+ }
39
+ if (opts.tags !== undefined) {
40
+ nextTags = opts.tags.split(',').map(t => t.trim()).filter(Boolean);
41
+ }
42
+ const fields = {};
43
+ if (nextContent !== undefined && nextContent !== match.content)
44
+ fields.content = nextContent;
45
+ if (nextTags !== undefined)
46
+ fields.tags = nextTags;
47
+ if (opts.expiresIn !== undefined) {
48
+ if (opts.expiresIn === '')
49
+ fields.expiresAt = null;
50
+ else {
51
+ const { expiresAtFromTtl } = await import('@mnemo-mcp/core');
52
+ const exp = expiresAtFromTtl(opts.expiresIn);
53
+ if (exp === null) {
54
+ console.error(chalk.red('invalid --expires-in value:'), opts.expiresIn);
55
+ process.exitCode = 2;
56
+ return;
57
+ }
58
+ fields.expiresAt = exp;
59
+ }
60
+ }
61
+ if (Object.keys(fields).length === 0) {
62
+ console.log(chalk.dim('no changes'));
63
+ return;
64
+ }
65
+ const updated = await m.update(match.id, fields);
66
+ console.log(chalk.green('updated'), chalk.dim(updated.id.slice(0, 8)));
67
+ }
68
+ finally {
69
+ await m.close();
70
+ }
71
+ });
72
+ }
73
+ async function editInTemp(initial) {
74
+ const editor = process.env.EDITOR ?? process.env.VISUAL ?? 'vi';
75
+ const dir = mkdtempSync(join(tmpdir(), 'mnemo-edit-'));
76
+ const file = join(dir, 'memory.txt');
77
+ writeFileSync(file, initial);
78
+ try {
79
+ const result = spawnSync(editor, [file], { stdio: 'inherit' });
80
+ if (result.status !== 0)
81
+ return '';
82
+ return readFileSync(file, 'utf8');
83
+ }
84
+ finally {
85
+ rmSync(dir, { recursive: true, force: true });
86
+ }
87
+ }
88
+ //# sourceMappingURL=edit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/commands/edit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerExport(program: Command): void;
3
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiBrD"}
@@ -0,0 +1,23 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { Mnemo } from '@mnemo-mcp/core';
3
+ import chalk from 'chalk';
4
+ export function registerExport(program) {
5
+ program
6
+ .command('export')
7
+ .description('Export all memories to a JSON file')
8
+ .requiredOption('-o, --out <file>', 'Output file path')
9
+ .option('--data-dir <path>', 'Data directory override')
10
+ .action(async (opts) => {
11
+ const embedderType = (process.env.MNEMO_EMBEDDER === 'hash' ? 'hash' : 'onnx');
12
+ const m = await Mnemo.open({ dataDir: opts.dataDir, embedderType });
13
+ try {
14
+ const dump = await m.export();
15
+ await writeFile(opts.out, JSON.stringify(dump, null, 2));
16
+ console.log(chalk.green('exported'), dump.length, 'memories →', opts.out);
17
+ }
18
+ finally {
19
+ await m.close();
20
+ }
21
+ });
22
+ }
23
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,oCAAoC,CAAC;SACjD,cAAc,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;SACtD,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;SACtD,MAAM,CAAC,KAAK,EAAE,IAAU,EAAE,EAAE;QAC3B,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAoB,CAAC;QAClG,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;YAC9B,MAAM,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5E,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerForget(program: Command): void;
3
+ //# sourceMappingURL=forget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forget.d.ts","sourceRoot":"","sources":["../../src/commands/forget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqBrD"}
@@ -0,0 +1,26 @@
1
+ import { Mnemo } from '@mnemo-mcp/core';
2
+ import chalk from 'chalk';
3
+ export function registerForget(program) {
4
+ program
5
+ .command('forget <id>')
6
+ .description('Delete a memory by id (full or 8-char prefix)')
7
+ .option('--data-dir <path>', 'Data directory override')
8
+ .action(async (id, opts) => {
9
+ const embedderType = (process.env.MNEMO_EMBEDDER === 'hash' ? 'hash' : 'onnx');
10
+ const m = await Mnemo.open({ dataDir: opts.dataDir, embedderType });
11
+ try {
12
+ const candidates = await m.list({});
13
+ const match = candidates.find(r => r.id === id || r.id.startsWith(id));
14
+ if (!match) {
15
+ console.log(chalk.yellow(`no memory matches "${id}"`));
16
+ return;
17
+ }
18
+ await m.forget(match.id);
19
+ console.log(chalk.green('forgotten'), chalk.dim(match.id.slice(0, 8)));
20
+ }
21
+ finally {
22
+ await m.close();
23
+ }
24
+ });
25
+ }
26
+ //# sourceMappingURL=forget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forget.js","sourceRoot":"","sources":["../../src/commands/forget.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,aAAa,CAAC;SACtB,WAAW,CAAC,+CAA+C,CAAC;SAC5D,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;SACtD,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAU,EAAE,EAAE;QACvC,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAoB,CAAC;QAClG,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;YACvE,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YACD,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerHook(program: Command): void;
3
+ //# sourceMappingURL=hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/commands/hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiCzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiCnD"}
@@ -0,0 +1,77 @@
1
+ import { runSessionStart } from '../hooks/session-start.js';
2
+ import { runPreTask } from '../hooks/pre-task.js';
3
+ import { runPostEdit } from '../hooks/post-edit.js';
4
+ import { runUserPromptSubmit } from '../hooks/user-prompt-submit.js';
5
+ const HANDLERS = {
6
+ 'session-start': runSessionStart,
7
+ 'pre-task': runPreTask,
8
+ 'post-edit': runPostEdit,
9
+ 'user-prompt-submit': runUserPromptSubmit,
10
+ };
11
+ async function readStdin() {
12
+ return new Promise((resolve, reject) => {
13
+ let data = '';
14
+ if (process.stdin.isTTY)
15
+ return resolve({});
16
+ process.stdin.setEncoding('utf8');
17
+ process.stdin.on('data', chunk => { data += chunk; });
18
+ process.stdin.on('end', () => {
19
+ if (!data.trim())
20
+ return resolve({});
21
+ try {
22
+ resolve(JSON.parse(data));
23
+ }
24
+ catch {
25
+ resolve({});
26
+ }
27
+ });
28
+ process.stdin.on('error', reject);
29
+ });
30
+ }
31
+ export function registerHook(program) {
32
+ program
33
+ .command('hook <name>')
34
+ .description('Run a Claude Code hook handler. Reads payload JSON from stdin.')
35
+ .option('--print-json', 'Print Claude Code hook JSON envelope', false)
36
+ .action(async (name, opts) => {
37
+ const handler = HANDLERS[name];
38
+ if (!handler) {
39
+ process.stderr.write(`unknown hook "${name}". Known: ${Object.keys(HANDLERS).join(', ')}\n`);
40
+ process.exit(2);
41
+ }
42
+ const payload = await readStdin();
43
+ let text = '';
44
+ try {
45
+ text = await handler(payload);
46
+ }
47
+ catch (err) {
48
+ // Hooks fail open — never block Claude Code.
49
+ process.stderr.write(`mnemo hook ${name} error: ${err.message}\n`);
50
+ process.exit(0);
51
+ }
52
+ if (!text)
53
+ return;
54
+ if (opts.printJson) {
55
+ const envelope = {
56
+ hookSpecificOutput: {
57
+ hookEventName: hookEventNameFor(name),
58
+ additionalContext: text,
59
+ },
60
+ };
61
+ process.stdout.write(JSON.stringify(envelope));
62
+ }
63
+ else {
64
+ process.stdout.write(text);
65
+ }
66
+ });
67
+ }
68
+ function hookEventNameFor(name) {
69
+ switch (name) {
70
+ case 'session-start': return 'SessionStart';
71
+ case 'pre-task': return 'PreToolUse';
72
+ case 'post-edit': return 'PostToolUse';
73
+ case 'user-prompt-submit': return 'UserPromptSubmit';
74
+ default: return name;
75
+ }
76
+ }
77
+ //# sourceMappingURL=hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/commands/hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerImport(program: Command): void;
3
+ //# sourceMappingURL=import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiBrD"}
@@ -0,0 +1,23 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { Mnemo } from '@mnemo-mcp/core';
3
+ import chalk from 'chalk';
4
+ export function registerImport(program) {
5
+ program
6
+ .command('import <file>')
7
+ .description('Import memories from a JSON file')
8
+ .option('--data-dir <path>', 'Data directory override')
9
+ .action(async (file, opts) => {
10
+ const embedderType = (process.env.MNEMO_EMBEDDER === 'hash' ? 'hash' : 'onnx');
11
+ const m = await Mnemo.open({ dataDir: opts.dataDir, embedderType });
12
+ try {
13
+ const raw = await readFile(file, 'utf8');
14
+ const records = JSON.parse(raw);
15
+ await m.import(records);
16
+ console.log(chalk.green('imported'), records.length, 'memories');
17
+ }
18
+ finally {
19
+ await m.close();
20
+ }
21
+ });
22
+ }
23
+ //# sourceMappingURL=import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;SACtD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,IAAU,EAAE,EAAE;QACzC,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAoB,CAAC;QAClG,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACnE,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerInit(program: Command): void;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiEnD"}