@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.
package/dist/bin/recursiv.js
CHANGED
|
@@ -10,10 +10,10 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/lib/logger.ts
|
|
13
|
-
import
|
|
13
|
+
import pc2 from "picocolors";
|
|
14
14
|
function banner() {
|
|
15
15
|
console.log();
|
|
16
|
-
console.log(
|
|
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(
|
|
25
|
+
console.log(pc2.cyan("info") + " " + msg);
|
|
26
26
|
},
|
|
27
27
|
success(msg) {
|
|
28
|
-
console.log(
|
|
28
|
+
console.log(pc2.green("ok") + " " + msg);
|
|
29
29
|
},
|
|
30
30
|
warn(msg) {
|
|
31
|
-
console.log(
|
|
31
|
+
console.log(pc2.yellow("warn") + " " + msg);
|
|
32
32
|
},
|
|
33
33
|
error(msg) {
|
|
34
|
-
console.error(
|
|
34
|
+
console.error(pc2.red("error") + " " + msg);
|
|
35
35
|
},
|
|
36
36
|
step(n, total, msg) {
|
|
37
|
-
console.log(
|
|
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
|
|
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(
|
|
182
|
-
console.log(
|
|
183
|
-
console.log(
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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
|
-
|
|
301
|
-
`Get your API key from ${
|
|
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
|
|
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
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
543
|
-
console.log(
|
|
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(
|
|
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(
|
|
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
|
|
588
|
+
const apiKey = process.env.RECURSIV_API_KEY;
|
|
593
589
|
if (!apiKey) {
|
|
594
|
-
console.error(
|
|
590
|
+
console.error(pc12.red(" error") + " RECURSIV_API_KEY not set in environment.");
|
|
595
591
|
process.exit(1);
|
|
596
592
|
}
|
|
597
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
652
|
-
if (stderr) console.error(
|
|
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(
|
|
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
|
|
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,
|
|
734
|
-
text = text.replace(/`([^`]+)`/g,
|
|
735
|
-
text = text.replace(/\*\*([^*]+)\*\*/g,
|
|
736
|
-
text = text.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g,
|
|
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
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
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 ?
|
|
758
|
-
console.log(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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 +
|
|
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(
|
|
908
|
+
process.stdout.write(pc14.bold(pc14.cyan("recursiv ")) + "\n");
|
|
794
909
|
}
|
|
795
910
|
function printToolCall(name) {
|
|
796
|
-
console.log(
|
|
911
|
+
console.log(pc14.yellow(" \u25B8 ") + pc14.dim(name));
|
|
797
912
|
}
|
|
798
913
|
function printToolResult(name, success) {
|
|
799
914
|
if (success) {
|
|
800
|
-
console.log(
|
|
915
|
+
console.log(pc14.green(" \u2713 ") + pc14.dim(name));
|
|
801
916
|
} else {
|
|
802
|
-
console.log(
|
|
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${
|
|
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
|
|
821
|
-
const rl =
|
|
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
|
-
|
|
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(
|
|
950
|
+
console.log(pc14.red(" \u2717 ") + message);
|
|
836
951
|
}
|
|
837
952
|
function printInfo(message) {
|
|
838
|
-
console.log(
|
|
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 +
|
|
979
|
+
process.stdout.write(INDENT + pc14.dim(line));
|
|
865
980
|
return;
|
|
866
981
|
}
|
|
867
982
|
if (this.inCodeBlock) {
|
|
868
|
-
process.stdout.write(INDENT +
|
|
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 +
|
|
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 +
|
|
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 +
|
|
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 +
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
2211
|
+
console.log(pc15.cyan(" \u25C6 Plan mode ON") + pc15.dim(" \u2014 agent will outline steps before executing"));
|
|
2091
2212
|
} else {
|
|
2092
|
-
console.log(
|
|
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(
|
|
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(
|
|
2104
|
-
console.log(
|
|
2105
|
-
console.log(
|
|
2106
|
-
console.log(
|
|
2107
|
-
console.log(
|
|
2108
|
-
console.log(
|
|
2109
|
-
console.log(
|
|
2110
|
-
console.log(
|
|
2111
|
-
console.log(
|
|
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(
|
|
2114
|
-
console.log(
|
|
2115
|
-
console.log(
|
|
2116
|
-
console.log(
|
|
2117
|
-
console.log(
|
|
2118
|
-
console.log(
|
|
2119
|
-
console.log(
|
|
2120
|
-
console.log(
|
|
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(
|
|
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(
|
|
2131
|
-
console.log(
|
|
2132
|
-
if (data.email) console.log(
|
|
2133
|
-
console.log(
|
|
2134
|
-
console.log(
|
|
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(
|
|
2270
|
+
console.log(pc15.bold(" User Context"));
|
|
2150
2271
|
if (profile.status === "fulfilled") {
|
|
2151
2272
|
const p = profile.value.data;
|
|
2152
|
-
console.log(
|
|
2153
|
-
console.log(
|
|
2154
|
-
console.log(
|
|
2155
|
-
console.log(
|
|
2156
|
-
console.log(
|
|
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(
|
|
2282
|
+
console.log(pc15.bold(" Organizations"));
|
|
2162
2283
|
if (orgList.length === 0) {
|
|
2163
|
-
console.log(
|
|
2284
|
+
console.log(pc15.dim(" None"));
|
|
2164
2285
|
} else {
|
|
2165
2286
|
for (const org of orgList) {
|
|
2166
|
-
const role = org.role ?
|
|
2167
|
-
console.log(` - ${
|
|
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(
|
|
2175
|
-
console.log(
|
|
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(
|
|
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(
|
|
2311
|
+
console.log(pc15.dim(" No saved sessions."));
|
|
2191
2312
|
} else {
|
|
2192
|
-
console.log(
|
|
2313
|
+
console.log(pc15.bold(" Recent Sessions"));
|
|
2193
2314
|
for (const s of sessions) {
|
|
2194
|
-
const current = s.id === session.id ?
|
|
2315
|
+
const current = s.id === session.id ? pc15.green(" (current)") : "";
|
|
2195
2316
|
const date = new Date(s.createdAt).toLocaleDateString();
|
|
2196
2317
|
console.log(
|
|
2197
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
|
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 ${
|
|
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} ${
|
|
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 ${
|
|
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(
|
|
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(` ${
|
|
2675
|
+
console.log(` ${pc4.dim("$")} cd ${projectName}`);
|
|
2542
2676
|
if (!apiKey) {
|
|
2543
|
-
console.log(` ${
|
|
2677
|
+
console.log(` ${pc4.dim("$")} ${pc4.dim("# Add your API key to .env")}`);
|
|
2544
2678
|
}
|
|
2545
|
-
console.log(` ${
|
|
2679
|
+
console.log(` ${pc4.dim("$")} ${runCommand(pm, "dev")}`);
|
|
2546
2680
|
log.blank();
|
|
2547
|
-
console.log(
|
|
2548
|
-
console.log(
|
|
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
|
|
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 ${
|
|
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 ${
|
|
2586
|
-
log.info(`Running: ${
|
|
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
|
|
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 ${
|
|
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: ${
|
|
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 ${
|
|
2840
|
+
spinner.succeed(`Created ${pc6.bold(file)}`);
|
|
2712
2841
|
log.blank();
|
|
2713
|
-
log.info(`Remember to set ${
|
|
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
|
|
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: ${
|
|
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 ${
|
|
2889
|
+
log.info(`Run ${pc7.bold("recursiv auth login")} to set one`);
|
|
2761
2890
|
return;
|
|
2762
2891
|
}
|
|
2763
|
-
log.info(`Key: ${
|
|
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: ${
|
|
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
|
|
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 ${
|
|
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(
|
|
2933
|
+
console.log(pc8.bold("Project Info"));
|
|
2805
2934
|
console.log();
|
|
2806
|
-
console.log(` 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: ${
|
|
2939
|
+
console.log(` Dev cmd: ${pc8.dim(config.dev.command)}`);
|
|
2811
2940
|
console.log(` Pkg mgr: ${pm}`);
|
|
2812
|
-
console.log(` API URL: ${
|
|
2813
|
-
console.log(` API key: ${apiKey ?
|
|
2814
|
-
console.log(` Config: ${
|
|
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
|
-
-
|
|
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
|
|
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(
|
|
3567
|
-
console.log(`${
|
|
3568
|
-
console.log(`${
|
|
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(`${
|
|
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
|
|
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
|
|
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 ${
|
|
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(
|
|
3676
|
-
console.log(` ${
|
|
3677
|
-
console.log(` ${
|
|
3678
|
-
console.log(` ${
|
|
3679
|
-
console.log(` ${
|
|
3680
|
-
console.log(` ${
|
|
3681
|
-
console.log(` ${
|
|
3682
|
-
console.log(` ${
|
|
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(
|
|
3827
|
+
console.log(pc11.bold("Communities"));
|
|
3699
3828
|
data.forEach((comm) => {
|
|
3700
|
-
const name =
|
|
3701
|
-
const slug = comm.slug ?
|
|
3702
|
-
const members =
|
|
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(` ${
|
|
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: ${
|
|
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(
|
|
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(` ${
|
|
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: ${
|
|
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(
|
|
3918
|
+
console.log(pc11.bold("Projects"));
|
|
3790
3919
|
data.forEach((proj) => {
|
|
3791
|
-
const name =
|
|
3792
|
-
const slug = proj.slug ?
|
|
3793
|
-
const 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: ${
|
|
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(
|
|
3962
|
+
console.log(pc11.bold("Agents"));
|
|
3834
3963
|
data.forEach((agent) => {
|
|
3835
|
-
const name =
|
|
3836
|
-
const handle = agent.username ?
|
|
3837
|
-
const model = 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: ${
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
4123
|
-
console.log(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
4302
|
+
printCliError(err);
|
|
4165
4303
|
process.exit(1);
|
|
4166
4304
|
}
|
|
4167
4305
|
return;
|