@cachly-dev/mcp-server 0.10.88 → 0.10.90

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/dist/src/index.js CHANGED
@@ -792,7 +792,7 @@ async function handleTool(name, args) {
792
792
  '',
793
793
  'Run the setup wizard once in your terminal:',
794
794
  ' ```',
795
- ' npx @cachly-dev/mcp-server@latest setup',
795
+ ' npx @cachly-dev/mcp-server@latest autopilot',
796
796
  ' ```',
797
797
  '',
798
798
  'Or get your API key at: https://cachly.dev/setup-ai',
@@ -1406,7 +1406,7 @@ if (process.argv[2] === 'digest') {
1406
1406
  const instanceId = process.env.CACHLY_BRAIN_INSTANCE_ID ?? '';
1407
1407
  if (!apiKey || !instanceId) {
1408
1408
  console.log('\n⚠️ CACHLY_JWT and CACHLY_BRAIN_INSTANCE_ID must be set.');
1409
- console.log(' Run: npx @cachly-dev/mcp-server@latest setup\n');
1409
+ console.log(' Run: npx @cachly-dev/mcp-server@latest autopilot\n');
1410
1410
  process.exit(1);
1411
1411
  }
1412
1412
  process.stdout.write('\n🧠 Fetching your weekly Brain digest...\n\n');
@@ -1495,7 +1495,7 @@ if (process.argv[2] === 'invite') {
1495
1495
  const apiKey = process.env.CACHLY_JWT ?? '';
1496
1496
  if (!apiKey) {
1497
1497
  console.log('\n⚠️ CACHLY_JWT must be set.');
1498
- console.log(' Run: npx @cachly-dev/mcp-server@latest setup\n');
1498
+ console.log(' Run: npx @cachly-dev/mcp-server@latest autopilot\n');
1499
1499
  process.exit(1);
1500
1500
  }
1501
1501
  try {
@@ -1742,7 +1742,7 @@ if (process.argv[2] === 'upgrade') {
1742
1742
  console.log('');
1743
1743
  console.log(' Update your editor configs to pick up the new version:');
1744
1744
  console.log('');
1745
- console.log(' \x1b[32m npx @cachly-dev/mcp-server@latest setup\x1b[0m');
1745
+ console.log(' \x1b[32m npx @cachly-dev/mcp-server@latest autopilot\x1b[0m');
1746
1746
  console.log('');
1747
1747
  console.log(' \x1b[2m(npx always fetches the latest when @latest is specified)\x1b[0m');
1748
1748
  console.log('');
@@ -1754,6 +1754,84 @@ if (process.argv[2] === 'upgrade') {
1754
1754
  }
1755
1755
  process.exit(0);
1756
1756
  }
1757
+ // ── CLI: cachly bench ─────────────────────────────────────────────────────────
1758
+ // Usage: npx @cachly-dev/mcp-server@latest bench [--json] [corpus.json]
1759
+ // Runs the three-ranker recall quality benchmark (cachly vs BM25 vs flat-file)
1760
+ // on the bundled external corpus. No auth required. One shareable headline.
1761
+ if (process.argv[2] === 'bench') {
1762
+ const { fileURLToPath } = await import('node:url');
1763
+ const { dirname: _bd, resolve: _br } = await import('node:path');
1764
+ const { loadExternalCorpus, runExternalBenchmark } = await import('./bench/external-corpus.js');
1765
+ const asJson = process.argv.includes('--json');
1766
+ const customPath = process.argv.slice(3).find(a => !a.startsWith('--'));
1767
+ const here = _bd(fileURLToPath(import.meta.url));
1768
+ const corpusPath = customPath
1769
+ ? _br(process.cwd(), customPath)
1770
+ : _br(here, 'bench', 'external', 'sample-corpus.json');
1771
+ try {
1772
+ const corpus = await loadExternalCorpus(corpusPath);
1773
+ const r = await runExternalBenchmark(corpus);
1774
+ if (asJson) {
1775
+ console.log(JSON.stringify({
1776
+ corpus: corpus.name,
1777
+ lessons: r.corpusSize,
1778
+ queries: r.queryCount,
1779
+ cachly_p1: Math.round(r.cachly.precisionAt1 * 1000) / 10,
1780
+ flatfile_p1: Math.round(r.flatfile.precisionAt1 * 1000) / 10,
1781
+ cachly_mrr: Math.round(r.cachly.mrr * 1000) / 10,
1782
+ flatfile_mrr: Math.round(r.flatfile.mrr * 1000) / 10,
1783
+ p1_lift_vs_flatfile_pct: Math.round((r.cachly.precisionAt1 - r.flatfile.precisionAt1) * 1000) / 10,
1784
+ mrr_lift_vs_flatfile_pct: Math.round((r.cachly.mrr - r.flatfile.mrr) * 1000) / 10,
1785
+ }, null, 2));
1786
+ process.exit(0);
1787
+ }
1788
+ const p1Lift = ((r.cachly.precisionAt1 - r.flatfile.precisionAt1) * 100).toFixed(1);
1789
+ const mrrLift = ((r.cachly.mrr - r.flatfile.mrr) * 100).toFixed(1);
1790
+ const p1Bm25 = ((r.cachly.precisionAt1 - r.baseline.precisionAt1) * 100).toFixed(1);
1791
+ const p1Sign = r.cachly.precisionAt1 >= r.flatfile.precisionAt1 ? '\x1b[32m+' : '\x1b[31m';
1792
+ const mrrSign = r.cachly.mrr >= r.flatfile.mrr ? '\x1b[32m+' : '\x1b[31m';
1793
+ console.log('');
1794
+ console.log('\x1b[35m ╔══════════════════════════════════════════════════════════════╗\x1b[0m');
1795
+ console.log('\x1b[35m ║\x1b[0m \x1b[1m🧠 cachly recall quality benchmark\x1b[0m \x1b[35m║\x1b[0m');
1796
+ console.log('\x1b[35m ╚══════════════════════════════════════════════════════════════╝\x1b[0m');
1797
+ console.log('');
1798
+ console.log(` Corpus : ${corpus.name ?? corpusPath}`);
1799
+ console.log(` Dataset: ${r.corpusSize} lessons · ${r.queryCount} queries · 10 engineering domains`);
1800
+ console.log(` (k8s, DB, auth, CI, frontend, API, payments, observability, Node.js, infra)`);
1801
+ console.log('');
1802
+ console.log(' \x1b[1mPrecision@1\x1b[0m (finds the right lesson at rank #1):');
1803
+ console.log(` flat-file memory : \x1b[33m${(r.flatfile.precisionAt1 * 100).toFixed(1)}%\x1b[0m (naive keyword overlap — no quality signal)`);
1804
+ console.log(` raw BM25 : \x1b[33m${(r.baseline.precisionAt1 * 100).toFixed(1)}%\x1b[0m (keyword ranking)`);
1805
+ console.log(` cachly : \x1b[1m\x1b[32m${(r.cachly.precisionAt1 * 100).toFixed(1)}%\x1b[0m (BM25 + quality reranking)`);
1806
+ console.log('');
1807
+ console.log(' \x1b[1mMean Reciprocal Rank\x1b[0m (average rank of the right answer):');
1808
+ console.log(` flat-file memory : \x1b[33m${(r.flatfile.mrr * 100).toFixed(1)}%\x1b[0m`);
1809
+ console.log(` raw BM25 : \x1b[33m${(r.baseline.mrr * 100).toFixed(1)}%\x1b[0m`);
1810
+ console.log(` cachly : \x1b[1m\x1b[32m${(r.cachly.mrr * 100).toFixed(1)}%\x1b[0m`);
1811
+ console.log('');
1812
+ console.log(' \x1b[1mLift vs flat-file memory\x1b[0m (what you get by switching from plain memory files):');
1813
+ console.log(` Precision@1 : ${p1Sign}${p1Lift}%\x1b[0m`);
1814
+ console.log(` MRR : ${mrrSign}${mrrLift}%\x1b[0m`);
1815
+ console.log(` vs BM25 : \x1b[32m+${p1Bm25}%\x1b[0m Precision@1 (quality reranking on top of keyword search)`);
1816
+ console.log('');
1817
+ console.log(' \x1b[2mFlat-file = lexical overlap over raw text files (how Anthropic/Claude Memory works).\x1b[0m');
1818
+ console.log(' \x1b[2mAdversarial distractors included — failure lessons that share the exact query vocabulary.\x1b[0m');
1819
+ console.log(' \x1b[2mcachly ignores them because they have low confidence / failed outcome.\x1b[0m');
1820
+ console.log('');
1821
+ console.log(' Share your results:');
1822
+ console.log(` \x1b[36m"My Brain: Precision@1 ${(r.cachly.precisionAt1 * 100).toFixed(1)}% (${p1Sign}${p1Lift}% vs flat-file memory, ${r.queryCount} queries)"\x1b[0m`);
1823
+ console.log('');
1824
+ console.log(' Run on a custom corpus:');
1825
+ console.log(' \x1b[2m npx @cachly-dev/mcp-server@latest bench my-incidents.json\x1b[0m');
1826
+ console.log(' \x1b[2m npx @cachly-dev/mcp-server@latest bench --json # machine-readable\x1b[0m');
1827
+ console.log('');
1828
+ }
1829
+ catch (e) {
1830
+ console.error(`\n❌ bench failed: ${e.message}\n`);
1831
+ process.exit(1);
1832
+ }
1833
+ process.exit(0);
1834
+ }
1757
1835
  // ── CLI: cachly demo ──────────────────────────────────────────────────────────
1758
1836
  // Usage: npx @cachly-dev/mcp-server@latest demo
1759
1837
  // Zero-signup. Reads local git history and shows what the AI Brain would know.
@@ -1905,7 +1983,7 @@ if (process.argv[2] === 'demo') {
1905
1983
  });
1906
1984
  const previewURL = `https://cachly.dev/preview?${previewParams.toString()}`;
1907
1985
  console.log(' \x1b[1mMake this permanent (free, 1–5 minutes):\x1b[0m');
1908
- console.log(' \x1b[32m$ npx @cachly-dev/mcp-server@latest setup\x1b[0m');
1986
+ console.log(' \x1b[32m$ npx @cachly-dev/mcp-server@latest autopilot\x1b[0m');
1909
1987
  console.log('');
1910
1988
  console.log(` \x1b[90m🔗 Shareable preview:\x1b[0m \x1b[36m${previewURL}\x1b[0m`);
1911
1989
  console.log('');
@@ -1922,7 +2000,7 @@ if (process.argv[2] === 'share') {
1922
2000
  const instanceId = process.env.CACHLY_BRAIN_INSTANCE_ID ?? '';
1923
2001
  if (!apiKey || !instanceId) {
1924
2002
  console.log('\n⚠️ CACHLY_JWT and CACHLY_BRAIN_INSTANCE_ID must be set.');
1925
- console.log(' Run: npx @cachly-dev/mcp-server@latest setup (takes 1–5 minutes)\n');
2003
+ console.log(' Run: npx @cachly-dev/mcp-server@latest autopilot (takes 1–5 minutes)\n');
1926
2004
  process.exit(1);
1927
2005
  }
1928
2006
  process.stdout.write('\n🧠 Fetching your Brain stats...\n');
@@ -1954,7 +2032,7 @@ if (process.argv[2] === 'share') {
1954
2032
  console.log('├─────────────────────────────────────────────────────────────┤');
1955
2033
  console.log('│ Works with: Claude Code · Cursor · Windsurf · Copilot │');
1956
2034
  console.log('│ Free · GDPR · German servers │');
1957
- console.log('│ \x1b[35mnpx @cachly-dev/mcp-server@latest setup\x1b[0m │');
2035
+ console.log('│ \x1b[35mnpx @cachly-dev/mcp-server@latest autopilot\x1b[0m │');
1958
2036
  console.log('└─────────────────────────────────────────────────────────────┘');
1959
2037
  console.log('');
1960
2038
  // Tweet text
@@ -1984,7 +2062,7 @@ if (process.argv[2] === 'publish') {
1984
2062
  const instanceId = process.env.CACHLY_BRAIN_INSTANCE_ID ?? '';
1985
2063
  if (!apiKey || !instanceId) {
1986
2064
  console.log('\n⚠️ CACHLY_JWT and CACHLY_BRAIN_INSTANCE_ID must be set.');
1987
- console.log(' Run: npx @cachly-dev/mcp-server@latest setup\n');
2065
+ console.log(' Run: npx @cachly-dev/mcp-server@latest autopilot\n');
1988
2066
  process.exit(1);
1989
2067
  }
1990
2068
  const titleIdx = process.argv.indexOf('--title');
@@ -2079,7 +2157,7 @@ if (process.argv[2] === 'badge') {
2079
2157
  const instanceId = process.env.CACHLY_BRAIN_INSTANCE_ID ?? '';
2080
2158
  if (!instanceId) {
2081
2159
  console.log('\n⚠️ CACHLY_BRAIN_INSTANCE_ID must be set.');
2082
- console.log(' Run: npx @cachly-dev/mcp-server@latest setup (takes 1–5 minutes)\n');
2160
+ console.log(' Run: npx @cachly-dev/mcp-server@latest autopilot (takes 1–5 minutes)\n');
2083
2161
  process.exit(1);
2084
2162
  }
2085
2163
  const badgeUrl = `${API_URL}/api/v1/badge/${instanceId}`;
@@ -2130,6 +2208,7 @@ if (!process.argv[2] && process.stdout.isTTY) {
2130
2208
  console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest badge\x1b[0m ← README badge for your Brain');
2131
2209
  console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest invite\x1b[0m ← Invite a teammate');
2132
2210
  console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest join <token>\x1b[0m ← Accept a Brain invite');
2211
+ console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest bench\x1b[0m ← Recall quality vs flat-file memory');
2133
2212
  console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest upgrade\x1b[0m ← Check for updates');
2134
2213
  console.log('');
2135
2214
  console.log(' \x1b[90mWorks with: Claude Code · Cursor · Windsurf · GitHub Copilot · Cline · Zed\x1b[0m');
@@ -2176,7 +2255,7 @@ if (process.argv[2] === 'init') {
2176
2255
  }
2177
2256
  if (!instanceId || !apiKey) {
2178
2257
  console.error('\nUsage: npx @cachly-dev/mcp-server@latest init --instance-id <uuid> --api-key <cky_live_...> [--editor claude|cursor|windsurf|copilot|continue] [--project-dir /path] [--api-url https://your-self-hosted-backend]\n');
2179
- console.error('First time? Run the zero-config wizard (signs you in, auto-provisions): npx @cachly-dev/mcp-server@latest setup\n');
2258
+ console.error('First time? Run the zero-config wizard (signs you in, auto-provisions): npx @cachly-dev/mcp-server@latest autopilot\n');
2180
2259
  console.error('Get your credentials from: https://cachly.dev/setup-ai\n');
2181
2260
  process.exit(1);
2182
2261
  }
@@ -2259,7 +2338,7 @@ if (process.argv[2] === 'status') {
2259
2338
  const instanceId = process.env.CACHLY_BRAIN_INSTANCE_ID ?? '';
2260
2339
  if (!apiKey || !instanceId) {
2261
2340
  console.log('\n⚠️ CACHLY_JWT and CACHLY_BRAIN_INSTANCE_ID must be set.');
2262
- console.log(' Run: npx @cachly-dev/mcp-server@latest setup\n');
2341
+ console.log(' Run: npx @cachly-dev/mcp-server@latest autopilot\n');
2263
2342
  process.exit(1);
2264
2343
  }
2265
2344
  try {
@@ -2337,7 +2416,7 @@ if (process.argv[2] === 'health') {
2337
2416
  console.log('🔑 Auth token');
2338
2417
  const jwt = process.env.CACHLY_JWT ?? '';
2339
2418
  if (!jwt) {
2340
- fail('CACHLY_JWT not set — run: npx @cachly-dev/mcp-server@latest setup');
2419
+ fail('CACHLY_JWT not set — run: npx @cachly-dev/mcp-server@latest autopilot');
2341
2420
  }
2342
2421
  else if (jwt.startsWith('cky_')) {
2343
2422
  // Long-lived API key (the credential `setup` provisions). It is not a JWT and
@@ -2486,7 +2565,7 @@ if (process.argv[2] === 'health') {
2486
2565
  }
2487
2566
  }
2488
2567
  if (configsFound === 0) {
2489
- fail('No editor MCP configs found — run: npx @cachly-dev/mcp-server@latest setup');
2568
+ fail('No editor MCP configs found — run: npx @cachly-dev/mcp-server@latest autopilot');
2490
2569
  }
2491
2570
  // ── 5. Git hook ─────────────────────────────────────────────────────────────
2492
2571
  console.log('\n🪝 Git hook (ambient learning)');
@@ -2509,7 +2588,7 @@ if (process.argv[2] === 'health') {
2509
2588
  }
2510
2589
  }
2511
2590
  else {
2512
- warn('.git/hooks/post-commit not found — run: npx @cachly-dev/mcp-server@latest setup');
2591
+ warn('.git/hooks/post-commit not found — run: npx @cachly-dev/mcp-server@latest autopilot');
2513
2592
  }
2514
2593
  // ── 6. Embedding provider (BYOK) ─────────────────────────────────────────────
2515
2594
  console.log('\n🧬 Embedding provider (semantic search)');
@@ -2542,7 +2621,7 @@ if (process.argv[2] === 'health') {
2542
2621
  }
2543
2622
  else {
2544
2623
  console.log(`❌ ${failed} check(s) failed, ${passed} passed\n`);
2545
- console.log(`💡 Fix issues with: npx @cachly-dev/mcp-server@latest setup\n`);
2624
+ console.log(`💡 Fix issues with: npx @cachly-dev/mcp-server@latest autopilot\n`);
2546
2625
  process.exit(1);
2547
2626
  }
2548
2627
  process.exit(0);
@@ -2732,7 +2811,7 @@ if (process.argv[2] === 'setup' || _isAutopilotCli) {
2732
2811
  sendFunnelEvent('device_flow_failed', { reason: 'non_interactive_no_key' });
2733
2812
  console.error('\n ⚠️ This terminal is non-interactive, so the key cannot be pasted here.');
2734
2813
  console.error(' Get your key at the URL above, then set it and re-run setup:\n');
2735
- console.error(' \x1b[1mCACHLY_JWT=cky_live_xxx npx @cachly-dev/mcp-server@latest setup\x1b[0m\n');
2814
+ console.error(' \x1b[1mCACHLY_JWT=cky_live_xxx npx @cachly-dev/mcp-server@latest autopilot\x1b[0m\n');
2736
2815
  console.error(' Or add it to your editor\'s MCP config under env.CACHLY_JWT.\n');
2737
2816
  rl.close();
2738
2817
  process.exit(1);
@@ -3312,7 +3391,7 @@ if (!JWT) {
3312
3391
  // • Editor as an MCP stdio server (non-TTY) → ONE stderr hint, then KEEP RUNNING
3313
3392
  // so tools/list works and the first tool call starts the browser sign-in.
3314
3393
  // Skip entirely for CLI subcommands that intentionally run without credentials.
3315
- const _cliNoAuthCommands = ['demo', 'share', 'publish', 'health', 'setup', 'autopilot', 'init', 'digest', 'invite', 'badge', 'join', 'upgrade', 'tool-specs', 'openapi'];
3394
+ const _cliNoAuthCommands = ['demo', 'share', 'publish', 'health', 'setup', 'autopilot', 'init', 'digest', 'invite', 'badge', 'join', 'upgrade', 'bench', 'tool-specs', 'openapi'];
3316
3395
  if (!JWT && !_cliNoAuthCommands.includes(process.argv[2] ?? '')) {
3317
3396
  const runningInTerminal = !process.argv[2] && process.stdout.isTTY === true && _isMain;
3318
3397
  if (runningInTerminal) {
@@ -3327,9 +3406,9 @@ if (!JWT && !_cliNoAuthCommands.includes(process.argv[2] ?? '')) {
3327
3406
  '║ ║\n' +
3328
3407
  '║ 👉 https://cachly.dev/setup-ai ║\n' +
3329
3408
  '║ ║\n' +
3330
- '║ Then run the interactive setup wizard: ║\n' +
3409
+ '║ Then run the one-command setup wizard: ║\n' +
3331
3410
  '║ ║\n' +
3332
- '║ npx @cachly-dev/mcp-server@latest setup ║\n' +
3411
+ '║ npx @cachly-dev/mcp-server@latest autopilot ║\n' +
3333
3412
  '║ ║\n' +
3334
3413
  '║ Free tier — no credit card required. ║\n' +
3335
3414
  '╚══════════════════════════════════════════════════════════════════╝\n' +
@@ -3343,7 +3422,7 @@ if (!JWT && !_cliNoAuthCommands.includes(process.argv[2] ?? '')) {
3343
3422
  // hint to stderr (shown in the editor's MCP log) and fall through so the
3344
3423
  // server starts and the zero-credential device flow can run on first tool call.
3345
3424
  process.stderr.write('\n🧠 cachly: no CACHLY_JWT set yet — call any cachly tool and a 10-second browser sign-in starts automatically.\n' +
3346
- ' (Or run once: npx @cachly-dev/mcp-server@latest setup)\n\n');
3425
+ ' (Or run once: npx @cachly-dev/mcp-server@latest autopilot)\n\n');
3347
3426
  }
3348
3427
  }
3349
3428
  else {
@@ -3373,7 +3452,7 @@ if (!process.env.CACHLY_NO_UPDATE_CHECK) {
3373
3452
  const latest = data?.version ?? '';
3374
3453
  if (latest && latest !== CURRENT_VERSION) {
3375
3454
  process.stderr.write(`\n⚡ cachly update available: ${CURRENT_VERSION} → ${latest}\n` +
3376
- ` Run: npx @cachly-dev/mcp-server@latest setup\n\n`);
3455
+ ` Run: npx @cachly-dev/mcp-server@latest autopilot\n\n`);
3377
3456
  }
3378
3457
  }
3379
3458
  }