claude-mem-lite 2.3.1 → 2.3.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/install.mjs CHANGED
@@ -21,6 +21,7 @@ const IS_NPX = process.env.npm_command === 'exec' ||
21
21
  const INSTALL_DIR = DATA_DIR;
22
22
  const SERVER_PATH = join(INSTALL_DIR, 'server.mjs');
23
23
  const HOOK_PATH = join(INSTALL_DIR, 'hook.mjs');
24
+ const MARKETPLACE_KEY = 'sdsrss';
24
25
 
25
26
  // ─── Curated Resource Metadata ───────────────────────────────────────────────
26
27
  // Replaces generic name-echo fallback with FTS5-optimized metadata per resource.
@@ -1174,6 +1175,292 @@ const RESOURCE_METADATA = {
1174
1175
  trigger_patterns: 'when user needs data visualization charts dashboards or interactive graph creation',
1175
1176
  },
1176
1177
 
1178
+ // ─── Plugin Skills (locally installed, no git repo) ────────────────────────
1179
+ 'skill:superpowers-executing-plans': {
1180
+ intent_tags: 'execute,plan,implementation,session,review,checkpoint,step-by-step',
1181
+ domain_tags: 'planning,execution,workflow',
1182
+ capability_summary: 'Execute written implementation plans in separate sessions with review checkpoints',
1183
+ trigger_patterns: 'when user has a written implementation plan to execute with review checkpoints',
1184
+ invocation_name: 'superpowers:executing-plans',
1185
+ },
1186
+ 'skill:superpowers-receiving-code-review': {
1187
+ intent_tags: 'code-review,feedback,receiving,review-response,technical-rigor,verification',
1188
+ domain_tags: 'quality,review,workflow',
1189
+ capability_summary: 'Handle received code review feedback with technical rigor and verification before implementing',
1190
+ trigger_patterns: 'when receiving code review feedback especially if unclear or technically questionable',
1191
+ invocation_name: 'superpowers:receiving-code-review',
1192
+ },
1193
+ 'skill:superpowers-subagent-development': {
1194
+ intent_tags: 'subagent,parallel,development,independent,tasks,concurrent,delegation',
1195
+ domain_tags: 'workflow,parallel,automation',
1196
+ capability_summary: 'Execute implementation plans with independent tasks via parallel subagents',
1197
+ trigger_patterns: 'when executing plans with independent tasks that can be parallelized via subagents',
1198
+ invocation_name: 'superpowers:subagent-driven-development',
1199
+ },
1200
+ 'skill:superpowers-finishing-branch': {
1201
+ intent_tags: 'finish,branch,merge,pr,cleanup,integrate,complete,development',
1202
+ domain_tags: 'git,workflow,integration',
1203
+ capability_summary: 'Guide completion of development branches with merge PR or cleanup options',
1204
+ trigger_patterns: 'when implementation is complete tests pass and need to decide how to integrate the work',
1205
+ invocation_name: 'superpowers:finishing-a-development-branch',
1206
+ },
1207
+ 'skill:superpowers-writing-skills': {
1208
+ intent_tags: 'skill,write,create,edit,deploy,verify,author,markdown',
1209
+ domain_tags: 'skills,meta,authoring',
1210
+ capability_summary: 'Create edit and verify Claude Code skills before deployment',
1211
+ trigger_patterns: 'when creating new skills editing existing skills or verifying skills work before deployment',
1212
+ invocation_name: 'superpowers:writing-skills',
1213
+ },
1214
+ 'skill:superpowers-parallel-agents': {
1215
+ intent_tags: 'parallel,agents,dispatch,concurrent,independent,tasks,multi-agent',
1216
+ domain_tags: 'workflow,parallel,agents',
1217
+ capability_summary: 'Dispatch parallel agents for 2+ independent tasks without shared state',
1218
+ trigger_patterns: 'when facing 2 or more independent tasks that can be worked on without shared state',
1219
+ invocation_name: 'superpowers:dispatching-parallel-agents',
1220
+ },
1221
+ 'skill:claude-api': {
1222
+ intent_tags: 'claude,api,anthropic,sdk,build,integration,tool-use,agent-sdk',
1223
+ domain_tags: 'anthropic,api,sdk,ai',
1224
+ capability_summary: 'Build apps with the Claude API or Anthropic SDK including Agent SDK',
1225
+ trigger_patterns: 'when code imports anthropic sdk or user asks to use Claude API Anthropic SDK or Agent SDK',
1226
+ invocation_name: 'claude-api',
1227
+ },
1228
+ 'skill:postgres-patterns': {
1229
+ intent_tags: 'postgresql,postgres,database,query,optimization,schema,indexing,security,supabase',
1230
+ domain_tags: 'postgresql,database,sql,supabase',
1231
+ capability_summary: 'PostgreSQL patterns for query optimization schema design indexing and security',
1232
+ trigger_patterns: 'when user needs PostgreSQL query optimization schema design indexing or security patterns',
1233
+ invocation_name: 'postgres-patterns',
1234
+ },
1235
+ 'skill:multi-model-reviewer': {
1236
+ intent_tags: 'multi-model,review,openrouter,gpt,qwen,claude,code-review,architecture',
1237
+ domain_tags: 'ai,review,quality',
1238
+ capability_summary: 'Multi-model code review via OpenRouter calling Claude GPT Qwen for joint assessment',
1239
+ trigger_patterns: 'when user requests code review architecture review or multi-model multi-angle analysis',
1240
+ invocation_name: 'multi-model-reviewer',
1241
+ },
1242
+ 'skill:build-error-resolver': {
1243
+ intent_tags: 'build,error,typescript,type-error,fix,compile,resolution,minimal',
1244
+ domain_tags: 'build,typescript,debugging',
1245
+ capability_summary: 'Fix build and TypeScript errors with minimal diffs focusing on getting build green',
1246
+ trigger_patterns: 'when build fails or type errors occur needing quick resolution with minimal changes',
1247
+ invocation_name: 'build-error-resolver',
1248
+ },
1249
+ 'skill:perplexity-search': {
1250
+ intent_tags: 'search,web,perplexity,latest,best-practice,documentation,solution',
1251
+ domain_tags: 'search,web,ai',
1252
+ capability_summary: 'Web search via Perplexity AI for latest programming resources and solutions',
1253
+ trigger_patterns: 'when needing latest API docs best practices tool recommendations or searching solutions online',
1254
+ invocation_name: 'perplexity-search',
1255
+ },
1256
+ 'skill:claude-code-plugin-dev': {
1257
+ intent_tags: 'plugin,claude-code,marketplace,mcp,hooks,commands,develop,publish',
1258
+ domain_tags: 'claude,plugin,mcp,development',
1259
+ capability_summary: 'Create and publish Claude Code plugins with correct metadata format and marketplace support',
1260
+ trigger_patterns: 'when building Claude Code plugins getting plugin install errors or packaging MCP servers as plugins',
1261
+ invocation_name: 'claude-code-plugin-dev',
1262
+ },
1263
+ 'skill:npm-cross-platform-release': {
1264
+ intent_tags: 'npm,publish,release,cross-platform,binary,github-actions,npx',
1265
+ domain_tags: 'npm,release,cicd',
1266
+ capability_summary: 'Cross-platform binary build and npm publish via GitHub Actions with npx support',
1267
+ trigger_patterns: 'when user needs to publish npm packages set up cross-platform binary distribution or CI/CD release',
1268
+ invocation_name: 'npm-cross-platform-release',
1269
+ },
1270
+ 'skill:fullstack-qa': {
1271
+ intent_tags: 'qa,fullstack,automation,test,browser,api,ui,e2e,visual,curl',
1272
+ domain_tags: 'testing,qa,browser,web',
1273
+ capability_summary: 'Fullstack automated testing: test suite curl API browser function UI visual review',
1274
+ trigger_patterns: 'when user needs fullstack testing QA automation browser testing API testing or UI visual review',
1275
+ invocation_name: 'fullstack-qa',
1276
+ },
1277
+ 'skill:strategic-compact': {
1278
+ intent_tags: 'compact,context,memory,compression,preserve,manual,window',
1279
+ domain_tags: 'context,workflow,memory',
1280
+ capability_summary: 'Manual context compaction at logical intervals to preserve context through task phases',
1281
+ trigger_patterns: 'when context window is getting full and need strategic compaction to preserve important context',
1282
+ invocation_name: 'strategic-compact',
1283
+ },
1284
+ 'skill:keybindings-help': {
1285
+ intent_tags: 'keybindings,keyboard,shortcuts,rebind,customize,chord,keys',
1286
+ domain_tags: 'claude,config,keyboard',
1287
+ capability_summary: 'Customize Claude Code keyboard shortcuts rebind keys and add chord bindings',
1288
+ trigger_patterns: 'when user wants to customize keyboard shortcuts rebind keys or modify keybindings',
1289
+ invocation_name: 'keybindings-help',
1290
+ },
1291
+ 'skill:simplify': {
1292
+ intent_tags: 'simplify,refactor,reuse,quality,efficiency,review,clean,code',
1293
+ domain_tags: 'quality,refactoring,code',
1294
+ capability_summary: 'Review changed code for reuse quality and efficiency then fix any issues found',
1295
+ trigger_patterns: 'when user wants to review and simplify recently changed code for quality and efficiency',
1296
+ invocation_name: 'simplify',
1297
+ },
1298
+ 'skill:loop': {
1299
+ intent_tags: 'loop,recurring,interval,poll,schedule,repeat,monitor,cron',
1300
+ domain_tags: 'automation,workflow,scheduling',
1301
+ capability_summary: 'Run a prompt or slash command on a recurring interval for monitoring or polling',
1302
+ trigger_patterns: 'when user wants to set up a recurring task poll for status or run something repeatedly',
1303
+ invocation_name: 'loop',
1304
+ },
1305
+ 'skill:feature-dev': {
1306
+ intent_tags: 'feature,development,guided,architecture,codebase,implementation,design',
1307
+ domain_tags: 'development,architecture,workflow',
1308
+ capability_summary: 'Guided feature development with codebase understanding and architecture focus',
1309
+ trigger_patterns: 'when user needs guided feature development with architecture analysis and codebase understanding',
1310
+ invocation_name: 'feature-dev:feature-dev',
1311
+ },
1312
+ 'skill:mem-search': {
1313
+ intent_tags: 'memory,search,manage,recall,observations,sessions,prompts,history',
1314
+ domain_tags: 'memory,ai,claude,search',
1315
+ capability_summary: 'Search and manage project memory including observations sessions and prompts',
1316
+ trigger_patterns: 'when user wants to search memory recall past work manage observations or browse session history',
1317
+ invocation_name: 'claude-mem-lite:mem',
1318
+ },
1319
+
1320
+ // ─── Plugin Commands as Skills ─────────────────────────────────────────────
1321
+ 'skill:commit-clean-gone': {
1322
+ intent_tags: 'git,clean,branch,gone,remote,prune,worktree,cleanup',
1323
+ domain_tags: 'git,cleanup,branch',
1324
+ capability_summary: 'Clean up git branches marked as gone with associated worktree removal',
1325
+ trigger_patterns: 'when user needs to clean up deleted remote branches or prune gone branches',
1326
+ invocation_name: 'commit-commands:clean_gone',
1327
+ },
1328
+ 'skill:commit': {
1329
+ intent_tags: 'git,commit,save,stage,message,changes',
1330
+ domain_tags: 'git,workflow',
1331
+ capability_summary: 'Create a git commit with staged changes',
1332
+ trigger_patterns: 'when user wants to create a git commit',
1333
+ invocation_name: 'commit-commands:commit',
1334
+ },
1335
+ 'skill:commit-push-pr': {
1336
+ intent_tags: 'git,commit,push,pr,pull-request,merge,publish',
1337
+ domain_tags: 'git,workflow,github',
1338
+ capability_summary: 'Commit push and open a pull request in one workflow',
1339
+ trigger_patterns: 'when user wants to commit push and create a PR in one step',
1340
+ invocation_name: 'commit-commands:commit-push-pr',
1341
+ },
1342
+ 'skill:ralph-cancel': {
1343
+ intent_tags: 'ralph,cancel,stop,loop,session,abort',
1344
+ domain_tags: 'ralph,workflow,automation',
1345
+ capability_summary: 'Cancel an active Ralph Loop session',
1346
+ trigger_patterns: 'when user wants to cancel or stop an active Ralph Loop',
1347
+ invocation_name: 'ralph-loop:cancel-ralph',
1348
+ },
1349
+ 'skill:ralph-help': {
1350
+ intent_tags: 'ralph,help,explain,commands,usage,documentation',
1351
+ domain_tags: 'ralph,workflow,help',
1352
+ capability_summary: 'Explain Ralph Loop plugin and list available commands',
1353
+ trigger_patterns: 'when user asks about Ralph Loop what it does or how to use it',
1354
+ invocation_name: 'ralph-loop:help',
1355
+ },
1356
+ 'skill:ralph-loop-start': {
1357
+ intent_tags: 'ralph,loop,start,autonomous,session,continuous',
1358
+ domain_tags: 'ralph,workflow,automation',
1359
+ capability_summary: 'Start Ralph Loop for autonomous continuous session execution',
1360
+ trigger_patterns: 'when user wants to start Ralph Loop for continuous autonomous work',
1361
+ invocation_name: 'ralph-loop:ralph-loop',
1362
+ },
1363
+ 'skill:gsd-resume': {
1364
+ intent_tags: 'gsd,resume,continue,restore,state,project,workspace',
1365
+ domain_tags: 'gsd,project,workflow',
1366
+ capability_summary: 'Resume project execution from saved state with workspace validation',
1367
+ trigger_patterns: 'when user wants to resume a paused GSD project from saved state',
1368
+ invocation_name: 'gsd:resume',
1369
+ },
1370
+ 'skill:gsd-start': {
1371
+ intent_tags: 'gsd,start,project,requirements,plan,discuss,execute',
1372
+ domain_tags: 'gsd,project,workflow',
1373
+ capability_summary: 'Interactive project start — discuss requirements research plan then auto-execute',
1374
+ trigger_patterns: 'when user wants to start a new GSD project with discussion planning and execution',
1375
+ invocation_name: 'gsd:start',
1376
+ },
1377
+ 'skill:gsd-stop': {
1378
+ intent_tags: 'gsd,stop,pause,save,state,checkpoint',
1379
+ domain_tags: 'gsd,project,workflow',
1380
+ capability_summary: 'Save current GSD project state and pause execution',
1381
+ trigger_patterns: 'when user wants to pause or stop a GSD project and save progress',
1382
+ invocation_name: 'gsd:stop',
1383
+ },
1384
+ 'skill:gsd-prd': {
1385
+ intent_tags: 'gsd,prd,requirements,document,description,spec,start',
1386
+ domain_tags: 'gsd,project,requirements',
1387
+ capability_summary: 'Start GSD project from a requirements document or description text',
1388
+ trigger_patterns: 'when user has a PRD or requirements document and wants to start a GSD project from it',
1389
+ invocation_name: 'gsd:prd',
1390
+ },
1391
+ 'skill:gsd-status': {
1392
+ intent_tags: 'gsd,status,progress,overview,dashboard,state',
1393
+ domain_tags: 'gsd,project,monitoring',
1394
+ capability_summary: 'Display GSD project progress overview from canonical state fields',
1395
+ trigger_patterns: 'when user wants to see GSD project status progress or current state',
1396
+ invocation_name: 'gsd:status',
1397
+ },
1398
+
1399
+ // ─── Plugin Agent Types ────────────────────────────────────────────────────
1400
+ 'agent:feature-dev-code-architect': {
1401
+ intent_tags: 'architecture,design,feature,blueprint,codebase,patterns,conventions,plan',
1402
+ domain_tags: 'architecture,development,design',
1403
+ capability_summary: 'Design feature architectures by analyzing codebase patterns with implementation blueprints',
1404
+ trigger_patterns: 'when user needs feature architecture design with codebase analysis and implementation blueprints',
1405
+ invocation_name: 'feature-dev:code-architect',
1406
+ },
1407
+ 'agent:feature-dev-code-reviewer': {
1408
+ intent_tags: 'review,bugs,logic,security,quality,conventions,confidence,priority',
1409
+ domain_tags: 'quality,review,security',
1410
+ capability_summary: 'Review code for bugs security vulnerabilities and quality with confidence-based filtering',
1411
+ trigger_patterns: 'when user needs focused code review for bugs security issues and high-priority quality problems',
1412
+ invocation_name: 'feature-dev:code-reviewer',
1413
+ },
1414
+ 'agent:feature-dev-code-explorer': {
1415
+ intent_tags: 'explore,analyze,trace,execution,architecture,dependencies,understand,codebase',
1416
+ domain_tags: 'architecture,analysis,exploration',
1417
+ capability_summary: 'Deep codebase analysis by tracing execution paths mapping architecture and understanding patterns',
1418
+ trigger_patterns: 'when user needs deep codebase analysis execution path tracing or architecture understanding',
1419
+ invocation_name: 'feature-dev:code-explorer',
1420
+ },
1421
+ 'agent:code-simplifier-agent': {
1422
+ intent_tags: 'simplify,refine,clarity,consistency,maintainability,clean,refactor',
1423
+ domain_tags: 'quality,refactoring,code',
1424
+ capability_summary: 'Simplify and refine code for clarity consistency and maintainability preserving functionality',
1425
+ trigger_patterns: 'when user wants to simplify code improve clarity or refine for consistency and maintainability',
1426
+ invocation_name: 'code-simplifier:code-simplifier',
1427
+ },
1428
+ 'agent:superpowers-code-reviewer-agent': {
1429
+ intent_tags: 'review,plan,standards,major-step,validate,milestone,code-review',
1430
+ domain_tags: 'quality,review,workflow',
1431
+ capability_summary: 'Review completed project steps against original plan and coding standards',
1432
+ trigger_patterns: 'when a major project step is completed and needs review against plan and coding standards',
1433
+ invocation_name: 'superpowers:code-reviewer',
1434
+ },
1435
+ 'agent:gsd-debugger': {
1436
+ intent_tags: 'debug,systematic,root-cause,analysis,fix,diagnose,gsd',
1437
+ domain_tags: 'debugging,gsd,analysis',
1438
+ capability_summary: 'Systematic GSD debugging with root cause analysis and targeted fixes',
1439
+ trigger_patterns: 'when GSD project encounters bugs needing systematic debugging and root cause analysis',
1440
+ invocation_name: 'gsd:debugger',
1441
+ },
1442
+ 'agent:gsd-executor': {
1443
+ intent_tags: 'execute,task,tdd,self-review,structured,result,gsd',
1444
+ domain_tags: 'gsd,execution,tdd',
1445
+ capability_summary: 'Execute one GSD task with TDD self-review and return structured result',
1446
+ trigger_patterns: 'when GSD project needs to execute a single task with TDD and structured output',
1447
+ invocation_name: 'gsd:executor',
1448
+ },
1449
+ 'agent:gsd-reviewer': {
1450
+ intent_tags: 'review,two-stage,quality,post-execution,gsd,verify',
1451
+ domain_tags: 'gsd,review,quality',
1452
+ capability_summary: 'Two-stage code review after GSD executor completes a task',
1453
+ trigger_patterns: 'when GSD executor completes a task and needs two-stage quality review',
1454
+ invocation_name: 'gsd:reviewer',
1455
+ },
1456
+ 'agent:gsd-researcher': {
1457
+ intent_tags: 'research,domain,ecosystem,planning,investigate,gsd,discovery',
1458
+ domain_tags: 'gsd,research,planning',
1459
+ capability_summary: 'Research domain ecosystem and gather information before GSD project planning',
1460
+ trigger_patterns: 'when GSD project needs domain research ecosystem investigation before planning',
1461
+ invocation_name: 'gsd:researcher',
1462
+ },
1463
+
1177
1464
  };
1178
1465
 
1179
1466
  /**
@@ -1193,7 +1480,10 @@ function reindexKnownResources(rdb) {
1193
1480
 
1194
1481
  rdb.transaction(() => {
1195
1482
  for (const [key, meta] of Object.entries(RESOURCE_METADATA)) {
1196
- const [type, name] = key.split(':');
1483
+ const sep = key.indexOf(':');
1484
+ if (sep < 0) continue; // skip malformed keys without type:name separator
1485
+ const type = key.slice(0, sep);
1486
+ const name = key.slice(sep + 1);
1197
1487
  const invName = meta.invocation_name || '';
1198
1488
  update.run(
1199
1489
  meta.intent_tags, meta.domain_tags,
@@ -1205,6 +1495,42 @@ function reindexKnownResources(rdb) {
1205
1495
  })();
1206
1496
  }
1207
1497
 
1498
+ /**
1499
+ * Register plugin resources that have no local files (virtual resources).
1500
+ * These are skills/agents from other installed plugins that the dispatch
1501
+ * system should know about for intelligent recommendation.
1502
+ * Only inserts entries that don't already exist in the resources table.
1503
+ * @param {Database} rdb Registry database handle
1504
+ */
1505
+ function registerVirtualResources(rdb) {
1506
+ const insert = rdb.prepare(`
1507
+ INSERT OR IGNORE INTO resources (name, type, status, source, local_path, invocation_name,
1508
+ intent_tags, domain_tags, capability_summary, trigger_patterns,
1509
+ created_at, updated_at)
1510
+ VALUES (?, ?, 'active', 'preinstalled', '', ?, ?, ?, ?, ?, datetime('now'), datetime('now'))
1511
+ `);
1512
+
1513
+ let count = 0;
1514
+ rdb.transaction(() => {
1515
+ for (const [key, meta] of Object.entries(RESOURCE_METADATA)) {
1516
+ const sep = key.indexOf(':');
1517
+ if (sep < 0) continue;
1518
+ const type = key.slice(0, sep);
1519
+ const name = key.slice(sep + 1);
1520
+ const { changes } = insert.run(
1521
+ name, type,
1522
+ meta.invocation_name || '',
1523
+ meta.intent_tags || name.replace(/-/g, ' '),
1524
+ meta.domain_tags || '',
1525
+ meta.capability_summary || `${type}: ${name.replace(/-/g, ' ')}`,
1526
+ meta.trigger_patterns || `when user needs ${name.replace(/-/g, ' ')}`,
1527
+ );
1528
+ count += changes;
1529
+ }
1530
+ })();
1531
+ return count;
1532
+ }
1533
+
1208
1534
  const cmd = process.argv[2];
1209
1535
  const flags = new Set(process.argv.slice(3));
1210
1536
 
@@ -1319,6 +1645,43 @@ async function install() {
1319
1645
  warn('Try manually: claude mcp add -s user -t stdio mem -- node ' + SERVER_PATH);
1320
1646
  }
1321
1647
 
1648
+ // 3b. Deduplicate: if marketplace plugin also registers MCP + hooks,
1649
+ // clear them to prevent double execution. install.mjs hooks (in settings.json)
1650
+ // point to ~/.claude-mem-lite/ (latest code in dev mode via symlinks),
1651
+ // while plugin hooks use ${CLAUDE_PLUGIN_ROOT} (potentially stale marketplace copy).
1652
+ const pluginDir = join(homedir(), '.claude', 'plugins', 'marketplaces', MARKETPLACE_KEY);
1653
+ const pluginMcpPath = join(pluginDir, '.mcp.json');
1654
+ const pluginHooksPath = join(pluginDir, 'hooks', 'hooks.json');
1655
+
1656
+ if (existsSync(pluginDir)) {
1657
+ // Clear plugin MCP to prevent duplicate "mem" server
1658
+ try {
1659
+ if (existsSync(pluginMcpPath)) {
1660
+ const pluginMcp = JSON.parse(readFileSync(pluginMcpPath, 'utf8'));
1661
+ if (pluginMcp.mcpServers?.mem) {
1662
+ delete pluginMcp.mcpServers.mem;
1663
+ writeFileSync(pluginMcpPath, JSON.stringify(pluginMcp, null, 2) + '\n');
1664
+ ok('Marketplace plugin: MCP cleared (prevents duplicate)');
1665
+ }
1666
+ }
1667
+ } catch (e) { warn(`Marketplace MCP dedup: ${e.message}`); }
1668
+
1669
+ // Clear plugin hooks to prevent double hook execution
1670
+ try {
1671
+ if (existsSync(pluginHooksPath)) {
1672
+ const pluginHooks = JSON.parse(readFileSync(pluginHooksPath, 'utf8'));
1673
+ if (pluginHooks.hooks && Object.keys(pluginHooks.hooks).length > 0) {
1674
+ writeFileSync(pluginHooksPath, JSON.stringify({
1675
+ description: pluginHooks.description || 'claude-mem-lite hooks',
1676
+ _note: 'Hooks managed by install.mjs in settings.json — this file cleared to prevent duplicates',
1677
+ hooks: {}
1678
+ }, null, 2) + '\n');
1679
+ ok('Marketplace plugin: hooks cleared (prevents duplicate)');
1680
+ }
1681
+ }
1682
+ } catch (e) { warn(`Marketplace hooks dedup: ${e.message}`); }
1683
+ }
1684
+
1322
1685
  // 4. Configure hooks (merge: preserve user's existing hooks, replace ours)
1323
1686
  log('Configuring hooks...');
1324
1687
  const settings = readSettings();
@@ -1444,35 +1807,82 @@ async function install() {
1444
1807
  repos.get(r.repo).push(r);
1445
1808
  }
1446
1809
 
1447
- let cloned = 0;
1810
+ let cloned = 0, updated = 0;
1811
+ const deadRepos = new Set(); // repos that no longer exist (404)
1812
+
1813
+ const isRepoNotFound = (err) => {
1814
+ const msg = (err?.stderr ? err.stderr.toString() : '') + (err?.message || '');
1815
+ return /repository.*not found|404/i.test(msg);
1816
+ };
1817
+
1448
1818
  for (const [repoUrl, entries] of repos) {
1449
1819
  const repoName = repoUrl.split('/').slice(-2).join('-');
1450
1820
  const clonePath = join(managedDir, 'repos', repoName);
1821
+ let repoReady = false;
1822
+
1451
1823
  if (!existsSync(clonePath)) {
1824
+ // Fresh clone
1452
1825
  try {
1453
1826
  mkdirSync(join(managedDir, 'repos'), { recursive: true });
1454
1827
  execFileSync('git', ['clone', '--depth', '1', `${repoUrl.replace(/\.git$/, '')}.git`, clonePath], { stdio: 'pipe', timeout: 30000 });
1455
1828
  cloned++;
1456
- } catch {
1457
- warn(` Clone failed: ${repoUrl}`);
1829
+ repoReady = true;
1830
+ } catch (err) {
1831
+ if (isRepoNotFound(err)) {
1832
+ deadRepos.add(repoUrl);
1833
+ warn(` Repo not found (removed?): ${repoUrl}`);
1834
+ } else {
1835
+ warn(` Clone failed: ${repoUrl}`);
1836
+ }
1458
1837
  continue;
1459
1838
  }
1839
+ } else {
1840
+ // Update existing: fetch latest and fast-forward
1841
+ try {
1842
+ const localHash = execFileSync('git', ['-C', clonePath, 'rev-parse', 'HEAD'], { encoding: 'utf8', stdio: 'pipe' }).trim();
1843
+ execFileSync('git', ['-C', clonePath, 'fetch', '--depth', '1', 'origin'], { stdio: 'pipe', timeout: 30000 });
1844
+ const remoteHash = execFileSync('git', ['-C', clonePath, 'rev-parse', 'FETCH_HEAD'], { encoding: 'utf8', stdio: 'pipe' }).trim();
1845
+ if (localHash !== remoteHash) {
1846
+ execFileSync('git', ['-C', clonePath, 'reset', '--hard', 'FETCH_HEAD'], { stdio: 'pipe' });
1847
+ updated++;
1848
+ repoReady = true; // needs re-copy
1849
+ }
1850
+ } catch (err) {
1851
+ if (isRepoNotFound(err)) {
1852
+ deadRepos.add(repoUrl);
1853
+ warn(` Repo not found (removed?): ${repoUrl} — cleaning up`);
1854
+ // Remove local clone
1855
+ try { rmSync(clonePath, { recursive: true, force: true }); } catch {}
1856
+ // Remove extracted resources
1857
+ for (const entry of entries) {
1858
+ const destDir = join(managedDir, entry.type === 'skill' ? 'skills' : 'agents');
1859
+ const destPath = join(destDir, entry.name);
1860
+ try { if (existsSync(destPath)) rmSync(destPath, { recursive: true, force: true }); } catch {}
1861
+ }
1862
+ continue;
1863
+ }
1864
+ // Transient failure — use existing clone as-is
1865
+ }
1460
1866
  }
1461
1867
 
1462
1868
  // Copy resources to managed/skills/ or managed/agents/
1869
+ // Re-copy if repo was freshly cloned or updated
1870
+ mkdirSync(join(managedDir, 'skills'), { recursive: true });
1871
+ mkdirSync(join(managedDir, 'agents'), { recursive: true });
1463
1872
  for (const entry of entries) {
1464
1873
  const srcPath = entry.path === '.' ? clonePath : join(clonePath, entry.path);
1465
1874
  const destDir = join(managedDir, entry.type === 'skill' ? 'skills' : 'agents');
1466
1875
  const destPath = join(destDir, entry.name);
1467
- if (!existsSync(destPath) && existsSync(srcPath)) {
1468
- mkdirSync(destDir, { recursive: true });
1876
+ if (existsSync(srcPath) && (repoReady || !existsSync(destPath))) {
1469
1877
  try {
1878
+ if (existsSync(destPath)) rmSync(destPath, { recursive: true, force: true });
1470
1879
  cpSync(srcPath, destPath, { recursive: true });
1471
1880
  } catch {}
1472
1881
  }
1473
1882
  }
1474
1883
  }
1475
- ok(`Repos cloned (${cloned} new / ${repos.size} total)`);
1884
+ ok(`Repos: ${cloned} cloned, ${updated} updated, ${repos.size - deadRepos.size} active` +
1885
+ (deadRepos.size > 0 ? `, ${deadRepos.size} dead removed` : ''));
1476
1886
 
1477
1887
  // 6b. Init registry DB and record preinstalled entries
1478
1888
  const { ensureRegistryDb } = await import('./registry.mjs');
@@ -1483,15 +1893,30 @@ async function install() {
1483
1893
  INSERT OR REPLACE INTO preinstalled (name, type, repo_url, repo_path, tags, enabled)
1484
1894
  VALUES (?, ?, ?, ?, ?, 1)
1485
1895
  `);
1486
- for (const r of resources) {
1896
+ const activeResources = deadRepos.size > 0
1897
+ ? resources.filter(r => !deadRepos.has(r.repo))
1898
+ : resources;
1899
+ for (const r of activeResources) {
1487
1900
  insertPre.run(r.name, r.type, r.repo, r.path, JSON.stringify(r.tags || []));
1488
1901
  }
1489
- ok(`Registry DB initialized (${resources.length} preinstalled entries)`);
1902
+
1903
+ // Clean up DB entries for dead repos
1904
+ if (deadRepos.size > 0) {
1905
+ const delPre = rdb.prepare('DELETE FROM preinstalled WHERE repo_url = ?');
1906
+ const delRes = rdb.prepare('DELETE FROM resources WHERE repo_url = ?');
1907
+ for (const deadUrl of deadRepos) {
1908
+ try { delPre.run(deadUrl); } catch {}
1909
+ try { delRes.run(deadUrl); } catch {}
1910
+ }
1911
+ }
1912
+ ok(`Registry DB initialized (${activeResources.length} preinstalled entries` +
1913
+ (deadRepos.size > 0 ? `, ${deadRepos.size} dead repos purged` : '') + ')');
1490
1914
 
1491
1915
  // 6c. Fetch GitHub stars (best-effort, unauthenticated)
1492
1916
  log(' Fetching GitHub stars...');
1493
1917
  const starCache = new Map();
1494
1918
  for (const [repoUrl] of repos) {
1919
+ if (deadRepos.has(repoUrl)) continue;
1495
1920
  const match = repoUrl.match(/github\.com\/([^/]+)\/([^/]+)/);
1496
1921
  if (match) {
1497
1922
  try {
@@ -1553,6 +1978,10 @@ async function install() {
1553
1978
  reindexKnownResources(rdb);
1554
1979
  ok('Resource metadata curated (FTS5 reindexed)');
1555
1980
 
1981
+ // Register plugin resources (skills/agents from other plugins, no local files)
1982
+ const virtualCount = registerVirtualResources(rdb);
1983
+ if (virtualCount > 0) ok(`Plugin resources registered: ${virtualCount} virtual entries`);
1984
+
1556
1985
  rdb.close();
1557
1986
  }
1558
1987
  } else {
@@ -1622,8 +2051,8 @@ async function uninstall() {
1622
2051
  }
1623
2052
 
1624
2053
  // 3. Clean plugin system entries from settings.json
1625
- const pluginKey = 'claude-mem-lite@sdsrss';
1626
- const marketplaceKey = 'sdsrss';
2054
+ const pluginKey = `claude-mem-lite@${MARKETPLACE_KEY}`;
2055
+ const marketplaceKey = MARKETPLACE_KEY;
1627
2056
  if (settings.enabledPlugins) {
1628
2057
  delete settings.enabledPlugins[pluginKey];
1629
2058
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.3.1",
3
+ "version": "2.3.3",
4
4
  "description": "Lightweight persistent memory system for Claude Code",
5
5
  "type": "module",
6
6
  "engines": {
@@ -1127,19 +1127,6 @@
1127
1127
  "natural"
1128
1128
  ]
1129
1129
  },
1130
- {
1131
- "name": "claudeception",
1132
- "type": "skill",
1133
- "repo": "https://github.com/blader/Claudeception",
1134
- "path": ".",
1135
- "tags": [
1136
- "meta",
1137
- "skill-extraction",
1138
- "learning",
1139
- "continuous",
1140
- "autonomous"
1141
- ]
1142
- },
1143
1130
  {
1144
1131
  "name": "anthropic-architect",
1145
1132
  "type": "skill",
@@ -374,9 +374,6 @@ const COMPOSITE_EXPR = `(
374
374
  ELSE 0 END
375
375
  )`;
376
376
 
377
- // COMPOSITE_ORDER kept for SEARCH_BY_TYPE_SQL and other queries
378
- const COMPOSITE_ORDER = `ORDER BY ${COMPOSITE_EXPR} ASC`;
379
-
380
377
  const SEARCH_SQL = `
381
378
  SELECT *, composite_score FROM (
382
379
  SELECT r.*,
package/registry.mjs CHANGED
@@ -20,7 +20,7 @@ const RESOURCES_SCHEMA = `
20
20
  repo_stars INTEGER DEFAULT 0,
21
21
  local_path TEXT NOT NULL,
22
22
  file_hash TEXT,
23
- parent_plugin TEXT,
23
+ parent_plugin TEXT, -- unused, kept for schema compat
24
24
  invocation_name TEXT DEFAULT '',
25
25
  intent_tags TEXT DEFAULT '',
26
26
  domain_tags TEXT DEFAULT '',
package/schema.mjs CHANGED
@@ -9,6 +9,7 @@ import { existsSync, mkdirSync, readdirSync, renameSync, rmSync } from 'fs';
9
9
 
10
10
  export const DB_DIR = process.env.CLAUDE_MEM_DIR || join(homedir(), '.claude-mem-lite');
11
11
  export const DB_PATH = join(DB_DIR, 'claude-mem-lite.db');
12
+ export const REGISTRY_DB_PATH = join(DB_DIR, 'resource-registry.db');
12
13
 
13
14
  const CORE_SCHEMA = `
14
15
  CREATE TABLE IF NOT EXISTS sdk_sessions (
package/scripts/setup.sh CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  #
3
3
  # claude-mem-lite SessionStart pre-hook
4
- # Data directory setup and migrations (deps handled by launch.mjs)
4
+ # Data directory setup, migrations, and dependency resolution
5
5
  #
6
6
 
7
7
  set -euo pipefail
@@ -66,5 +66,24 @@ fi
66
66
  # 5. Ensure runtime directory exists (after migration to not mask migration check)
67
67
  mkdir -p "$DATA_DIR/runtime"
68
68
 
69
+ # 6. Ensure native dependencies available for hooks (ESM import needs node_modules in resolution chain)
70
+ # Plugin cache doesn't include node_modules — symlink from data dir or npm install on first run
71
+ if [[ ! -d "$ROOT/node_modules/better-sqlite3" ]]; then
72
+ # Fast path: symlink from data dir (instant, no network needed)
73
+ if [[ -d "$DATA_DIR/node_modules/better-sqlite3" ]]; then
74
+ ln -sfn "$DATA_DIR/node_modules" "$ROOT/node_modules" 2>/dev/null && \
75
+ log_ok "Dependencies linked from $DATA_DIR" || true
76
+ fi
77
+ # Slow path: npm install (first-time only, ~10-20s for native addon)
78
+ if [[ ! -d "$ROOT/node_modules/better-sqlite3" ]]; then
79
+ log_info "Installing dependencies (first-time setup)..."
80
+ if (cd "$ROOT" && npm install --omit=dev --no-audit --no-fund 2>&1) >&2; then
81
+ log_ok "Dependencies installed"
82
+ else
83
+ log_warn "Dependency install failed — hooks may have limited functionality"
84
+ fi
85
+ fi
86
+ fi
87
+
69
88
  log_ok "claude-mem-lite ready"
70
89
  exit 0