claude-memory-layer 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 (127) hide show
  1. package/.claude-plugin/commands/memory-forget.md +42 -0
  2. package/.claude-plugin/commands/memory-history.md +34 -0
  3. package/.claude-plugin/commands/memory-import.md +56 -0
  4. package/.claude-plugin/commands/memory-list.md +37 -0
  5. package/.claude-plugin/commands/memory-search.md +36 -0
  6. package/.claude-plugin/commands/memory-stats.md +34 -0
  7. package/.claude-plugin/hooks.json +59 -0
  8. package/.claude-plugin/plugin.json +24 -0
  9. package/.history/package_20260201112328.json +45 -0
  10. package/.history/package_20260201113602.json +45 -0
  11. package/.history/package_20260201113713.json +45 -0
  12. package/.history/package_20260201114110.json +45 -0
  13. package/Memo.txt +558 -0
  14. package/README.md +520 -0
  15. package/context.md +636 -0
  16. package/dist/.claude-plugin/commands/memory-forget.md +42 -0
  17. package/dist/.claude-plugin/commands/memory-history.md +34 -0
  18. package/dist/.claude-plugin/commands/memory-import.md +56 -0
  19. package/dist/.claude-plugin/commands/memory-list.md +37 -0
  20. package/dist/.claude-plugin/commands/memory-search.md +36 -0
  21. package/dist/.claude-plugin/commands/memory-stats.md +34 -0
  22. package/dist/.claude-plugin/hooks.json +59 -0
  23. package/dist/.claude-plugin/plugin.json +24 -0
  24. package/dist/cli/index.js +3539 -0
  25. package/dist/cli/index.js.map +7 -0
  26. package/dist/core/index.js +4408 -0
  27. package/dist/core/index.js.map +7 -0
  28. package/dist/hooks/session-end.js +2971 -0
  29. package/dist/hooks/session-end.js.map +7 -0
  30. package/dist/hooks/session-start.js +2969 -0
  31. package/dist/hooks/session-start.js.map +7 -0
  32. package/dist/hooks/stop.js +3123 -0
  33. package/dist/hooks/stop.js.map +7 -0
  34. package/dist/hooks/user-prompt-submit.js +2960 -0
  35. package/dist/hooks/user-prompt-submit.js.map +7 -0
  36. package/dist/services/memory-service.js +2931 -0
  37. package/dist/services/memory-service.js.map +7 -0
  38. package/package.json +45 -0
  39. package/plan.md +1642 -0
  40. package/scripts/build.ts +102 -0
  41. package/spec.md +624 -0
  42. package/specs/citations-system/context.md +243 -0
  43. package/specs/citations-system/plan.md +495 -0
  44. package/specs/citations-system/spec.md +371 -0
  45. package/specs/endless-mode/context.md +305 -0
  46. package/specs/endless-mode/plan.md +620 -0
  47. package/specs/endless-mode/spec.md +455 -0
  48. package/specs/entity-edge-model/context.md +401 -0
  49. package/specs/entity-edge-model/plan.md +459 -0
  50. package/specs/entity-edge-model/spec.md +391 -0
  51. package/specs/evidence-aligner-v2/context.md +401 -0
  52. package/specs/evidence-aligner-v2/plan.md +303 -0
  53. package/specs/evidence-aligner-v2/spec.md +312 -0
  54. package/specs/mcp-desktop-integration/context.md +278 -0
  55. package/specs/mcp-desktop-integration/plan.md +550 -0
  56. package/specs/mcp-desktop-integration/spec.md +494 -0
  57. package/specs/post-tool-use-hook/context.md +319 -0
  58. package/specs/post-tool-use-hook/plan.md +469 -0
  59. package/specs/post-tool-use-hook/spec.md +364 -0
  60. package/specs/private-tags/context.md +288 -0
  61. package/specs/private-tags/plan.md +412 -0
  62. package/specs/private-tags/spec.md +345 -0
  63. package/specs/progressive-disclosure/context.md +346 -0
  64. package/specs/progressive-disclosure/plan.md +663 -0
  65. package/specs/progressive-disclosure/spec.md +415 -0
  66. package/specs/task-entity-system/context.md +297 -0
  67. package/specs/task-entity-system/plan.md +301 -0
  68. package/specs/task-entity-system/spec.md +314 -0
  69. package/specs/vector-outbox-v2/context.md +470 -0
  70. package/specs/vector-outbox-v2/plan.md +562 -0
  71. package/specs/vector-outbox-v2/spec.md +466 -0
  72. package/specs/web-viewer-ui/context.md +384 -0
  73. package/specs/web-viewer-ui/plan.md +797 -0
  74. package/specs/web-viewer-ui/spec.md +516 -0
  75. package/src/cli/index.ts +570 -0
  76. package/src/core/canonical-key.ts +186 -0
  77. package/src/core/citation-generator.ts +63 -0
  78. package/src/core/consolidated-store.ts +279 -0
  79. package/src/core/consolidation-worker.ts +384 -0
  80. package/src/core/context-formatter.ts +276 -0
  81. package/src/core/continuity-manager.ts +336 -0
  82. package/src/core/edge-repo.ts +324 -0
  83. package/src/core/embedder.ts +124 -0
  84. package/src/core/entity-repo.ts +342 -0
  85. package/src/core/event-store.ts +672 -0
  86. package/src/core/evidence-aligner.ts +635 -0
  87. package/src/core/graduation.ts +365 -0
  88. package/src/core/index.ts +32 -0
  89. package/src/core/matcher.ts +210 -0
  90. package/src/core/metadata-extractor.ts +203 -0
  91. package/src/core/privacy/filter.ts +179 -0
  92. package/src/core/privacy/index.ts +20 -0
  93. package/src/core/privacy/tag-parser.ts +145 -0
  94. package/src/core/progressive-retriever.ts +415 -0
  95. package/src/core/retriever.ts +235 -0
  96. package/src/core/task/blocker-resolver.ts +325 -0
  97. package/src/core/task/index.ts +9 -0
  98. package/src/core/task/task-matcher.ts +238 -0
  99. package/src/core/task/task-projector.ts +345 -0
  100. package/src/core/task/task-resolver.ts +414 -0
  101. package/src/core/types.ts +841 -0
  102. package/src/core/vector-outbox.ts +295 -0
  103. package/src/core/vector-store.ts +182 -0
  104. package/src/core/vector-worker.ts +488 -0
  105. package/src/core/working-set-store.ts +244 -0
  106. package/src/hooks/post-tool-use.ts +127 -0
  107. package/src/hooks/session-end.ts +78 -0
  108. package/src/hooks/session-start.ts +57 -0
  109. package/src/hooks/stop.ts +78 -0
  110. package/src/hooks/user-prompt-submit.ts +54 -0
  111. package/src/mcp/handlers.ts +212 -0
  112. package/src/mcp/index.ts +47 -0
  113. package/src/mcp/tools.ts +78 -0
  114. package/src/server/api/citations.ts +101 -0
  115. package/src/server/api/events.ts +101 -0
  116. package/src/server/api/index.ts +18 -0
  117. package/src/server/api/search.ts +98 -0
  118. package/src/server/api/sessions.ts +111 -0
  119. package/src/server/api/stats.ts +97 -0
  120. package/src/server/index.ts +91 -0
  121. package/src/services/memory-service.ts +626 -0
  122. package/src/services/session-history-importer.ts +367 -0
  123. package/tests/canonical-key.test.ts +101 -0
  124. package/tests/evidence-aligner.test.ts +152 -0
  125. package/tests/matcher.test.ts +112 -0
  126. package/tsconfig.json +24 -0
  127. package/vitest.config.ts +15 -0
@@ -0,0 +1,570 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Code Memory CLI
4
+ * Command-line interface for memory operations
5
+ */
6
+
7
+ import { Command } from 'commander';
8
+ import { getDefaultMemoryService } from '../services/memory-service.js';
9
+ import { createSessionHistoryImporter } from '../services/session-history-importer.js';
10
+
11
+ const program = new Command();
12
+
13
+ program
14
+ .name('code-memory')
15
+ .description('Claude Code Memory Plugin CLI')
16
+ .version('1.0.0');
17
+
18
+ /**
19
+ * Search command
20
+ */
21
+ program
22
+ .command('search <query>')
23
+ .description('Search memories using semantic search')
24
+ .option('-k, --top-k <number>', 'Number of results', '5')
25
+ .option('-s, --min-score <number>', 'Minimum similarity score', '0.7')
26
+ .option('--session <id>', 'Filter by session ID')
27
+ .action(async (query: string, options) => {
28
+ const service = getDefaultMemoryService();
29
+
30
+ try {
31
+ const result = await service.retrieveMemories(query, {
32
+ topK: parseInt(options.topK),
33
+ minScore: parseFloat(options.minScore),
34
+ sessionId: options.session
35
+ });
36
+
37
+ console.log('\nšŸ“š Search Results\n');
38
+ console.log(`Confidence: ${result.matchResult.confidence}`);
39
+ console.log(`Total memories found: ${result.memories.length}\n`);
40
+
41
+ for (const memory of result.memories) {
42
+ const date = memory.event.timestamp.toISOString().split('T')[0];
43
+ console.log(`---`);
44
+ console.log(`šŸ“Œ ${memory.event.eventType} (${date})`);
45
+ console.log(` Score: ${memory.score.toFixed(3)}`);
46
+ console.log(` Session: ${memory.event.sessionId.slice(0, 8)}...`);
47
+ console.log(` Content: ${memory.event.content.slice(0, 200)}${memory.event.content.length > 200 ? '...' : ''}`);
48
+ console.log('');
49
+ }
50
+
51
+ await service.shutdown();
52
+ } catch (error) {
53
+ console.error('Search failed:', error);
54
+ process.exit(1);
55
+ }
56
+ });
57
+
58
+ /**
59
+ * History command
60
+ */
61
+ program
62
+ .command('history')
63
+ .description('View conversation history')
64
+ .option('-l, --limit <number>', 'Number of events', '20')
65
+ .option('--session <id>', 'Filter by session ID')
66
+ .option('--type <type>', 'Filter by event type')
67
+ .action(async (options) => {
68
+ const service = getDefaultMemoryService();
69
+
70
+ try {
71
+ let events;
72
+
73
+ if (options.session) {
74
+ events = await service.getSessionHistory(options.session);
75
+ } else {
76
+ events = await service.getRecentEvents(parseInt(options.limit));
77
+ }
78
+
79
+ if (options.type) {
80
+ events = events.filter(e => e.eventType === options.type);
81
+ }
82
+
83
+ console.log('\nšŸ“œ Memory History\n');
84
+ console.log(`Total events: ${events.length}\n`);
85
+
86
+ for (const event of events.slice(0, parseInt(options.limit))) {
87
+ const date = event.timestamp.toISOString();
88
+ const icon = event.eventType === 'user_prompt' ? 'šŸ‘¤' :
89
+ event.eventType === 'agent_response' ? 'šŸ¤–' : 'šŸ“';
90
+
91
+ console.log(`${icon} [${date}] ${event.eventType}`);
92
+ console.log(` Session: ${event.sessionId.slice(0, 8)}...`);
93
+ console.log(` ${event.content.slice(0, 150)}${event.content.length > 150 ? '...' : ''}`);
94
+ console.log('');
95
+ }
96
+
97
+ await service.shutdown();
98
+ } catch (error) {
99
+ console.error('History failed:', error);
100
+ process.exit(1);
101
+ }
102
+ });
103
+
104
+ /**
105
+ * Stats command
106
+ */
107
+ program
108
+ .command('stats')
109
+ .description('View memory statistics')
110
+ .action(async () => {
111
+ const service = getDefaultMemoryService();
112
+
113
+ try {
114
+ const stats = await service.getStats();
115
+
116
+ console.log('\nšŸ“Š Memory Statistics\n');
117
+ console.log(`Total Events: ${stats.totalEvents}`);
118
+ console.log(`Vector Count: ${stats.vectorCount}`);
119
+ console.log('\nMemory Levels:');
120
+
121
+ for (const level of stats.levelStats) {
122
+ const bar = 'ā–ˆ'.repeat(Math.min(20, Math.ceil(level.count / 10)));
123
+ console.log(` ${level.level}: ${bar} ${level.count}`);
124
+ }
125
+
126
+ await service.shutdown();
127
+ } catch (error) {
128
+ console.error('Stats failed:', error);
129
+ process.exit(1);
130
+ }
131
+ });
132
+
133
+ /**
134
+ * Forget command
135
+ */
136
+ program
137
+ .command('forget [eventId]')
138
+ .description('Remove memories from storage')
139
+ .option('--session <id>', 'Forget all events from a session')
140
+ .option('--before <date>', 'Forget events before date (YYYY-MM-DD)')
141
+ .option('--confirm', 'Skip confirmation')
142
+ .action(async (eventId: string | undefined, options) => {
143
+ const service = getDefaultMemoryService();
144
+
145
+ try {
146
+ if (!eventId && !options.session && !options.before) {
147
+ console.error('Please specify an event ID, --session, or --before option');
148
+ process.exit(1);
149
+ }
150
+
151
+ if (!options.confirm) {
152
+ console.log('āš ļø This will remove memories from storage.');
153
+ console.log('Add --confirm to proceed.');
154
+ process.exit(0);
155
+ }
156
+
157
+ // Note: Full forget implementation would require additional EventStore methods
158
+ console.log('šŸ—‘ļø Forget functionality requires additional implementation.');
159
+ console.log('Events are append-only; soft-delete markers would be added.');
160
+
161
+ await service.shutdown();
162
+ } catch (error) {
163
+ console.error('Forget failed:', error);
164
+ process.exit(1);
165
+ }
166
+ });
167
+
168
+ /**
169
+ * Process command - manually process pending embeddings
170
+ */
171
+ program
172
+ .command('process')
173
+ .description('Process pending embeddings')
174
+ .action(async () => {
175
+ const service = getDefaultMemoryService();
176
+
177
+ try {
178
+ console.log('ā³ Processing pending embeddings...');
179
+ const count = await service.processPendingEmbeddings();
180
+ console.log(`āœ… Processed ${count} embeddings`);
181
+
182
+ await service.shutdown();
183
+ } catch (error) {
184
+ console.error('Process failed:', error);
185
+ process.exit(1);
186
+ }
187
+ });
188
+
189
+ /**
190
+ * Import command - import existing Claude Code sessions
191
+ */
192
+ program
193
+ .command('import')
194
+ .description('Import existing Claude Code conversation history')
195
+ .option('-p, --project <path>', 'Import from specific project path')
196
+ .option('-s, --session <file>', 'Import specific session file (JSONL)')
197
+ .option('-a, --all', 'Import all sessions from all projects')
198
+ .option('-l, --limit <number>', 'Limit messages per session')
199
+ .option('-v, --verbose', 'Show detailed progress')
200
+ .action(async (options) => {
201
+ const service = getDefaultMemoryService();
202
+ const importer = createSessionHistoryImporter(service);
203
+
204
+ try {
205
+ await service.initialize();
206
+
207
+ let result;
208
+
209
+ if (options.session) {
210
+ // Import specific session file
211
+ console.log(`\nšŸ“„ Importing session: ${options.session}\n`);
212
+ result = await importer.importSessionFile(options.session, {
213
+ projectPath: options.project,
214
+ limit: options.limit ? parseInt(options.limit) : undefined,
215
+ verbose: options.verbose
216
+ });
217
+ } else if (options.project) {
218
+ // Import all sessions from a project
219
+ console.log(`\nšŸ“„ Importing project: ${options.project}\n`);
220
+ result = await importer.importProject(options.project, {
221
+ limit: options.limit ? parseInt(options.limit) : undefined,
222
+ verbose: options.verbose
223
+ });
224
+ } else if (options.all) {
225
+ // Import all sessions from all projects
226
+ console.log('\nšŸ“„ Importing all sessions from all projects\n');
227
+ result = await importer.importAll({
228
+ limit: options.limit ? parseInt(options.limit) : undefined,
229
+ verbose: options.verbose
230
+ });
231
+ } else {
232
+ // Default: import current project
233
+ const cwd = process.cwd();
234
+ console.log(`\nšŸ“„ Importing sessions for current project: ${cwd}\n`);
235
+ result = await importer.importProject(cwd, {
236
+ projectPath: cwd,
237
+ limit: options.limit ? parseInt(options.limit) : undefined,
238
+ verbose: options.verbose
239
+ });
240
+ }
241
+
242
+ // Process embeddings
243
+ console.log('\nā³ Processing embeddings...');
244
+ const embedCount = await service.processPendingEmbeddings();
245
+
246
+ // Show results
247
+ console.log('\nāœ… Import Complete\n');
248
+ console.log(`Sessions processed: ${result.totalSessions}`);
249
+ console.log(`Total messages: ${result.totalMessages}`);
250
+ console.log(`Imported prompts: ${result.importedPrompts}`);
251
+ console.log(`Imported responses: ${result.importedResponses}`);
252
+ console.log(`Skipped duplicates: ${result.skippedDuplicates}`);
253
+ console.log(`Embeddings processed: ${embedCount}`);
254
+
255
+ if (result.errors.length > 0) {
256
+ console.log(`\nāš ļø Errors (${result.errors.length}):`);
257
+ for (const error of result.errors.slice(0, 5)) {
258
+ console.log(` - ${error}`);
259
+ }
260
+ if (result.errors.length > 5) {
261
+ console.log(` ... and ${result.errors.length - 5} more`);
262
+ }
263
+ }
264
+
265
+ await service.shutdown();
266
+ } catch (error) {
267
+ console.error('Import failed:', error);
268
+ process.exit(1);
269
+ }
270
+ });
271
+
272
+ /**
273
+ * List command - list available sessions for import
274
+ */
275
+ program
276
+ .command('list')
277
+ .description('List available Claude Code sessions')
278
+ .option('-p, --project <path>', 'Filter by project path')
279
+ .action(async (options) => {
280
+ const service = getDefaultMemoryService();
281
+ const importer = createSessionHistoryImporter(service);
282
+
283
+ try {
284
+ const sessions = await importer.listAvailableSessions(options.project);
285
+
286
+ console.log('\nšŸ“‹ Available Sessions\n');
287
+ console.log(`Found ${sessions.length} session(s)\n`);
288
+
289
+ for (const session of sessions.slice(0, 20)) {
290
+ const date = session.modifiedAt.toISOString().split('T')[0];
291
+ const sizeKB = (session.size / 1024).toFixed(1);
292
+ console.log(`šŸ“ ${session.sessionId.slice(0, 16)}...`);
293
+ console.log(` Modified: ${date}`);
294
+ console.log(` Size: ${sizeKB} KB`);
295
+ console.log(` Path: ${session.filePath}`);
296
+ console.log('');
297
+ }
298
+
299
+ if (sessions.length > 20) {
300
+ console.log(`... and ${sessions.length - 20} more sessions`);
301
+ }
302
+
303
+ console.log('\nUse "code-memory import --session <path>" to import a specific session');
304
+ } catch (error) {
305
+ console.error('List failed:', error);
306
+ process.exit(1);
307
+ }
308
+ });
309
+
310
+ // ============================================================
311
+ // Endless Mode Commands
312
+ // ============================================================
313
+
314
+ /**
315
+ * Endless Mode parent command
316
+ */
317
+ const endlessCmd = program
318
+ .command('endless')
319
+ .description('Manage Endless Mode (biomimetic continuous memory)');
320
+
321
+ /**
322
+ * Enable Endless Mode
323
+ */
324
+ endlessCmd
325
+ .command('enable')
326
+ .description('Enable Endless Mode')
327
+ .action(async () => {
328
+ const service = getDefaultMemoryService();
329
+
330
+ try {
331
+ await service.initialize();
332
+ await service.setMode('endless');
333
+
334
+ console.log('\nā™¾ļø Endless Mode Enabled\n');
335
+ console.log('Your conversations will now be continuously integrated');
336
+ console.log('across session boundaries.\n');
337
+ console.log('Features:');
338
+ console.log(' - Working Set: Recent context kept active');
339
+ console.log(' - Consolidation: Automatic memory integration');
340
+ console.log(' - Continuity: Seamless context transitions\n');
341
+ console.log('Use "code-memory endless status" to view current state');
342
+
343
+ await service.shutdown();
344
+ } catch (error) {
345
+ console.error('Enable failed:', error);
346
+ process.exit(1);
347
+ }
348
+ });
349
+
350
+ /**
351
+ * Disable Endless Mode
352
+ */
353
+ endlessCmd
354
+ .command('disable')
355
+ .description('Disable Endless Mode (return to Session Mode)')
356
+ .action(async () => {
357
+ const service = getDefaultMemoryService();
358
+
359
+ try {
360
+ await service.initialize();
361
+ await service.setMode('session');
362
+
363
+ console.log('\nšŸ“‹ Session Mode Enabled\n');
364
+ console.log('Returned to traditional session-based memory.');
365
+ console.log('Existing Endless Mode data is preserved for future use.');
366
+
367
+ await service.shutdown();
368
+ } catch (error) {
369
+ console.error('Disable failed:', error);
370
+ process.exit(1);
371
+ }
372
+ });
373
+
374
+ /**
375
+ * Endless Mode Status
376
+ */
377
+ endlessCmd
378
+ .command('status')
379
+ .description('Show Endless Mode status')
380
+ .action(async () => {
381
+ const service = getDefaultMemoryService();
382
+
383
+ try {
384
+ await service.initialize();
385
+ const status = await service.getEndlessModeStatus();
386
+
387
+ const modeIcon = status.mode === 'endless' ? 'ā™¾ļø' : 'šŸ“‹';
388
+ const modeName = status.mode === 'endless' ? 'Endless Mode' : 'Session Mode';
389
+
390
+ console.log(`\n${modeIcon} ${modeName}\n`);
391
+
392
+ if (status.mode === 'endless') {
393
+ // Continuity score bar
394
+ const continuityBars = 'ā–ˆ'.repeat(Math.round(status.continuityScore * 10));
395
+ const continuityEmpty = 'ā–‘'.repeat(10 - Math.round(status.continuityScore * 10));
396
+
397
+ console.log('šŸ“Š Status:');
398
+ console.log(` Working Set: ${status.workingSetSize} events`);
399
+ console.log(` Continuity: [${continuityBars}${continuityEmpty}] ${(status.continuityScore * 100).toFixed(0)}%`);
400
+ console.log(` Consolidated: ${status.consolidatedCount} memories`);
401
+
402
+ if (status.lastConsolidation) {
403
+ const ago = Math.round((Date.now() - status.lastConsolidation.getTime()) / 60000);
404
+ console.log(` Last Consolidation: ${ago} minutes ago`);
405
+ } else {
406
+ console.log(' Last Consolidation: Never');
407
+ }
408
+ } else {
409
+ console.log('Endless Mode is disabled.');
410
+ console.log('Use "code-memory endless enable" to activate.');
411
+ }
412
+
413
+ await service.shutdown();
414
+ } catch (error) {
415
+ console.error('Status failed:', error);
416
+ process.exit(1);
417
+ }
418
+ });
419
+
420
+ /**
421
+ * Consolidate command - manually trigger consolidation
422
+ */
423
+ endlessCmd
424
+ .command('consolidate')
425
+ .description('Manually trigger memory consolidation')
426
+ .action(async () => {
427
+ const service = getDefaultMemoryService();
428
+
429
+ try {
430
+ await service.initialize();
431
+
432
+ if (!service.isEndlessModeActive()) {
433
+ console.log('\nāš ļø Endless Mode is not active');
434
+ console.log('Use "code-memory endless enable" first');
435
+ process.exit(1);
436
+ }
437
+
438
+ console.log('\nā³ Running memory consolidation...');
439
+ const count = await service.forceConsolidation();
440
+
441
+ if (count > 0) {
442
+ console.log(`\nāœ… Consolidated ${count} memory group(s)`);
443
+ } else {
444
+ console.log('\nšŸ“‹ No memories to consolidate');
445
+ console.log('(Working set may not have enough events yet)');
446
+ }
447
+
448
+ await service.shutdown();
449
+ } catch (error) {
450
+ console.error('Consolidation failed:', error);
451
+ process.exit(1);
452
+ }
453
+ });
454
+
455
+ /**
456
+ * Working Set command - view current working set
457
+ */
458
+ endlessCmd
459
+ .command('working-set')
460
+ .alias('ws')
461
+ .description('View current working set')
462
+ .option('-l, --limit <number>', 'Number of events to show', '10')
463
+ .action(async (options) => {
464
+ const service = getDefaultMemoryService();
465
+
466
+ try {
467
+ await service.initialize();
468
+
469
+ if (!service.isEndlessModeActive()) {
470
+ console.log('\nāš ļø Endless Mode is not active');
471
+ console.log('Use "code-memory endless enable" first');
472
+ process.exit(1);
473
+ }
474
+
475
+ const workingSet = await service.getWorkingSet();
476
+
477
+ if (!workingSet || workingSet.recentEvents.length === 0) {
478
+ console.log('\nšŸ“‹ Working Set is empty');
479
+ console.log('Events will be added as you interact with Claude');
480
+ process.exit(0);
481
+ }
482
+
483
+ console.log('\n🧠 Working Set\n');
484
+ console.log(`Total events: ${workingSet.recentEvents.length}`);
485
+ console.log(`Continuity score: ${(workingSet.continuityScore * 100).toFixed(0)}%`);
486
+ console.log(`Last activity: ${workingSet.lastActivity.toISOString()}\n`);
487
+
488
+ const limit = parseInt(options.limit);
489
+ const events = workingSet.recentEvents.slice(0, limit);
490
+
491
+ for (const event of events) {
492
+ const icon = event.eventType === 'user_prompt' ? 'šŸ‘¤' :
493
+ event.eventType === 'agent_response' ? 'šŸ¤–' :
494
+ event.eventType === 'tool_observation' ? 'šŸ”§' : 'šŸ“';
495
+ const time = event.timestamp.toLocaleTimeString();
496
+ const preview = event.content.slice(0, 80) + (event.content.length > 80 ? '...' : '');
497
+
498
+ console.log(`${icon} [${time}] ${event.eventType}`);
499
+ console.log(` ${preview}`);
500
+ console.log('');
501
+ }
502
+
503
+ if (workingSet.recentEvents.length > limit) {
504
+ console.log(`... and ${workingSet.recentEvents.length - limit} more events`);
505
+ }
506
+
507
+ await service.shutdown();
508
+ } catch (error) {
509
+ console.error('Working set failed:', error);
510
+ process.exit(1);
511
+ }
512
+ });
513
+
514
+ /**
515
+ * Consolidated memories command
516
+ */
517
+ endlessCmd
518
+ .command('memories')
519
+ .description('View consolidated memories')
520
+ .option('-l, --limit <number>', 'Number of memories to show', '10')
521
+ .option('-q, --query <text>', 'Search consolidated memories')
522
+ .action(async (options) => {
523
+ const service = getDefaultMemoryService();
524
+
525
+ try {
526
+ await service.initialize();
527
+
528
+ let memories;
529
+
530
+ if (options.query) {
531
+ memories = await service.searchConsolidated(options.query, {
532
+ topK: parseInt(options.limit)
533
+ });
534
+ console.log(`\nšŸ” Searching for: "${options.query}"\n`);
535
+ } else {
536
+ memories = await service.getConsolidatedMemories(parseInt(options.limit));
537
+ console.log('\nšŸ’¾ Consolidated Memories\n');
538
+ }
539
+
540
+ if (memories.length === 0) {
541
+ console.log('No consolidated memories found.');
542
+ if (!service.isEndlessModeActive()) {
543
+ console.log('Enable Endless Mode to start consolidating memories.');
544
+ }
545
+ process.exit(0);
546
+ }
547
+
548
+ console.log(`Showing ${memories.length} memory(ies)\n`);
549
+
550
+ for (const memory of memories) {
551
+ const date = memory.createdAt.toISOString().split('T')[0];
552
+ const confidenceBars = 'ā–ˆ'.repeat(Math.round(memory.confidence * 5));
553
+
554
+ console.log(`šŸ“š ${memory.topics.slice(0, 3).join(', ')}`);
555
+ console.log(` Created: ${date}`);
556
+ console.log(` Confidence: [${confidenceBars}] ${(memory.confidence * 100).toFixed(0)}%`);
557
+ console.log(` Sources: ${memory.sourceEvents.length} events`);
558
+ console.log(` Access count: ${memory.accessCount}`);
559
+ console.log(` Summary: ${memory.summary.slice(0, 200)}${memory.summary.length > 200 ? '...' : ''}`);
560
+ console.log('');
561
+ }
562
+
563
+ await service.shutdown();
564
+ } catch (error) {
565
+ console.error('Memories failed:', error);
566
+ process.exit(1);
567
+ }
568
+ });
569
+
570
+ program.parse();