minimem 0.0.1 → 0.0.3
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 +556 -2
- package/dist/cli/index.js +5563 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +591 -1
- package/dist/index.js +2496 -3
- package/dist/index.js.map +1 -1
- package/package.json +32 -7
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +0 -3
- package/dist/index.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,2 +1,556 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# minimem
|
|
2
|
+
|
|
3
|
+
A lightweight, file-based memory system with vector search for AI agents.
|
|
4
|
+
|
|
5
|
+
Turn your filesystem into a searchable knowledge base. Write memories in Markdown, search them semantically.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **File-based storage** - Memories are plain Markdown files you can edit, version with git, and sync anywhere
|
|
10
|
+
- **Semantic search** - Find relevant memories using natural language queries powered by embeddings
|
|
11
|
+
- **Hybrid search** - Combines vector similarity with full-text search (BM25) for better results
|
|
12
|
+
- **Multiple embedding providers** - OpenAI, Google Gemini, or local models via llama.cpp
|
|
13
|
+
- **MCP server** - Integrate with Claude Desktop, Cursor, and other MCP-compatible tools
|
|
14
|
+
- **CLI tool** - Initialize, search, sync, and manage memories from the command line
|
|
15
|
+
- **Multi-directory search** - Search across multiple memory banks in a single query
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install minimem
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or install globally for CLI usage:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g minimem
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Requires Node.js 22+ (uses experimental `node:sqlite`).
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### CLI Usage
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Initialize a memory directory
|
|
37
|
+
minimem init ~/memories
|
|
38
|
+
|
|
39
|
+
# Set your embedding API key
|
|
40
|
+
export OPENAI_API_KEY=your-key
|
|
41
|
+
# or: export GOOGLE_API_KEY=your-key
|
|
42
|
+
|
|
43
|
+
# Add some memories
|
|
44
|
+
minimem append "Decided to use PostgreSQL for the main database" --dir ~/memories
|
|
45
|
+
|
|
46
|
+
# Search your memories
|
|
47
|
+
minimem search "database decisions" --dir ~/memories
|
|
48
|
+
|
|
49
|
+
# Create or update a memory file
|
|
50
|
+
minimem upsert "memory/architecture.md" "# Architecture Notes..." --dir ~/memories
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Library Usage
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { Minimem } from 'minimem';
|
|
57
|
+
|
|
58
|
+
// Create a Minimem instance
|
|
59
|
+
const mem = await Minimem.create({
|
|
60
|
+
memoryDir: './memories',
|
|
61
|
+
embedding: {
|
|
62
|
+
provider: 'openai',
|
|
63
|
+
openai: { apiKey: process.env.OPENAI_API_KEY }
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Search memories
|
|
68
|
+
const results = await mem.search('database architecture');
|
|
69
|
+
for (const result of results) {
|
|
70
|
+
console.log(`[${result.score}] ${result.path}:${result.startLine}`);
|
|
71
|
+
console.log(result.snippet);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Append to today's log
|
|
75
|
+
await mem.appendToday('Reviewed the API design document');
|
|
76
|
+
|
|
77
|
+
// Clean up
|
|
78
|
+
mem.close();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## CLI Commands
|
|
82
|
+
|
|
83
|
+
| Command | Description |
|
|
84
|
+
|---------|-------------|
|
|
85
|
+
| `minimem init [dir]` | Initialize a memory directory |
|
|
86
|
+
| `minimem search <query>` | Semantic search through memories |
|
|
87
|
+
| `minimem sync` | Force re-index memory files |
|
|
88
|
+
| `minimem status` | Show index stats and provider info |
|
|
89
|
+
| `minimem append <text>` | Append to today's daily log |
|
|
90
|
+
| `minimem upsert <file> [content]` | Create or update a memory file |
|
|
91
|
+
| `minimem mcp` | Run as MCP server (stdio) |
|
|
92
|
+
|
|
93
|
+
### Common Options
|
|
94
|
+
|
|
95
|
+
- `-d, --dir <path>` - Memory directory (default: current directory)
|
|
96
|
+
- `-g, --global` - Use `~/.minimem` as the memory directory
|
|
97
|
+
- `-p, --provider <name>` - Embedding provider: `openai`, `gemini`, `local`, or `auto`
|
|
98
|
+
|
|
99
|
+
### Search Options
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Search with options
|
|
103
|
+
minimem search "project decisions" \
|
|
104
|
+
--dir ~/memories \
|
|
105
|
+
--max 5 \
|
|
106
|
+
--min-score 0.5 \
|
|
107
|
+
--json
|
|
108
|
+
|
|
109
|
+
# Search multiple directories
|
|
110
|
+
minimem search "api design" \
|
|
111
|
+
--dir ~/work-memories \
|
|
112
|
+
--dir ~/personal-notes \
|
|
113
|
+
--global
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Upsert Examples
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Create/update with inline content
|
|
120
|
+
minimem upsert "notes.md" "# My Notes" --dir ~/memories
|
|
121
|
+
|
|
122
|
+
# Pipe content from stdin
|
|
123
|
+
cat document.md | minimem upsert "imported.md" --stdin --dir ~/memories
|
|
124
|
+
|
|
125
|
+
# Use heredoc for multi-line content
|
|
126
|
+
minimem upsert "memory/decisions.md" --stdin --dir ~/memories << 'EOF'
|
|
127
|
+
# Architecture Decisions
|
|
128
|
+
|
|
129
|
+
## Database
|
|
130
|
+
We chose PostgreSQL for its reliability and JSON support.
|
|
131
|
+
|
|
132
|
+
## API
|
|
133
|
+
REST with OpenAPI documentation.
|
|
134
|
+
EOF
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Memory Directory Structure
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
my-memories/
|
|
141
|
+
├── MEMORY.md # Main memory file (indexed)
|
|
142
|
+
├── memory/ # Additional memory files
|
|
143
|
+
│ ├── 2024-01-15.md # Daily logs
|
|
144
|
+
│ ├── 2024-01-16.md
|
|
145
|
+
│ └── projects.md # Topic-specific notes
|
|
146
|
+
└── .minimem/ # Internal data (gitignored)
|
|
147
|
+
├── config.json # Configuration
|
|
148
|
+
└── index.db # SQLite database with vectors
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Configuration
|
|
152
|
+
|
|
153
|
+
Configuration is stored in `.minimem/config.json`:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"embedding": {
|
|
158
|
+
"provider": "auto",
|
|
159
|
+
"model": "text-embedding-3-small"
|
|
160
|
+
},
|
|
161
|
+
"hybrid": {
|
|
162
|
+
"enabled": true,
|
|
163
|
+
"vectorWeight": 0.7,
|
|
164
|
+
"textWeight": 0.3
|
|
165
|
+
},
|
|
166
|
+
"query": {
|
|
167
|
+
"maxResults": 10,
|
|
168
|
+
"minScore": 0.3
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Environment Variables
|
|
174
|
+
|
|
175
|
+
| Variable | Description |
|
|
176
|
+
|----------|-------------|
|
|
177
|
+
| `OPENAI_API_KEY` | OpenAI API key for embeddings |
|
|
178
|
+
| `GOOGLE_API_KEY` | Google/Gemini API key for embeddings |
|
|
179
|
+
| `GEMINI_API_KEY` | Alternative Gemini API key |
|
|
180
|
+
| `MEMORY_DIR` | Default memory directory |
|
|
181
|
+
|
|
182
|
+
### Embedding Providers
|
|
183
|
+
|
|
184
|
+
**OpenAI** (recommended for quality):
|
|
185
|
+
```bash
|
|
186
|
+
export OPENAI_API_KEY=sk-...
|
|
187
|
+
minimem search "query" --provider openai
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Gemini** (good free tier):
|
|
191
|
+
```bash
|
|
192
|
+
export GOOGLE_API_KEY=...
|
|
193
|
+
minimem search "query" --provider gemini
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Local** (no API needed, requires setup):
|
|
197
|
+
```bash
|
|
198
|
+
minimem search "query" --provider local
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Auto** (default): Tries OpenAI → Gemini → Local based on available API keys.
|
|
202
|
+
|
|
203
|
+
## MCP Server Integration
|
|
204
|
+
|
|
205
|
+
minimem can run as an [MCP server](https://modelcontextprotocol.io/) for integration with Claude Desktop, Cursor, and other tools.
|
|
206
|
+
|
|
207
|
+
### Claude Desktop
|
|
208
|
+
|
|
209
|
+
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"mcpServers": {
|
|
214
|
+
"minimem": {
|
|
215
|
+
"command": "minimem",
|
|
216
|
+
"args": ["mcp", "--global"],
|
|
217
|
+
"env": {
|
|
218
|
+
"OPENAI_API_KEY": "your-key"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Multiple Memory Directories
|
|
226
|
+
|
|
227
|
+
The MCP server supports searching across multiple memory directories:
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"mcpServers": {
|
|
232
|
+
"minimem": {
|
|
233
|
+
"command": "minimem",
|
|
234
|
+
"args": ["mcp", "--dir", "/path/to/work", "--dir", "/path/to/personal", "--global"],
|
|
235
|
+
"env": {
|
|
236
|
+
"OPENAI_API_KEY": "your-key"
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
When multiple directories are configured:
|
|
244
|
+
- The `memory_search` tool searches all directories by default
|
|
245
|
+
- Results are merged and ranked by score
|
|
246
|
+
- Each result shows which directory it came from
|
|
247
|
+
- Use the optional `directories` parameter to filter to specific directories
|
|
248
|
+
|
|
249
|
+
### Cursor
|
|
250
|
+
|
|
251
|
+
Add to Cursor's MCP settings:
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"mcpServers": {
|
|
256
|
+
"minimem": {
|
|
257
|
+
"command": "minimem",
|
|
258
|
+
"args": ["mcp", "--dir", "/path/to/memories"],
|
|
259
|
+
"env": {
|
|
260
|
+
"OPENAI_API_KEY": "your-key"
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Available MCP Tool
|
|
268
|
+
|
|
269
|
+
The MCP server exposes a `memory_search` tool:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
{
|
|
273
|
+
name: "memory_search",
|
|
274
|
+
description: "Search through memory files using semantic search",
|
|
275
|
+
inputSchema: {
|
|
276
|
+
type: "object",
|
|
277
|
+
properties: {
|
|
278
|
+
query: { type: "string", description: "Search query" },
|
|
279
|
+
maxResults: { type: "number", description: "Max results (default: 10)" },
|
|
280
|
+
minScore: { type: "number", description: "Min score 0-1 (default: 0.3)" },
|
|
281
|
+
directories: {
|
|
282
|
+
type: "array",
|
|
283
|
+
items: { type: "string" },
|
|
284
|
+
description: "Filter to specific directories (searches all if omitted)"
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
required: ["query"]
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Library API
|
|
293
|
+
|
|
294
|
+
### Creating an Instance
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import { Minimem, type MinimemConfig } from 'minimem';
|
|
298
|
+
|
|
299
|
+
const config: MinimemConfig = {
|
|
300
|
+
memoryDir: './memories',
|
|
301
|
+
embedding: {
|
|
302
|
+
provider: 'openai',
|
|
303
|
+
openai: {
|
|
304
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
305
|
+
model: 'text-embedding-3-small' // or text-embedding-3-large
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
hybrid: {
|
|
309
|
+
enabled: true,
|
|
310
|
+
vectorWeight: 0.7,
|
|
311
|
+
textWeight: 0.3
|
|
312
|
+
},
|
|
313
|
+
watch: true, // Auto-sync on file changes
|
|
314
|
+
debug: console.log // Optional debug logging
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const mem = await Minimem.create(config);
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Search
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const results = await mem.search('database architecture', {
|
|
324
|
+
maxResults: 10,
|
|
325
|
+
minScore: 0.3
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// Results include:
|
|
329
|
+
// - path: relative file path
|
|
330
|
+
// - snippet: matching text chunk
|
|
331
|
+
// - score: relevance score (0-1)
|
|
332
|
+
// - startLine, endLine: line numbers
|
|
333
|
+
// - heading: section heading if available
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### File Operations
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
// Append to today's daily log (memory/YYYY-MM-DD.md)
|
|
340
|
+
await mem.appendToday('Meeting notes: discussed API design');
|
|
341
|
+
|
|
342
|
+
// Append to specific file
|
|
343
|
+
await mem.appendFile('memory/project.md', 'New decision made');
|
|
344
|
+
|
|
345
|
+
// List all memory files
|
|
346
|
+
const files = await mem.listFiles();
|
|
347
|
+
|
|
348
|
+
// Get status
|
|
349
|
+
const status = await mem.status();
|
|
350
|
+
console.log(`Files: ${status.fileCount}, Chunks: ${status.chunkCount}`);
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Sync Control
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
// Manual sync (usually automatic)
|
|
357
|
+
await mem.sync();
|
|
358
|
+
|
|
359
|
+
// Force full re-index
|
|
360
|
+
await mem.sync({ force: true });
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Custom Embedding Providers
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
import { createEmbeddingProvider } from 'minimem';
|
|
367
|
+
|
|
368
|
+
// Create provider with custom settings
|
|
369
|
+
const provider = createEmbeddingProvider({
|
|
370
|
+
provider: 'openai',
|
|
371
|
+
openai: {
|
|
372
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
373
|
+
model: 'text-embedding-3-large',
|
|
374
|
+
dimensions: 1536
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// Or use Gemini
|
|
379
|
+
const geminiProvider = createEmbeddingProvider({
|
|
380
|
+
provider: 'gemini',
|
|
381
|
+
gemini: {
|
|
382
|
+
apiKey: process.env.GOOGLE_API_KEY,
|
|
383
|
+
model: 'text-embedding-004'
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## How It Works
|
|
389
|
+
|
|
390
|
+
### Architecture Overview
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
394
|
+
│ minimem │
|
|
395
|
+
├─────────────────────────────────────────────────────────────┤
|
|
396
|
+
│ Memory Files (.md) │
|
|
397
|
+
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
398
|
+
│ │MEMORY.md│ │daily.md │ │notes.md │ ← Plain Markdown │
|
|
399
|
+
│ └────┬────┘ └────┬────┘ └────┬────┘ │
|
|
400
|
+
│ │ │ │ │
|
|
401
|
+
│ └───────────┴───────────┘ │
|
|
402
|
+
│ │ │
|
|
403
|
+
│ ▼ │
|
|
404
|
+
│ ┌─────────────────────────────────────┐ │
|
|
405
|
+
│ │ Chunking │ │
|
|
406
|
+
│ │ Split by headings/paragraphs │ │
|
|
407
|
+
│ │ ~500 chars per chunk │ │
|
|
408
|
+
│ └──────────────────┬──────────────────┘ │
|
|
409
|
+
│ │ │
|
|
410
|
+
│ ▼ │
|
|
411
|
+
│ ┌─────────────────────────────────────┐ │
|
|
412
|
+
│ │ Embedding Provider │ │
|
|
413
|
+
│ │ OpenAI / Gemini / Local │ │
|
|
414
|
+
│ │ text → [0.1, -0.3, 0.8, ...] │ │
|
|
415
|
+
│ └──────────────────┬──────────────────┘ │
|
|
416
|
+
│ │ │
|
|
417
|
+
│ ▼ │
|
|
418
|
+
│ ┌─────────────────────────────────────┐ │
|
|
419
|
+
│ │ SQLite Database │ │
|
|
420
|
+
│ │ ┌─────────┐ ┌─────────────────┐ │ │
|
|
421
|
+
│ │ │ FTS5 │ │ sqlite-vec │ │ │
|
|
422
|
+
│ │ │ (text) │ │ (vectors) │ │ │
|
|
423
|
+
│ │ └─────────┘ └─────────────────┘ │ │
|
|
424
|
+
│ └──────────────────┬──────────────────┘ │
|
|
425
|
+
│ │ │
|
|
426
|
+
│ ▼ │
|
|
427
|
+
│ ┌─────────────────────────────────────┐ │
|
|
428
|
+
│ │ Hybrid Search │ │
|
|
429
|
+
│ │ Vector similarity + BM25 ranking │ │
|
|
430
|
+
│ │ Weighted merge of results │ │
|
|
431
|
+
│ └─────────────────────────────────────┘ │
|
|
432
|
+
└─────────────────────────────────────────────────────────────┘
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Indexing Process
|
|
436
|
+
|
|
437
|
+
1. **File Discovery**: Scans for `MEMORY.md` and `memory/*.md` files
|
|
438
|
+
2. **Chunking**: Splits content by Markdown headings and paragraphs (~500 chars each)
|
|
439
|
+
3. **Hashing**: Each chunk gets a content hash to detect changes
|
|
440
|
+
4. **Embedding**: New/changed chunks are sent to the embedding provider
|
|
441
|
+
5. **Storage**: Chunks and vectors stored in SQLite with sqlite-vec extension
|
|
442
|
+
6. **Caching**: Embeddings cached by content hash to avoid re-computation
|
|
443
|
+
|
|
444
|
+
### Search Process
|
|
445
|
+
|
|
446
|
+
1. **Query Embedding**: Convert search query to vector using same embedding model
|
|
447
|
+
2. **Vector Search**: Find similar chunks using cosine similarity (sqlite-vec)
|
|
448
|
+
3. **Text Search**: Find matching chunks using FTS5 full-text search (BM25)
|
|
449
|
+
4. **Hybrid Merge**: Combine results with configurable weights (default 70% vector, 30% text)
|
|
450
|
+
5. **Ranking**: Sort by combined score, apply min-score filter
|
|
451
|
+
|
|
452
|
+
### Why Hybrid Search?
|
|
453
|
+
|
|
454
|
+
Pure vector search excels at semantic similarity but can miss exact matches. Pure text search finds exact terms but misses synonyms. Hybrid search combines both:
|
|
455
|
+
|
|
456
|
+
- **Vector (70%)**: Finds conceptually related content ("database" matches "PostgreSQL")
|
|
457
|
+
- **Text (30%)**: Boosts exact keyword matches ("PostgreSQL" query ranks PostgreSQL mentions higher)
|
|
458
|
+
|
|
459
|
+
### Storage Format
|
|
460
|
+
|
|
461
|
+
SQLite database with three main tables:
|
|
462
|
+
|
|
463
|
+
```sql
|
|
464
|
+
-- File metadata and modification tracking
|
|
465
|
+
CREATE TABLE memory_files (
|
|
466
|
+
path TEXT PRIMARY KEY,
|
|
467
|
+
mtime INTEGER,
|
|
468
|
+
hash TEXT
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
-- Content chunks with embeddings
|
|
472
|
+
CREATE TABLE memory_chunks (
|
|
473
|
+
id INTEGER PRIMARY KEY,
|
|
474
|
+
path TEXT,
|
|
475
|
+
content TEXT,
|
|
476
|
+
hash TEXT,
|
|
477
|
+
start_line INTEGER,
|
|
478
|
+
end_line INTEGER,
|
|
479
|
+
heading TEXT,
|
|
480
|
+
embedding BLOB -- F32 vector
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
-- Full-text search index
|
|
484
|
+
CREATE VIRTUAL TABLE memory_fts USING fts5(content, path);
|
|
485
|
+
|
|
486
|
+
-- Vector similarity index (when sqlite-vec available)
|
|
487
|
+
CREATE VIRTUAL TABLE memory_vec USING vec0(embedding float[128]);
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Embedding Cache
|
|
491
|
+
|
|
492
|
+
Embeddings are cached by content hash in a separate table:
|
|
493
|
+
|
|
494
|
+
```sql
|
|
495
|
+
CREATE TABLE embedding_cache (
|
|
496
|
+
hash TEXT PRIMARY KEY,
|
|
497
|
+
embedding BLOB,
|
|
498
|
+
model TEXT,
|
|
499
|
+
created_at INTEGER
|
|
500
|
+
);
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
This means:
|
|
504
|
+
- Identical text always produces the same embedding (deterministic)
|
|
505
|
+
- Moving/copying chunks doesn't require re-embedding
|
|
506
|
+
- Switching files with same content is instant
|
|
507
|
+
|
|
508
|
+
## Claude Code Plugin
|
|
509
|
+
|
|
510
|
+
A ready-to-use Claude Code plugin is included in the `claude-plugin/` directory.
|
|
511
|
+
|
|
512
|
+
### Quick Install
|
|
513
|
+
|
|
514
|
+
```bash
|
|
515
|
+
# Install minimem globally
|
|
516
|
+
npm install -g minimem
|
|
517
|
+
|
|
518
|
+
# Initialize global memory
|
|
519
|
+
minimem init --global
|
|
520
|
+
|
|
521
|
+
# Test the plugin
|
|
522
|
+
claude --plugin-dir /path/to/minimem/claude-plugin
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### Plugin Features
|
|
526
|
+
|
|
527
|
+
- **MCP Server**: `memory_search` tool for semantic search
|
|
528
|
+
- **Memory Skill**: Auto-invoked for storing/recalling context
|
|
529
|
+
- **Commands**:
|
|
530
|
+
- `/minimem:remember <text>` - Store information
|
|
531
|
+
- `/minimem:recall <query>` - Search memories
|
|
532
|
+
|
|
533
|
+
See `claude-plugin/README.md` for detailed documentation.
|
|
534
|
+
|
|
535
|
+
## Development
|
|
536
|
+
|
|
537
|
+
```bash
|
|
538
|
+
# Install dependencies
|
|
539
|
+
npm install
|
|
540
|
+
|
|
541
|
+
# Build
|
|
542
|
+
npm run build
|
|
543
|
+
|
|
544
|
+
# Run tests
|
|
545
|
+
npm run test:all # All tests
|
|
546
|
+
npm run test:unit # Unit tests (vitest)
|
|
547
|
+
npm run test:cli # CLI command tests
|
|
548
|
+
npm run test:integration # E2E integration tests
|
|
549
|
+
|
|
550
|
+
# Development mode
|
|
551
|
+
npm run dev
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
## License
|
|
555
|
+
|
|
556
|
+
MIT
|