@recursiv/cli 0.1.6 → 0.1.7

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