@cachly-dev/mcp-server 0.10.84 → 0.10.85

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
@@ -65,7 +65,7 @@ import { Redis } from 'ioredis';
65
65
  let API_URL = process.env.CACHLY_API_URL ?? 'https://api.cachly.dev';
66
66
  let JWT = process.env.CACHLY_JWT ?? '';
67
67
  const _EMBED_MODEL = process.env.CACHLY_EMBED_MODEL ?? '';
68
- const CURRENT_VERSION = '0.10.84';
68
+ const CURRENT_VERSION = '0.10.85';
69
69
  // Max time to wait for a freshly-provisioned instance to become "running" before
70
70
  // giving up. Free-tier provisioning in high-latency regions can take 45–90s, so the
71
71
  // old hard-coded 25s caused spurious "instance_not_reachable" on first run.
@@ -2056,8 +2056,9 @@ if (!process.argv[2] && process.stdout.isTTY) {
2056
2056
  console.log(' cachly gives it a permanent brain — pre-briefed every session.');
2057
2057
  console.log('');
2058
2058
  console.log(' \x1b[1mCommands:\x1b[0m');
2059
- console.log(' \x1b[32m npx @cachly-dev/mcp-server@latest demo\x1b[0m ← Start here (no account)');
2060
- console.log(' \x1b[32m npx @cachly-dev/mcp-server@latest setup\x1b[0m ← Wire up your AI editors');
2059
+ console.log(' \x1b[1m\x1b[32m npx @cachly-dev/mcp-server@latest autopilot\x1b[0m ← \x1b[1mOne command, fully ready\x1b[0m');
2060
+ console.log(' \x1b[32m npx @cachly-dev/mcp-server@latest demo\x1b[0m ← Try it first (no account)');
2061
+ console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest setup\x1b[0m ← Interactive setup (pick editors)');
2061
2062
  console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest health\x1b[0m ← Check everything works');
2062
2063
  console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest digest\x1b[0m ← Weekly Brain summary');
2063
2064
  console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest share\x1b[0m ← Share your Brain stats');
@@ -2067,7 +2068,7 @@ if (!process.argv[2] && process.stdout.isTTY) {
2067
2068
  console.log(' \x1b[36m npx @cachly-dev/mcp-server@latest upgrade\x1b[0m ← Check for updates');
2068
2069
  console.log('');
2069
2070
  console.log(' \x1b[90mWorks with: Claude Code · Cursor · Windsurf · GitHub Copilot · Cline · Zed\x1b[0m');
2070
- console.log(' \x1b[90mFree forever · GDPR · German servers · 107 MCP tools\x1b[0m');
2071
+ console.log(' \x1b[90mFree forever · GDPR · German servers · 114 MCP tools\x1b[0m');
2071
2072
  console.log('');
2072
2073
  process.exit(0);
2073
2074
  }
@@ -2483,7 +2484,11 @@ if (process.argv[2] === 'health') {
2483
2484
  }
2484
2485
  // ── CLI: cachly setup (interactive — no flags required) ───────────────────────
2485
2486
  // Usage: npx @cachly-dev/mcp-server setup
2486
- if (process.argv[2] === 'setup') {
2487
+ // `autopilot` is the one-command entrypoint: it runs the exact same wizard as
2488
+ // `setup` but fully automatic (no prompts) — auth → instance → all editor
2489
+ // configs → CLAUDE.md → git/starter bootstrap → health, in a single shot.
2490
+ const _isAutopilotCli = process.argv[2] === 'autopilot';
2491
+ if (process.argv[2] === 'setup' || _isAutopilotCli) {
2487
2492
  const { writeFile, mkdir, readFile } = await import('node:fs/promises');
2488
2493
  const { existsSync } = await import('node:fs');
2489
2494
  const { resolve, dirname } = await import('node:path');
@@ -2502,8 +2507,12 @@ if (process.argv[2] === 'setup') {
2502
2507
  // a readline question against a non-TTY stdin never resolves and hangs the
2503
2508
  // wizard forever. Treat that exactly like --yes so we never block.
2504
2509
  const stdinIsInteractive = process.stdin.isTTY === true;
2505
- const nonInteractive = process.argv.includes('--yes') || process.argv.includes('-y') || !stdinIsInteractive;
2506
- if (!stdinIsInteractive && !process.argv.includes('--yes') && !process.argv.includes('-y')) {
2510
+ // `autopilot` is always fully automatic — it IS the one-step onboarding.
2511
+ const nonInteractive = _isAutopilotCli || process.argv.includes('--yes') || process.argv.includes('-y') || !stdinIsInteractive;
2512
+ if (_isAutopilotCli) {
2513
+ console.log('🤖 Autopilot — one-command setup (auth → instance → configs → Brain), zero prompts.\n');
2514
+ }
2515
+ else if (!stdinIsInteractive && !process.argv.includes('--yes') && !process.argv.includes('-y')) {
2507
2516
  console.log('ℹ️ Non-interactive terminal detected — running in automatic mode (no prompts).\n');
2508
2517
  }
2509
2518
  const rl = createInterface({ input: process.stdin, output: process.stdout });
@@ -2872,22 +2881,40 @@ if (process.argv[2] === 'setup') {
2872
2881
  // ── Step 5b: Bootstrap Brain from git history ─────────────────────────────
2873
2882
  // Pre-populates the Brain with real lessons so the first session_start shows
2874
2883
  // actual project knowledge instead of an empty brain.
2884
+ JWT = token; // set global JWT so handleTool can authenticate
2885
+ let gitLessonCount = 0;
2875
2886
  if (existsSync(resolve(cwd, '.git'))) {
2876
2887
  process.stdout.write('⏳ Bootstrapping Brain from git history (~10s)...');
2877
2888
  try {
2878
- JWT = token; // set global JWT so handleTool can authenticate
2879
2889
  const gitResult = await handleTool('brain_from_git', {
2880
2890
  instance_id: instance.id,
2881
2891
  repo_path: cwd,
2882
2892
  limit: 100,
2883
2893
  });
2884
2894
  const match = gitResult.match(/(\d+) lesson/);
2895
+ gitLessonCount = match ? parseInt(match[1], 10) : 0;
2885
2896
  console.log(` ✓ ${match ? match[1] + ' lessons' : 'done'} extracted from git history`);
2886
2897
  }
2887
2898
  catch (e) {
2888
2899
  console.log(` (skipped: ${e.message.slice(0, 80)})`);
2889
2900
  }
2890
2901
  }
2902
+ // ── Step 5c: Seed the starter corpus when git yielded nothing ─────────────
2903
+ // Closes the empty-brain gap: a fresh repo (no .git, shallow clone, or no
2904
+ // fix-shaped commits) would otherwise leave the Brain empty and the very first
2905
+ // smart_recall returning nothing. Seeding 16 curated universal lessons makes
2906
+ // the single setup command produce an immediately-useful Brain — true 1-step
2907
+ // onboarding. Idempotent; never overwrites real lessons.
2908
+ if (gitLessonCount === 0) {
2909
+ process.stdout.write('🌱 Seeding 16 universal engineering lessons (first recall works instantly)...');
2910
+ try {
2911
+ await handleTool('brain_seed_starter', { instance_id: instance.id });
2912
+ console.log(' ✓');
2913
+ }
2914
+ catch (e) {
2915
+ console.log(` (skipped: ${e.message.slice(0, 60)})`);
2916
+ }
2917
+ }
2891
2918
  // ── Step 6: Show Brain health (Aha moment) ────────────────────────────────
2892
2919
  // Fetch brain health from the API to show the user what their agent will see.
2893
2920
  process.stdout.write('\n⏳ Fetching your Brain health preview...');
@@ -3174,7 +3201,7 @@ if (!JWT) {
3174
3201
  // • Editor as an MCP stdio server (non-TTY) → ONE stderr hint, then KEEP RUNNING
3175
3202
  // so tools/list works and the first tool call starts the browser sign-in.
3176
3203
  // Skip entirely for CLI subcommands that intentionally run without credentials.
3177
- const _cliNoAuthCommands = ['demo', 'share', 'publish', 'health', 'setup', 'init', 'digest', 'invite', 'badge', 'join', 'upgrade', 'tool-specs', 'openapi'];
3204
+ const _cliNoAuthCommands = ['demo', 'share', 'publish', 'health', 'setup', 'autopilot', 'init', 'digest', 'invite', 'badge', 'join', 'upgrade', 'tool-specs', 'openapi'];
3178
3205
  if (!JWT && !_cliNoAuthCommands.includes(process.argv[2] ?? '')) {
3179
3206
  const runningInTerminal = !process.argv[2] && process.stdout.isTTY === true && _isMain;
3180
3207
  if (runningInTerminal) {