@s_s/mnemo 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.
package/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # Mnemo
2
+
3
+ [中文文档](./docs/README.zh-CN.md)
4
+
5
+ Persistent memory management for AI coding assistants via [MCP](https://modelcontextprotocol.io/).
6
+
7
+ Mnemo solves the problem of context window overflow — important decisions, user preferences, and project knowledge get lost when conversations reset. Mnemo distills key information into persistent memory notes that can be recalled across sessions using semantic search.
8
+
9
+ ## Features
10
+
11
+ - **Semantic search** — find memories by meaning, not just keywords (powered by local embeddings)
12
+ - **Multi-agent support** — works with OpenCode, Claude Code, Openclaw, and Codex
13
+ - **Fully local** — no API calls, no cloud storage; all data stays on your machine
14
+ - **Auto-prompted** — injects instructions into your agent's config so it knows when to save and recall memories
15
+ - **Compression workflow** — atomic distillation of old notes into fewer, concise ones
16
+
17
+ ## Quick Start
18
+
19
+ ### Install
20
+
21
+ ```bash
22
+ npm install -g mnemo
23
+ ```
24
+
25
+ ### Configure your MCP client
26
+
27
+ Add Mnemo to your MCP client configuration. For example, in OpenCode (`opencode.json`):
28
+
29
+ ```json
30
+ {
31
+ "mcp": {
32
+ "mnemo": {
33
+ "command": "mnemo"
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ For Claude Code (`.claude/settings.json`):
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "mnemo": {
45
+ "command": "mnemo"
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ### Initialize
52
+
53
+ Once connected, call the `memory_setup` tool to inject memory management instructions into your agent's config file:
54
+
55
+ ```
56
+ > Use the memory_setup tool to initialize Mnemo
57
+ ```
58
+
59
+ This writes a prompt block into your agent's config (e.g., `AGENTS.md` for OpenCode, `CLAUDE.md` for Claude Code) that teaches the agent when and how to use Mnemo's tools.
60
+
61
+ ## Usage Examples
62
+
63
+ > **Important:** You don't call Mnemo tools directly. You chat with your AI agent in natural language, and the agent decides when to call Mnemo tools behind the scenes. After running `memory_setup`, the agent already knows when and how to use them.
64
+
65
+ ### First-time setup
66
+
67
+ ```
68
+ You: Help me set up Mnemo for memory management
69
+ Agent: I'll initialize Mnemo for you.
70
+ → [calls memory_setup tool]
71
+ Mnemo has been initialized. I've added memory management
72
+ instructions to your AGENTS.md file.
73
+ ```
74
+
75
+ ### Saving memories (automatic)
76
+
77
+ The agent saves memories on its own when it recognizes important information:
78
+
79
+ ```
80
+ You: Let's use 4-space indentation and single quotes for this project.
81
+ Agent: Got it. I'll follow that style.
82
+ → [calls memory_save: "Project code style: 4-space indentation,
83
+ single quotes", tags: ["preference", "code-style"]]
84
+ I've saved this as a memory so I'll remember it next time.
85
+ ```
86
+
87
+ ### Recalling context (automatic)
88
+
89
+ When you start a new conversation, the agent searches for relevant memories:
90
+
91
+ ```
92
+ You: Let's continue working on the auth module.
93
+ Agent: → [calls memory_search: "auth module"]
94
+ Based on my memories, last time we decided to use JWT with
95
+ refresh tokens and store them in httpOnly cookies. Let me
96
+ pick up from there.
97
+ ```
98
+
99
+ ### Searching memories (on request)
100
+
101
+ ```
102
+ You: Do you remember what database we chose?
103
+ Agent: → [calls memory_search: "database choice"]
104
+ Yes — we decided on PostgreSQL with Prisma ORM, mainly for
105
+ its type safety and migration tooling.
106
+ ```
107
+
108
+ ### Compressing memories
109
+
110
+ When memories accumulate, you can ask the agent to clean up:
111
+
112
+ ```
113
+ You: We have a lot of memories now. Can you clean them up?
114
+ Agent: → [calls memory_compress]
115
+ I found 23 memories. Let me distill them into fewer notes...
116
+ → [calls memory_compress_apply: saves 8 distilled notes,
117
+ deletes 23 originals]
118
+ Done. Compressed 23 memories into 8 concise notes.
119
+ ```
120
+
121
+ ## Tools
122
+
123
+ Mnemo provides 6 MCP tools:
124
+
125
+ | Tool | Description |
126
+ | ----------------------- | --------------------------------------------------------------------------- |
127
+ | `memory_setup` | Initialize Mnemo — inject usage instructions into agent config |
128
+ | `memory_save` | Save a memory note with optional tags and source |
129
+ | `memory_search` | Semantic search across memories (supports `source_filter` and `tag_filter`) |
130
+ | `memory_compress` | List all notes for review/distillation |
131
+ | `memory_compress_apply` | Atomically save distilled notes and delete originals |
132
+ | `memory_delete` | Delete notes by ID |
133
+
134
+ ## How It Works
135
+
136
+ ### Storage
137
+
138
+ Memory notes are stored as Markdown files with YAML frontmatter:
139
+
140
+ ```
141
+ ~/Library/Application Support/mnemo/ # macOS
142
+ ~/.local/share/mnemo/ # Linux
143
+ %APPDATA%/mnemo/ # Windows
144
+ ├── notes/ # Markdown files
145
+ │ ├── 20260305-172200-a3f1.md
146
+ │ └── 20260305-183015-b7c2.md
147
+ └── index/ # Vector index (vectra)
148
+ ```
149
+
150
+ Override the data directory with `MNEMO_DATA_DIR` environment variable.
151
+
152
+ ### Semantic Search
153
+
154
+ Mnemo uses [all-MiniLM-L6-v2](https://huggingface.co/Xenova/all-MiniLM-L6-v2) (33MB, 384 dimensions) for local embeddings via `@huggingface/transformers`. The model is preloaded at server startup so it's ready before the first search.
155
+
156
+ ### Memory Lifecycle
157
+
158
+ 1. **Save** — Agent saves key info during conversations (decisions, preferences, architecture choices, or when context is running low)
159
+ 2. **Search** — Agent retrieves relevant context at the start of new conversations or when needed
160
+ 3. **Compress** — When notes accumulate, the agent distills them into fewer, concise notes via `memory_compress` → review → `memory_compress_apply`
161
+
162
+ ## Development
163
+
164
+ ```bash
165
+ git clone git@github.com:See-Cat/mnemo.git
166
+ cd mnemo
167
+ npm install
168
+ npm run build
169
+ npm test
170
+ ```
171
+
172
+ ### Scripts
173
+
174
+ | Command | Description |
175
+ | ---------------------- | ---------------------------- |
176
+ | `npm run build` | Compile TypeScript |
177
+ | `npm run dev` | Watch mode compilation |
178
+ | `npm test` | Run tests (Vitest) |
179
+ | `npm run test:watch` | Watch mode tests |
180
+ | `npm run prettier:fix` | Format all files |
181
+ | `npm run release` | Interactive release workflow |
182
+
183
+ ### Release
184
+
185
+ ```bash
186
+ npm run release
187
+ ```
188
+
189
+ Interactive script that walks through: git check → branch check → version selection → format → test → build → publish → push.
190
+
191
+ ## License
192
+
193
+ MIT
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Supported agent tool types
3
+ */
4
+ export declare const AGENT_TYPES: readonly ["opencode", "claude-code", "openclaw", "codex"];
5
+ export type AgentType = (typeof AGENT_TYPES)[number];
6
+ /**
7
+ * Get platform-appropriate data directory for Mnemo.
8
+ *
9
+ * Follows platform conventions:
10
+ * - macOS: ~/Library/Application Support/mnemo
11
+ * - Linux: $XDG_DATA_HOME/mnemo (defaults to ~/.local/share/mnemo)
12
+ * - Windows: %APPDATA%/mnemo
13
+ *
14
+ * Can be overridden via MNEMO_DATA_DIR env var.
15
+ */
16
+ export declare function getDataDir(): string;
17
+ /**
18
+ * Get the notes directory
19
+ */
20
+ export declare function getNotesDir(): string;
21
+ /**
22
+ * Get the vector index directory
23
+ */
24
+ export declare function getIndexDir(): string;
25
+ /**
26
+ * Ensure a directory exists
27
+ */
28
+ export declare function ensureDir(dir: string): Promise<void>;
29
+ /**
30
+ * Memory note metadata
31
+ */
32
+ export interface NoteMeta {
33
+ id: string;
34
+ created: string;
35
+ updated: string;
36
+ tags: string[];
37
+ source: string;
38
+ }
39
+ /**
40
+ * Memory note (metadata + content)
41
+ */
42
+ export interface Note {
43
+ meta: NoteMeta;
44
+ content: string;
45
+ }
46
+ /**
47
+ * Compress trigger thresholds
48
+ */
49
+ export declare const COMPRESS_THRESHOLDS: {
50
+ /** Max number of notes before auto-compress suggestion */
51
+ readonly maxNotes: 50;
52
+ /** Max total content size (chars) before auto-compress suggestion */
53
+ readonly maxTotalSize: 100000;
54
+ };
@@ -0,0 +1,61 @@
1
+ import path from 'node:path';
2
+ import os from 'node:os';
3
+ import fs from 'node:fs/promises';
4
+ /**
5
+ * Supported agent tool types
6
+ */
7
+ export const AGENT_TYPES = ['opencode', 'claude-code', 'openclaw', 'codex'];
8
+ /**
9
+ * Get platform-appropriate data directory for Mnemo.
10
+ *
11
+ * Follows platform conventions:
12
+ * - macOS: ~/Library/Application Support/mnemo
13
+ * - Linux: $XDG_DATA_HOME/mnemo (defaults to ~/.local/share/mnemo)
14
+ * - Windows: %APPDATA%/mnemo
15
+ *
16
+ * Can be overridden via MNEMO_DATA_DIR env var.
17
+ */
18
+ export function getDataDir() {
19
+ const envDir = process.env.MNEMO_DATA_DIR;
20
+ if (envDir)
21
+ return envDir;
22
+ const platform = process.platform;
23
+ const home = os.homedir();
24
+ switch (platform) {
25
+ case 'darwin':
26
+ return path.join(home, 'Library', 'Application Support', 'mnemo');
27
+ case 'win32':
28
+ return path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'mnemo');
29
+ default:
30
+ // Linux and others: follow XDG Base Directory spec
31
+ return path.join(process.env.XDG_DATA_HOME || path.join(home, '.local', 'share'), 'mnemo');
32
+ }
33
+ }
34
+ /**
35
+ * Get the notes directory
36
+ */
37
+ export function getNotesDir() {
38
+ return path.join(getDataDir(), 'notes');
39
+ }
40
+ /**
41
+ * Get the vector index directory
42
+ */
43
+ export function getIndexDir() {
44
+ return path.join(getDataDir(), 'index');
45
+ }
46
+ /**
47
+ * Ensure a directory exists
48
+ */
49
+ export async function ensureDir(dir) {
50
+ await fs.mkdir(dir, { recursive: true });
51
+ }
52
+ /**
53
+ * Compress trigger thresholds
54
+ */
55
+ export const COMPRESS_THRESHOLDS = {
56
+ /** Max number of notes before auto-compress suggestion */
57
+ maxNotes: 50,
58
+ /** Max total content size (chars) before auto-compress suggestion */
59
+ maxTotalSize: 100_000,
60
+ };
61
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,CAAU,CAAC;AAIrF;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU;IACtB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC1C,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAE1B,QAAQ,QAAQ,EAAE,CAAC;QACf,KAAK,QAAQ;YACT,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAC;QACtE,KAAK,OAAO;YACR,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5F;YACI,mDAAmD;YACnD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IACnG,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACvC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC;AAqBD;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAC/B,0DAA0D;IAC1D,QAAQ,EAAE,EAAE;IACZ,qEAAqE;IACrE,YAAY,EAAE,OAAO;CACf,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { type Note } from './config.js';
2
+ /**
3
+ * Pre-warm the embedding model in the background.
4
+ * Call this at server startup so the model is ready before the first tool call.
5
+ */
6
+ export declare function preloadEmbedding(): void;
7
+ /**
8
+ * Check if the embedding model is ready
9
+ */
10
+ export declare function isEmbeddingReady(): boolean;
11
+ /**
12
+ * Generate embedding vector for text
13
+ */
14
+ export declare function embed(text: string): Promise<number[]>;
15
+ /**
16
+ * Index a note (generate embedding and store in vector index)
17
+ */
18
+ export declare function indexNote(note: Note): Promise<void>;
19
+ /**
20
+ * Remove a note from the vector index
21
+ */
22
+ export declare function removeFromIndex(noteId: string): Promise<void>;
23
+ /**
24
+ * Remove multiple notes from the vector index
25
+ */
26
+ export declare function removeMultipleFromIndex(noteIds: string[]): Promise<void>;
27
+ /**
28
+ * Search for similar notes by query text
29
+ */
30
+ export declare function searchNotes(query: string, topK?: number, sourceFilter?: string): Promise<Array<{
31
+ id: string;
32
+ score: number;
33
+ text: string;
34
+ tags: string;
35
+ source: string;
36
+ created: string;
37
+ }>>;
@@ -0,0 +1,119 @@
1
+ import { LocalIndex } from 'vectra';
2
+ import { getIndexDir, ensureDir } from './config.js';
3
+ let embedder = null;
4
+ let embedderLoading = null;
5
+ let indexInstance = null;
6
+ /**
7
+ * Load the embedding model.
8
+ * Uses all-MiniLM-L6-v2 (384 dims, ~33MB, good quality/speed tradeoff).
9
+ * Deduplicates concurrent calls so the model is only loaded once.
10
+ */
11
+ async function getEmbedder() {
12
+ if (embedder)
13
+ return embedder;
14
+ if (!embedderLoading) {
15
+ embedderLoading = (async () => {
16
+ console.error('Mnemo: loading embedding model...');
17
+ const { pipeline } = await import('@huggingface/transformers');
18
+ embedder = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');
19
+ console.error('Mnemo: embedding model loaded');
20
+ return embedder;
21
+ })();
22
+ }
23
+ return embedderLoading;
24
+ }
25
+ /**
26
+ * Pre-warm the embedding model in the background.
27
+ * Call this at server startup so the model is ready before the first tool call.
28
+ */
29
+ export function preloadEmbedding() {
30
+ getEmbedder().catch((err) => {
31
+ console.error('Mnemo: failed to preload embedding model:', err);
32
+ });
33
+ }
34
+ /**
35
+ * Check if the embedding model is ready
36
+ */
37
+ export function isEmbeddingReady() {
38
+ return embedder !== null;
39
+ }
40
+ /**
41
+ * Generate embedding vector for text
42
+ */
43
+ export async function embed(text) {
44
+ const model = await getEmbedder();
45
+ const output = await model(text, { pooling: 'mean', normalize: true });
46
+ return Array.from(output.data);
47
+ }
48
+ /**
49
+ * Get or create the vector index
50
+ */
51
+ async function getIndex() {
52
+ if (!indexInstance) {
53
+ const indexDir = getIndexDir();
54
+ await ensureDir(indexDir);
55
+ indexInstance = new LocalIndex(indexDir);
56
+ if (!(await indexInstance.isIndexCreated())) {
57
+ await indexInstance.createIndex({
58
+ version: 1,
59
+ metadata_config: { indexed: ['source'] },
60
+ });
61
+ console.error('Mnemo: vector index created');
62
+ }
63
+ }
64
+ return indexInstance;
65
+ }
66
+ /**
67
+ * Index a note (generate embedding and store in vector index)
68
+ */
69
+ export async function indexNote(note) {
70
+ const index = await getIndex();
71
+ const vector = await embed(note.content);
72
+ await index.insertItem({
73
+ id: note.meta.id,
74
+ vector,
75
+ metadata: {
76
+ id: note.meta.id,
77
+ text: note.content.slice(0, 500), // store truncated text for quick access
78
+ tags: note.meta.tags.join(','),
79
+ source: note.meta.source,
80
+ created: note.meta.created,
81
+ },
82
+ });
83
+ }
84
+ /**
85
+ * Remove a note from the vector index
86
+ */
87
+ export async function removeFromIndex(noteId) {
88
+ const index = await getIndex();
89
+ const item = await index.getItem(noteId);
90
+ if (item) {
91
+ await index.deleteItem(noteId);
92
+ }
93
+ }
94
+ /**
95
+ * Remove multiple notes from the vector index
96
+ */
97
+ export async function removeMultipleFromIndex(noteIds) {
98
+ for (const id of noteIds) {
99
+ await removeFromIndex(id);
100
+ }
101
+ }
102
+ /**
103
+ * Search for similar notes by query text
104
+ */
105
+ export async function searchNotes(query, topK = 5, sourceFilter) {
106
+ const index = await getIndex();
107
+ const vector = await embed(query);
108
+ const filter = sourceFilter ? { source: { $eq: sourceFilter } } : undefined;
109
+ const results = await index.queryItems(vector, '', topK, filter);
110
+ return results.map((r) => ({
111
+ id: r.item.metadata.id,
112
+ score: r.score,
113
+ text: r.item.metadata.text,
114
+ tags: r.item.metadata.tags,
115
+ source: r.item.metadata.source,
116
+ created: r.item.metadata.created,
117
+ }));
118
+ }
119
+ //# sourceMappingURL=embedding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding.js","sourceRoot":"","sources":["../../src/core/embedding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { type Note } from './config.js';
2
+ /**
3
+ * Parse a note markdown file into Note object
4
+ */
5
+ export declare function parseNote(raw: string): Note | null;
6
+ /**
7
+ * Serialize a Note to markdown string
8
+ */
9
+ export declare function serializeNote(note: Note): string;
10
+ /**
11
+ * Save a new note to disk and return it
12
+ */
13
+ export declare function saveNote(content: string, tags?: string[], source?: string): Promise<Note>;
14
+ /**
15
+ * Read a single note by ID
16
+ */
17
+ export declare function readNote(id: string): Promise<Note | null>;
18
+ /**
19
+ * Read all notes from disk
20
+ */
21
+ export declare function readAllNotes(): Promise<Note[]>;
22
+ /**
23
+ * Delete a note by ID
24
+ */
25
+ export declare function deleteNote(id: string): Promise<boolean>;
26
+ /**
27
+ * Delete multiple notes by ID
28
+ */
29
+ export declare function deleteNotes(ids: string[]): Promise<number>;
30
+ /**
31
+ * Get note stats (count and total size)
32
+ */
33
+ export declare function getNoteStats(): Promise<{
34
+ count: number;
35
+ totalSize: number;
36
+ }>;