claude-memory-store 0.1.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 (158) hide show
  1. package/README.md +364 -0
  2. package/dist/acknowledgement.d.ts +14 -0
  3. package/dist/acknowledgement.d.ts.map +1 -0
  4. package/dist/acknowledgement.js +55 -0
  5. package/dist/acknowledgement.js.map +1 -0
  6. package/dist/atlas/client.d.ts +9 -0
  7. package/dist/atlas/client.d.ts.map +1 -0
  8. package/dist/atlas/client.js +64 -0
  9. package/dist/atlas/client.js.map +1 -0
  10. package/dist/atlas/embeddings.d.ts +18 -0
  11. package/dist/atlas/embeddings.d.ts.map +1 -0
  12. package/dist/atlas/embeddings.js +56 -0
  13. package/dist/atlas/embeddings.js.map +1 -0
  14. package/dist/atlas/indexes.d.ts +4 -0
  15. package/dist/atlas/indexes.d.ts.map +1 -0
  16. package/dist/atlas/indexes.js +78 -0
  17. package/dist/atlas/indexes.js.map +1 -0
  18. package/dist/atlas/vector.d.ts +17 -0
  19. package/dist/atlas/vector.d.ts.map +1 -0
  20. package/dist/atlas/vector.js +61 -0
  21. package/dist/atlas/vector.js.map +1 -0
  22. package/dist/bin/claude-memory.d.ts +3 -0
  23. package/dist/bin/claude-memory.d.ts.map +1 -0
  24. package/dist/bin/claude-memory.js +648 -0
  25. package/dist/bin/claude-memory.js.map +1 -0
  26. package/dist/bin/mcp-server.d.ts +3 -0
  27. package/dist/bin/mcp-server.d.ts.map +1 -0
  28. package/dist/bin/mcp-server.js +165 -0
  29. package/dist/bin/mcp-server.js.map +1 -0
  30. package/dist/cache/command-cache.d.ts +12 -0
  31. package/dist/cache/command-cache.d.ts.map +1 -0
  32. package/dist/cache/command-cache.js +63 -0
  33. package/dist/cache/command-cache.js.map +1 -0
  34. package/dist/cleanup.d.ts +8 -0
  35. package/dist/cleanup.d.ts.map +1 -0
  36. package/dist/cleanup.js +22 -0
  37. package/dist/cleanup.js.map +1 -0
  38. package/dist/config.d.ts +10 -0
  39. package/dist/config.d.ts.map +1 -0
  40. package/dist/config.js +97 -0
  41. package/dist/config.js.map +1 -0
  42. package/dist/detector.d.ts +20 -0
  43. package/dist/detector.d.ts.map +1 -0
  44. package/dist/detector.js +92 -0
  45. package/dist/detector.js.map +1 -0
  46. package/dist/editor/file-editor.d.ts +7 -0
  47. package/dist/editor/file-editor.d.ts.map +1 -0
  48. package/dist/editor/file-editor.js +73 -0
  49. package/dist/editor/file-editor.js.map +1 -0
  50. package/dist/editor/tui.d.ts +11 -0
  51. package/dist/editor/tui.d.ts.map +1 -0
  52. package/dist/editor/tui.js +75 -0
  53. package/dist/editor/tui.js.map +1 -0
  54. package/dist/hooks/post-tool-use.d.ts +11 -0
  55. package/dist/hooks/post-tool-use.d.ts.map +1 -0
  56. package/dist/hooks/post-tool-use.js +36 -0
  57. package/dist/hooks/post-tool-use.js.map +1 -0
  58. package/dist/hooks/pre-tool-use.d.ts +5 -0
  59. package/dist/hooks/pre-tool-use.d.ts.map +1 -0
  60. package/dist/hooks/pre-tool-use.js +103 -0
  61. package/dist/hooks/pre-tool-use.js.map +1 -0
  62. package/dist/hooks/startup.d.ts +25 -0
  63. package/dist/hooks/startup.d.ts.map +1 -0
  64. package/dist/hooks/startup.js +62 -0
  65. package/dist/hooks/startup.js.map +1 -0
  66. package/dist/hooks/stop.d.ts +39 -0
  67. package/dist/hooks/stop.d.ts.map +1 -0
  68. package/dist/hooks/stop.js +102 -0
  69. package/dist/hooks/stop.js.map +1 -0
  70. package/dist/index.d.ts +35 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +166 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/memory/commands.d.ts +15 -0
  75. package/dist/memory/commands.d.ts.map +1 -0
  76. package/dist/memory/commands.js +55 -0
  77. package/dist/memory/commands.js.map +1 -0
  78. package/dist/memory/developer.d.ts +17 -0
  79. package/dist/memory/developer.d.ts.map +1 -0
  80. package/dist/memory/developer.js +233 -0
  81. package/dist/memory/developer.js.map +1 -0
  82. package/dist/memory/project.d.ts +25 -0
  83. package/dist/memory/project.d.ts.map +1 -0
  84. package/dist/memory/project.js +341 -0
  85. package/dist/memory/project.js.map +1 -0
  86. package/dist/memory/threads.d.ts +10 -0
  87. package/dist/memory/threads.d.ts.map +1 -0
  88. package/dist/memory/threads.js +57 -0
  89. package/dist/memory/threads.js.map +1 -0
  90. package/dist/memory/working.d.ts +16 -0
  91. package/dist/memory/working.d.ts.map +1 -0
  92. package/dist/memory/working.js +80 -0
  93. package/dist/memory/working.js.map +1 -0
  94. package/dist/natural-language/intent.d.ts +4 -0
  95. package/dist/natural-language/intent.d.ts.map +1 -0
  96. package/dist/natural-language/intent.js +169 -0
  97. package/dist/natural-language/intent.js.map +1 -0
  98. package/dist/natural-language/parser.d.ts +5 -0
  99. package/dist/natural-language/parser.d.ts.map +1 -0
  100. package/dist/natural-language/parser.js +63 -0
  101. package/dist/natural-language/parser.js.map +1 -0
  102. package/dist/natural-language/router.d.ts +9 -0
  103. package/dist/natural-language/router.d.ts.map +1 -0
  104. package/dist/natural-language/router.js +171 -0
  105. package/dist/natural-language/router.js.map +1 -0
  106. package/dist/project-id.d.ts +5 -0
  107. package/dist/project-id.d.ts.map +1 -0
  108. package/dist/project-id.js +78 -0
  109. package/dist/project-id.js.map +1 -0
  110. package/dist/slash-commands/edit.d.ts +10 -0
  111. package/dist/slash-commands/edit.d.ts.map +1 -0
  112. package/dist/slash-commands/edit.js +312 -0
  113. package/dist/slash-commands/edit.js.map +1 -0
  114. package/dist/slash-commands/memory.d.ts +3 -0
  115. package/dist/slash-commands/memory.d.ts.map +1 -0
  116. package/dist/slash-commands/memory.js +69 -0
  117. package/dist/slash-commands/memory.js.map +1 -0
  118. package/dist/slash-commands/recall.d.ts +2 -0
  119. package/dist/slash-commands/recall.d.ts.map +1 -0
  120. package/dist/slash-commands/recall.js +81 -0
  121. package/dist/slash-commands/recall.js.map +1 -0
  122. package/dist/slash-commands/remember.d.ts +2 -0
  123. package/dist/slash-commands/remember.d.ts.map +1 -0
  124. package/dist/slash-commands/remember.js +21 -0
  125. package/dist/slash-commands/remember.js.map +1 -0
  126. package/dist/slash-commands/stats.d.ts +2 -0
  127. package/dist/slash-commands/stats.d.ts.map +1 -0
  128. package/dist/slash-commands/stats.js +55 -0
  129. package/dist/slash-commands/stats.js.map +1 -0
  130. package/dist/slash-commands/threads.d.ts +4 -0
  131. package/dist/slash-commands/threads.d.ts.map +1 -0
  132. package/dist/slash-commands/threads.js +36 -0
  133. package/dist/slash-commands/threads.js.map +1 -0
  134. package/dist/startup/conversation.d.ts +17 -0
  135. package/dist/startup/conversation.d.ts.map +1 -0
  136. package/dist/startup/conversation.js +78 -0
  137. package/dist/startup/conversation.js.map +1 -0
  138. package/dist/startup/feature-search.d.ts +9 -0
  139. package/dist/startup/feature-search.d.ts.map +1 -0
  140. package/dist/startup/feature-search.js +62 -0
  141. package/dist/startup/feature-search.js.map +1 -0
  142. package/dist/startup/injector.d.ts +4 -0
  143. package/dist/startup/injector.d.ts.map +1 -0
  144. package/dist/startup/injector.js +190 -0
  145. package/dist/startup/injector.js.map +1 -0
  146. package/dist/summarizer.d.ts +15 -0
  147. package/dist/summarizer.d.ts.map +1 -0
  148. package/dist/summarizer.js +92 -0
  149. package/dist/summarizer.js.map +1 -0
  150. package/dist/types.d.ts +151 -0
  151. package/dist/types.d.ts.map +1 -0
  152. package/dist/types.js +3 -0
  153. package/dist/types.js.map +1 -0
  154. package/dist/utils.d.ts +5 -0
  155. package/dist/utils.d.ts.map +1 -0
  156. package/dist/utils.js +16 -0
  157. package/dist/utils.js.map +1 -0
  158. package/package.json +67 -0
package/README.md ADDED
@@ -0,0 +1,364 @@
1
+ # Claude Memory
2
+
3
+ **The first developer-focused persistent memory system for Claude Code.**
4
+
5
+ Claude forgets everything when the context window clears. Claude Memory fixes that. Your architecture decisions, deploy commands, database configs, team conventions, and project patterns persist across every session — stored in your own MongoDB Atlas instance, searchable in under 50ms.
6
+
7
+ One command to install. Zero config after setup. Your data, your database, forever.
8
+
9
+ ```bash
10
+ npx claude-memory-store init
11
+ ```
12
+
13
+ [![npm version](https://img.shields.io/npm/v/claude-memory-store)](https://www.npmjs.com/package/claude-memory-store)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
15
+
16
+ ---
17
+
18
+ ## The Problem
19
+
20
+ You spend 10 minutes explaining your deploy process to Claude. Next session — gone. You tell Claude about your database clusters, your migration rules, your team conventions. Context clears — gone. Every session starts from zero.
21
+
22
+ Claude Code's context window is powerful but temporary. When it fills up or you start a new session, everything disappears.
23
+
24
+ ## The Solution
25
+
26
+ Claude Memory gives Claude persistent, searchable memory powered entirely by MongoDB Atlas:
27
+
28
+ - **Architecture decisions** — "MongoDB Atlas prod-cluster-east, database api_prod, staging on staging-cluster"
29
+ - **Deploy commands** — "docker build → ECR push → Dokploy webhook → health check" (with aliases like "deploy", "ship it")
30
+ - **Team conventions** — "always use pnpm", "prefer Vitest over Jest", "strict TypeScript everywhere"
31
+ - **Avoid rules** — "never run migrations directly on prod", "never deploy on Fridays"
32
+ - **Open threads** — "production index on users collection is missing — causing slow queries"
33
+ - **Developer preferences** — follow you across every project, every machine
34
+
35
+ Every memory item is an individual document with its own vector embedding. Search returns the **specific decision** you need, not a truncated blob.
36
+
37
+ ---
38
+
39
+ ## How It Works
40
+
41
+ Claude Memory integrates with Claude Code at four levels:
42
+
43
+ ### 1. Hooks (Passive — Automatic)
44
+ Lifecycle hooks fire automatically during every Claude Code session:
45
+ - **Startup** — ultra-minimal banner showing memory stats (zero context cost)
46
+ - **Pre-tool-use** — queries Atlas on every prompt, injects relevant context if found
47
+ - **Post-tool-use** — detects "remember this" intents and stores automatically
48
+ - **Session end** — saves working memory, increments session counters
49
+
50
+ ### 2. MCP Server (Active — Claude Decides)
51
+ Four MCP tools Claude can call on its own:
52
+ - `recall(topic)` — search memory for relevant decisions
53
+ - `remember(text)` — store a decision with auto-classification
54
+ - `memory_threads()` — list open threads
55
+ - `memory_stats()` — show memory statistics
56
+
57
+ ### 3. Skill File (Discoverable — User Types `/`)
58
+ Slash commands available when you type `/` in Claude Code:
59
+ - `/recall <topic>` — search memory
60
+ - `/remember <text>` — store a decision
61
+ - `/threads` — view open threads
62
+ - `/stats` — memory statistics
63
+
64
+ ### 4. CLAUDE.md Instructions (Context — Always Present)
65
+ Instructions in your global CLAUDE.md tell Claude it has memory available and when to use it.
66
+
67
+ ### The Lazy Injection Strategy
68
+
69
+ Claude Memory does **not** dump everything into the context window at startup. Atlas queries take under 50ms — there's no reason to waste context space.
70
+
71
+ - Startup banner: **<500 characters** (just stats: "3 decisions, 2 patterns, 1 thread")
72
+ - Continue context: **1-2 line summary** of last session
73
+ - New session: **zero context cost**
74
+ - Memory surfaces **on-demand** via pre-tool-use search when relevant
75
+
76
+ The full memory dump is only loaded when you explicitly ask for it (`?` at the startup menu).
77
+
78
+ ---
79
+
80
+ ## Quick Start
81
+
82
+ ### Prerequisites
83
+ - Node.js 18+
84
+ - MongoDB Atlas account ([free tier works](https://cloud.mongodb.com/register) — no credit card required)
85
+
86
+ ### Install
87
+
88
+ ```bash
89
+ npx claude-memory-store init
90
+ ```
91
+
92
+ That single command:
93
+ 1. Prompts for your Atlas connection string (auto-detects from `CLAUDE_MEMORY_ATLAS_URI` env var or `.env` file)
94
+ 2. Tests the connection
95
+ 3. Creates the `claude_memory` database and indexes
96
+ 4. Sets up Atlas vector search index (M10+ only, skipped gracefully on free tier)
97
+ 5. Installs Claude Code hooks (startup, pre-tool-use, post-tool-use, stop)
98
+ 6. Registers the MCP server (recall, remember, threads, stats tools)
99
+ 7. Installs the skill file (`/recall`, `/remember`, `/threads`, `/stats`)
100
+ 8. Adds memory instructions to your global CLAUDE.md
101
+
102
+ **That's it.** No other setup. No API keys. No external services. Just Atlas.
103
+
104
+ ### Verify Installation
105
+
106
+ ```bash
107
+ claude-memory info # Show project ID, developer ID, config path
108
+ claude-memory stats # Show memory statistics
109
+ claude-memory memory # Show memory summary
110
+ ```
111
+
112
+ ---
113
+
114
+ ## Commands
115
+
116
+ ### CLI Commands
117
+
118
+ ```bash
119
+ claude-memory init # First-time setup (one command does everything)
120
+ claude-memory info # Show project/developer IDs and config path
121
+ claude-memory memory # Show memory summary
122
+ claude-memory stats # Show detailed statistics
123
+ claude-memory recall <topic> # Search memory for a topic
124
+ claude-memory remember <text> # Store a decision/pattern/rule
125
+ claude-memory threads # Show open threads
126
+ claude-memory commands # Show verified commands
127
+ claude-memory edit # TUI memory editor
128
+ claude-memory edit --file # Edit memory in $EDITOR (JSON)
129
+ claude-memory edit --developer # Edit developer memory
130
+ claude-memory clear --working # Clear session history
131
+ claude-memory clear --all # Clear all project memory
132
+ ```
133
+
134
+ ### MCP Tools (Claude calls these automatically)
135
+
136
+ | Tool | Description |
137
+ |------|-------------|
138
+ | `recall(topic, limit?)` | Search memory via semantic + keyword search |
139
+ | `remember(text, category?)` | Store with auto-classification (avoid/pattern/architecture/preference) |
140
+ | `memory_threads()` | List open threads with status and age |
141
+ | `memory_stats()` | Full memory statistics |
142
+
143
+ ### Slash Commands (Type `/` in Claude Code)
144
+
145
+ | Command | Description |
146
+ |---------|-------------|
147
+ | `/recall <topic>` | Search memory |
148
+ | `/remember <text>` | Store a decision |
149
+ | `/threads` | View open threads |
150
+ | `/stats` | Memory statistics |
151
+
152
+ ---
153
+
154
+ ## What Gets Stored
155
+
156
+ ### Auto-Classification
157
+
158
+ When you tell Claude to remember something, it classifies automatically:
159
+
160
+ | Your input | Classification | Example |
161
+ |------------|---------------|---------|
162
+ | "never..." / "don't..." / "avoid..." | **Avoid rule** | "never deploy on Fridays" |
163
+ | "always use..." / "pattern..." / "convention..." | **Pattern** | "always use pnpm not npm" |
164
+ | "architecture..." / "database..." / "schema..." | **Architecture decision** | "MongoDB Atlas on prod-cluster-east" |
165
+ | "across all projects..." | **Developer preference** | "prefer Vitest over Jest everywhere" |
166
+ | Everything else | **Architecture decision** | (default) |
167
+
168
+ ### Memory Types
169
+
170
+ | Type | Scope | Persists Across |
171
+ |------|-------|----------------|
172
+ | Architecture decisions | Per project | Sessions |
173
+ | Patterns | Per project | Sessions |
174
+ | Avoid rules | Per project | Sessions |
175
+ | Verified commands | Per project | Sessions |
176
+ | Open threads | Per project | Sessions |
177
+ | Working memory | Per project | Sessions (auto-saved) |
178
+ | Developer preferences | Per developer | All projects |
179
+ | Style rules | Per developer | All projects |
180
+
181
+ ### Verified Commands
182
+
183
+ Store multi-step workflows with trigger aliases:
184
+
185
+ ```
186
+ Store: "deploy" command with steps:
187
+ 1. docker build -t myteam/api-service .
188
+ 2. aws ecr push to us-east-1
189
+ 3. curl -X POST https://deploy.example.com/webhook/abc123
190
+ 4. curl https://api.example.com/health
191
+
192
+ Triggers: "deploy", "ship it", "push to prod"
193
+ ```
194
+
195
+ Next session, say "deploy" and Claude gets the full pipeline injected automatically.
196
+
197
+ ---
198
+
199
+ ## Architecture
200
+
201
+ ### Powered Entirely by MongoDB Atlas
202
+
203
+ Claude Memory uses a single MongoDB Atlas collection (`claude_memory`) with a type discriminator. No Redis. No Postgres. No external APIs. No vector database. Just Atlas.
204
+
205
+ **Why Atlas?**
206
+ - Free tier (M0) — no credit card, never expires
207
+ - Atlas Vector Search with automated embedding via Voyage AI (M10+)
208
+ - Global availability, automatic backups, zero maintenance
209
+ - Your data stays in your own database — not a third-party service
210
+
211
+ ### Individual Document Architecture
212
+
213
+ Every memory item is its own document:
214
+
215
+ ```
216
+ claude_memory collection:
217
+ ├── type: "working" — session snapshots (one per session)
218
+ ├── type: "project_meta" — project metadata (one per project)
219
+ ├── type: "developer_meta" — developer metadata (one per developer)
220
+ ├── type: "architecture" — individual decisions
221
+ ├── type: "pattern" — individual patterns
222
+ ├── type: "avoid" — individual avoid rules
223
+ ├── type: "thread" — individual open threads
224
+ ├── type: "command" — individual verified commands
225
+ ├── type: "preference" — individual developer preferences (cross-project)
226
+ ├── type: "style" — individual style rules (cross-project)
227
+ ├── type: "dev_default" — individual defaults (cross-project)
228
+ └── type: "dev_avoid" — individual developer avoid rules (cross-project)
229
+ ```
230
+
231
+ Each document has its own `searchable_text` field — Atlas generates vector embeddings per item, so search returns the **specific decision** you need, not a truncated snippet of a giant concatenated blob.
232
+
233
+ ### TTL with Renewal
234
+
235
+ Memories aren't permanent by default. Unused memories expire naturally:
236
+
237
+ - Every document has a `last_accessed` timestamp
238
+ - When a search returns a document, `last_accessed` is renewed (fire-and-forget)
239
+ - On startup, documents older than `memory_ttl_days` (configurable, default 30 days) are cleaned up
240
+ - `project_meta` and `developer_meta` never expire
241
+ - **Active memories live forever** — only forgotten ones decay
242
+
243
+ ### Deduplication
244
+
245
+ Two-layer dedup prevents duplicate entries:
246
+ 1. Application-level check (`findOne` before `insertOne`)
247
+ 2. Unique compound indexes as safety net
248
+
249
+ ---
250
+
251
+ ## Configuration
252
+
253
+ Config is stored at `~/.claude-memory/config.json`:
254
+
255
+ ```json
256
+ {
257
+ "atlas_uri": "mongodb+srv://...",
258
+ "team_memory": false,
259
+ "memory_ttl_days": 30
260
+ }
261
+ ```
262
+
263
+ | Setting | Default | Description |
264
+ |---------|---------|-------------|
265
+ | `atlas_uri` | — | MongoDB Atlas connection string |
266
+ | `team_memory` | `false` | Reserved for future team memory features |
267
+ | `memory_ttl_days` | `30` | Days before unused memories expire (0 = never) |
268
+
269
+ You can also set `CLAUDE_MEMORY_ATLAS_URI` as an environment variable or in a `.env` file — the init command auto-detects both.
270
+
271
+ ---
272
+
273
+ ## Atlas Tier Comparison
274
+
275
+ Claude Memory works on all Atlas tiers. The difference is search precision:
276
+
277
+ | Feature | Free Tier (M0) | M10+ |
278
+ |---------|---------------|------|
279
+ | Store/recall memory | Yes | Yes |
280
+ | Hooks (startup, pre/post-tool-use, stop) | Yes | Yes |
281
+ | MCP tools (recall, remember, threads, stats) | Yes | Yes |
282
+ | Keyword search (regex matching) | Yes | Yes |
283
+ | TTL with renewal | Yes | Yes |
284
+ | Verified commands with aliases | Yes | Yes |
285
+ | Open threads | Yes | Yes |
286
+ | **Semantic vector search** | No | **Yes** |
287
+ | **Atlas Automated Embedding (Voyage AI)** | No | **Yes** |
288
+
289
+ **Free tier** uses keyword search — your query terms need to match the words in stored memories. Works well when you search with the same terms you used when storing.
290
+
291
+ **M10+** adds semantic vector search via Voyage AI auto-embedding. Atlas automatically generates and maintains vector embeddings for every document. This means "what's our production database?" finds "MongoDB Atlas prod-cluster-east with database api_prod" even though the words don't overlap.
292
+
293
+ **Recommendation:** Start with the free tier. It's fully functional. Upgrade to M10+ if you find keyword search isn't precise enough for your workflow.
294
+
295
+ ---
296
+
297
+ ## Project Identity
298
+
299
+ Claude Memory identifies projects by hashing the git remote URL (first 16 chars of SHA-256). This means:
300
+ - Same project = same memory, regardless of machine or directory
301
+ - Rename the folder? Memory stays
302
+ - Clone on a different machine? Memory is there
303
+ - Different developer on the same project? Same project memory, different developer preferences
304
+
305
+ Developer identity is based on hostname + username hash — your preferences follow you across all projects.
306
+
307
+ ---
308
+
309
+ ## File Structure
310
+
311
+ ```
312
+ src/
313
+ atlas/ — MongoDB Atlas client, indexes, vector search
314
+ memory/ — CRUD for all memory types
315
+ hooks/ — Claude Code lifecycle hooks
316
+ startup/ — Startup banner, context injection, feature search
317
+ cache/ — In-memory command cache (<1ms lookups)
318
+ natural-language/ — Intent detection, parsing, routing
319
+ slash-commands/ — /memory, /recall, /remember, /threads, /stats, /edit
320
+ editor/ — TUI and file-based memory editors
321
+ bin/ — CLI entry point + MCP server
322
+ cleanup.ts — TTL-based memory expiration
323
+ config.ts — Configuration management
324
+ types.ts — TypeScript type definitions
325
+ ```
326
+
327
+ ---
328
+
329
+ ## Development
330
+
331
+ ```bash
332
+ git clone git@github.com:TheDecipherist/claude-memory.git
333
+ cd claude-memory
334
+ npm install
335
+ npm run build # Compile TypeScript
336
+ npm run dev # Watch mode
337
+ npm test # Run tests (requires Atlas connection)
338
+ npm run lint # Type check
339
+ ```
340
+
341
+ ### Testing
342
+
343
+ Tests run against a real Atlas cluster (no mocks). Set `CLAUDE_MEMORY_ATLAS_URI` in `.env`:
344
+
345
+ ```
346
+ CLAUDE_MEMORY_ATLAS_URI=mongodb+srv://...
347
+ ```
348
+
349
+ ```bash
350
+ npm test # Full suite (270 tests)
351
+ npx vitest run tests/multi-session.test.ts # Multi-session simulation
352
+ npx vitest run tests/scenarios.test.ts # Real-world developer scenarios
353
+ npx vitest run tests/context-budget.test.ts # Context budget guarantees
354
+ ```
355
+
356
+ ---
357
+
358
+ ## License
359
+
360
+ MIT
361
+
362
+ ---
363
+
364
+ **Built by [TheDecipherist](https://github.com/TheDecipherist)** — because Claude should remember what you told it yesterday.
@@ -0,0 +1,14 @@
1
+ import type { SummaryItem } from './types.js';
2
+ /**
3
+ * Save a single summary item to the appropriate memory store.
4
+ */
5
+ export declare function saveSummaryItem(item: SummaryItem): Promise<void>;
6
+ /**
7
+ * Save all summary items at once.
8
+ */
9
+ export declare function saveAllSummaryItems(items: SummaryItem[]): Promise<number>;
10
+ /**
11
+ * Format the acknowledgement prompt shown to the developer.
12
+ */
13
+ export declare function buildAcknowledgementPrompt(items: SummaryItem[], formattedSummary: string): string;
14
+ //# sourceMappingURL=acknowledgement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acknowledgement.d.ts","sourceRoot":"","sources":["../src/acknowledgement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAK9C;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBtE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/E;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,WAAW,EAAE,EACpB,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAMR"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.saveSummaryItem = saveSummaryItem;
4
+ exports.saveAllSummaryItems = saveAllSummaryItems;
5
+ exports.buildAcknowledgementPrompt = buildAcknowledgementPrompt;
6
+ const project_js_1 = require("./memory/project.js");
7
+ const developer_js_1 = require("./memory/developer.js");
8
+ const threads_js_1 = require("./memory/threads.js");
9
+ /**
10
+ * Save a single summary item to the appropriate memory store.
11
+ */
12
+ async function saveSummaryItem(item) {
13
+ switch (item.category) {
14
+ case 'ARCHITECTURE':
15
+ await (0, project_js_1.addArchitectureDecision)(item.content);
16
+ break;
17
+ case 'PATTERN':
18
+ await (0, project_js_1.addPattern)(item.content);
19
+ break;
20
+ case 'AVOID':
21
+ await (0, project_js_1.addAvoid)(item.content);
22
+ break;
23
+ case 'OPEN_THREAD':
24
+ await (0, threads_js_1.createThread)(item.content, 'Detected during session summarization');
25
+ break;
26
+ case 'DEVELOPER_PREF':
27
+ await (0, developer_js_1.addPreference)(item.content);
28
+ break;
29
+ // WORKING is handled separately via working memory
30
+ // TRANSIENT is discarded
31
+ default:
32
+ break;
33
+ }
34
+ }
35
+ /**
36
+ * Save all summary items at once.
37
+ */
38
+ async function saveAllSummaryItems(items) {
39
+ let saved = 0;
40
+ for (const item of items) {
41
+ if (item.category !== 'WORKING' && item.category !== 'TRANSIENT') {
42
+ await saveSummaryItem(item);
43
+ saved++;
44
+ }
45
+ }
46
+ return saved;
47
+ }
48
+ /**
49
+ * Format the acknowledgement prompt shown to the developer.
50
+ */
51
+ function buildAcknowledgementPrompt(items, formattedSummary) {
52
+ const nonWorking = items.filter((i) => i.category !== 'WORKING' && i.category !== 'TRANSIENT');
53
+ return `Session complete. ${nonWorking.length} items flagged for memory:\n\n${formattedSummary}\nSave all? (a) Review individually? (r) Skip all? (s)`;
54
+ }
55
+ //# sourceMappingURL=acknowledgement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acknowledgement.js","sourceRoot":"","sources":["../src/acknowledgement.ts"],"names":[],"mappings":";;AAQA,0CAsBC;AAKD,kDASC;AAKD,gEASC;AAzDD,oDAAoF;AACpF,wDAAsD;AACtD,oDAAmD;AAEnD;;GAEG;AACI,KAAK,UAAU,eAAe,CAAC,IAAiB;IACrD,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,KAAK,cAAc;YACjB,MAAM,IAAA,oCAAuB,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5C,MAAM;QACR,KAAK,SAAS;YACZ,MAAM,IAAA,uBAAU,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/B,MAAM;QACR,KAAK,OAAO;YACV,MAAM,IAAA,qBAAQ,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC7B,MAAM;QACR,KAAK,aAAa;YAChB,MAAM,IAAA,yBAAY,EAAC,IAAI,CAAC,OAAO,EAAE,uCAAuC,CAAC,CAAC;YAC1E,MAAM;QACR,KAAK,gBAAgB;YACnB,MAAM,IAAA,4BAAa,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAClC,MAAM;QACR,mDAAmD;QACnD,yBAAyB;QACzB;YACE,MAAM;IACV,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,mBAAmB,CAAC,KAAoB;IAC5D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;YACjE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;YAC5B,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAgB,0BAA0B,CACxC,KAAoB,EACpB,gBAAwB;IAExB,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,KAAK,WAAW,CAC9D,CAAC;IAEF,OAAO,qBAAqB,UAAU,CAAC,MAAM,iCAAiC,gBAAgB,0DAA0D,CAAC;AAC3J,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Db, Collection } from 'mongodb';
2
+ import type { MemoryDocument } from '../types.js';
3
+ export declare function connect(uri?: string): Promise<Db>;
4
+ export declare function getCollection(): Promise<Collection<MemoryDocument>>;
5
+ export declare function disconnect(): Promise<void>;
6
+ export declare function testConnection(uri: string): Promise<boolean>;
7
+ export declare function getDbName(): string;
8
+ export declare function getCollectionName(): string;
9
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/atlas/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,EAAE,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAQlD,wBAAsB,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAkBvD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAGzE;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAMhD;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAclE;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.connect = connect;
4
+ exports.getCollection = getCollection;
5
+ exports.disconnect = disconnect;
6
+ exports.testConnection = testConnection;
7
+ exports.getDbName = getDbName;
8
+ exports.getCollectionName = getCollectionName;
9
+ const mongodb_1 = require("mongodb");
10
+ const config_js_1 = require("../config.js");
11
+ const DB_NAME = 'claude_memory';
12
+ const COLLECTION_NAME = 'claude_memory';
13
+ let client = null;
14
+ let db = null;
15
+ async function connect(uri) {
16
+ if (db)
17
+ return db;
18
+ const atlasUri = uri || (0, config_js_1.getAtlasUri)();
19
+ if (!atlasUri) {
20
+ throw new Error('No Atlas URI configured. Run "claude-memory init" or set CLAUDE_MEMORY_ATLAS_URI.');
21
+ }
22
+ client = new mongodb_1.MongoClient(atlasUri, {
23
+ connectTimeoutMS: 10000,
24
+ serverSelectionTimeoutMS: 10000,
25
+ });
26
+ await client.connect();
27
+ db = client.db(DB_NAME);
28
+ return db;
29
+ }
30
+ async function getCollection() {
31
+ const database = await connect();
32
+ return database.collection(COLLECTION_NAME);
33
+ }
34
+ async function disconnect() {
35
+ if (client) {
36
+ await client.close();
37
+ client = null;
38
+ db = null;
39
+ }
40
+ }
41
+ async function testConnection(uri) {
42
+ const testClient = new mongodb_1.MongoClient(uri, {
43
+ connectTimeoutMS: 10000,
44
+ serverSelectionTimeoutMS: 10000,
45
+ });
46
+ try {
47
+ await testClient.connect();
48
+ await testClient.db(DB_NAME).command({ ping: 1 });
49
+ return true;
50
+ }
51
+ catch {
52
+ return false;
53
+ }
54
+ finally {
55
+ await testClient.close();
56
+ }
57
+ }
58
+ function getDbName() {
59
+ return DB_NAME;
60
+ }
61
+ function getCollectionName() {
62
+ return COLLECTION_NAME;
63
+ }
64
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/atlas/client.ts"],"names":[],"mappings":";;AAUA,0BAkBC;AAED,sCAGC;AAED,gCAMC;AAED,wCAcC;AAED,8BAEC;AAED,8CAEC;AAjED,qCAAsD;AACtD,4CAA2C;AAG3C,MAAM,OAAO,GAAG,eAAe,CAAC;AAChC,MAAM,eAAe,GAAG,eAAe,CAAC;AAExC,IAAI,MAAM,GAAuB,IAAI,CAAC;AACtC,IAAI,EAAE,GAAc,IAAI,CAAC;AAElB,KAAK,UAAU,OAAO,CAAC,GAAY;IACxC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IAElB,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAA,uBAAW,GAAE,CAAC;IACtC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,mFAAmF,CACpF,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,IAAI,qBAAW,CAAC,QAAQ,EAAE;QACjC,gBAAgB,EAAE,KAAK;QACvB,wBAAwB,EAAE,KAAK;KAChC,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACvB,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;IACxB,OAAO,EAAE,CAAC;AACZ,CAAC;AAEM,KAAK,UAAU,aAAa;IACjC,MAAM,QAAQ,GAAG,MAAM,OAAO,EAAE,CAAC;IACjC,OAAO,QAAQ,CAAC,UAAU,CAAiB,eAAe,CAAC,CAAC;AAC9D,CAAC;AAEM,KAAK,UAAU,UAAU;IAC9B,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,GAAG,IAAI,CAAC;QACd,EAAE,GAAG,IAAI,CAAC;IACZ,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,GAAW;IAC9C,MAAM,UAAU,GAAG,IAAI,qBAAW,CAAC,GAAG,EAAE;QACtC,gBAAgB,EAAE,KAAK;QACvB,wBAAwB,EAAE,KAAK;KAChC,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;QAC3B,MAAM,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;YAAS,CAAC;QACT,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,SAAgB,SAAS;IACvB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAgB,iBAAiB;IAC/B,OAAO,eAAe,CAAC;AACzB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Local embedding generation via HuggingFace Transformers (ONNX).
3
+ *
4
+ * Uses all-MiniLM-L6-v2 — a sentence-transformer that produces 384-dimension
5
+ * vectors. Runs entirely in Node.js, no API keys, no external services.
6
+ * Model downloads on first use (~23MB) and is cached locally.
7
+ */
8
+ export declare const EMBEDDING_DIMENSIONS = 384;
9
+ /**
10
+ * Generate an embedding vector for a text string.
11
+ * Returns a plain number array of 384 dimensions.
12
+ */
13
+ export declare function generateEmbedding(text: string): Promise<number[]>;
14
+ /**
15
+ * Generate embeddings for multiple texts in one batch.
16
+ */
17
+ export declare function generateEmbeddings(texts: string[]): Promise<number[][]>;
18
+ //# sourceMappingURL=embeddings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/atlas/embeddings.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAwBxC;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAIvE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAM7E"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ /**
3
+ * Local embedding generation via HuggingFace Transformers (ONNX).
4
+ *
5
+ * Uses all-MiniLM-L6-v2 — a sentence-transformer that produces 384-dimension
6
+ * vectors. Runs entirely in Node.js, no API keys, no external services.
7
+ * Model downloads on first use (~23MB) and is cached locally.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.EMBEDDING_DIMENSIONS = void 0;
11
+ exports.generateEmbedding = generateEmbedding;
12
+ exports.generateEmbeddings = generateEmbeddings;
13
+ let pipeline = null;
14
+ let loading = null;
15
+ const MODEL_NAME = 'Xenova/all-MiniLM-L6-v2';
16
+ exports.EMBEDDING_DIMENSIONS = 384;
17
+ /**
18
+ * Initialize the embedding pipeline. Lazy — only loads on first call.
19
+ * Subsequent calls return the cached pipeline.
20
+ */
21
+ async function getPipeline() {
22
+ if (pipeline)
23
+ return pipeline;
24
+ if (loading)
25
+ return loading;
26
+ loading = (async () => {
27
+ const { pipeline: createPipeline } = await import('@huggingface/transformers');
28
+ pipeline = await createPipeline('feature-extraction', MODEL_NAME, {
29
+ dtype: 'fp32',
30
+ });
31
+ return pipeline;
32
+ })();
33
+ pipeline = await loading;
34
+ loading = null;
35
+ return pipeline;
36
+ }
37
+ /**
38
+ * Generate an embedding vector for a text string.
39
+ * Returns a plain number array of 384 dimensions.
40
+ */
41
+ async function generateEmbedding(text) {
42
+ const pipe = await getPipeline();
43
+ const output = await pipe(text, { pooling: 'mean', normalize: true });
44
+ return Array.from(output.data);
45
+ }
46
+ /**
47
+ * Generate embeddings for multiple texts in one batch.
48
+ */
49
+ async function generateEmbeddings(texts) {
50
+ const results = [];
51
+ for (const text of texts) {
52
+ results.push(await generateEmbedding(text));
53
+ }
54
+ return results;
55
+ }
56
+ //# sourceMappingURL=embeddings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/atlas/embeddings.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAkCH,8CAIC;AAKD,gDAMC;AA/CD,IAAI,QAAQ,GAAQ,IAAI,CAAC;AACzB,IAAI,OAAO,GAAwB,IAAI,CAAC;AAExC,MAAM,UAAU,GAAG,yBAAyB,CAAC;AAChC,QAAA,oBAAoB,GAAG,GAAG,CAAC;AAExC;;;GAGG;AACH,KAAK,UAAU,WAAW;IACxB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;QAC/E,QAAQ,GAAG,MAAM,cAAc,CAAC,oBAAoB,EAAE,UAAU,EAAE;YAChE,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,EAAE,CAAC;IAEL,QAAQ,GAAG,MAAM,OAAO,CAAC;IACzB,OAAO,GAAG,IAAI,CAAC;IACf,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,iBAAiB,CAAC,IAAY;IAClD,MAAM,IAAI,GAAG,MAAM,WAAW,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAoB,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,kBAAkB,CAAC,KAAe;IACtD,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Db } from 'mongodb';
2
+ export declare function createIndexes(db: Db): Promise<void>;
3
+ export declare function createVectorSearchIndex(db: Db): Promise<void>;
4
+ //# sourceMappingURL=indexes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexes.d.ts","sourceRoot":"","sources":["../../src/atlas/indexes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAI7B,wBAAsB,aAAa,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEzD;AAED,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgCnE"}