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