@recursiv/cli 0.1.6 → 0.1.8

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.
@@ -10,10 +10,10 @@ var __export = (target, all) => {
10
10
  };
11
11
 
12
12
  // src/lib/logger.ts
13
- import pc from "picocolors";
13
+ import pc2 from "picocolors";
14
14
  function banner() {
15
15
  console.log();
16
- console.log(pc.bold("Recursiv") + pc.dim(" \u2014 build and ship apps with AI"));
16
+ console.log(pc2.bold("Recursiv") + pc2.dim(" \u2014 build and ship apps with AI"));
17
17
  console.log();
18
18
  }
19
19
  var log;
@@ -22,19 +22,19 @@ var init_logger = __esm({
22
22
  "use strict";
23
23
  log = {
24
24
  info(msg) {
25
- console.log(pc.cyan("info") + " " + msg);
25
+ console.log(pc2.cyan("info") + " " + msg);
26
26
  },
27
27
  success(msg) {
28
- console.log(pc.green("ok") + " " + msg);
28
+ console.log(pc2.green("ok") + " " + msg);
29
29
  },
30
30
  warn(msg) {
31
- console.log(pc.yellow("warn") + " " + msg);
31
+ console.log(pc2.yellow("warn") + " " + msg);
32
32
  },
33
33
  error(msg) {
34
- console.error(pc.red("error") + " " + msg);
34
+ console.error(pc2.red("error") + " " + msg);
35
35
  },
36
36
  step(n, total, msg) {
37
- console.log(pc.dim(`[${n}/${total}]`) + " " + msg);
37
+ console.log(pc2.dim(`[${n}/${total}]`) + " " + msg);
38
38
  },
39
39
  blank() {
40
40
  console.log();
@@ -106,10 +106,6 @@ async function writeEnvFile(dir, apiKey) {
106
106
  const content = [
107
107
  "# Recursiv API key",
108
108
  `RECURSIV_API_KEY=${apiKey}`,
109
- "",
110
- "# Framework-specific public keys (uncomment as needed)",
111
- `# NEXT_PUBLIC_RECURSIV_API_KEY=${apiKey}`,
112
- `# VITE_RECURSIV_API_KEY=${apiKey}`,
113
109
  ""
114
110
  ].join("\n");
115
111
  await writeFile2(envPath, content, "utf-8");
@@ -158,7 +154,7 @@ __export(auth_flow_exports, {
158
154
  validateApiKey: () => validateApiKey
159
155
  });
160
156
  import prompts from "prompts";
161
- import pc2 from "picocolors";
157
+ import pc3 from "picocolors";
162
158
  function isValidKeyFormat(key) {
163
159
  return API_KEY_PATTERN.test(key);
164
160
  }
@@ -178,9 +174,10 @@ async function validateApiKey(apiKey, baseUrl) {
178
174
  async function terminalSignup(baseUrl) {
179
175
  const rootUrl = baseUrl.replace(/\/api\/v1\/?$/, "");
180
176
  console.log();
181
- console.log(pc2.bold("Create a free Recursiv account"));
182
- console.log(pc2.dim("Free tier: 1,000 API calls/day, 1 agent, 3 projects"));
183
- console.log(pc2.dim("We'll send a 6-digit code to your email \u2014 no password needed."));
177
+ console.log(pc3.bold("Sign in to Recursiv"));
178
+ console.log(pc3.dim("We'll send a 6-digit code to your email \u2014 no password needed."));
179
+ console.log(pc3.dim("If your email isn't registered yet, we'll create a free account."));
180
+ console.log(pc3.dim("Free tier: 1,000 API calls/day, 1 agent, 3 projects"));
184
181
  console.log();
185
182
  const { email } = await prompts(
186
183
  {
@@ -211,7 +208,7 @@ async function terminalSignup(baseUrl) {
211
208
  log.error(
212
209
  `Could not reach ${rootUrl} \u2014 ${err instanceof Error ? err.message : "network error"}`
213
210
  );
214
- log.info(`You can create an API key manually at ${pc2.underline(DASHBOARD_URL)}`);
211
+ log.info(`You can create an API key manually at ${pc3.underline(DASHBOARD_URL)}`);
215
212
  return null;
216
213
  }
217
214
  log.success(`Verification code sent to ${email}`);
@@ -251,7 +248,7 @@ async function terminalSignup(baseUrl) {
251
248
  }
252
249
  if (!sessionCookie) {
253
250
  log.error("No session returned from server");
254
- log.info(`Create an API key manually at ${pc2.underline(DASHBOARD_URL)}`);
251
+ log.info(`Create an API key manually at ${pc3.underline(DASHBOARD_URL)}`);
255
252
  return null;
256
253
  }
257
254
  log.success("Authenticated");
@@ -270,7 +267,7 @@ async function terminalSignup(baseUrl) {
270
267
  if (!keyRes.ok) {
271
268
  const errBody = await keyRes.text().catch(() => "");
272
269
  log.error(`Failed to create API key (${keyRes.status}): ${errBody}`);
273
- log.info(`Create one manually at ${pc2.underline(DASHBOARD_URL)}`);
270
+ log.info(`Create one manually at ${pc3.underline(DASHBOARD_URL)}`);
274
271
  return null;
275
272
  }
276
273
  const { data } = await keyRes.json();
@@ -280,7 +277,7 @@ async function terminalSignup(baseUrl) {
280
277
  log.error(
281
278
  `Failed to create API key: ${err instanceof Error ? err.message : "unknown error"}`
282
279
  );
283
- log.info(`Create one manually at ${pc2.underline(DASHBOARD_URL)}`);
280
+ log.info(`Create one manually at ${pc3.underline(DASHBOARD_URL)}`);
284
281
  return null;
285
282
  }
286
283
  }
@@ -297,8 +294,8 @@ function extractSessionCookie(res) {
297
294
  }
298
295
  async function promptApiKey() {
299
296
  console.log(
300
- pc2.dim(
301
- `Get your API key from ${pc2.underline(DASHBOARD_URL)}
297
+ pc3.dim(
298
+ `Get your API key from ${pc3.underline(DASHBOARD_URL)}
302
299
  Keys start with sk_live_ or sk_test_`
303
300
  )
304
301
  );
@@ -345,13 +342,13 @@ async function getOrCreateApiKey(baseUrl) {
345
342
  message: "How would you like to authenticate?",
346
343
  choices: [
347
344
  {
348
- title: "Create a free account",
349
- description: "Sign up with email (we'll send a 6-digit code)",
345
+ title: "Sign in or create an account with my email",
346
+ description: "We'll send a 6-digit code. Works whether you're new or returning.",
350
347
  value: "signup"
351
348
  },
352
349
  {
353
- title: "Enter an existing API key",
354
- description: "Paste a key from your dashboard",
350
+ title: "Paste an existing API key",
351
+ description: "Use a key you've already saved from the dashboard",
355
352
  value: "paste"
356
353
  },
357
354
  {
@@ -425,7 +422,7 @@ async function saveCredentials(creds) {
425
422
  });
426
423
  }
427
424
  async function resolveRecursivKey(projectDir) {
428
- const envKey = process.env.RECURSIV_API_KEY || process.env.SOCIAL_DEV_API_KEY;
425
+ const envKey = process.env.RECURSIV_API_KEY;
429
426
  if (envKey) return envKey;
430
427
  if (projectDir) {
431
428
  try {
@@ -461,12 +458,12 @@ __export(mcp_install_exports, {
461
458
  import { readFile as readFile5, writeFile as writeFile6, mkdir as mkdir3 } from "fs/promises";
462
459
  import { join as join5, resolve as resolve3 } from "path";
463
460
  import { homedir as homedir2, platform } from "os";
464
- import pc11 from "picocolors";
461
+ import pc12 from "picocolors";
465
462
  async function mcpInstallCommand(opts) {
466
463
  const target = opts.target;
467
464
  if (!VALID_TARGETS.includes(target)) {
468
465
  console.error(
469
- pc11.red("error") + ` Unknown target "${opts.target}". Valid targets: ${VALID_TARGETS.join(", ")}`
466
+ pc12.red("error") + ` Unknown target "${opts.target}". Valid targets: ${VALID_TARGETS.join(", ")}`
470
467
  );
471
468
  process.exit(1);
472
469
  }
@@ -474,17 +471,17 @@ async function mcpInstallCommand(opts) {
474
471
  let apiKey = opts.apiKey || await resolveRecursivKey2(process.cwd());
475
472
  if (!apiKey) {
476
473
  console.log();
477
- console.log(pc11.dim(" No Recursiv API key found. Let's authenticate."));
474
+ console.log(pc12.dim(" No Recursiv API key found. Let's authenticate."));
478
475
  console.log();
479
476
  const { getOrCreateApiKey: getOrCreateApiKey2 } = await Promise.resolve().then(() => (init_auth_flow(), auth_flow_exports));
480
477
  const baseUrl = process.env.RECURSIV_BASE_URL || "https://api.recursiv.io/api/v1";
481
478
  apiKey = await getOrCreateApiKey2(baseUrl);
482
479
  if (!apiKey) {
483
- console.error(pc11.red(" error") + " Authentication required to continue.");
480
+ console.error(pc12.red(" error") + " Authentication required to continue.");
484
481
  process.exit(1);
485
482
  }
486
483
  await saveCredentials2({ recursivApiKey: apiKey });
487
- console.log(pc11.dim(" Credentials saved to ~/.recursiv/credentials"));
484
+ console.log(pc12.dim(" Credentials saved to ~/.recursiv/credentials"));
488
485
  console.log();
489
486
  }
490
487
  switch (target) {
@@ -511,14 +508,14 @@ async function installClaudeCode(apiKey, global) {
511
508
  if (!settings.mcpServers) settings.mcpServers = {};
512
509
  settings.mcpServers.recursiv = mcpServerEntry(apiKey);
513
510
  await writeFile6(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
514
- console.log(pc11.green("\u2713") + ` Recursiv MCP added to ${pc11.dim(settingsPath)}`);
511
+ console.log(pc12.green("\u2713") + ` Recursiv MCP added to ${pc12.dim(settingsPath)}`);
515
512
  } else {
516
513
  const mcpPath = join5(process.cwd(), ".mcp.json");
517
514
  const config = await readJsonSafe(mcpPath);
518
515
  if (!config.mcpServers) config.mcpServers = {};
519
516
  config.mcpServers.recursiv = mcpServerEntry(apiKey);
520
517
  await writeFile6(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
521
- console.log(pc11.green("\u2713") + ` Recursiv MCP added to ${pc11.dim(mcpPath)}`);
518
+ console.log(pc12.green("\u2713") + ` Recursiv MCP added to ${pc12.dim(mcpPath)}`);
522
519
  }
523
520
  }
524
521
  function claudeDesktopConfigPath() {
@@ -539,8 +536,8 @@ async function installClaudeDesktop(apiKey) {
539
536
  if (!config.mcpServers) config.mcpServers = {};
540
537
  config.mcpServers.recursiv = mcpServerEntry(apiKey);
541
538
  await writeFile6(configPath2, JSON.stringify(config, null, 2) + "\n", "utf-8");
542
- console.log(pc11.green("\u2713") + ` Recursiv MCP added to ${pc11.dim(configPath2)}`);
543
- console.log(pc11.dim(" Restart Claude Desktop to pick up the change."));
539
+ console.log(pc12.green("\u2713") + ` Recursiv MCP added to ${pc12.dim(configPath2)}`);
540
+ console.log(pc12.dim(" Restart Claude Desktop to pick up the change."));
544
541
  }
545
542
  async function installCodex(apiKey) {
546
543
  const codexDir = join5(homedir2(), ".codex");
@@ -563,7 +560,7 @@ async function installCodex(apiKey) {
563
560
  ].join("\n");
564
561
  const final = existing.trimEnd() + "\n" + tomlBlock + "\n";
565
562
  await writeFile6(configPath2, final, "utf-8");
566
- console.log(pc11.green("\u2713") + ` Recursiv MCP added to ${pc11.dim(configPath2)}`);
563
+ console.log(pc12.green("\u2713") + ` Recursiv MCP added to ${pc12.dim(configPath2)}`);
567
564
  }
568
565
  async function installOpenCode(apiKey, global) {
569
566
  let configPath2;
@@ -585,16 +582,16 @@ async function installOpenCode(apiKey, global) {
585
582
  }
586
583
  };
587
584
  await writeFile6(configPath2, JSON.stringify(config, null, 2) + "\n", "utf-8");
588
- console.log(pc11.green("\u2713") + ` Recursiv MCP added to ${pc11.dim(configPath2)}`);
585
+ console.log(pc12.green("\u2713") + ` Recursiv MCP added to ${pc12.dim(configPath2)}`);
589
586
  }
590
587
  async function mcpVerifyCommand() {
591
588
  const { spawn: spawn2 } = await import("child_process");
592
- const apiKey = process.env.RECURSIV_API_KEY || process.env.SOCIAL_DEV_API_KEY;
589
+ const apiKey = process.env.RECURSIV_API_KEY;
593
590
  if (!apiKey) {
594
- console.error(pc11.red(" error") + " RECURSIV_API_KEY not set in environment.");
591
+ console.error(pc12.red(" error") + " RECURSIV_API_KEY not set in environment.");
595
592
  process.exit(1);
596
593
  }
597
- console.log(pc11.dim(" Verifying Recursiv MCP server..."));
594
+ console.log(pc12.dim(" Verifying Recursiv MCP server..."));
598
595
  const child = spawn2("npx", ["-y", "@recursiv/mcp"], {
599
596
  env: { ...process.env, RECURSIV_API_KEY: apiKey },
600
597
  stdio: ["pipe", "pipe", "pipe"]
@@ -636,24 +633,24 @@ async function mcpVerifyCommand() {
636
633
  child.kill();
637
634
  switch (result) {
638
635
  case "ok":
639
- console.log(pc11.green(" \u2713") + " MCP server responded successfully.");
636
+ console.log(pc12.green(" \u2713") + " MCP server responded successfully.");
640
637
  try {
641
638
  const parsed = JSON.parse(stdout.trim().split("\n").pop() || "{}");
642
639
  const serverName = parsed?.result?.serverInfo?.name;
643
640
  const version = parsed?.result?.serverInfo?.version;
644
641
  if (serverName) {
645
- console.log(pc11.dim(` Server: ${serverName} v${version || "?"}`));
642
+ console.log(pc12.dim(` Server: ${serverName} v${version || "?"}`));
646
643
  }
647
644
  } catch {
648
645
  }
649
646
  break;
650
647
  case "error":
651
- console.error(pc11.red(" \u2717") + " MCP server returned an error.");
652
- if (stderr) console.error(pc11.dim(` ${stderr.trim()}`));
648
+ console.error(pc12.red(" \u2717") + " MCP server returned an error.");
649
+ if (stderr) console.error(pc12.dim(` ${stderr.trim()}`));
653
650
  process.exit(1);
654
651
  break;
655
652
  case "timeout":
656
- console.error(pc11.red(" \u2717") + " MCP server did not respond within 10s.");
653
+ console.error(pc12.red(" \u2717") + " MCP server did not respond within 10s.");
657
654
  process.exit(1);
658
655
  break;
659
656
  }
@@ -703,8 +700,127 @@ var init_mcp_install = __esm({
703
700
  }
704
701
  });
705
702
 
703
+ // src/commands/quickstart.ts
704
+ var quickstart_exports = {};
705
+ __export(quickstart_exports, {
706
+ checkGitHubCli: () => checkGitHubCli,
707
+ quickstartCommand: () => quickstartCommand
708
+ });
709
+ import { execFile } from "child_process";
710
+ import { promisify } from "util";
711
+ import { platform as platform2 } from "os";
712
+ import pc13 from "picocolors";
713
+ async function checkGitHubCli() {
714
+ try {
715
+ await execFileAsync("gh", ["--version"]);
716
+ } catch {
717
+ return { installed: false, authenticated: false };
718
+ }
719
+ try {
720
+ await execFileAsync("gh", ["auth", "status"]);
721
+ return { installed: true, authenticated: true };
722
+ } catch {
723
+ return { installed: true, authenticated: false };
724
+ }
725
+ }
726
+ function ghInstallHint() {
727
+ const p = platform2();
728
+ if (p === "darwin") return "Install with: brew install gh";
729
+ if (p === "win32") return "Install with: winget install GitHub.cli";
730
+ return "Install instructions: https://cli.github.com/";
731
+ }
732
+ async function fetchUsername(apiKey, baseUrl) {
733
+ try {
734
+ const res = await fetch(`${baseUrl}/users/me`, {
735
+ headers: {
736
+ Authorization: `Bearer ${apiKey}`,
737
+ Accept: "application/json"
738
+ }
739
+ });
740
+ if (!res.ok) return null;
741
+ const body = await res.json();
742
+ return body.data?.username ?? body.data?.email ?? null;
743
+ } catch {
744
+ return null;
745
+ }
746
+ }
747
+ async function quickstartCommand(opts = {}) {
748
+ console.log();
749
+ console.log(pc13.bold(" Setting up Recursiv on this machine") + pc13.dim(" \u2014 Claude Code + GitHub CLI + Recursiv account. ~3 minutes."));
750
+ console.log();
751
+ log.step(1, 3, "Checking GitHub CLI");
752
+ const ghCheck = opts.ghCheck ?? checkGitHubCli;
753
+ const gh = await ghCheck();
754
+ if (!gh.installed) {
755
+ log.error("GitHub CLI (`gh`) is not installed.");
756
+ log.info(ghInstallHint());
757
+ log.info("After installing, re-run `recursiv quickstart`.");
758
+ process.exit(1);
759
+ return;
760
+ }
761
+ if (!gh.authenticated) {
762
+ log.error("GitHub CLI is installed but not authenticated.");
763
+ log.info("Run `gh auth login` in another terminal, then re-run `recursiv quickstart`.");
764
+ process.exit(1);
765
+ return;
766
+ }
767
+ log.success("GitHub CLI installed and authenticated");
768
+ log.step(2, 3, "Checking Recursiv account");
769
+ const cwd = process.cwd();
770
+ const config = await readConfig(cwd).catch(() => null);
771
+ const baseUrl = config?.api.baseUrl ?? "https://api.recursiv.io/api/v1";
772
+ let apiKey = await resolveRecursivKey(cwd);
773
+ if (apiKey) {
774
+ const username = await fetchUsername(apiKey, baseUrl);
775
+ if (username) {
776
+ log.success(`Already authenticated as ${pc13.bold(username)}`);
777
+ } else {
778
+ log.success("Already authenticated (using existing API key)");
779
+ }
780
+ } else {
781
+ console.log();
782
+ console.log(pc13.dim(" No Recursiv API key found. Let's create one."));
783
+ console.log();
784
+ apiKey = await getOrCreateApiKey(baseUrl);
785
+ if (!apiKey) {
786
+ log.error("Authentication required to continue.");
787
+ process.exit(1);
788
+ return;
789
+ }
790
+ await saveCredentials({ recursivApiKey: apiKey });
791
+ log.success("Credentials saved to ~/.recursiv/credentials");
792
+ }
793
+ log.step(3, 3, "Configuring Recursiv MCP for Claude Code");
794
+ await mcpInstallCommand({ target: "claude-code", apiKey });
795
+ console.log();
796
+ console.log(pc13.green(pc13.bold(" Done.")) + pc13.dim(" Next steps:"));
797
+ console.log();
798
+ const quitHint = platform2() === "win32" ? "fully quit Claude Code (exit from the system tray)" : "fully quit Claude Code (Cmd-Q on macOS)";
799
+ console.log(" 1. " + quitHint);
800
+ console.log(" 2. Reopen Claude Code in this folder");
801
+ console.log(" 3. Paste the prompt from " + pc13.underline(TUTORIAL_URL));
802
+ console.log(" into your first chat message");
803
+ console.log();
804
+ console.log(pc13.dim(" Tip: when Claude Code asks to approve the first Recursiv tool call,"));
805
+ console.log(pc13.dim(' choose "Always allow recursiv" so you are not prompted again.'));
806
+ console.log();
807
+ }
808
+ var execFileAsync, TUTORIAL_URL;
809
+ var init_quickstart = __esm({
810
+ "src/commands/quickstart.ts"() {
811
+ "use strict";
812
+ init_logger();
813
+ init_config();
814
+ init_credentials();
815
+ init_auth_flow();
816
+ init_mcp_install();
817
+ execFileAsync = promisify(execFile);
818
+ TUTORIAL_URL = "https://docs.recursiv.io/guides/tutorials/build-your-first-app";
819
+ }
820
+ });
821
+
706
822
  // src/chat/renderer.ts
707
- import pc12 from "picocolors";
823
+ import pc14 from "picocolors";
708
824
  function getWidth() {
709
825
  return Math.max((process.stdout.columns || 80) - INDENT.length, 40);
710
826
  }
@@ -730,23 +846,23 @@ function wordWrap(text, width, indent = INDENT) {
730
846
  return lines.join("\n");
731
847
  }
732
848
  function colorize(text) {
733
- text = text.replace(/(https?:\/\/[^\s)\]>]+)/g, pc12.cyan(pc12.underline("$1")));
734
- text = text.replace(/`([^`]+)`/g, pc12.yellow("`$1`"));
735
- text = text.replace(/\*\*([^*]+)\*\*/g, pc12.bold("$1"));
736
- text = text.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, pc12.italic("$1"));
849
+ text = text.replace(/(https?:\/\/[^\s)\]>]+)/g, pc14.cyan(pc14.underline("$1")));
850
+ text = text.replace(/`([^`]+)`/g, pc14.yellow("`$1`"));
851
+ text = text.replace(/\*\*([^*]+)\*\*/g, pc14.bold("$1"));
852
+ text = text.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, pc14.italic("$1"));
737
853
  return text;
738
854
  }
739
855
  function printBanner(opts) {
740
856
  const v = opts?.version ?? "0.1.4";
741
857
  const logo = [
742
- pc12.cyan(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),
743
- pc12.cyan(" \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502"),
744
- pc12.cyan(" \u2502 \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2510 \u2502 \u2502") + " " + pc12.bold(pc12.cyan("recursiv")) + pc12.dim(` v${v}`),
745
- pc12.cyan(" \u2502 \u2502 \u2502 \u250C\u2500\u2510 \u2502 \u2502 \u2502") + " " + pc12.dim("https://recursiv.io"),
746
- pc12.cyan(" \u2502 \u2502 \u2502 \u2514\u2500\u2518 \u2502 \u2502 \u2502"),
747
- pc12.cyan(" \u2502 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2518 \u2502 \u2502"),
748
- pc12.cyan(" \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502"),
749
- pc12.cyan(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518")
858
+ pc14.cyan(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),
859
+ pc14.cyan(" \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502"),
860
+ pc14.cyan(" \u2502 \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2510 \u2502 \u2502") + " " + pc14.bold(pc14.cyan("recursiv")) + pc14.dim(` v${v}`),
861
+ pc14.cyan(" \u2502 \u2502 \u2502 \u250C\u2500\u2510 \u2502 \u2502 \u2502") + " " + pc14.dim("https://recursiv.io"),
862
+ pc14.cyan(" \u2502 \u2502 \u2502 \u2514\u2500\u2518 \u2502 \u2502 \u2502"),
863
+ pc14.cyan(" \u2502 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2518 \u2502 \u2502"),
864
+ pc14.cyan(" \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502"),
865
+ pc14.cyan(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518")
750
866
  ];
751
867
  console.log();
752
868
  for (const line of logo) {
@@ -754,26 +870,26 @@ function printBanner(opts) {
754
870
  }
755
871
  console.log();
756
872
  if (opts?.email || opts?.username) {
757
- const identity = opts.email ? `${opts.username ? pc12.bold(`@${opts.username}`) : "signed in"} ${pc12.dim(`(${opts.email})`)}` : pc12.bold(`@${opts.username}`);
758
- console.log(pc12.dim(" ") + identity);
873
+ const identity = opts.email ? `${opts.username ? pc14.bold(`@${opts.username}`) : "signed in"} ${pc14.dim(`(${opts.email})`)}` : pc14.bold(`@${opts.username}`);
874
+ console.log(pc14.dim(" ") + identity);
759
875
  }
760
876
  if (opts?.resumed) {
761
877
  console.log(
762
- pc12.dim(" ") + pc12.dim(`resumed session ${opts.resumed.id} (${opts.resumed.messageCount} messages)`)
878
+ pc14.dim(" ") + pc14.dim(`resumed session ${opts.resumed.id} (${opts.resumed.messageCount} messages)`)
763
879
  );
764
880
  }
765
881
  console.log();
766
- console.log(pc12.dim(" Type a message to get started. /help for commands. Ctrl-D to exit."));
882
+ console.log(pc14.dim(" Type a message to get started. /help for commands. Ctrl-D to exit."));
767
883
  }
768
884
  function printPrompt() {
769
- process.stdout.write(pc12.bold(pc12.green("> ")));
885
+ process.stdout.write(pc14.bold(pc14.green("> ")));
770
886
  }
771
887
  function printTips(context = "welcome") {
772
888
  const tips = HINT_MAP[context] || HINT_MAP.default;
773
889
  console.log();
774
890
  for (const [cmd, desc] of tips) {
775
891
  console.log(
776
- INDENT + pc12.dim(" ") + pc12.cyan(cmd) + pc12.dim(` \u2014 ${desc}`)
892
+ INDENT + pc14.dim(" ") + pc14.cyan(cmd) + pc14.dim(` \u2014 ${desc}`)
777
893
  );
778
894
  }
779
895
  console.log();
@@ -790,23 +906,23 @@ function detectHintContext(responseText) {
790
906
  }
791
907
  function printAssistantLabel() {
792
908
  console.log();
793
- process.stdout.write(pc12.bold(pc12.cyan("recursiv ")) + "\n");
909
+ process.stdout.write(pc14.bold(pc14.cyan("recursiv ")) + "\n");
794
910
  }
795
911
  function printToolCall(name) {
796
- console.log(pc12.yellow(" \u25B8 ") + pc12.dim(name));
912
+ console.log(pc14.yellow(" \u25B8 ") + pc14.dim(name));
797
913
  }
798
914
  function printToolResult(name, success) {
799
915
  if (success) {
800
- console.log(pc12.green(" \u2713 ") + pc12.dim(name));
916
+ console.log(pc14.green(" \u2713 ") + pc14.dim(name));
801
917
  } else {
802
- console.log(pc12.red(" \u2717 ") + pc12.dim(name));
918
+ console.log(pc14.red(" \u2717 ") + pc14.dim(name));
803
919
  }
804
920
  }
805
921
  function startThinking() {
806
922
  const frames = [" \xB7", " \xB7\xB7", " \xB7\xB7\xB7"];
807
923
  let i = 0;
808
924
  const interval = setInterval(() => {
809
- process.stdout.write(`\r${pc12.dim(frames[i % frames.length])} `);
925
+ process.stdout.write(`\r${pc14.dim(frames[i % frames.length])} `);
810
926
  i++;
811
927
  }, 250);
812
928
  return {
@@ -817,11 +933,11 @@ function startThinking() {
817
933
  };
818
934
  }
819
935
  async function confirmAction(description) {
820
- const { createInterface: createInterface2 } = await import("readline");
821
- const rl = createInterface2({ input: process.stdin, output: process.stdout, terminal: true });
936
+ const readline = await import("readline");
937
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
822
938
  return new Promise((resolve4) => {
823
939
  process.stdout.write(
824
- pc12.yellow(" ? ") + description + pc12.dim(" (y/n) ")
940
+ pc14.yellow(" ? ") + description + pc14.dim(" (y/n) ")
825
941
  );
826
942
  rl.once("line", (line) => {
827
943
  rl.close();
@@ -832,10 +948,10 @@ async function confirmAction(description) {
832
948
  });
833
949
  }
834
950
  function printError(message) {
835
- console.log(pc12.red(" \u2717 ") + message);
951
+ console.log(pc14.red(" \u2717 ") + message);
836
952
  }
837
953
  function printInfo(message) {
838
- console.log(pc12.dim(message));
954
+ console.log(pc14.dim(message));
839
955
  }
840
956
  var INDENT, StreamWriter, HINT_MAP;
841
957
  var init_renderer = __esm({
@@ -861,11 +977,11 @@ var init_renderer = __esm({
861
977
  const width = getWidth();
862
978
  if (line.trimStart().startsWith("```")) {
863
979
  this.inCodeBlock = !this.inCodeBlock;
864
- process.stdout.write(INDENT + pc12.dim(line));
980
+ process.stdout.write(INDENT + pc14.dim(line));
865
981
  return;
866
982
  }
867
983
  if (this.inCodeBlock) {
868
- process.stdout.write(INDENT + pc12.cyan(line));
984
+ process.stdout.write(INDENT + pc14.cyan(line));
869
985
  return;
870
986
  }
871
987
  if (line.trim() === "") {
@@ -874,18 +990,18 @@ var init_renderer = __esm({
874
990
  }
875
991
  const headingMatch = line.match(/^(#{1,3})\s+(.+)\n?$/);
876
992
  if (headingMatch) {
877
- process.stdout.write(INDENT + pc12.bold(pc12.cyan(headingMatch[2])) + "\n");
993
+ process.stdout.write(INDENT + pc14.bold(pc14.cyan(headingMatch[2])) + "\n");
878
994
  return;
879
995
  }
880
996
  if (/^---+\s*\n?$/.test(line)) {
881
- process.stdout.write(INDENT + pc12.dim("\u2500".repeat(Math.min(width, 60))) + "\n");
997
+ process.stdout.write(INDENT + pc14.dim("\u2500".repeat(Math.min(width, 60))) + "\n");
882
998
  return;
883
999
  }
884
1000
  const bulletMatch = line.match(/^(\s*)([-*])\s+(.*)$/);
885
1001
  if (bulletMatch) {
886
1002
  const extraIndent = bulletMatch[1];
887
1003
  const content = colorize(bulletMatch[3]);
888
- const prefix = INDENT + extraIndent + pc12.cyan("\u2022") + " ";
1004
+ const prefix = INDENT + extraIndent + pc14.cyan("\u2022") + " ";
889
1005
  process.stdout.write(prefix + content + "\n");
890
1006
  return;
891
1007
  }
@@ -894,7 +1010,7 @@ var init_renderer = __esm({
894
1010
  const extraIndent = numMatch[1];
895
1011
  const num = numMatch[2];
896
1012
  const content = colorize(numMatch[3]);
897
- const prefix = INDENT + extraIndent + pc12.cyan(num + ".") + " ";
1013
+ const prefix = INDENT + extraIndent + pc14.cyan(num + ".") + " ";
898
1014
  process.stdout.write(prefix + content + "\n");
899
1015
  return;
900
1016
  }
@@ -910,7 +1026,7 @@ var init_renderer = __esm({
910
1026
  const remaining = this.lineBuffer;
911
1027
  this.lineBuffer = "";
912
1028
  if (this.inCodeBlock) {
913
- process.stdout.write(pc12.cyan(remaining));
1029
+ process.stdout.write(pc14.cyan(remaining));
914
1030
  } else {
915
1031
  process.stdout.write(colorize(remaining));
916
1032
  }
@@ -1764,8 +1880,8 @@ import { createInterface } from "readline";
1764
1880
  import { existsSync as existsSync3, readFileSync } from "fs";
1765
1881
  import { basename as basename2, join as join7 } from "path";
1766
1882
  import { execSync as execSync2 } from "child_process";
1767
- import { Recursiv } from "@recursiv/sdk";
1768
- import pc13 from "picocolors";
1883
+ import { Recursiv, InsufficientCreditsError as InsufficientCreditsError2 } from "@recursiv/sdk";
1884
+ import pc15 from "picocolors";
1769
1885
  async function startAgent(config) {
1770
1886
  const client = new Recursiv({
1771
1887
  apiKey: config.recursivApiKey,
@@ -1868,7 +1984,7 @@ async function replProxy(rl, client, session) {
1868
1984
  ${trimmed}` : trimmed;
1869
1985
  try {
1870
1986
  if (planMode) {
1871
- console.log(pc13.dim(" \u25C6 plan mode"));
1987
+ console.log(pc15.dim(" \u25C6 plan mode"));
1872
1988
  }
1873
1989
  printAssistantLabel();
1874
1990
  const thinking = startThinking();
@@ -1917,6 +2033,12 @@ ${trimmed}` : trimmed;
1917
2033
  printTips(hintCtx);
1918
2034
  }
1919
2035
  } catch (err) {
2036
+ if (err instanceof InsufficientCreditsError2) {
2037
+ printError("Out of credits \u2014 your account has no remaining balance.");
2038
+ printInfo(` Upgrade: ${err.upgradeUrl}`);
2039
+ console.log();
2040
+ continue;
2041
+ }
1920
2042
  const message = err instanceof Error ? err.message : String(err);
1921
2043
  if (message.includes("rate_limit") || message.includes("429")) {
1922
2044
  printError("Rate limited \u2014 wait a moment and try again.");
@@ -2087,39 +2209,39 @@ async function handleSlashCommand(input, session, client) {
2087
2209
  case "/plan":
2088
2210
  planMode = !planMode;
2089
2211
  if (planMode) {
2090
- console.log(pc13.cyan(" \u25C6 Plan mode ON") + pc13.dim(" \u2014 agent will outline steps before executing"));
2212
+ console.log(pc15.cyan(" \u25C6 Plan mode ON") + pc15.dim(" \u2014 agent will outline steps before executing"));
2091
2213
  } else {
2092
- console.log(pc13.green(" \u25C6 Plan mode OFF") + pc13.dim(" \u2014 agent will execute immediately"));
2214
+ console.log(pc15.green(" \u25C6 Plan mode OFF") + pc15.dim(" \u2014 agent will execute immediately"));
2093
2215
  }
2094
2216
  console.log();
2095
2217
  return true;
2096
2218
  case "/clear":
2097
2219
  session.messages = [];
2098
- console.log(pc13.dim(" Conversation cleared."));
2220
+ console.log(pc15.dim(" Conversation cleared."));
2099
2221
  console.log();
2100
2222
  return true;
2101
2223
  case "/help":
2102
2224
  console.log();
2103
- console.log(pc13.bold(" Commands"));
2104
- console.log(pc13.dim(" /help ") + "Show this help");
2105
- console.log(pc13.dim(" /plan ") + "Toggle plan mode (outline before executing)");
2106
- console.log(pc13.dim(" /clear ") + "Clear conversation history");
2107
- console.log(pc13.dim(" /status ") + "Show connection status");
2108
- console.log(pc13.dim(" /context ") + "Show full user context (profile, orgs, tier)");
2109
- console.log(pc13.dim(" /sessions ") + "List recent sessions");
2110
- console.log(pc13.dim(" /load <id> ") + "Load a previous session by ID");
2111
- console.log(pc13.dim(" /exit ") + "Exit the CLI");
2225
+ console.log(pc15.bold(" Commands"));
2226
+ console.log(pc15.dim(" /help ") + "Show this help");
2227
+ console.log(pc15.dim(" /plan ") + "Toggle plan mode (outline before executing)");
2228
+ console.log(pc15.dim(" /clear ") + "Clear conversation history");
2229
+ console.log(pc15.dim(" /status ") + "Show connection status");
2230
+ console.log(pc15.dim(" /context ") + "Show full user context (profile, orgs, tier)");
2231
+ console.log(pc15.dim(" /sessions ") + "List recent sessions");
2232
+ console.log(pc15.dim(" /load <id> ") + "Load a previous session by ID");
2233
+ console.log(pc15.dim(" /exit ") + "Exit the CLI");
2112
2234
  console.log();
2113
- console.log(pc13.bold(" Usage"));
2114
- console.log(pc13.dim(" Just type naturally. Examples:"));
2115
- console.log(pc13.dim(' "show my posts"'));
2116
- console.log(pc13.dim(' "create a post saying hello world"'));
2117
- console.log(pc13.dim(' "list my agents"'));
2118
- console.log(pc13.dim(' "what communities can I join?"'));
2119
- console.log(pc13.dim(' "check my unread messages"'));
2120
- console.log(pc13.dim(' "show dispatcher tasks"'));
2235
+ console.log(pc15.bold(" Usage"));
2236
+ console.log(pc15.dim(" Just type naturally. Examples:"));
2237
+ console.log(pc15.dim(' "show my posts"'));
2238
+ console.log(pc15.dim(' "create a post saying hello world"'));
2239
+ console.log(pc15.dim(' "list my agents"'));
2240
+ console.log(pc15.dim(' "what communities can I join?"'));
2241
+ console.log(pc15.dim(' "check my unread messages"'));
2242
+ console.log(pc15.dim(' "show dispatcher tasks"'));
2121
2243
  console.log();
2122
- console.log(pc13.dim(" Destructive actions (delete, deploy, send) require confirmation."));
2244
+ console.log(pc15.dim(" Destructive actions (delete, deploy, send) require confirmation."));
2123
2245
  console.log();
2124
2246
  return true;
2125
2247
  case "/status":
@@ -2127,11 +2249,11 @@ async function handleSlashCommand(input, session, client) {
2127
2249
  const profile = await client.profiles.me();
2128
2250
  const data = profile.data;
2129
2251
  console.log();
2130
- console.log(pc13.bold(" Status"));
2131
- console.log(pc13.dim(" User: ") + pc13.bold(`@${data.username || "unknown"}`));
2132
- if (data.email) console.log(pc13.dim(" Email: ") + data.email);
2133
- console.log(pc13.dim(" Session: ") + session.id.slice(0, 8));
2134
- console.log(pc13.dim(" History: ") + `${session.messages.length} messages`);
2252
+ console.log(pc15.bold(" Status"));
2253
+ console.log(pc15.dim(" User: ") + pc15.bold(`@${data.username || "unknown"}`));
2254
+ if (data.email) console.log(pc15.dim(" Email: ") + data.email);
2255
+ console.log(pc15.dim(" Session: ") + session.id.slice(0, 8));
2256
+ console.log(pc15.dim(" History: ") + `${session.messages.length} messages`);
2135
2257
  console.log();
2136
2258
  } catch {
2137
2259
  printError("Could not fetch status \u2014 check your API key");
@@ -2146,35 +2268,35 @@ async function handleSlashCommand(input, session, client) {
2146
2268
  client.freeTier.getTier()
2147
2269
  ]);
2148
2270
  console.log();
2149
- console.log(pc13.bold(" User Context"));
2271
+ console.log(pc15.bold(" User Context"));
2150
2272
  if (profile.status === "fulfilled") {
2151
2273
  const p = profile.value.data;
2152
- console.log(pc13.dim(" User: ") + pc13.bold(`@${p.username || "unknown"}`));
2153
- console.log(pc13.dim(" Name: ") + (p.name || "-"));
2154
- console.log(pc13.dim(" Email: ") + (p.email || "-"));
2155
- console.log(pc13.dim(" Followers: ") + (p.followers_count ?? 0));
2156
- console.log(pc13.dim(" Following: ") + (p.following_count ?? 0));
2274
+ console.log(pc15.dim(" User: ") + pc15.bold(`@${p.username || "unknown"}`));
2275
+ console.log(pc15.dim(" Name: ") + (p.name || "-"));
2276
+ console.log(pc15.dim(" Email: ") + (p.email || "-"));
2277
+ console.log(pc15.dim(" Followers: ") + (p.followers_count ?? 0));
2278
+ console.log(pc15.dim(" Following: ") + (p.following_count ?? 0));
2157
2279
  }
2158
2280
  if (orgs.status === "fulfilled") {
2159
2281
  const orgList = orgs.value.data;
2160
2282
  console.log();
2161
- console.log(pc13.bold(" Organizations"));
2283
+ console.log(pc15.bold(" Organizations"));
2162
2284
  if (orgList.length === 0) {
2163
- console.log(pc13.dim(" None"));
2285
+ console.log(pc15.dim(" None"));
2164
2286
  } else {
2165
2287
  for (const org of orgList) {
2166
- const role = org.role ? pc13.dim(` (${org.role})`) : "";
2167
- console.log(` - ${pc13.bold(org.name)}${role}`);
2288
+ const role = org.role ? pc15.dim(` (${org.role})`) : "";
2289
+ console.log(` - ${pc15.bold(org.name)}${role}`);
2168
2290
  }
2169
2291
  }
2170
2292
  }
2171
2293
  if (tier.status === "fulfilled") {
2172
2294
  const t = tier.value.data;
2173
2295
  console.log();
2174
- console.log(pc13.bold(" Tier"));
2175
- console.log(pc13.dim(" Plan: ") + (t.tier || t.plan || "free"));
2296
+ console.log(pc15.bold(" Tier"));
2297
+ console.log(pc15.dim(" Plan: ") + (t.tier || t.plan || "free"));
2176
2298
  if (t.api_calls_remaining != null) {
2177
- console.log(pc13.dim(" Calls: ") + `${t.api_calls_remaining} remaining`);
2299
+ console.log(pc15.dim(" Calls: ") + `${t.api_calls_remaining} remaining`);
2178
2300
  }
2179
2301
  }
2180
2302
  console.log();
@@ -2187,14 +2309,14 @@ async function handleSlashCommand(input, session, client) {
2187
2309
  const sessions = await listSessions();
2188
2310
  console.log();
2189
2311
  if (sessions.length === 0) {
2190
- console.log(pc13.dim(" No saved sessions."));
2312
+ console.log(pc15.dim(" No saved sessions."));
2191
2313
  } else {
2192
- console.log(pc13.bold(" Recent Sessions"));
2314
+ console.log(pc15.bold(" Recent Sessions"));
2193
2315
  for (const s of sessions) {
2194
- const current = s.id === session.id ? pc13.green(" (current)") : "";
2316
+ const current = s.id === session.id ? pc15.green(" (current)") : "";
2195
2317
  const date = new Date(s.createdAt).toLocaleDateString();
2196
2318
  console.log(
2197
- pc13.dim(" ") + pc13.bold(s.id.slice(0, 8)) + pc13.dim(` \u2014 ${date}, ${s.messageCount} messages`) + current
2319
+ pc15.dim(" ") + pc15.bold(s.id.slice(0, 8)) + pc15.dim(` \u2014 ${date}, ${s.messageCount} messages`) + current
2198
2320
  );
2199
2321
  }
2200
2322
  }
@@ -2205,7 +2327,7 @@ async function handleSlashCommand(input, session, client) {
2205
2327
  const parts = input.split(/\s+/);
2206
2328
  const targetId = parts[1];
2207
2329
  if (!targetId) {
2208
- console.log(pc13.dim(" Usage: /load <session-id>"));
2330
+ console.log(pc15.dim(" Usage: /load <session-id>"));
2209
2331
  console.log();
2210
2332
  return true;
2211
2333
  }
@@ -2226,13 +2348,13 @@ async function handleSlashCommand(input, session, client) {
2226
2348
  session.createdAt = loaded.createdAt;
2227
2349
  session.messages = loaded.messages;
2228
2350
  console.log(
2229
- pc13.dim(" ") + `Loaded session ${pc13.bold(loaded.id.slice(0, 8))} (${loaded.messages.length} messages)`
2351
+ pc15.dim(" ") + `Loaded session ${pc15.bold(loaded.id.slice(0, 8))} (${loaded.messages.length} messages)`
2230
2352
  );
2231
2353
  console.log();
2232
2354
  return true;
2233
2355
  }
2234
2356
  default:
2235
- console.log(pc13.dim(` Unknown command: ${cmd}. Type /help for available commands.`));
2357
+ console.log(pc15.dim(` Unknown command: ${cmd}. Type /help for available commands.`));
2236
2358
  console.log();
2237
2359
  return true;
2238
2360
  }
@@ -2329,6 +2451,19 @@ Tone: precise, efficient, slightly warm. Senior engineer energy.`;
2329
2451
  // src/bin/recursiv.ts
2330
2452
  import { Command } from "commander";
2331
2453
 
2454
+ // src/lib/cli-errors.ts
2455
+ import pc from "picocolors";
2456
+ import { InsufficientCreditsError } from "@recursiv/sdk";
2457
+ function printCliError(err) {
2458
+ if (err instanceof InsufficientCreditsError) {
2459
+ console.error(pc.red(" Out of credits."));
2460
+ console.error(` ${err.message.split("\n")[0]}`);
2461
+ console.error(` Upgrade: ${pc.bold(pc.cyan(err.upgradeUrl))}`);
2462
+ return;
2463
+ }
2464
+ console.error(err instanceof Error ? err.message : err);
2465
+ }
2466
+
2332
2467
  // src/commands/init.ts
2333
2468
  init_logger();
2334
2469
  init_config();
@@ -2338,7 +2473,7 @@ import { mkdir, readFile as readFile3, unlink, writeFile as writeFile3 } from "f
2338
2473
  import { resolve } from "path";
2339
2474
  import { execSync } from "child_process";
2340
2475
  import prompts2 from "prompts";
2341
- import pc3 from "picocolors";
2476
+ import pc4 from "picocolors";
2342
2477
  import ora2 from "ora";
2343
2478
 
2344
2479
  // src/lib/templates.ts
@@ -2450,12 +2585,12 @@ async function initCommand(nameArg) {
2450
2585
  }
2451
2586
  const projectDir = resolve(process.cwd(), projectName);
2452
2587
  if (existsSync2(projectDir)) {
2453
- log.error(`Directory ${pc3.bold(projectName)} already exists`);
2588
+ log.error(`Directory ${pc4.bold(projectName)} already exists`);
2454
2589
  process.exit(1);
2455
2590
  }
2456
2591
  log.step(2, totalSteps, "Choose a template");
2457
2592
  const templateChoices = templates.map((t) => ({
2458
- title: t.recommended ? `${t.name} ${pc3.dim("(recommended)")}` : t.name,
2593
+ title: t.recommended ? `${t.name} ${pc4.dim("(recommended)")}` : t.name,
2459
2594
  description: t.description,
2460
2595
  value: t.id
2461
2596
  }));
@@ -2510,7 +2645,7 @@ async function initCommand(nameArg) {
2510
2645
  );
2511
2646
  }
2512
2647
  log.step(6, totalSteps, "Installing dependencies");
2513
- const installSpinner = ora2(`Running ${pc3.bold(installCommand(pm))}...`).start();
2648
+ const installSpinner = ora2(`Running ${pc4.bold(installCommand(pm))}...`).start();
2514
2649
  try {
2515
2650
  execSync(installCommand(pm), {
2516
2651
  cwd: projectDir,
@@ -2534,18 +2669,18 @@ async function initCommand(nameArg) {
2534
2669
  log.warn("Could not initialize git repository");
2535
2670
  }
2536
2671
  log.blank();
2537
- console.log(pc3.bold(pc3.green("Your Recursiv app is ready!")));
2672
+ console.log(pc4.bold(pc4.green("Your Recursiv app is ready!")));
2538
2673
  log.blank();
2539
2674
  console.log(" Next steps:");
2540
2675
  console.log();
2541
- console.log(` ${pc3.dim("$")} cd ${projectName}`);
2676
+ console.log(` ${pc4.dim("$")} cd ${projectName}`);
2542
2677
  if (!apiKey) {
2543
- console.log(` ${pc3.dim("$")} ${pc3.dim("# Add your API key to .env")}`);
2678
+ console.log(` ${pc4.dim("$")} ${pc4.dim("# Add your API key to .env")}`);
2544
2679
  }
2545
- console.log(` ${pc3.dim("$")} ${runCommand(pm, "dev")}`);
2680
+ console.log(` ${pc4.dim("$")} ${runCommand(pm, "dev")}`);
2546
2681
  log.blank();
2547
- console.log(pc3.dim("Docs: https://docs.recursiv.io"));
2548
- console.log(pc3.dim("Dashboard: https://recursiv.io/dashboard"));
2682
+ console.log(pc4.dim("Docs: https://docs.recursiv.io"));
2683
+ console.log(pc4.dim("Dashboard: https://recursiv.io/dashboard"));
2549
2684
  log.blank();
2550
2685
  }
2551
2686
 
@@ -2554,13 +2689,13 @@ init_logger();
2554
2689
  init_config();
2555
2690
  init_env();
2556
2691
  import { spawn } from "child_process";
2557
- import pc4 from "picocolors";
2692
+ import pc5 from "picocolors";
2558
2693
  async function devCommand(opts) {
2559
2694
  const cwd = process.cwd();
2560
2695
  const config = await readConfig(cwd);
2561
2696
  if (!config) {
2562
2697
  log.error("No .recursiv.json found \u2014 are you in a Recursiv project?");
2563
- log.info(`Run ${pc4.bold("create-recursiv-app")} to create a new project`);
2698
+ log.info(`Run ${pc5.bold("create-recursiv-app")} to create a new project`);
2564
2699
  process.exit(1);
2565
2700
  }
2566
2701
  const apiKey = await readApiKeyFromEnv(cwd);
@@ -2576,14 +2711,9 @@ async function devCommand(opts) {
2576
2711
  };
2577
2712
  if (apiKey) {
2578
2713
  env.RECURSIV_API_KEY = apiKey;
2579
- if (config.project.framework === "nextjs") {
2580
- env.NEXT_PUBLIC_RECURSIV_API_KEY = apiKey;
2581
- } else if (config.project.framework === "vite") {
2582
- env.VITE_RECURSIV_API_KEY = apiKey;
2583
- }
2584
2714
  }
2585
- log.info(`Starting dev server on port ${pc4.bold(port)}`);
2586
- log.info(`Running: ${pc4.dim(devCmd)}`);
2715
+ log.info(`Starting dev server on port ${pc5.bold(port)}`);
2716
+ log.info(`Running: ${pc5.dim(devCmd)}`);
2587
2717
  console.log();
2588
2718
  const [cmd, ...args] = devCmd.split(" ");
2589
2719
  const child = spawn(cmd, args, {
@@ -2607,7 +2737,7 @@ init_logger();
2607
2737
  init_config();
2608
2738
  import { writeFile as writeFile4 } from "fs/promises";
2609
2739
  import { resolve as resolve2 } from "path";
2610
- import pc5 from "picocolors";
2740
+ import pc6 from "picocolors";
2611
2741
  import ora3 from "ora";
2612
2742
  var targets = [
2613
2743
  {
@@ -2693,12 +2823,12 @@ async function deployCommand(target) {
2693
2823
  }
2694
2824
  if (target === "cloud") {
2695
2825
  log.info("Cloud deployment via Recursiv is coming soon");
2696
- log.info(`For now, deploy to Vercel, Render, or Railway with ${pc5.bold("recursiv deploy <target>")}`);
2826
+ log.info(`For now, deploy to Vercel, Render, or Railway with ${pc6.bold("recursiv deploy <target>")}`);
2697
2827
  return;
2698
2828
  }
2699
2829
  const deployTarget = targets.find((t) => t.id === target);
2700
2830
  if (!deployTarget) {
2701
- log.error(`Unknown target: ${pc5.bold(target)}`);
2831
+ log.error(`Unknown target: ${pc6.bold(target)}`);
2702
2832
  log.info(`Available targets: ${targets.map((t) => t.id).join(", ")}, cloud`);
2703
2833
  process.exit(1);
2704
2834
  }
@@ -2708,9 +2838,9 @@ async function deployCommand(target) {
2708
2838
  config.project.framework
2709
2839
  );
2710
2840
  await writeFile4(resolve2(cwd, file), content + "\n", "utf-8");
2711
- spinner.succeed(`Created ${pc5.bold(file)}`);
2841
+ spinner.succeed(`Created ${pc6.bold(file)}`);
2712
2842
  log.blank();
2713
- log.info(`Remember to set ${pc5.bold("RECURSIV_API_KEY")} in your ${deployTarget.name} environment`);
2843
+ log.info(`Remember to set ${pc6.bold("RECURSIV_API_KEY")} in your ${deployTarget.name} environment`);
2714
2844
  }
2715
2845
 
2716
2846
  // src/commands/auth.ts
@@ -2719,14 +2849,14 @@ init_env();
2719
2849
  init_auth_flow();
2720
2850
  init_config();
2721
2851
  init_credentials();
2722
- import pc6 from "picocolors";
2852
+ import pc7 from "picocolors";
2723
2853
  async function loginCommand() {
2724
2854
  const cwd = process.cwd();
2725
2855
  const config = await readConfig(cwd);
2726
2856
  const baseUrl = config?.api.baseUrl ?? "https://api.recursiv.io/api/v1";
2727
2857
  const existing = await resolveRecursivKey(cwd);
2728
2858
  if (existing) {
2729
- log.info(`Existing key found: ${pc6.dim(maskKey(existing))}`);
2859
+ log.info(`Existing key found: ${pc7.dim(maskKey(existing))}`);
2730
2860
  log.info("Enter a new key to replace it, or press Enter to keep it");
2731
2861
  }
2732
2862
  const apiKey = await getOrCreateApiKey(baseUrl);
@@ -2757,10 +2887,10 @@ async function whoamiCommand() {
2757
2887
  const apiKey = await resolveRecursivKey(cwd);
2758
2888
  if (!apiKey) {
2759
2889
  log.error("No API key found in .env");
2760
- log.info(`Run ${pc6.bold("recursiv auth login")} to set one`);
2890
+ log.info(`Run ${pc7.bold("recursiv auth login")} to set one`);
2761
2891
  return;
2762
2892
  }
2763
- log.info(`Key: ${pc6.dim(maskKey(apiKey))}`);
2893
+ log.info(`Key: ${pc7.dim(maskKey(apiKey))}`);
2764
2894
  try {
2765
2895
  const res = await fetch(`${baseUrl}/users/me`, {
2766
2896
  headers: {
@@ -2773,7 +2903,7 @@ async function whoamiCommand() {
2773
2903
  return;
2774
2904
  }
2775
2905
  const body = await res.json();
2776
- if (body.data.username) log.info(`User: ${pc6.bold(body.data.username)}`);
2906
+ if (body.data.username) log.info(`User: ${pc7.bold(body.data.username)}`);
2777
2907
  if (body.data.email) log.info(`Email: ${body.data.email}`);
2778
2908
  } catch {
2779
2909
  log.warn("Could not reach API \u2014 check your network");
@@ -2788,30 +2918,30 @@ function maskKey(key) {
2788
2918
  init_logger();
2789
2919
  init_config();
2790
2920
  init_env();
2791
- import pc7 from "picocolors";
2921
+ import pc8 from "picocolors";
2792
2922
  async function infoCommand() {
2793
2923
  const cwd = process.cwd();
2794
2924
  const config = await readConfig(cwd);
2795
2925
  if (!config) {
2796
2926
  log.error("No .recursiv.json found \u2014 are you in a Recursiv project?");
2797
- log.info(`Run ${pc7.bold("create-recursiv-app")} to create a new project`);
2927
+ log.info(`Run ${pc8.bold("create-recursiv-app")} to create a new project`);
2798
2928
  process.exit(1);
2799
2929
  }
2800
2930
  const apiKey = await readApiKeyFromEnv(cwd);
2801
2931
  const pm = detectPackageManager(cwd);
2802
2932
  const template = getTemplate(config.project.template);
2803
2933
  console.log();
2804
- console.log(pc7.bold("Project Info"));
2934
+ console.log(pc8.bold("Project Info"));
2805
2935
  console.log();
2806
- console.log(` Name: ${pc7.bold(config.project.name)}`);
2936
+ console.log(` Name: ${pc8.bold(config.project.name)}`);
2807
2937
  console.log(` Template: ${template?.name ?? config.project.template}`);
2808
2938
  console.log(` Framework: ${config.project.framework}`);
2809
2939
  console.log(` Dev port: ${config.dev.port}`);
2810
- console.log(` Dev cmd: ${pc7.dim(config.dev.command)}`);
2940
+ console.log(` Dev cmd: ${pc8.dim(config.dev.command)}`);
2811
2941
  console.log(` Pkg mgr: ${pm}`);
2812
- console.log(` API URL: ${pc7.dim(config.api.baseUrl)}`);
2813
- console.log(` API key: ${apiKey ? pc7.green("configured") : pc7.yellow("not set")}`);
2814
- console.log(` Config: ${pc7.dim(".recursiv.json v" + config.version)}`);
2942
+ console.log(` API URL: ${pc8.dim(config.api.baseUrl)}`);
2943
+ console.log(` API key: ${apiKey ? pc8.green("configured") : pc8.yellow("not set")}`);
2944
+ console.log(` Config: ${pc8.dim(".recursiv.json v" + config.version)}`);
2815
2945
  console.log();
2816
2946
  if (apiKey) {
2817
2947
  try {
@@ -2905,7 +3035,7 @@ A neural CLI reflection of your product surface with neurons, particles, and wav
2905
3035
 
2906
3036
  ## Data + Realtime
2907
3037
  - PostgreSQL + Drizzle ORM
2908
- - Kafka + Socket.IO
3038
+ - Socket.IO + optional Redis adapter
2909
3039
 
2910
3040
  ## Agents
2911
3041
  - Composio + E2B + OpenRouter`
@@ -3537,7 +3667,7 @@ async function studioCommand(opts) {
3537
3667
  }
3538
3668
 
3539
3669
  // src/commands/browser-use.ts
3540
- import pc8 from "picocolors";
3670
+ import pc9 from "picocolors";
3541
3671
  import { BrowserUse } from "browser-use-sdk";
3542
3672
  function getClient() {
3543
3673
  const apiKey = process.env.BROWSER_USE_API_KEY;
@@ -3563,11 +3693,11 @@ async function browserUseRunCommand(opts) {
3563
3693
  console.log(JSON.stringify(result, null, 2));
3564
3694
  return;
3565
3695
  }
3566
- console.log(pc8.green("Browser Use task complete"));
3567
- console.log(`${pc8.dim("Task:")} ${opts.task}`);
3568
- console.log(`${pc8.dim("Status:")} ${result.status}`);
3696
+ console.log(pc9.green("Browser Use task complete"));
3697
+ console.log(`${pc9.dim("Task:")} ${opts.task}`);
3698
+ console.log(`${pc9.dim("Status:")} ${result.status}`);
3569
3699
  if (result.output) {
3570
- console.log(`${pc8.dim("Output:")} ${String(result.output)}`);
3700
+ console.log(`${pc9.dim("Output:")} ${String(result.output)}`);
3571
3701
  }
3572
3702
  }
3573
3703
  async function browserUseMcpSnippetCommand(opts) {
@@ -3611,19 +3741,19 @@ async function browserUseMcpSnippetCommand(opts) {
3611
3741
  }
3612
3742
 
3613
3743
  // src/commands/api.ts
3614
- import pc10 from "picocolors";
3744
+ import pc11 from "picocolors";
3615
3745
 
3616
3746
  // src/lib/api.ts
3617
3747
  init_config();
3618
3748
  init_env();
3619
3749
  init_logger();
3620
- import pc9 from "picocolors";
3750
+ import pc10 from "picocolors";
3621
3751
  async function getApiContext(cwd) {
3622
3752
  const config = await readConfig(cwd);
3623
3753
  const apiKey = await readApiKeyFromEnv(cwd);
3624
3754
  if (!apiKey) {
3625
3755
  log.error("No API key configured.");
3626
- log.info(`Run ${pc9.bold("recursiv auth login")} to set your key.`);
3756
+ log.info(`Run ${pc10.bold("recursiv auth login")} to set your key.`);
3627
3757
  process.exit(1);
3628
3758
  }
3629
3759
  return {
@@ -3672,14 +3802,14 @@ async function usersMeCommand(opts) {
3672
3802
  const res = await apiRequest(ctx, { method: "GET", path: "users/me" });
3673
3803
  output(res, opts.json, (data) => {
3674
3804
  log.blank();
3675
- console.log(pc10.bold("User"));
3676
- console.log(` ${pc10.dim("id")}: ${data.id}`);
3677
- console.log(` ${pc10.dim("name")}: ${data.name ?? "-"}`);
3678
- console.log(` ${pc10.dim("username")}: ${data.username ?? "-"}`);
3679
- console.log(` ${pc10.dim("email")}: ${data.email ?? "-"}`);
3680
- console.log(` ${pc10.dim("followers")}: ${data.followers_count ?? 0}`);
3681
- console.log(` ${pc10.dim("following")}: ${data.following_count ?? 0}`);
3682
- console.log(` ${pc10.dim("posts")}: ${data.posts_count ?? 0}`);
3805
+ console.log(pc11.bold("User"));
3806
+ console.log(` ${pc11.dim("id")}: ${data.id}`);
3807
+ console.log(` ${pc11.dim("name")}: ${data.name ?? "-"}`);
3808
+ console.log(` ${pc11.dim("username")}: ${data.username ?? "-"}`);
3809
+ console.log(` ${pc11.dim("email")}: ${data.email ?? "-"}`);
3810
+ console.log(` ${pc11.dim("followers")}: ${data.followers_count ?? 0}`);
3811
+ console.log(` ${pc11.dim("following")}: ${data.following_count ?? 0}`);
3812
+ console.log(` ${pc11.dim("posts")}: ${data.posts_count ?? 0}`);
3683
3813
  log.blank();
3684
3814
  });
3685
3815
  }
@@ -3695,13 +3825,13 @@ async function communitiesListCommand(opts) {
3695
3825
  });
3696
3826
  output(res, opts.json, (data, meta) => {
3697
3827
  log.blank();
3698
- console.log(pc10.bold("Communities"));
3828
+ console.log(pc11.bold("Communities"));
3699
3829
  data.forEach((comm) => {
3700
- const name = pc10.bold(comm.name);
3701
- const slug = comm.slug ? pc10.dim(`/${comm.slug}`) : "";
3702
- const members = pc10.dim(`members ${comm.member_count ?? 0}`);
3830
+ const name = pc11.bold(comm.name);
3831
+ const slug = comm.slug ? pc11.dim(`/${comm.slug}`) : "";
3832
+ const members = pc11.dim(`members ${comm.member_count ?? 0}`);
3703
3833
  console.log(` ${name} ${slug} ${members}`);
3704
- if (comm.description) console.log(` ${pc10.dim(comm.description)}`);
3834
+ if (comm.description) console.log(` ${pc11.dim(comm.description)}`);
3705
3835
  });
3706
3836
  printMeta(meta);
3707
3837
  });
@@ -3723,7 +3853,7 @@ async function communitiesCreateCommand(opts) {
3723
3853
  }
3724
3854
  });
3725
3855
  output(res, opts.json, (data) => {
3726
- log.success(`Community created: ${pc10.bold(data.name)} (${data.id})`);
3856
+ log.success(`Community created: ${pc11.bold(data.name)} (${data.id})`);
3727
3857
  });
3728
3858
  }
3729
3859
  async function postsListCommand(opts) {
@@ -3740,11 +3870,11 @@ async function postsListCommand(opts) {
3740
3870
  });
3741
3871
  output(res, opts.json, (data, meta) => {
3742
3872
  log.blank();
3743
- console.log(pc10.bold("Posts"));
3873
+ console.log(pc11.bold("Posts"));
3744
3874
  data.forEach((post) => {
3745
3875
  const author = post.author?.username ? `@${post.author.username}` : "unknown";
3746
3876
  const content = truncate(post.content ?? "", 100);
3747
- console.log(` ${pc10.bold(author)} ${pc10.dim(post.id)}`);
3877
+ console.log(` ${pc11.bold(author)} ${pc11.dim(post.id)}`);
3748
3878
  console.log(` ${content}`);
3749
3879
  });
3750
3880
  printMeta(meta);
@@ -3770,7 +3900,7 @@ async function postsCreateCommand(opts) {
3770
3900
  }
3771
3901
  });
3772
3902
  output(res, opts.json, (data) => {
3773
- log.success(`Post created: ${pc10.dim(data.id)}`);
3903
+ log.success(`Post created: ${pc11.dim(data.id)}`);
3774
3904
  });
3775
3905
  }
3776
3906
  async function projectsListCommand(opts) {
@@ -3786,11 +3916,11 @@ async function projectsListCommand(opts) {
3786
3916
  });
3787
3917
  output(res, opts.json, (data, meta) => {
3788
3918
  log.blank();
3789
- console.log(pc10.bold("Projects"));
3919
+ console.log(pc11.bold("Projects"));
3790
3920
  data.forEach((proj) => {
3791
- const name = pc10.bold(proj.name);
3792
- const slug = proj.slug ? pc10.dim(`/${proj.slug}`) : "";
3793
- const org = proj.organization?.slug ? pc10.dim(`org ${proj.organization.slug}`) : "";
3921
+ const name = pc11.bold(proj.name);
3922
+ const slug = proj.slug ? pc11.dim(`/${proj.slug}`) : "";
3923
+ const org = proj.organization?.slug ? pc11.dim(`org ${proj.organization.slug}`) : "";
3794
3924
  console.log(` ${name} ${slug} ${org}`);
3795
3925
  });
3796
3926
  printMeta(meta);
@@ -3815,7 +3945,7 @@ async function projectsCreateCommand(opts) {
3815
3945
  }
3816
3946
  });
3817
3947
  output(res, opts.json, (data) => {
3818
- log.success(`Project created: ${pc10.bold(data.name)} (${data.id})`);
3948
+ log.success(`Project created: ${pc11.bold(data.name)} (${data.id})`);
3819
3949
  });
3820
3950
  }
3821
3951
  async function agentsListCommand(opts) {
@@ -3830,11 +3960,11 @@ async function agentsListCommand(opts) {
3830
3960
  });
3831
3961
  output(res, opts.json, (data, meta) => {
3832
3962
  log.blank();
3833
- console.log(pc10.bold("Agents"));
3963
+ console.log(pc11.bold("Agents"));
3834
3964
  data.forEach((agent) => {
3835
- const name = pc10.bold(agent.name);
3836
- const handle = agent.username ? pc10.dim(`@${agent.username}`) : "";
3837
- const model = agent.model ? pc10.dim(agent.model) : "";
3965
+ const name = pc11.bold(agent.name);
3966
+ const handle = agent.username ? pc11.dim(`@${agent.username}`) : "";
3967
+ const model = agent.model ? pc11.dim(agent.model) : "";
3838
3968
  console.log(` ${name} ${handle} ${model}`);
3839
3969
  });
3840
3970
  printMeta(meta);
@@ -3863,7 +3993,7 @@ async function agentsCreateCommand(opts) {
3863
3993
  }
3864
3994
  });
3865
3995
  output(res, opts.json, (data) => {
3866
- log.success(`Agent created: ${pc10.bold(data.name)} (${data.id})`);
3996
+ log.success(`Agent created: ${pc11.bold(data.name)} (${data.id})`);
3867
3997
  });
3868
3998
  }
3869
3999
  function output(res, json, render2) {
@@ -3876,7 +4006,7 @@ function output(res, json, render2) {
3876
4006
  function printMeta(meta) {
3877
4007
  if (!meta) return;
3878
4008
  log.blank();
3879
- console.log(pc10.dim(`limit ${meta.limit ?? 0} offset ${meta.offset ?? 0} has_more ${meta.has_more ?? false}`));
4009
+ console.log(pc11.dim(`limit ${meta.limit ?? 0} offset ${meta.offset ?? 0} has_more ${meta.has_more ?? false}`));
3880
4010
  log.blank();
3881
4011
  }
3882
4012
  function truncate(value, max) {
@@ -3891,7 +4021,7 @@ program.command("chat").description("Start the chat-first AI agent (default when
3891
4021
  try {
3892
4022
  await launchChatAgent({ model: opts.model, resume: opts.resume });
3893
4023
  } catch (err) {
3894
- console.error(err instanceof Error ? err.message : err);
4024
+ printCliError(err);
3895
4025
  process.exit(1);
3896
4026
  }
3897
4027
  });
@@ -3899,7 +4029,7 @@ program.command("create [name]").description("Create a new Recursiv application"
3899
4029
  try {
3900
4030
  await initCommand(name);
3901
4031
  } catch (err) {
3902
- console.error(err instanceof Error ? err.message : err);
4032
+ printCliError(err);
3903
4033
  process.exit(1);
3904
4034
  }
3905
4035
  });
@@ -3907,7 +4037,7 @@ program.command("dev").description("Start the development server").option("-p, -
3907
4037
  try {
3908
4038
  await devCommand(opts);
3909
4039
  } catch (err) {
3910
- console.error(err instanceof Error ? err.message : err);
4040
+ printCliError(err);
3911
4041
  process.exit(1);
3912
4042
  }
3913
4043
  });
@@ -3915,7 +4045,7 @@ program.command("deploy <target>").description("Generate deployment config (verc
3915
4045
  try {
3916
4046
  await deployCommand(target);
3917
4047
  } catch (err) {
3918
- console.error(err instanceof Error ? err.message : err);
4048
+ printCliError(err);
3919
4049
  process.exit(1);
3920
4050
  }
3921
4051
  });
@@ -3924,7 +4054,7 @@ auth.command("login").description("Set or update your API key").action(async ()
3924
4054
  try {
3925
4055
  await loginCommand();
3926
4056
  } catch (err) {
3927
- console.error(err instanceof Error ? err.message : err);
4057
+ printCliError(err);
3928
4058
  process.exit(1);
3929
4059
  }
3930
4060
  });
@@ -3932,7 +4062,7 @@ auth.command("logout").description("Remove API key from .env").action(async () =
3932
4062
  try {
3933
4063
  await logoutCommand();
3934
4064
  } catch (err) {
3935
- console.error(err instanceof Error ? err.message : err);
4065
+ printCliError(err);
3936
4066
  process.exit(1);
3937
4067
  }
3938
4068
  });
@@ -3940,7 +4070,7 @@ auth.command("whoami").description("Show current authenticated user").action(asy
3940
4070
  try {
3941
4071
  await whoamiCommand();
3942
4072
  } catch (err) {
3943
- console.error(err instanceof Error ? err.message : err);
4073
+ printCliError(err);
3944
4074
  process.exit(1);
3945
4075
  }
3946
4076
  });
@@ -3948,7 +4078,7 @@ program.command("info").description("Display project information").action(async
3948
4078
  try {
3949
4079
  await infoCommand();
3950
4080
  } catch (err) {
3951
- console.error(err instanceof Error ? err.message : err);
4081
+ printCliError(err);
3952
4082
  process.exit(1);
3953
4083
  }
3954
4084
  });
@@ -3957,7 +4087,7 @@ browserUse.command("run").description("Run a Browser Use task with the official
3957
4087
  try {
3958
4088
  await browserUseRunCommand(opts);
3959
4089
  } catch (err) {
3960
- console.error(err instanceof Error ? err.message : err);
4090
+ printCliError(err);
3961
4091
  process.exit(1);
3962
4092
  }
3963
4093
  });
@@ -3965,7 +4095,7 @@ browserUse.command("mcp-snippet").description("Print Browser Use MCP configurati
3965
4095
  try {
3966
4096
  await browserUseMcpSnippetCommand(opts);
3967
4097
  } catch (err) {
3968
- console.error(err instanceof Error ? err.message : err);
4098
+ printCliError(err);
3969
4099
  process.exit(1);
3970
4100
  }
3971
4101
  });
@@ -3974,7 +4104,7 @@ users.command("me").description("Show current authenticated user").option("--jso
3974
4104
  try {
3975
4105
  await usersMeCommand(opts);
3976
4106
  } catch (err) {
3977
- console.error(err instanceof Error ? err.message : err);
4107
+ printCliError(err);
3978
4108
  process.exit(1);
3979
4109
  }
3980
4110
  });
@@ -3983,7 +4113,7 @@ communities.command("list").description("List communities").option("--limit <lim
3983
4113
  try {
3984
4114
  await communitiesListCommand(opts);
3985
4115
  } catch (err) {
3986
- console.error(err instanceof Error ? err.message : err);
4116
+ printCliError(err);
3987
4117
  process.exit(1);
3988
4118
  }
3989
4119
  });
@@ -3991,7 +4121,7 @@ communities.command("create").description("Create a community").requiredOption("
3991
4121
  try {
3992
4122
  await communitiesCreateCommand(opts);
3993
4123
  } catch (err) {
3994
- console.error(err instanceof Error ? err.message : err);
4124
+ printCliError(err);
3995
4125
  process.exit(1);
3996
4126
  }
3997
4127
  });
@@ -4000,7 +4130,7 @@ posts.command("list").description("List posts").option("--community-id <id>", "f
4000
4130
  try {
4001
4131
  await postsListCommand(opts);
4002
4132
  } catch (err) {
4003
- console.error(err instanceof Error ? err.message : err);
4133
+ printCliError(err);
4004
4134
  process.exit(1);
4005
4135
  }
4006
4136
  });
@@ -4008,7 +4138,7 @@ posts.command("create").description("Create a post").requiredOption("--content <
4008
4138
  try {
4009
4139
  await postsCreateCommand(opts);
4010
4140
  } catch (err) {
4011
- console.error(err instanceof Error ? err.message : err);
4141
+ printCliError(err);
4012
4142
  process.exit(1);
4013
4143
  }
4014
4144
  });
@@ -4022,7 +4152,7 @@ projects.command("list").description("List projects").option("--org <id>", "orga
4022
4152
  json: opts.json
4023
4153
  });
4024
4154
  } catch (err) {
4025
- console.error(err instanceof Error ? err.message : err);
4155
+ printCliError(err);
4026
4156
  process.exit(1);
4027
4157
  }
4028
4158
  });
@@ -4038,7 +4168,7 @@ projects.command("create").description("Create a project").requiredOption("--org
4038
4168
  json: opts.json
4039
4169
  });
4040
4170
  } catch (err) {
4041
- console.error(err instanceof Error ? err.message : err);
4171
+ printCliError(err);
4042
4172
  process.exit(1);
4043
4173
  }
4044
4174
  });
@@ -4047,7 +4177,7 @@ agents.command("list").description("List agents").option("--limit <limit>", "num
4047
4177
  try {
4048
4178
  await agentsListCommand(opts);
4049
4179
  } catch (err) {
4050
- console.error(err instanceof Error ? err.message : err);
4180
+ printCliError(err);
4051
4181
  process.exit(1);
4052
4182
  }
4053
4183
  });
@@ -4067,7 +4197,7 @@ agents.command("create").description("Create an AI agent").requiredOption("--nam
4067
4197
  json: opts.json
4068
4198
  });
4069
4199
  } catch (err) {
4070
- console.error(err instanceof Error ? err.message : err);
4200
+ printCliError(err);
4071
4201
  process.exit(1);
4072
4202
  }
4073
4203
  });
@@ -4075,7 +4205,7 @@ program.command("brain").description("Launch the visual Recursiv brain TUI").opt
4075
4205
  try {
4076
4206
  await brainCommand(opts);
4077
4207
  } catch (err) {
4078
- console.error(err instanceof Error ? err.message : err);
4208
+ printCliError(err);
4079
4209
  process.exit(1);
4080
4210
  }
4081
4211
  });
@@ -4083,7 +4213,16 @@ program.command("studio").description("Legacy alias for brain").option("--no-ani
4083
4213
  try {
4084
4214
  await studioCommand(opts);
4085
4215
  } catch (err) {
4086
- console.error(err instanceof Error ? err.message : err);
4216
+ printCliError(err);
4217
+ process.exit(1);
4218
+ }
4219
+ });
4220
+ program.command("quickstart").description("Set up Claude Code + GitHub CLI + Recursiv account in one shot (~3 min)").action(async () => {
4221
+ try {
4222
+ const { quickstartCommand: quickstartCommand2 } = await Promise.resolve().then(() => (init_quickstart(), quickstart_exports));
4223
+ await quickstartCommand2();
4224
+ } catch (err) {
4225
+ printCliError(err);
4087
4226
  process.exit(1);
4088
4227
  }
4089
4228
  });
@@ -4093,7 +4232,7 @@ mcp.command("install <target>").description("Configure Recursiv MCP server for a
4093
4232
  const { mcpInstallCommand: mcpInstallCommand2 } = await Promise.resolve().then(() => (init_mcp_install(), mcp_install_exports));
4094
4233
  await mcpInstallCommand2({ target, apiKey: opts.apiKey, global: opts.global });
4095
4234
  } catch (err) {
4096
- console.error(err instanceof Error ? err.message : err);
4235
+ printCliError(err);
4097
4236
  process.exit(1);
4098
4237
  }
4099
4238
  });
@@ -4102,7 +4241,7 @@ mcp.command("verify").description("Verify that the Recursiv MCP server starts an
4102
4241
  const { mcpVerifyCommand: mcpVerifyCommand2 } = await Promise.resolve().then(() => (init_mcp_install(), mcp_install_exports));
4103
4242
  await mcpVerifyCommand2();
4104
4243
  } catch (err) {
4105
- console.error(err instanceof Error ? err.message : err);
4244
+ printCliError(err);
4106
4245
  process.exit(1);
4107
4246
  }
4108
4247
  });
@@ -4111,7 +4250,7 @@ async function launchChatAgent(opts) {
4111
4250
  const { readConfig: readConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
4112
4251
  const { resolveRecursivKey: resolveRecursivKey2, resolveAnthropicKey: resolveAnthropicKey2, saveCredentials: saveCredentials2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
4113
4252
  const { getOrCreateApiKey: getOrCreateApiKey2 } = await Promise.resolve().then(() => (init_auth_flow(), auth_flow_exports));
4114
- const pc14 = (await import("picocolors")).default;
4253
+ const pc16 = (await import("picocolors")).default;
4115
4254
  const prompts3 = (await import("prompts")).default;
4116
4255
  const cwd = process.cwd();
4117
4256
  const config = await readConfig2(cwd);
@@ -4119,16 +4258,16 @@ async function launchChatAgent(opts) {
4119
4258
  let recursivApiKey = await resolveRecursivKey2(cwd);
4120
4259
  if (!recursivApiKey) {
4121
4260
  console.log();
4122
- console.log(pc14.bold(" Welcome to Recursiv"));
4123
- console.log(pc14.dim(" Let's get you authenticated."));
4261
+ console.log(pc16.bold(" Welcome to Recursiv"));
4262
+ console.log(pc16.dim(" Let's get you authenticated."));
4124
4263
  console.log();
4125
4264
  recursivApiKey = await getOrCreateApiKey2(baseUrl);
4126
4265
  if (!recursivApiKey) {
4127
- console.error(pc14.red(" error") + " Authentication required to continue.");
4266
+ console.error(pc16.red(" error") + " Authentication required to continue.");
4128
4267
  process.exit(1);
4129
4268
  }
4130
4269
  await saveCredentials2({ recursivApiKey });
4131
- console.log(pc14.dim(" Credentials saved to ~/.recursiv/credentials"));
4270
+ console.log(pc16.dim(" Credentials saved to ~/.recursiv/credentials"));
4132
4271
  console.log();
4133
4272
  }
4134
4273
  const anthropicApiKey = await resolveAnthropicKey2() ?? void 0;
@@ -4161,7 +4300,7 @@ async function main() {
4161
4300
  try {
4162
4301
  await launchChatAgent();
4163
4302
  } catch (err) {
4164
- console.error(err instanceof Error ? err.message : err);
4303
+ printCliError(err);
4165
4304
  process.exit(1);
4166
4305
  }
4167
4306
  return;