@cortexmemory/cli 0.26.2 → 0.27.1

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 (58) hide show
  1. package/dist/commands/dev.d.ts.map +1 -1
  2. package/dist/commands/dev.js +121 -10
  3. package/dist/commands/dev.js.map +1 -1
  4. package/dist/commands/init.d.ts.map +1 -1
  5. package/dist/commands/init.js +273 -43
  6. package/dist/commands/init.js.map +1 -1
  7. package/dist/commands/setup.d.ts.map +1 -1
  8. package/dist/commands/setup.js +102 -46
  9. package/dist/commands/setup.js.map +1 -1
  10. package/dist/commands/status.d.ts.map +1 -1
  11. package/dist/commands/status.js +94 -7
  12. package/dist/commands/status.js.map +1 -1
  13. package/dist/types.d.ts +23 -0
  14. package/dist/types.d.ts.map +1 -1
  15. package/dist/utils/config.d.ts +11 -0
  16. package/dist/utils/config.d.ts.map +1 -1
  17. package/dist/utils/config.js +20 -0
  18. package/dist/utils/config.js.map +1 -1
  19. package/dist/utils/init/graph-setup.d.ts.map +1 -1
  20. package/dist/utils/init/graph-setup.js +12 -0
  21. package/dist/utils/init/graph-setup.js.map +1 -1
  22. package/dist/utils/init/quickstart-setup.d.ts +87 -0
  23. package/dist/utils/init/quickstart-setup.d.ts.map +1 -0
  24. package/dist/utils/init/quickstart-setup.js +462 -0
  25. package/dist/utils/init/quickstart-setup.js.map +1 -0
  26. package/dist/utils/schema-sync.d.ts.map +1 -1
  27. package/dist/utils/schema-sync.js +27 -21
  28. package/dist/utils/schema-sync.js.map +1 -1
  29. package/package.json +3 -2
  30. package/templates/vercel-ai-quickstart/.env.local.example +45 -0
  31. package/templates/vercel-ai-quickstart/README.md +280 -0
  32. package/templates/vercel-ai-quickstart/app/api/chat/route.ts +196 -0
  33. package/templates/vercel-ai-quickstart/app/api/facts/route.ts +39 -0
  34. package/templates/vercel-ai-quickstart/app/api/health/route.ts +99 -0
  35. package/templates/vercel-ai-quickstart/app/api/memories/route.ts +37 -0
  36. package/templates/vercel-ai-quickstart/app/globals.css +114 -0
  37. package/templates/vercel-ai-quickstart/app/layout.tsx +19 -0
  38. package/templates/vercel-ai-quickstart/app/page.tsx +131 -0
  39. package/templates/vercel-ai-quickstart/components/ChatInterface.tsx +237 -0
  40. package/templates/vercel-ai-quickstart/components/ConvexClientProvider.tsx +21 -0
  41. package/templates/vercel-ai-quickstart/components/DataPreview.tsx +57 -0
  42. package/templates/vercel-ai-quickstart/components/HealthStatus.tsx +214 -0
  43. package/templates/vercel-ai-quickstart/components/LayerCard.tsx +263 -0
  44. package/templates/vercel-ai-quickstart/components/LayerFlowDiagram.tsx +195 -0
  45. package/templates/vercel-ai-quickstart/components/MemorySpaceSwitcher.tsx +93 -0
  46. package/templates/vercel-ai-quickstart/convex/conversations.ts +67 -0
  47. package/templates/vercel-ai-quickstart/convex/facts.ts +131 -0
  48. package/templates/vercel-ai-quickstart/convex/health.ts +15 -0
  49. package/templates/vercel-ai-quickstart/convex/memories.ts +104 -0
  50. package/templates/vercel-ai-quickstart/convex/schema.ts +20 -0
  51. package/templates/vercel-ai-quickstart/convex/users.ts +105 -0
  52. package/templates/vercel-ai-quickstart/lib/animations.ts +146 -0
  53. package/templates/vercel-ai-quickstart/lib/layer-tracking.ts +214 -0
  54. package/templates/vercel-ai-quickstart/next.config.js +7 -0
  55. package/templates/vercel-ai-quickstart/package.json +41 -0
  56. package/templates/vercel-ai-quickstart/postcss.config.js +5 -0
  57. package/templates/vercel-ai-quickstart/tailwind.config.js +37 -0
  58. package/templates/vercel-ai-quickstart/tsconfig.json +33 -0
@@ -13,6 +13,7 @@ import { spawn } from "child_process";
13
13
  import { loadConfig, saveUserConfig } from "../utils/config.js";
14
14
  import { isValidProjectName, isDirectoryEmpty, fetchLatestSDKMetadata, execCommand, commandExists, } from "../utils/shell.js";
15
15
  import { setupNewConvex, setupExistingConvex, deployToConvex, ensureConvexAuth, sanitizeProjectName, } from "../utils/init/convex-setup.js";
16
+ import { installVercelAIQuickstart, startApp, stopApp, findAppPidFiles, isAppRunning, findProcessByPort, stopProcessByPort, } from "../utils/init/quickstart-setup.js";
16
17
  import { getGraphConfig, setupGraphFiles, addGraphDependencies, createGraphExample, startGraphContainers, stopGraphContainers, } from "../utils/init/graph-setup.js";
17
18
  import { copyTemplate, deployCortexBackend, createConvexJson, ensureGitignore, } from "../utils/init/file-operations.js";
18
19
  import { createEnvFile, appendGraphEnvVars, } from "../utils/init/env-generator.js";
@@ -101,12 +102,24 @@ export function registerLifecycleCommands(program, _config) {
101
102
  console.log(pc.dim(" Use 'cortex start -d <name> -f' for foreground mode"));
102
103
  process.exit(1);
103
104
  }
104
- console.log(pc.cyan(`\n Starting ${deploymentsToStart.length} deployment(s)...\n`));
105
+ // Collect enabled apps for summary
106
+ const apps = Object.entries(config.apps || {});
107
+ const enabledApps = apps.filter(([, app]) => app.enabled);
108
+ // Show summary header
109
+ console.log();
110
+ console.log(pc.bold(" ═══════════════════════════════════════════════════════════"));
111
+ console.log(pc.bold(" Cortex Start"));
112
+ console.log(pc.bold(" ═══════════════════════════════════════════════════════════"));
113
+ console.log();
114
+ // Deployments section
115
+ console.log(pc.bold(pc.cyan(` Deployments (${deploymentsToStart.length})`)));
116
+ console.log(pc.dim(" ───────────────────────────────────────────────────────────"));
105
117
  // Start each deployment
106
118
  for (const dep of deploymentsToStart) {
107
- console.log(pc.bold(` ${dep.name}`));
108
- console.log(pc.dim(` Project: ${dep.projectPath}`));
109
- console.log(pc.dim(` URL: ${dep.url}\n`));
119
+ console.log(` ${pc.green("●")} ${pc.cyan(dep.name)}`);
120
+ console.log(pc.dim(` Project: ${dep.projectPath}`));
121
+ console.log(pc.dim(` URL: ${dep.url}`));
122
+ console.log();
110
123
  // Start graph database if configured and not convex-only
111
124
  if (!options.convexOnly) {
112
125
  const dockerComposePath = path.join(dep.projectPath, "docker-compose.graph.yml");
@@ -185,28 +198,86 @@ export function registerLifecycleCommands(program, _config) {
185
198
  }
186
199
  }
187
200
  }
201
+ // Start enabled apps (unless convex-only or graph-only)
202
+ if (!options.convexOnly && !options.graphOnly && !options.foreground) {
203
+ if (enabledApps.length > 0) {
204
+ console.log(pc.bold(pc.cyan(` Apps (${enabledApps.length})`)));
205
+ console.log(pc.dim(" ───────────────────────────────────────────────────────────"));
206
+ for (const [name, app] of enabledApps) {
207
+ console.log(` ${pc.green("●")} ${pc.cyan(name)}`);
208
+ console.log(pc.dim(` Type: ${app.type}`));
209
+ console.log(pc.dim(` Path: ${path.join(app.projectPath, app.path)}`));
210
+ console.log(pc.dim(` Port: ${app.port || 3000}`));
211
+ console.log();
212
+ await startApp(name, app);
213
+ }
214
+ }
215
+ }
188
216
  // Show summary
189
217
  if (!options.foreground) {
190
- console.log(pc.green("\n ✓ All deployments started\n"));
191
- console.log(pc.dim(" Use 'cortex stop' to stop all services"));
192
- console.log(pc.dim(" Use 'cortex config list' to see deployment status"));
218
+ const totalStarted = deploymentsToStart.length + (enabledApps.length || 0);
219
+ console.log(pc.bold(" ═══════════════════════════════════════════════════════════"));
220
+ console.log(pc.green(` ✓ Started ${totalStarted} service(s)`));
221
+ console.log(pc.bold(" ═══════════════════════════════════════════════════════════"));
222
+ console.log();
223
+ console.log(pc.dim(" Use 'cortex stop' to stop all services"));
224
+ console.log(pc.dim(" Use 'cortex config list' to see deployment status"));
225
+ console.log();
193
226
  }
194
227
  });
195
228
  // Stop command
196
229
  program
197
230
  .command("stop")
198
- .description("Stop background services (Convex and graph database)")
231
+ .description("Stop background services (Convex, graph database, and apps)")
199
232
  .option("-d, --deployment <name>", "Stop specific deployment only")
233
+ .option("-a, --app <name>", "Stop specific app only")
200
234
  .option("--convex-only", "Only stop Convex server", false)
201
235
  .option("--graph-only", "Only stop graph database", false)
236
+ .option("--apps-only", "Only stop template apps", false)
202
237
  .action(async (options) => {
238
+ // Load fresh config to get current state
239
+ const config = await loadConfig();
203
240
  let stoppedSomething = false;
204
241
  let stoppedCount = 0;
205
- // Determine which deployments to stop
242
+ let stoppedAppsCount = 0;
243
+ // If stopping specific app only
244
+ if (options.app) {
245
+ const appConfig = config.apps?.[options.app];
246
+ if (!appConfig) {
247
+ // Try to find app in current directory
248
+ const cwd = process.cwd();
249
+ const appPidFiles = await findAppPidFiles(cwd);
250
+ const matchingApp = appPidFiles.find((a) => a.name === options.app);
251
+ if (!matchingApp) {
252
+ console.error(pc.red(`\n Error: App "${options.app}" not found`));
253
+ console.log(pc.dim(" Run 'cortex config list' to see available apps\n"));
254
+ process.exit(1);
255
+ }
256
+ // Stop from current directory
257
+ const stopped = await stopApp(options.app, cwd);
258
+ if (stopped) {
259
+ console.log(pc.green(`\n ✓ App "${options.app}" stopped\n`));
260
+ }
261
+ else {
262
+ console.log(pc.yellow(`\n App "${options.app}" was not running\n`));
263
+ }
264
+ return;
265
+ }
266
+ // Stop specific configured app
267
+ const stopped = await stopApp(options.app, appConfig.projectPath);
268
+ if (stopped) {
269
+ console.log(pc.green(`\n ✓ App "${options.app}" stopped\n`));
270
+ }
271
+ else {
272
+ console.log(pc.yellow(`\n App "${options.app}" was not running\n`));
273
+ }
274
+ return;
275
+ }
276
+ // Determine which deployments/project paths to stop
206
277
  const deploymentsToStop = [];
207
278
  if (options.deployment) {
208
279
  // Stop specific deployment
209
- const deployment = _config.deployments?.[options.deployment];
280
+ const deployment = config.deployments?.[options.deployment];
210
281
  if (!deployment) {
211
282
  console.error(pc.red(`\n Error: Deployment "${options.deployment}" not found`));
212
283
  console.log(pc.dim(" Run 'cortex config list' to see available deployments\n"));
@@ -224,36 +295,52 @@ export function registerLifecycleCommands(program, _config) {
224
295
  }
225
296
  else {
226
297
  // Stop all deployments that have running processes
227
- const deploymentEntries = Object.entries(_config.deployments || {});
228
- if (deploymentEntries.length === 0) {
298
+ const deploymentEntries = Object.entries(config.deployments || {});
299
+ // Collect project paths from both deployments and apps
300
+ const projectPaths = new Map(); // path -> name
301
+ if (deploymentEntries.length === 0 && !config.apps) {
229
302
  // Fallback to current directory
230
303
  const cwd = process.cwd();
231
- deploymentsToStop.push({
232
- name: "current directory",
233
- projectPath: cwd,
234
- });
304
+ projectPaths.set(cwd, "current directory");
235
305
  }
236
306
  else {
307
+ // Add deployment project paths
237
308
  for (const [name, deployment] of deploymentEntries) {
238
309
  if (deployment.projectPath &&
239
310
  fs.existsSync(deployment.projectPath)) {
240
- // Check if anything is running for this deployment
241
- const pidFile = path.join(deployment.projectPath, ".convex-dev.pid");
242
- const dockerCompose = path.join(deployment.projectPath, "docker-compose.graph.yml");
243
- const hasPidFile = fs.existsSync(pidFile);
244
- const hasDockerCompose = fs.existsSync(dockerCompose);
245
- if (hasPidFile || hasDockerCompose) {
246
- deploymentsToStop.push({
247
- name,
248
- projectPath: deployment.projectPath,
249
- });
311
+ projectPaths.set(deployment.projectPath, name);
312
+ }
313
+ }
314
+ // Add app project paths (may overlap with deployments)
315
+ if (config.apps) {
316
+ for (const [appName, app] of Object.entries(config.apps)) {
317
+ if (app.projectPath && fs.existsSync(app.projectPath)) {
318
+ // Use app name if no deployment for this path
319
+ if (!projectPaths.has(app.projectPath)) {
320
+ projectPaths.set(app.projectPath, `app:${appName}`);
321
+ }
250
322
  }
251
323
  }
252
324
  }
253
325
  }
326
+ // Check each project path for running services
327
+ for (const [projectPath, name] of projectPaths) {
328
+ // Check if anything is running for this deployment
329
+ const pidFile = path.join(projectPath, ".convex-dev.pid");
330
+ const dockerCompose = path.join(projectPath, "docker-compose.graph.yml");
331
+ const appPidFiles = await findAppPidFiles(projectPath);
332
+ const hasPidFile = fs.existsSync(pidFile);
333
+ const hasDockerCompose = fs.existsSync(dockerCompose);
334
+ const hasApps = appPidFiles.length > 0;
335
+ if (hasPidFile || hasDockerCompose || hasApps) {
336
+ deploymentsToStop.push({ name, projectPath });
337
+ }
338
+ }
254
339
  }
255
340
  if (deploymentsToStop.length === 0) {
256
- console.log(pc.yellow("\n No deployments with running services found\n"));
341
+ console.log(pc.yellow("\n No deployments with running services found"));
342
+ console.log(pc.dim(" Note: Services started without PID files cannot be auto-detected.\n" +
343
+ " Use 'ps aux | grep convex' or 'ps aux | grep next' to find running processes.\n"));
257
344
  return;
258
345
  }
259
346
  console.log(pc.cyan(`\n Stopping ${deploymentsToStop.length} deployment(s)...\n`));
@@ -261,8 +348,9 @@ export function registerLifecycleCommands(program, _config) {
261
348
  console.log(pc.bold(` ${name}`));
262
349
  console.log(pc.dim(` ${projectPath}`));
263
350
  let deploymentStopped = false;
264
- // Stop Convex if not graph-only
265
- if (!options.graphOnly) {
351
+ let convexStopped = false;
352
+ // Stop Convex if not graph-only and not apps-only
353
+ if (!options.graphOnly && !options.appsOnly) {
266
354
  const pidFile = path.join(projectPath, ".convex-dev.pid");
267
355
  try {
268
356
  const pid = await fs.readFile(pidFile, "utf-8");
@@ -272,11 +360,13 @@ export function registerLifecycleCommands(program, _config) {
272
360
  console.log(pc.green(` ✓ Convex stopped (PID: ${pidNum})`));
273
361
  stoppedSomething = true;
274
362
  deploymentStopped = true;
363
+ convexStopped = true;
275
364
  }
276
365
  catch (e) {
277
366
  const err = e;
278
367
  if (err.code === "ESRCH") {
279
368
  console.log(pc.yellow(" Convex was already stopped"));
369
+ convexStopped = true; // Consider it handled
280
370
  }
281
371
  else {
282
372
  throw e;
@@ -290,13 +380,37 @@ export function registerLifecycleCommands(program, _config) {
290
380
  if (err.code !== "ENOENT") {
291
381
  console.error(pc.red(" Error stopping Convex:"), e);
292
382
  }
293
- else if (!options.graphOnly) {
294
- console.log(pc.dim(" No Convex process running"));
383
+ // No PID file - will try port-based detection below
384
+ }
385
+ // Fallback: try to stop by port if no PID file and deployment is local
386
+ if (!convexStopped) {
387
+ // Check if this is a local deployment (port 3210)
388
+ const deploymentConfig = Object.values(config.deployments || {}).find((d) => d.projectPath === projectPath);
389
+ const isLocal = deploymentConfig?.url?.includes("127.0.0.1:3210") ||
390
+ deploymentConfig?.url?.includes("localhost:3210");
391
+ if (isLocal) {
392
+ const convexPid = await findProcessByPort(3210);
393
+ if (convexPid) {
394
+ console.log(pc.yellow(` Found Convex on port 3210 (no PID file)`));
395
+ const stopped = await stopProcessByPort(3210);
396
+ if (stopped) {
397
+ console.log(pc.green(` ✓ Convex stopped (port 3210, PID: ${convexPid})`));
398
+ stoppedSomething = true;
399
+ deploymentStopped = true;
400
+ convexStopped = true;
401
+ }
402
+ }
403
+ else {
404
+ console.log(pc.dim(" No Convex process running"));
405
+ }
406
+ }
407
+ else if (!options.graphOnly && !options.appsOnly) {
408
+ console.log(pc.dim(" No Convex process running (PID file not found)"));
295
409
  }
296
410
  }
297
411
  }
298
- // Stop graph containers if not convex-only
299
- if (!options.convexOnly) {
412
+ // Stop graph containers if not convex-only and not apps-only
413
+ if (!options.convexOnly && !options.appsOnly) {
300
414
  const dockerComposePath = path.join(projectPath, "docker-compose.graph.yml");
301
415
  if (fs.existsSync(dockerComposePath)) {
302
416
  const stopped = await stopGraphContainers(projectPath);
@@ -309,17 +423,76 @@ export function registerLifecycleCommands(program, _config) {
309
423
  console.log(pc.dim(" No graph container running"));
310
424
  }
311
425
  }
312
- else if (!options.convexOnly) {
426
+ else if (!options.convexOnly && !options.appsOnly) {
313
427
  console.log(pc.dim(" No graph database configured"));
314
428
  }
315
429
  }
430
+ // Stop apps if not convex-only and not graph-only
431
+ if (!options.convexOnly && !options.graphOnly) {
432
+ const appPidFiles = await findAppPidFiles(projectPath);
433
+ const stoppedAppNames = new Set();
434
+ // First, try to stop apps with PID files
435
+ if (appPidFiles.length > 0) {
436
+ for (const { name: appName } of appPidFiles) {
437
+ const appStatus = await isAppRunning(appName, projectPath);
438
+ if (appStatus.running) {
439
+ const stopped = await stopApp(appName, projectPath);
440
+ if (stopped) {
441
+ console.log(pc.green(` ✓ App "${appName}" stopped (PID: ${appStatus.pid})`));
442
+ stoppedSomething = true;
443
+ stoppedAppsCount++;
444
+ deploymentStopped = true;
445
+ stoppedAppNames.add(appName);
446
+ }
447
+ }
448
+ else {
449
+ // Clean up stale PID file (already handled by isAppRunning)
450
+ console.log(pc.dim(` App "${appName}" was not running`));
451
+ }
452
+ }
453
+ }
454
+ // Also check configured apps that might not have PID files
455
+ // (started before PID tracking was added)
456
+ if (config.apps) {
457
+ for (const [appName, appConfig] of Object.entries(config.apps)) {
458
+ // Skip if already stopped via PID file or not matching this project
459
+ if (stoppedAppNames.has(appName))
460
+ continue;
461
+ if (appConfig.projectPath !== projectPath)
462
+ continue;
463
+ const port = appConfig.port || 3000;
464
+ const pid = await findProcessByPort(port);
465
+ if (pid) {
466
+ console.log(pc.yellow(` Found app "${appName}" on port ${port} (no PID file)`));
467
+ const stopped = await stopProcessByPort(port);
468
+ if (stopped) {
469
+ console.log(pc.green(` ✓ App "${appName}" stopped (port ${port}, PID: ${pid})`));
470
+ stoppedSomething = true;
471
+ stoppedAppsCount++;
472
+ deploymentStopped = true;
473
+ }
474
+ }
475
+ }
476
+ }
477
+ if (appPidFiles.length === 0 && !config.apps && options.appsOnly) {
478
+ console.log(pc.dim(" No apps configured"));
479
+ }
480
+ }
316
481
  if (deploymentStopped) {
317
482
  stoppedCount++;
318
483
  }
319
484
  console.log();
320
485
  }
486
+ // Summary
321
487
  if (stoppedSomething) {
322
- console.log(pc.green(` ✓ Stopped ${stoppedCount} deployment(s)\n`));
488
+ const parts = [];
489
+ if (stoppedCount > 0 && !options.appsOnly) {
490
+ parts.push(`${stoppedCount} deployment(s)`);
491
+ }
492
+ if (stoppedAppsCount > 0) {
493
+ parts.push(`${stoppedAppsCount} app(s)`);
494
+ }
495
+ console.log(pc.green(` ✓ Stopped ${parts.join(" and ")}\n`));
323
496
  }
324
497
  else {
325
498
  console.log(pc.yellow(" No services were running\n"));
@@ -401,26 +574,64 @@ export async function runInitWizard(targetDir, options = {}) {
401
574
  if (!options.yes) {
402
575
  await showConfirmation(config);
403
576
  }
404
- // Execute setup
405
- await executeSetup(config);
406
- // Ask to start Convex if not already specified
577
+ // Execute setup (returns SDK metadata for post-setup steps)
578
+ const sdkMetadata = await executeSetup(config);
579
+ // Ask about Vercel AI quickstart (optional demo app)
580
+ let installedQuickstart = false;
581
+ let quickstartAppConfig = null;
582
+ if (!options.yes) {
583
+ const { installQuickstart } = await prompts({
584
+ type: "confirm",
585
+ name: "installQuickstart",
586
+ message: "Install Vercel AI quickstart demo?",
587
+ initial: false,
588
+ });
589
+ if (installQuickstart) {
590
+ // Need the actual Convex URL from the config that was just set up
591
+ const convexUrl = config.convexUrl || "";
592
+ // Pass graph config if it was enabled during init
593
+ const graphConfig = config.graphEnabled
594
+ ? {
595
+ enabled: true,
596
+ uri: config.graphUri,
597
+ username: config.graphUsername,
598
+ password: config.graphPassword,
599
+ }
600
+ : undefined;
601
+ quickstartAppConfig = await installVercelAIQuickstart(config.projectPath, sdkMetadata.sdkVersion, convexUrl, config.openaiApiKey, graphConfig);
602
+ // Save app to CLI config
603
+ const cliConfig = await loadConfig();
604
+ cliConfig.apps = cliConfig.apps || {};
605
+ cliConfig.apps["quickstart"] = quickstartAppConfig;
606
+ await saveUserConfig(cliConfig);
607
+ installedQuickstart = true;
608
+ }
609
+ }
610
+ // Context-aware start prompt
407
611
  let shouldStart = options.start;
408
612
  if (!shouldStart && !options.yes) {
613
+ const message = installedQuickstart
614
+ ? "Start Convex backend and quickstart app now?"
615
+ : "Start Convex development server now?";
409
616
  const response = await prompts({
410
617
  type: "confirm",
411
618
  name: "startNow",
412
- message: "Start Convex development server now?",
619
+ message,
413
620
  initial: true,
414
621
  });
415
622
  shouldStart = response.startNow;
416
623
  }
417
- // Start Convex if requested
624
+ // Start services if requested
418
625
  if (shouldStart) {
419
626
  const isLocal = config.convexSetupType === "local";
420
627
  await startConvexInBackground(config.projectPath, isLocal);
628
+ // Start quickstart app if installed
629
+ if (installedQuickstart && quickstartAppConfig) {
630
+ await startApp("quickstart", quickstartAppConfig);
631
+ }
421
632
  // Show running status dashboard
422
633
  console.log();
423
- await showRunningStatus(config.projectPath, isLocal);
634
+ await showRunningStatus(config.projectPath, isLocal, installedQuickstart);
424
635
  }
425
636
  }
426
637
  /**
@@ -643,6 +854,7 @@ async function showConfirmation(config) {
643
854
  }
644
855
  /**
645
856
  * Execute the setup
857
+ * Returns SDK metadata for use in post-setup steps (like quickstart installation)
646
858
  */
647
859
  async function executeSetup(config) {
648
860
  console.log(pc.cyan("\n Setting up Cortex...\n"));
@@ -788,6 +1000,11 @@ async function executeSetup(config) {
788
1000
  await saveDeploymentToConfig(config);
789
1001
  // Success!
790
1002
  showSuccessMessage(config);
1003
+ // Return SDK metadata for use in post-setup steps
1004
+ return {
1005
+ sdkVersion: sdkMetadata.sdkVersion,
1006
+ convexVersion: sdkMetadata.convexVersion,
1007
+ };
791
1008
  }
792
1009
  catch (error) {
793
1010
  console.error(pc.red("\n Setup failed:"), error);
@@ -809,11 +1026,12 @@ async function saveDeploymentToConfig(config) {
809
1026
  const deploymentName = config.projectName
810
1027
  .toLowerCase()
811
1028
  .replace(/[^a-z0-9-]/g, "-");
812
- // Add the deployment
1029
+ // Add the deployment (enabled by default when created by init)
813
1030
  userConfig.deployments[deploymentName] = {
814
1031
  url: config.convexUrl,
815
1032
  key: config.deployKey,
816
1033
  projectPath: config.projectPath,
1034
+ enabled: true,
817
1035
  };
818
1036
  // Set as default if no default exists
819
1037
  if (!userConfig.default) {
@@ -934,7 +1152,7 @@ async function startConvexInBackground(projectPath, isLocal, deploymentUrl, depl
934
1152
  /**
935
1153
  * Show running services status dashboard
936
1154
  */
937
- async function showRunningStatus(projectPath, isLocal) {
1155
+ async function showRunningStatus(projectPath, isLocal, hasQuickstart = false) {
938
1156
  const width = 56;
939
1157
  const line = "═".repeat(width);
940
1158
  const thinLine = "─".repeat(width);
@@ -1006,6 +1224,15 @@ async function showRunningStatus(projectPath, isLocal) {
1006
1224
  console.log(` ${pc.dim("○")} Not configured`);
1007
1225
  }
1008
1226
  console.log();
1227
+ // Quickstart App Status (if installed)
1228
+ if (hasQuickstart) {
1229
+ console.log(pc.bold(pc.white(" Vercel AI Quickstart")));
1230
+ console.log(pc.dim(" " + thinLine));
1231
+ console.log(` ${pc.green("●")} Running`);
1232
+ console.log(pc.dim(" URL: http://localhost:3000"));
1233
+ console.log(pc.dim(" Interactive chat demo with memory visualization"));
1234
+ console.log();
1235
+ }
1009
1236
  // Quick Actions
1010
1237
  console.log(pc.bold(pc.white(" Quick Actions")));
1011
1238
  console.log(pc.dim(" " + thinLine));
@@ -1014,6 +1241,9 @@ async function showRunningStatus(projectPath, isLocal) {
1014
1241
  pc.dim(" # Foreground mode (see logs)"));
1015
1242
  console.log(pc.dim(" cortex stop") +
1016
1243
  pc.dim(" # Stop background services"));
1244
+ if (hasQuickstart) {
1245
+ console.log(pc.dim(" npm run quickstart") + pc.dim(" # Start quickstart demo"));
1246
+ }
1017
1247
  console.log(pc.dim(" npm start") + pc.dim(" # Run your AI agent"));
1018
1248
  console.log();
1019
1249
  // Log file hint