claude-recall 0.7.0 → 0.7.2

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/.claude/CLAUDE.md CHANGED
@@ -84,6 +84,58 @@ Claude Recall provides these MCP tools (access via `mcp__claude-recall__*`):
84
84
  - **`mcp__claude-recall__get_stats`**: View memory statistics
85
85
  - **`mcp__claude-recall__clear_context`**: Clear session context
86
86
 
87
+ ## Intelligence & Evolution (v0.7.0+)
88
+
89
+ ### Automatic Failure Learning
90
+
91
+ Claude Recall now **automatically captures failures with counterfactual reasoning**:
92
+ - **What failed**: The approach or action that didn't work
93
+ - **Why it failed**: Root cause analysis (file not found, permission denied, etc.)
94
+ - **What should be done instead**: Counterfactual suggestion (the right approach)
95
+ - **Preventative checks**: Steps to prevent the failure from recurring
96
+
97
+ **No manual storage needed** - failures are auto-detected from:
98
+ - Error messages and exceptions
99
+ - User corrections ("That didn't work", "Failed", "Error")
100
+
101
+ ### Sophistication Tracking
102
+
103
+ Every memory is **automatically classified by sophistication level**:
104
+ - **L1 Procedural**: Basic tool use, simple actions
105
+ - **L2 Self-Reflection**: Error checking, corrections, learning from failures
106
+ - **L3 Adaptive**: Systematic workflows, devops patterns
107
+ - **L4 Compositional**: Multi-constraint reasoning, complex decision-making
108
+
109
+ View your agent's evolution: `npx claude-recall evolution`
110
+
111
+ ### New CLI Commands (v0.7.0+)
112
+
113
+ **View memory evolution metrics:**
114
+ ```bash
115
+ npx claude-recall evolution # Last 30 days
116
+ npx claude-recall evolution --days 60 # Last 60 days
117
+ npx claude-recall evolution --project my-app # Filter by project
118
+ ```
119
+
120
+ Shows:
121
+ - Progression score (0-100)
122
+ - Sophistication breakdown (L1-L4 percentages)
123
+ - Confidence trends (improving/stable/declining)
124
+ - Failure rate trends (improving/stable/worsening)
125
+
126
+ **View failure memories with counterfactual learning:**
127
+ ```bash
128
+ npx claude-recall failures # Last 10 failures
129
+ npx claude-recall failures --limit 20 # Show 20 most recent
130
+ npx claude-recall failures --project my-app # Filter by project
131
+ ```
132
+
133
+ Shows:
134
+ - What failed and why
135
+ - What should have been done instead
136
+ - Preventative checks to avoid recurrence
137
+ - Alternative approaches to consider
138
+
87
139
  ## Memory Types
88
140
 
89
141
  Memories are categorized by type (sorted by priority):
@@ -181,6 +233,87 @@ Confirm: "✓ Stored preference"
181
233
  5. **Use broad search terms**: Include task type + language + preferences + success/failure/correction
182
234
  6. **Close the loop**: Pre-action search → Execute → Post-action outcome storage
183
235
 
236
+ ## Project Scoping (v0.7.2+)
237
+
238
+ Claude Recall now supports **project-specific memory isolation** to keep universal preferences separate from project-specific information.
239
+
240
+ ### Three Memory Scopes
241
+
242
+ 1. **Universal** (`scope='universal'`): Available in all projects
243
+ - User says: "Remember everywhere: I prefer TypeScript with strict mode"
244
+ - Stored as universal memory, accessible from any project
245
+
246
+ 2. **Project** (`scope='project'`): Only available in current project
247
+ - User says: "For this project, we use PostgreSQL"
248
+ - Stored with project_id, only accessible from this project
249
+
250
+ 3. **Unscoped** (`scope=null`, default): Available everywhere (backward compatible)
251
+ - User says: "I prefer Jest for testing"
252
+ - Stored without scope, works like v0.7.1 and earlier
253
+
254
+ ### Auto-Detection
255
+
256
+ When storing memories, the system automatically detects scope from user language:
257
+
258
+ **Universal indicators**:
259
+ - "remember everywhere"
260
+ - "for all projects"
261
+ - "globally"
262
+ - "always use"
263
+
264
+ **Project indicators**:
265
+ - "for this project"
266
+ - "project-specific"
267
+ - "only here"
268
+ - "in this project"
269
+
270
+ **Default**: If no indicator, memory is unscoped (available everywhere)
271
+
272
+ ### How Search Works
273
+
274
+ **Default behavior** (project + universal):
275
+ ```
276
+ mcp__claude-recall__search("database")
277
+ ```
278
+ Returns: Current project memories + universal memories + unscoped memories
279
+
280
+ **Global search** (all projects):
281
+ ```
282
+ mcp__claude-recall__search("database", filters: { globalSearch: true })
283
+ ```
284
+ Returns: All memories from all projects
285
+
286
+ ### CLI Usage
287
+
288
+ ```bash
289
+ # Current project stats
290
+ npx claude-recall stats
291
+
292
+ # Global stats (all projects)
293
+ npx claude-recall stats --global
294
+
295
+ # Search current project
296
+ npx claude-recall search "database"
297
+
298
+ # Search specific project
299
+ npx claude-recall search "database" --project my-app
300
+
301
+ # Search all projects
302
+ npx claude-recall search "database" --global
303
+ ```
304
+
305
+ ### Use Cases
306
+
307
+ **Universal memories**: Preferences that apply across all your work
308
+ - Coding style: "Always use TypeScript with strict mode"
309
+ - Tools: "Prefer Jest for testing"
310
+ - Conventions: "Name files with kebab-case"
311
+
312
+ **Project memories**: Project-specific details
313
+ - Database: "This project uses PostgreSQL"
314
+ - API: "Base URL is https://api.example.com"
315
+ - Build: "Run npm run build:prod for production"
316
+
184
317
  ## Advanced: Optional Context-Manager Agent
185
318
 
186
319
  For complex multi-step research, a `context-manager` agent is available at `.claude/agents/context-manager.md`.
package/README.md CHANGED
@@ -28,6 +28,13 @@ Every time you start a new conversation with Claude, you're starting from scratc
28
28
  - **Optional agent** - Advanced context-manager agent available for complex workflows
29
29
  - **Correction priority** - User corrections given highest priority (never repeat mistakes)
30
30
 
31
+ ### 🧠 Intelligence & Evolution (v0.7.0+)
32
+ - **Sophistication tracking** - Measures agent progression from basic tool use to compositional reasoning
33
+ - **Failure learning** - Captures what failed, why it failed, and what should be done instead (counterfactual reasoning)
34
+ - **Evolution metrics** - View progression score, confidence trends, and failure rates over time
35
+ - **Structured memories** - Rich Title/Description/Content format for better human readability
36
+ - **Automatic classification** - Memories auto-classified by sophistication level (L1-L4)
37
+
31
38
  ### 🔒 Privacy & Security First
32
39
  - **100% Local** - All memories stored locally in SQLite (~/.claude-recall/)
33
40
  - **No cloud sync** - Your data never leaves your machine
@@ -386,6 +393,148 @@ claude-recall clear --force # Clear everything
386
393
  claude-recall capture user-prompt '{"content":"your message here"}'
387
394
  ```
388
395
 
396
+ ### Intelligence & Evolution Commands (v0.7.0+)
397
+
398
+ ```bash
399
+ # View memory evolution and sophistication metrics
400
+ claude-recall evolution
401
+ claude-recall evolution --days 60 # Analyze last 60 days
402
+ claude-recall evolution --project my-app # Filter by project
403
+
404
+ # View failure memories with counterfactual learning
405
+ claude-recall failures
406
+ claude-recall failures --limit 20 # Show 20 most recent
407
+ claude-recall failures --project my-app # Filter by project
408
+ ```
409
+
410
+ **Example `evolution` output:**
411
+ ```
412
+ 📈 Memory Evolution
413
+
414
+ Analysis Period: Last 30 days
415
+ Total Memories: 145
416
+ Progression Score: 67/100
417
+
418
+ Sophistication Breakdown:
419
+ Procedural (L1): 45 ( 31.0%)
420
+ Self-Reflection (L2): 38 ( 26.2%)
421
+ Adaptive (L3): 52 ( 35.9%)
422
+ Compositional (L4): 10 ( 6.9%)
423
+
424
+ Average Confidence: 0.78 ↗
425
+ Failure Rate: 12.4% ↘
426
+
427
+ ○ Agent developing adaptive patterns
428
+ ```
429
+
430
+ **Example `failures` output:**
431
+ ```
432
+ ❌ Failure Memories (Counterfactual Learning)
433
+
434
+ 1. Avoid: Reading file without existence check
435
+ What Failed: Attempted to read config.json directly
436
+ Why Failed: File does not exist at expected location
437
+ Should Do: Verify file path exists before reading. Use fs.existsSync()
438
+ Preventative Checks:
439
+ - Verify file exists before reading (fs.existsSync)
440
+ - Handle ENOENT errors gracefully
441
+
442
+ 2. Avoid: Session-based authentication
443
+ What Failed: Session-based auth implementation
444
+ Why Failed: User reported: Doesn't scale across multiple servers
445
+ Should Do: Use JWT tokens instead
446
+ ```
447
+
448
+ **Sophistication Levels:**
449
+ - **L1 Procedural**: Basic tool use, simple actions
450
+ - **L2 Self-Reflection**: Error checking, corrections, learning from failures
451
+ - **L3 Adaptive**: Systematic workflows, devops patterns
452
+ - **L4 Compositional**: Multi-constraint reasoning, complex decision-making
453
+
454
+ ## Project Scoping (v0.7.2+)
455
+
456
+ Claude Recall now supports **project-specific memory isolation** while keeping universal preferences available everywhere.
457
+
458
+ ### How It Works
459
+
460
+ - **Single global database**: `~/.claude-recall/claude-recall.db`
461
+ - **Three memory scopes**:
462
+ - **Universal**: Available in all projects (coding preferences, tools)
463
+ - **Project**: Only available in the specific project
464
+ - **Unscoped** (default): Available everywhere (backward compatible)
465
+ - **Project ID**: Automatically detected from directory name
466
+
467
+ ### Storing Memories
468
+
469
+ **Universal memories** (available everywhere):
470
+ ```
471
+ User: "Remember everywhere: I prefer TypeScript with strict mode"
472
+ Claude: [Stores with scope='universal']
473
+ ```
474
+
475
+ **Project-specific memories**:
476
+ ```
477
+ User: "For this project, we use SQLite for the database"
478
+ Claude: [Stores with scope='project', project_id='my-app']
479
+ ```
480
+
481
+ **Default** (unscoped, works like before):
482
+ ```
483
+ User: "I prefer Jest for testing"
484
+ Claude: [Stores with scope=null, available everywhere]
485
+ ```
486
+
487
+ ### Searching with Scopes
488
+
489
+ **Default** (current project + universal):
490
+ ```bash
491
+ npx claude-recall search "database"
492
+ # Returns: Current project memories + universal memories + unscoped
493
+ ```
494
+
495
+ **Specific project**:
496
+ ```bash
497
+ npx claude-recall search "database" --project my-app
498
+ # Returns: my-app memories + universal memories + unscoped
499
+ ```
500
+
501
+ **All projects**:
502
+ ```bash
503
+ npx claude-recall search "database" --global
504
+ # Returns: All memories from all projects
505
+ ```
506
+
507
+ ### Stats with Scopes
508
+
509
+ **Current project**:
510
+ ```bash
511
+ npx claude-recall stats
512
+ # Shows: Memories for current project (claude-recall) + universal + unscoped
513
+ ```
514
+
515
+ **All projects**:
516
+ ```bash
517
+ npx claude-recall stats --global
518
+ # Shows: All memories across all projects
519
+ ```
520
+
521
+ ### Use Cases
522
+
523
+ **Universal memories** (scope='universal'):
524
+ - Coding style preferences: "Always use TypeScript with strict mode"
525
+ - Tool preferences: "Prefer Jest for testing"
526
+ - File naming conventions: "Name markdown files with lowercase-dash-case"
527
+
528
+ **Project-specific memories** (scope='project'):
529
+ - Database choice: "This project uses PostgreSQL"
530
+ - API endpoints: "API base URL is https://api.example.com"
531
+ - Build commands: "Run npm run build:prod for production"
532
+
533
+ **Unscoped memories** (scope=null, default):
534
+ - Backward compatible
535
+ - Works like v0.7.1 and earlier
536
+ - Available everywhere unless you explicitly scope them
537
+
389
538
  ## Memory Management
390
539
 
391
540
  Claude Recall automatically manages memory to prevent unlimited database growth, with user notifications:
@@ -67,13 +67,28 @@ class ClaudeRecallCLI {
67
67
  /**
68
68
  * Show memory statistics
69
69
  */
70
- showStats() {
71
- const stats = this.memoryService.getStats();
70
+ showStats(options) {
71
+ let stats;
72
72
  const configService = config_1.ConfigService.getInstance();
73
73
  const config = configService.getConfig();
74
74
  const maxMemories = config.database.compaction?.maxMemories || 10000;
75
+ if (options?.global) {
76
+ // Show stats for all memories
77
+ stats = this.memoryService.getStats();
78
+ console.log('\n📊 Claude Recall Statistics (All Projects)\n');
79
+ }
80
+ else if (options?.project) {
81
+ // Show stats for specific project + universal
82
+ stats = this.getProjectStats(options.project);
83
+ console.log(`\n📊 Claude Recall Statistics (Project: ${options.project})\n`);
84
+ }
85
+ else {
86
+ // Show stats for current project + universal
87
+ const projectId = configService.getProjectId();
88
+ stats = this.getProjectStats(projectId);
89
+ console.log(`\n📊 Claude Recall Statistics (Project: ${projectId})\n`);
90
+ }
75
91
  const usagePercent = (stats.total / maxMemories) * 100;
76
- console.log('\n📊 Claude Recall Statistics\n');
77
92
  console.log(`Total Memories: ${stats.total}/${maxMemories} (${usagePercent.toFixed(1)}%)`);
78
93
  // Simple status indicator
79
94
  if (usagePercent >= 90) {
@@ -95,6 +110,24 @@ class ClaudeRecallCLI {
95
110
  console.log('\n');
96
111
  this.logger.info('CLI', 'Stats displayed', stats);
97
112
  }
113
+ /**
114
+ * Get stats for a specific project (includes universal and unscoped memories)
115
+ */
116
+ getProjectStats(projectId) {
117
+ const allMemories = this.memoryService.search('');
118
+ const projectMemories = allMemories.filter(m => m.project_id === projectId ||
119
+ m.scope === 'universal' ||
120
+ m.project_id === null);
121
+ // Calculate byType breakdown
122
+ const byType = {};
123
+ for (const mem of projectMemories) {
124
+ byType[mem.type] = (byType[mem.type] || 0) + 1;
125
+ }
126
+ return {
127
+ total: projectMemories.length,
128
+ byType
129
+ };
130
+ }
98
131
  /**
99
132
  * Show skills evolution breakdown
100
133
  */
@@ -254,7 +287,27 @@ class ClaudeRecallCLI {
254
287
  */
255
288
  search(query, options) {
256
289
  const limit = options.limit || 10;
257
- const results = this.memoryService.search(query);
290
+ // Determine search scope
291
+ let results;
292
+ if (options.global) {
293
+ // Global search: all memories
294
+ results = this.memoryService.search(query);
295
+ }
296
+ else if (options.project) {
297
+ // Project-specific search: project + universal
298
+ results = this.memoryService.findRelevant({
299
+ query,
300
+ projectId: options.project
301
+ });
302
+ }
303
+ else {
304
+ // Default: current project + universal
305
+ const config = config_1.ConfigService.getInstance();
306
+ results = this.memoryService.findRelevant({
307
+ query,
308
+ projectId: config.getProjectId()
309
+ });
310
+ }
258
311
  const topResults = results.slice(0, limit);
259
312
  if (options.json) {
260
313
  // Format for hook consumption - include relevance_score field
@@ -566,11 +619,15 @@ async function main() {
566
619
  .description('Search memories by query')
567
620
  .option('-l, --limit <number>', 'Maximum results to show', '10')
568
621
  .option('--json', 'Output as JSON')
622
+ .option('--project <id>', 'Filter by project ID (includes universal memories)')
623
+ .option('--global', 'Search all projects and memories')
569
624
  .action((query, options) => {
570
625
  const cli = new ClaudeRecallCLI(program.opts());
571
626
  cli.search(query, {
572
627
  limit: parseInt(options.limit),
573
- json: options.json
628
+ json: options.json,
629
+ project: options.project,
630
+ global: options.global
574
631
  });
575
632
  process.exit(0);
576
633
  });
@@ -578,9 +635,14 @@ async function main() {
578
635
  program
579
636
  .command('stats')
580
637
  .description('Show memory statistics')
581
- .action(() => {
638
+ .option('--project <id>', 'Filter by project ID')
639
+ .option('--global', 'Show all memories across all projects')
640
+ .action((options) => {
582
641
  const cli = new ClaudeRecallCLI(program.opts());
583
- cli.showStats();
642
+ cli.showStats({
643
+ project: options.project,
644
+ global: options.global
645
+ });
584
646
  process.exit(0);
585
647
  });
586
648
  // Evolution command
@@ -190,10 +190,10 @@ class MemoryCaptureMiddleware {
190
190
  });
191
191
  }
192
192
  }
193
- // PRIORITY 1: Check for explicit "remember" commands
194
- const rememberRegex = /(?:remember|Remember)\s+(?:that\s+)?(.+?)(?:[.!?]|$)/gi;
195
- const rememberMatches = content.matchAll(rememberRegex);
196
- for (const match of rememberMatches) {
193
+ // PRIORITY 1: Check for explicit "remember" or "recall" commands
194
+ const explicitMemoryRegex = /(?:remember|Remember|recall|Recall)\s+(?:that\s+)?(.+?)(?:[.!?]|$)/gi;
195
+ const explicitMemoryMatches = content.matchAll(explicitMemoryRegex);
196
+ for (const match of explicitMemoryMatches) {
197
197
  const memoryContent = match[1].trim();
198
198
  if (memoryContent) {
199
199
  memories.push({
@@ -201,7 +201,7 @@ class MemoryCaptureMiddleware {
201
201
  content: memoryContent,
202
202
  data: {
203
203
  raw: memoryContent,
204
- source: 'explicit_remember_command',
204
+ source: 'explicit_memory_command',
205
205
  confidence: 1.0
206
206
  },
207
207
  confidence: 1.0, // Always highest confidence
@@ -230,7 +230,8 @@ class MemoryCaptureMiddleware {
230
230
  const matches = content.matchAll(regex);
231
231
  for (const match of matches) {
232
232
  // Skip if this was already captured as explicit memory
233
- if (match[0].toLowerCase().includes('remember'))
233
+ const lower = match[0].toLowerCase();
234
+ if (lower.includes('remember') || lower.includes('recall'))
234
235
  continue;
235
236
  memories.push({
236
237
  type: pattern.type,
@@ -86,6 +86,11 @@ class MemoryTools {
86
86
  metadata: {
87
87
  type: 'object',
88
88
  description: 'Optional metadata for the memory'
89
+ },
90
+ scope: {
91
+ type: 'string',
92
+ enum: ['universal', 'project'],
93
+ description: 'Memory scope: "universal" (available in all projects) or "project" (current project only). Default: unscoped (available everywhere for backward compatibility)'
89
94
  }
90
95
  },
91
96
  required: ['content']
@@ -139,7 +144,11 @@ class MemoryTools {
139
144
  },
140
145
  projectId: {
141
146
  type: 'string',
142
- description: 'Filter by project ID'
147
+ description: 'Filter by project ID (includes universal memories)'
148
+ },
149
+ globalSearch: {
150
+ type: 'boolean',
151
+ description: 'Search all projects (ignores projectId filter)'
143
152
  }
144
153
  }
145
154
  },
@@ -264,7 +273,7 @@ class MemoryTools {
264
273
  }
265
274
  async handleStoreMemory(input, context) {
266
275
  try {
267
- const { content, metadata } = input;
276
+ const { content, metadata, scope } = input;
268
277
  if (!content || typeof content !== 'string') {
269
278
  throw new Error('Content is required and must be a string');
270
279
  }
@@ -280,8 +289,9 @@ class MemoryTools {
280
289
  type: 'conversation',
281
290
  context: {
282
291
  sessionId: context.sessionId,
283
- projectId: context.projectId,
284
- timestamp: context.timestamp
292
+ projectId: scope === 'project' ? context.projectId : undefined,
293
+ timestamp: context.timestamp,
294
+ scope: scope || null
285
295
  }
286
296
  });
287
297
  this.logger.info('MemoryTools', 'Memory stored successfully', {
@@ -379,8 +389,15 @@ class MemoryTools {
379
389
  if (filters.type && result.type !== filters.type) {
380
390
  return false;
381
391
  }
382
- if (filters.projectId && result.project_id !== filters.projectId) {
383
- return false;
392
+ // Global search: include all memories
393
+ if (filters.globalSearch) {
394
+ return true;
395
+ }
396
+ // Project-scoped search: include project + universal + unscoped memories
397
+ if (filters.projectId) {
398
+ return result.project_id === filters.projectId ||
399
+ result.scope === 'universal' ||
400
+ result.project_id === null;
384
401
  }
385
402
  return true;
386
403
  });
@@ -14,10 +14,12 @@ CREATE TABLE IF NOT EXISTS memories (
14
14
  superseded_by TEXT,
15
15
  superseded_at INTEGER,
16
16
  confidence_score REAL,
17
- sophistication_level INTEGER DEFAULT 1
17
+ sophistication_level INTEGER DEFAULT 1,
18
+ scope TEXT CHECK(scope IN ('universal', 'project', NULL))
18
19
  );
19
20
 
20
21
  CREATE INDEX IF NOT EXISTS idx_memories_project ON memories(project_id);
22
+ CREATE INDEX IF NOT EXISTS idx_memories_scope_project ON memories(scope, project_id);
21
23
  CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(type);
22
24
  CREATE INDEX IF NOT EXISTS idx_memories_timestamp ON memories(timestamp);
23
25
  CREATE INDEX IF NOT EXISTS idx_memories_preference_key ON memories(preference_key, is_active);
@@ -82,10 +82,10 @@ class MemoryStorage {
82
82
  const stmt = this.db.prepare(`
83
83
  INSERT OR REPLACE INTO memories
84
84
  (key, value, type, project_id, file_path, timestamp, relevance_score, access_count,
85
- preference_key, is_active, superseded_by, superseded_at, confidence_score, sophistication_level)
86
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
85
+ preference_key, is_active, superseded_by, superseded_at, confidence_score, sophistication_level, scope)
86
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
87
87
  `);
88
- stmt.run(memory.key, JSON.stringify(memory.value), memory.type, memory.project_id || null, memory.file_path || null, memory.timestamp || Date.now(), memory.relevance_score || 1.0, memory.access_count || 0, memory.preference_key || null, memory.is_active !== undefined ? (memory.is_active ? 1 : 0) : 1, memory.superseded_by || null, memory.superseded_at || null, memory.confidence_score || null, memory.sophistication_level || 1);
88
+ stmt.run(memory.key, JSON.stringify(memory.value), memory.type, memory.project_id || null, memory.file_path || null, memory.timestamp || Date.now(), memory.relevance_score || 1.0, memory.access_count || 0, memory.preference_key || null, memory.is_active !== undefined ? (memory.is_active ? 1 : 0) : 1, memory.superseded_by || null, memory.superseded_at || null, memory.confidence_score || null, memory.sophistication_level || 1, memory.scope || null);
89
89
  // Force a WAL checkpoint to ensure the data is written to the main database file
90
90
  // This ensures that other processes (like CLI) can see the changes immediately
91
91
  this.db.pragma('wal_checkpoint(TRUNCATE)');
@@ -133,8 +133,9 @@ class MemoryStorage {
133
133
  let query = 'SELECT * FROM memories WHERE 1=1';
134
134
  const params = [];
135
135
  if (context.project_id) {
136
- query += ' AND project_id = ?';
137
- params.push(context.project_id);
136
+ // Include project-specific OR universal OR unscoped (NULL) memories
137
+ query += ' AND (project_id = ? OR scope = ? OR project_id IS NULL)';
138
+ params.push(context.project_id, 'universal');
138
139
  }
139
140
  if (context.file_path) {
140
141
  query += ' AND file_path = ?';
@@ -144,7 +144,12 @@ class ConfigService {
144
144
  return path.join(this.config.logging.directory, logName);
145
145
  }
146
146
  getProjectId() {
147
- return this.config.project.id || this.config.project.rootDir;
147
+ if (this.config.project.id) {
148
+ return this.config.project.id;
149
+ }
150
+ // Use directory name (basename) instead of full path
151
+ const rootDir = this.config.project.rootDir;
152
+ return path.basename(rootDir);
148
153
  }
149
154
  updateConfig(updates) {
150
155
  this.config = this.mergeConfig(this.config, updates);
@@ -35,14 +35,17 @@ class MemoryService {
35
35
  const percent = ((stats.total / maxMemories) * 100).toFixed(0);
36
36
  console.log(`⚠️ Memory usage at ${percent}% (${stats.total}/${maxMemories})`);
37
37
  }
38
+ // Detect scope (v0.8.0)
39
+ const scope = this.detectScope(request);
38
40
  const memory = {
39
41
  key: request.key,
40
42
  value: request.value,
41
43
  type: request.type,
42
- project_id: request.context?.projectId || this.config.getProjectId(),
44
+ project_id: scope === 'universal' ? undefined : (request.context?.projectId || this.config.getProjectId()),
43
45
  file_path: request.context?.filePath,
44
46
  timestamp: request.context?.timestamp || Date.now(),
45
- relevance_score: request.relevanceScore || 1.0
47
+ relevance_score: request.relevanceScore || 1.0,
48
+ scope: scope
46
49
  };
47
50
  // Auto-classify sophistication level (v0.7.0)
48
51
  memory.sophistication_level = this.evolution.classifySophistication(memory);
@@ -354,6 +357,37 @@ class MemoryService {
354
357
  return false;
355
358
  }
356
359
  }
360
+ /**
361
+ * Detect memory scope from request (v0.8.0)
362
+ * @private
363
+ */
364
+ detectScope(request) {
365
+ // Check explicit scope in context
366
+ if (request.context?.scope) {
367
+ return request.context.scope;
368
+ }
369
+ // Extract content for analysis
370
+ const content = typeof request.value === 'string'
371
+ ? request.value
372
+ : JSON.stringify(request.value);
373
+ const lowerContent = content.toLowerCase();
374
+ // Explicit user indicators for universal scope
375
+ if (lowerContent.includes('remember everywhere') ||
376
+ lowerContent.includes('for all projects') ||
377
+ lowerContent.includes('globally') ||
378
+ lowerContent.includes('always use')) {
379
+ return 'universal';
380
+ }
381
+ // Explicit user indicators for project scope
382
+ if (lowerContent.includes('for this project') ||
383
+ lowerContent.includes('project-specific') ||
384
+ lowerContent.includes('only here') ||
385
+ lowerContent.includes('in this project')) {
386
+ return 'project';
387
+ }
388
+ // Default: unscoped (null) for backward compatibility
389
+ return null;
390
+ }
357
391
  /**
358
392
  * Close database connection
359
393
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "claude-recall",
3
- "version": "0.7.0",
4
- "description": "Persistent memory for Claude Code with automatic capture, failure learning, and sophistication tracking via MCP server",
3
+ "version": "0.7.2",
4
+ "description": "Persistent memory for Claude Code with automatic capture, failure learning, sophistication tracking, and project scoping via MCP server",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "claude-recall": "dist/cli/claude-recall-cli.js"