@react-grab/cli 0.1.11 → 0.1.13
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/cli.cjs +527 -87
- package/dist/cli.js +525 -89
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -8,12 +8,18 @@ var child_process = require('child_process');
|
|
|
8
8
|
var fs = require('fs');
|
|
9
9
|
var path = require('path');
|
|
10
10
|
var ni = require('@antfu/ni');
|
|
11
|
+
var os = require('os');
|
|
12
|
+
var process2 = require('process');
|
|
11
13
|
var ora = require('ora');
|
|
12
14
|
|
|
13
15
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
16
|
|
|
15
17
|
var pc__default = /*#__PURE__*/_interopDefault(pc);
|
|
16
18
|
var basePrompts__default = /*#__PURE__*/_interopDefault(basePrompts);
|
|
19
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
20
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
21
|
+
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
22
|
+
var process2__default = /*#__PURE__*/_interopDefault(process2);
|
|
17
23
|
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
18
24
|
|
|
19
25
|
var highlighter = {
|
|
@@ -302,7 +308,8 @@ var AGENT_PACKAGES = [
|
|
|
302
308
|
"@react-grab/codex",
|
|
303
309
|
"@react-grab/gemini",
|
|
304
310
|
"@react-grab/amp",
|
|
305
|
-
"@react-grab/ami"
|
|
311
|
+
"@react-grab/ami",
|
|
312
|
+
"@react-grab/mcp"
|
|
306
313
|
];
|
|
307
314
|
var detectUnsupportedFramework = (projectRoot) => {
|
|
308
315
|
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
@@ -533,6 +540,301 @@ var getPackagesToUninstall = (agent) => {
|
|
|
533
540
|
};
|
|
534
541
|
var spinner = (text, options) => ora__default.default({ text, isSilent: options?.silent });
|
|
535
542
|
|
|
543
|
+
// src/utils/install-mcp.ts
|
|
544
|
+
var SERVER_NAME = "react-grab-mcp";
|
|
545
|
+
var PACKAGE_NAME = "@react-grab/mcp";
|
|
546
|
+
var getBaseDir = () => {
|
|
547
|
+
const homeDir = os__default.default.homedir();
|
|
548
|
+
if (process2__default.default.platform === "win32") {
|
|
549
|
+
return process2__default.default.env.APPDATA || path__default.default.join(homeDir, "AppData", "Roaming");
|
|
550
|
+
}
|
|
551
|
+
if (process2__default.default.platform === "darwin") {
|
|
552
|
+
return path__default.default.join(homeDir, "Library", "Application Support");
|
|
553
|
+
}
|
|
554
|
+
return process2__default.default.env.XDG_CONFIG_HOME || path__default.default.join(homeDir, ".config");
|
|
555
|
+
};
|
|
556
|
+
var getZedConfigPath = () => {
|
|
557
|
+
const homeDir = os__default.default.homedir();
|
|
558
|
+
if (process2__default.default.platform === "win32") {
|
|
559
|
+
const appData = process2__default.default.env.APPDATA || path__default.default.join(homeDir, "AppData", "Roaming");
|
|
560
|
+
return path__default.default.join(appData, "Zed", "settings.json");
|
|
561
|
+
}
|
|
562
|
+
return path__default.default.join(homeDir, ".config", "zed", "settings.json");
|
|
563
|
+
};
|
|
564
|
+
var getClients = () => {
|
|
565
|
+
const homeDir = os__default.default.homedir();
|
|
566
|
+
const baseDir = getBaseDir();
|
|
567
|
+
const stdioConfig = {
|
|
568
|
+
command: "npx",
|
|
569
|
+
args: ["-y", PACKAGE_NAME, "--stdio"]
|
|
570
|
+
};
|
|
571
|
+
return [
|
|
572
|
+
{
|
|
573
|
+
name: "Cursor",
|
|
574
|
+
configPath: path__default.default.join(homeDir, ".cursor", "mcp.json"),
|
|
575
|
+
configKey: "mcpServers",
|
|
576
|
+
format: "json",
|
|
577
|
+
serverConfig: stdioConfig
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
name: "VS Code",
|
|
581
|
+
configPath: path__default.default.join(baseDir, "Code", "User", "mcp.json"),
|
|
582
|
+
configKey: "servers",
|
|
583
|
+
format: "json",
|
|
584
|
+
serverConfig: { type: "stdio", ...stdioConfig }
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
name: "Claude Code",
|
|
588
|
+
configPath: path__default.default.join(homeDir, ".claude.json"),
|
|
589
|
+
configKey: "mcpServers",
|
|
590
|
+
format: "json",
|
|
591
|
+
serverConfig: stdioConfig
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
name: "Amp",
|
|
595
|
+
configPath: path__default.default.join(homeDir, ".config", "amp", "settings.json"),
|
|
596
|
+
configKey: "amp.mcpServers",
|
|
597
|
+
format: "json",
|
|
598
|
+
serverConfig: stdioConfig
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
name: "Droid",
|
|
602
|
+
configPath: path__default.default.join(homeDir, ".factory", "mcp.json"),
|
|
603
|
+
configKey: "mcpServers",
|
|
604
|
+
format: "json",
|
|
605
|
+
serverConfig: { type: "stdio", ...stdioConfig }
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
name: "Codex",
|
|
609
|
+
configPath: path__default.default.join(
|
|
610
|
+
process2__default.default.env.CODEX_HOME || path__default.default.join(homeDir, ".codex"),
|
|
611
|
+
"config.toml"
|
|
612
|
+
),
|
|
613
|
+
configKey: "mcp_servers",
|
|
614
|
+
format: "toml",
|
|
615
|
+
serverConfig: stdioConfig
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
name: "Zed",
|
|
619
|
+
configPath: getZedConfigPath(),
|
|
620
|
+
configKey: "context_servers",
|
|
621
|
+
format: "json",
|
|
622
|
+
serverConfig: { source: "custom", ...stdioConfig, env: {} }
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
name: "Windsurf",
|
|
626
|
+
configPath: path__default.default.join(homeDir, ".codeium", "windsurf", "mcp_config.json"),
|
|
627
|
+
configKey: "mcpServers",
|
|
628
|
+
format: "json",
|
|
629
|
+
serverConfig: stdioConfig
|
|
630
|
+
}
|
|
631
|
+
];
|
|
632
|
+
};
|
|
633
|
+
var ensureDirectory = (filePath) => {
|
|
634
|
+
const directory = path__default.default.dirname(filePath);
|
|
635
|
+
if (!fs__default.default.existsSync(directory)) {
|
|
636
|
+
fs__default.default.mkdirSync(directory, { recursive: true });
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
var indentJson = (json, baseIndent) => json.split("\n").map((line, index) => index === 0 ? line : baseIndent + line).join("\n");
|
|
640
|
+
var insertIntoJsonc = (filePath, content, configKey, serverName, serverConfig) => {
|
|
641
|
+
if (content.includes(`"${serverName}"`)) return;
|
|
642
|
+
const serverJson = indentJson(
|
|
643
|
+
JSON.stringify(serverConfig, null, 2),
|
|
644
|
+
" "
|
|
645
|
+
);
|
|
646
|
+
const escapedConfigKey = configKey.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
647
|
+
const keyPattern = new RegExp(`"${escapedConfigKey}"\\s*:\\s*\\{`);
|
|
648
|
+
const keyMatch = keyPattern.exec(content);
|
|
649
|
+
if (keyMatch) {
|
|
650
|
+
const insertPosition = keyMatch.index + keyMatch[0].length;
|
|
651
|
+
const entry = `
|
|
652
|
+
"${serverName}": ${serverJson},`;
|
|
653
|
+
fs__default.default.writeFileSync(
|
|
654
|
+
filePath,
|
|
655
|
+
content.slice(0, insertPosition) + entry + content.slice(insertPosition)
|
|
656
|
+
);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
const lastBrace = content.lastIndexOf("}");
|
|
660
|
+
if (lastBrace === -1) return;
|
|
661
|
+
const beforeBrace = content.slice(0, lastBrace).trimEnd();
|
|
662
|
+
const withoutComments = beforeBrace.replace(/\/\/.*$/, "").trimEnd();
|
|
663
|
+
const lastChar = withoutComments[withoutComments.length - 1];
|
|
664
|
+
const needsComma = lastChar !== void 0 && lastChar !== "{" && lastChar !== ",";
|
|
665
|
+
const section = `${needsComma ? "," : ""}
|
|
666
|
+
"${configKey}": {
|
|
667
|
+
"${serverName}": ${serverJson}
|
|
668
|
+
}`;
|
|
669
|
+
fs__default.default.writeFileSync(filePath, beforeBrace + section + "\n}\n");
|
|
670
|
+
};
|
|
671
|
+
var installJsonClient = (client) => {
|
|
672
|
+
ensureDirectory(client.configPath);
|
|
673
|
+
if (!fs__default.default.existsSync(client.configPath)) {
|
|
674
|
+
const config = {
|
|
675
|
+
[client.configKey]: { [SERVER_NAME]: client.serverConfig }
|
|
676
|
+
};
|
|
677
|
+
fs__default.default.writeFileSync(client.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
const content = fs__default.default.readFileSync(client.configPath, "utf8");
|
|
681
|
+
try {
|
|
682
|
+
const config = JSON.parse(content);
|
|
683
|
+
const servers = config[client.configKey] ?? {};
|
|
684
|
+
servers[SERVER_NAME] = client.serverConfig;
|
|
685
|
+
config[client.configKey] = servers;
|
|
686
|
+
fs__default.default.writeFileSync(client.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
687
|
+
} catch {
|
|
688
|
+
insertIntoJsonc(
|
|
689
|
+
client.configPath,
|
|
690
|
+
content,
|
|
691
|
+
client.configKey,
|
|
692
|
+
SERVER_NAME,
|
|
693
|
+
client.serverConfig
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
var buildTomlSection = (configKey, serverConfig) => {
|
|
698
|
+
const lines = [`[${configKey}.${SERVER_NAME}]`];
|
|
699
|
+
for (const [key, value] of Object.entries(serverConfig)) {
|
|
700
|
+
if (typeof value === "string") {
|
|
701
|
+
lines.push(`${key} = "${value}"`);
|
|
702
|
+
} else if (Array.isArray(value)) {
|
|
703
|
+
const items = value.map((item) => `"${item}"`).join(", ");
|
|
704
|
+
lines.push(`${key} = [${items}]`);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
return lines.join("\n");
|
|
708
|
+
};
|
|
709
|
+
var installTomlClient = (client) => {
|
|
710
|
+
ensureDirectory(client.configPath);
|
|
711
|
+
const sectionHeader = `[${client.configKey}.${SERVER_NAME}]`;
|
|
712
|
+
const newSection = buildTomlSection(client.configKey, client.serverConfig);
|
|
713
|
+
if (!fs__default.default.existsSync(client.configPath)) {
|
|
714
|
+
fs__default.default.writeFileSync(client.configPath, newSection + "\n");
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
const content = fs__default.default.readFileSync(client.configPath, "utf8");
|
|
718
|
+
if (!content.includes(sectionHeader)) {
|
|
719
|
+
fs__default.default.writeFileSync(
|
|
720
|
+
client.configPath,
|
|
721
|
+
content.trimEnd() + "\n\n" + newSection + "\n"
|
|
722
|
+
);
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
const lines = content.split("\n");
|
|
726
|
+
const resultLines = [];
|
|
727
|
+
let isInsideOurSection = false;
|
|
728
|
+
let didInsertReplacement = false;
|
|
729
|
+
for (const line of lines) {
|
|
730
|
+
if (line.trim() === sectionHeader) {
|
|
731
|
+
isInsideOurSection = true;
|
|
732
|
+
if (!didInsertReplacement) {
|
|
733
|
+
resultLines.push(newSection);
|
|
734
|
+
didInsertReplacement = true;
|
|
735
|
+
}
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
if (isInsideOurSection && line.startsWith("[")) {
|
|
739
|
+
isInsideOurSection = false;
|
|
740
|
+
}
|
|
741
|
+
if (!isInsideOurSection) {
|
|
742
|
+
resultLines.push(line);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
fs__default.default.writeFileSync(client.configPath, resultLines.join("\n"));
|
|
746
|
+
};
|
|
747
|
+
var getMcpClientNames = () => getClients().map((client) => client.name);
|
|
748
|
+
var installMcpServers = (selectedClients) => {
|
|
749
|
+
const allClients = getClients();
|
|
750
|
+
const clients = selectedClients ? allClients.filter((client) => selectedClients.includes(client.name)) : allClients;
|
|
751
|
+
const results = [];
|
|
752
|
+
const installSpinner = spinner("Installing MCP server.").start();
|
|
753
|
+
for (const client of clients) {
|
|
754
|
+
try {
|
|
755
|
+
if (client.format === "toml") {
|
|
756
|
+
installTomlClient(client);
|
|
757
|
+
} else {
|
|
758
|
+
installJsonClient(client);
|
|
759
|
+
}
|
|
760
|
+
results.push({
|
|
761
|
+
client: client.name,
|
|
762
|
+
configPath: client.configPath,
|
|
763
|
+
success: true
|
|
764
|
+
});
|
|
765
|
+
} catch (error) {
|
|
766
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
767
|
+
results.push({
|
|
768
|
+
client: client.name,
|
|
769
|
+
configPath: client.configPath,
|
|
770
|
+
success: false,
|
|
771
|
+
error: message
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
const successCount = results.filter((result) => result.success).length;
|
|
776
|
+
const failedCount = results.length - successCount;
|
|
777
|
+
if (failedCount > 0) {
|
|
778
|
+
installSpinner.warn(
|
|
779
|
+
`Installed to ${successCount}/${results.length} agents.`
|
|
780
|
+
);
|
|
781
|
+
} else {
|
|
782
|
+
installSpinner.succeed(`Installed to ${successCount} agents.`);
|
|
783
|
+
}
|
|
784
|
+
for (const result of results) {
|
|
785
|
+
if (result.success) {
|
|
786
|
+
logger.log(
|
|
787
|
+
` ${highlighter.success("\u2713")} ${result.client} ${highlighter.dim("\u2192")} ${highlighter.dim(result.configPath)}`
|
|
788
|
+
);
|
|
789
|
+
} else {
|
|
790
|
+
logger.log(
|
|
791
|
+
` ${highlighter.error("\u2717")} ${result.client} ${highlighter.dim("\u2192")} ${result.error}`
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
return results;
|
|
796
|
+
};
|
|
797
|
+
var promptConnectionMode = async () => {
|
|
798
|
+
const { connectionMode } = await prompts({
|
|
799
|
+
type: "select",
|
|
800
|
+
name: "connectionMode",
|
|
801
|
+
message: "How would you like to connect?",
|
|
802
|
+
choices: [
|
|
803
|
+
{
|
|
804
|
+
title: `MCP ${highlighter.dim("(recommended)")}`,
|
|
805
|
+
description: "Installs to all supported agents at once",
|
|
806
|
+
value: "mcp"
|
|
807
|
+
},
|
|
808
|
+
{
|
|
809
|
+
title: "Legacy",
|
|
810
|
+
description: "Install a per-project agent package",
|
|
811
|
+
value: "legacy"
|
|
812
|
+
}
|
|
813
|
+
]
|
|
814
|
+
});
|
|
815
|
+
return connectionMode;
|
|
816
|
+
};
|
|
817
|
+
var promptMcpInstall = async () => {
|
|
818
|
+
const clientNames = getMcpClientNames();
|
|
819
|
+
const { selectedAgents } = await prompts({
|
|
820
|
+
type: "multiselect",
|
|
821
|
+
name: "selectedAgents",
|
|
822
|
+
message: "Select agents to install MCP server for:",
|
|
823
|
+
choices: clientNames.map((name) => ({
|
|
824
|
+
title: name,
|
|
825
|
+
value: name,
|
|
826
|
+
selected: true
|
|
827
|
+
}))
|
|
828
|
+
});
|
|
829
|
+
if (selectedAgents === void 0 || selectedAgents.length === 0) {
|
|
830
|
+
return false;
|
|
831
|
+
}
|
|
832
|
+
logger.break();
|
|
833
|
+
const results = installMcpServers(selectedAgents);
|
|
834
|
+
const hasSuccess = results.some((result) => result.success);
|
|
835
|
+
return hasSuccess;
|
|
836
|
+
};
|
|
837
|
+
|
|
536
838
|
// src/utils/templates.ts
|
|
537
839
|
var AGENTS = [
|
|
538
840
|
"claude-code",
|
|
@@ -554,6 +856,13 @@ var AGENT_NAMES = {
|
|
|
554
856
|
ami: "Ami",
|
|
555
857
|
droid: "Droid"
|
|
556
858
|
};
|
|
859
|
+
var getAgentDisplayName = (agent) => {
|
|
860
|
+
if (agent === "mcp") return "MCP";
|
|
861
|
+
if (agent in AGENT_NAMES) {
|
|
862
|
+
return AGENT_NAMES[agent];
|
|
863
|
+
}
|
|
864
|
+
return agent;
|
|
865
|
+
};
|
|
557
866
|
var NEXT_APP_ROUTER_SCRIPT = `{process.env.NODE_ENV === "development" && (
|
|
558
867
|
<Script
|
|
559
868
|
src="//unpkg.com/react-grab/dist/index.global.js"
|
|
@@ -1307,6 +1616,14 @@ var previewPackageJsonTransform = (projectRoot, agent, installedAgents, packageM
|
|
|
1307
1616
|
noChanges: true
|
|
1308
1617
|
};
|
|
1309
1618
|
}
|
|
1619
|
+
if (agent === "mcp") {
|
|
1620
|
+
return {
|
|
1621
|
+
success: true,
|
|
1622
|
+
filePath: "",
|
|
1623
|
+
message: "MCP does not use package.json dev script",
|
|
1624
|
+
noChanges: true
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1310
1627
|
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
1311
1628
|
if (!fs.existsSync(packageJsonPath)) {
|
|
1312
1629
|
return {
|
|
@@ -1868,9 +2185,9 @@ var previewCdnTransform = (projectRoot, framework, nextRouterType, targetCdnDoma
|
|
|
1868
2185
|
};
|
|
1869
2186
|
|
|
1870
2187
|
// src/commands/add.ts
|
|
1871
|
-
var VERSION = "0.1.
|
|
2188
|
+
var VERSION = "0.1.13";
|
|
1872
2189
|
var formatInstalledAgentNames = (agents) => agents.map((agent) => AGENT_NAMES[agent] || agent).join(", ");
|
|
1873
|
-
var add = new commander.Command().name("add").alias("install").description("
|
|
2190
|
+
var add = new commander.Command().name("add").alias("install").description("connect React Grab to your agent").argument("[agent]", `agent to add (${AGENTS.join(", ")})`).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
1874
2191
|
"-c, --cwd <cwd>",
|
|
1875
2192
|
"working directory (defaults to current directory)",
|
|
1876
2193
|
process.cwd()
|
|
@@ -1897,9 +2214,10 @@ var add = new commander.Command().name("add").alias("install").description("add
|
|
|
1897
2214
|
const availableAgents = AGENTS.filter(
|
|
1898
2215
|
(agent) => !projectInfo.installedAgents.includes(agent)
|
|
1899
2216
|
);
|
|
1900
|
-
if (availableAgents.length === 0) {
|
|
2217
|
+
if (availableAgents.length === 0 && isNonInteractive && !agentArg) {
|
|
1901
2218
|
logger.break();
|
|
1902
|
-
logger.success("All
|
|
2219
|
+
logger.success("All legacy agents are already installed.");
|
|
2220
|
+
logger.log("Run without -y to add MCP.");
|
|
1903
2221
|
logger.break();
|
|
1904
2222
|
process.exit(0);
|
|
1905
2223
|
}
|
|
@@ -1933,11 +2251,11 @@ var add = new commander.Command().name("add").alias("install").description("add
|
|
|
1933
2251
|
message: "How would you like to proceed?",
|
|
1934
2252
|
choices: [
|
|
1935
2253
|
{
|
|
1936
|
-
title: `Replace with ${
|
|
2254
|
+
title: `Replace with ${getAgentDisplayName(agentIntegration)}`,
|
|
1937
2255
|
value: "replace"
|
|
1938
2256
|
},
|
|
1939
2257
|
{
|
|
1940
|
-
title: `Add ${
|
|
2258
|
+
title: `Add ${getAgentDisplayName(agentIntegration)} alongside existing`,
|
|
1941
2259
|
value: "add"
|
|
1942
2260
|
},
|
|
1943
2261
|
{ title: "Cancel", value: "cancel" }
|
|
@@ -1961,48 +2279,72 @@ var add = new commander.Command().name("add").alias("install").description("add
|
|
|
1961
2279
|
logger.warn(`Currently installed: ${installedNames}`);
|
|
1962
2280
|
logger.break();
|
|
1963
2281
|
}
|
|
1964
|
-
const
|
|
1965
|
-
|
|
1966
|
-
name: "agent",
|
|
1967
|
-
message: `Which ${highlighter.info("coding agent")} would you like to connect?`,
|
|
1968
|
-
choices: availableAgents.map((availableAgent) => ({
|
|
1969
|
-
title: AGENT_NAMES[availableAgent],
|
|
1970
|
-
value: availableAgent
|
|
1971
|
-
}))
|
|
1972
|
-
});
|
|
1973
|
-
if (!agent) {
|
|
2282
|
+
const connectionMode = await promptConnectionMode();
|
|
2283
|
+
if (connectionMode === void 0) {
|
|
1974
2284
|
logger.break();
|
|
1975
2285
|
process.exit(1);
|
|
1976
2286
|
}
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
2287
|
+
if (connectionMode === "mcp") {
|
|
2288
|
+
const didInstall = await promptMcpInstall();
|
|
2289
|
+
if (!didInstall) {
|
|
2290
|
+
logger.break();
|
|
2291
|
+
process.exit(0);
|
|
2292
|
+
}
|
|
2293
|
+
logger.break();
|
|
2294
|
+
logger.log(
|
|
2295
|
+
`${highlighter.success("Success!")} MCP server has been configured.`
|
|
1981
2296
|
);
|
|
1982
|
-
|
|
2297
|
+
logger.log("Restart your agents to activate.");
|
|
2298
|
+
logger.break();
|
|
2299
|
+
agentIntegration = "mcp";
|
|
2300
|
+
projectInfo.installedAgents = [...projectInfo.installedAgents, "mcp"];
|
|
2301
|
+
} else {
|
|
2302
|
+
const { agent } = await prompts({
|
|
1983
2303
|
type: "select",
|
|
1984
|
-
name: "
|
|
1985
|
-
message: "
|
|
2304
|
+
name: "agent",
|
|
2305
|
+
message: `Which ${highlighter.info("agent")} would you like to connect?`,
|
|
1986
2306
|
choices: [
|
|
1987
|
-
{
|
|
1988
|
-
title:
|
|
1989
|
-
value:
|
|
1990
|
-
},
|
|
1991
|
-
{
|
|
1992
|
-
title: `Add ${AGENT_NAMES[agentIntegration]} alongside existing`,
|
|
1993
|
-
value: "add"
|
|
1994
|
-
},
|
|
1995
|
-
{ title: "Cancel", value: "cancel" }
|
|
2307
|
+
...availableAgents.map((availableAgent) => ({
|
|
2308
|
+
title: AGENT_NAMES[availableAgent],
|
|
2309
|
+
value: availableAgent
|
|
2310
|
+
})),
|
|
2311
|
+
{ title: "Skip", value: "skip" }
|
|
1996
2312
|
]
|
|
1997
2313
|
});
|
|
1998
|
-
if (!
|
|
1999
|
-
logger.break();
|
|
2000
|
-
logger.log("Changes cancelled.");
|
|
2314
|
+
if (!agent || agent === "skip") {
|
|
2001
2315
|
logger.break();
|
|
2002
2316
|
process.exit(0);
|
|
2003
2317
|
}
|
|
2004
|
-
|
|
2005
|
-
|
|
2318
|
+
agentIntegration = agent;
|
|
2319
|
+
if (projectInfo.installedAgents.length > 0) {
|
|
2320
|
+
const installedNames = formatInstalledAgentNames(
|
|
2321
|
+
projectInfo.installedAgents
|
|
2322
|
+
);
|
|
2323
|
+
const { action } = await prompts({
|
|
2324
|
+
type: "select",
|
|
2325
|
+
name: "action",
|
|
2326
|
+
message: "How would you like to proceed?",
|
|
2327
|
+
choices: [
|
|
2328
|
+
{
|
|
2329
|
+
title: `Replace ${installedNames} with ${getAgentDisplayName(agentIntegration)}`,
|
|
2330
|
+
value: "replace"
|
|
2331
|
+
},
|
|
2332
|
+
{
|
|
2333
|
+
title: `Add ${getAgentDisplayName(agentIntegration)} alongside existing`,
|
|
2334
|
+
value: "add"
|
|
2335
|
+
},
|
|
2336
|
+
{ title: "Cancel", value: "cancel" }
|
|
2337
|
+
]
|
|
2338
|
+
});
|
|
2339
|
+
if (!action || action === "cancel") {
|
|
2340
|
+
logger.break();
|
|
2341
|
+
logger.log("Changes cancelled.");
|
|
2342
|
+
logger.break();
|
|
2343
|
+
process.exit(0);
|
|
2344
|
+
}
|
|
2345
|
+
if (action === "replace") {
|
|
2346
|
+
agentsToRemove = [...projectInfo.installedAgents];
|
|
2347
|
+
}
|
|
2006
2348
|
}
|
|
2007
2349
|
}
|
|
2008
2350
|
} else {
|
|
@@ -2079,7 +2421,7 @@ var add = new commander.Command().name("add").alias("install").description("add
|
|
|
2079
2421
|
);
|
|
2080
2422
|
}
|
|
2081
2423
|
const addingSpinner = spinner(
|
|
2082
|
-
`Adding ${
|
|
2424
|
+
`Adding ${getAgentDisplayName(agentIntegration)}.`
|
|
2083
2425
|
).start();
|
|
2084
2426
|
addingSpinner.succeed();
|
|
2085
2427
|
const result = previewTransform(
|
|
@@ -2185,7 +2527,7 @@ var add = new commander.Command().name("add").alias("install").description("add
|
|
|
2185
2527
|
}
|
|
2186
2528
|
logger.break();
|
|
2187
2529
|
logger.log(
|
|
2188
|
-
`${highlighter.success("Success!")} ${
|
|
2530
|
+
`${highlighter.success("Success!")} ${getAgentDisplayName(agentIntegration)} has been added.`
|
|
2189
2531
|
);
|
|
2190
2532
|
if (packageJsonResult.warning) {
|
|
2191
2533
|
logger.warn(packageJsonResult.warning);
|
|
@@ -2204,7 +2546,7 @@ var MAX_KEY_HOLD_DURATION_MS = 2e3;
|
|
|
2204
2546
|
var MAX_CONTEXT_LINES = 50;
|
|
2205
2547
|
|
|
2206
2548
|
// src/commands/configure.ts
|
|
2207
|
-
var VERSION2 = "0.1.
|
|
2549
|
+
var VERSION2 = "0.1.13";
|
|
2208
2550
|
var isMac = process.platform === "darwin";
|
|
2209
2551
|
var META_LABEL = isMac ? "Cmd" : "Win";
|
|
2210
2552
|
var ALT_LABEL = isMac ? "Option" : "Alt";
|
|
@@ -2707,7 +3049,7 @@ var configure = new commander.Command().name("configure").alias("config").descri
|
|
|
2707
3049
|
});
|
|
2708
3050
|
|
|
2709
3051
|
// src/utils/cli-helpers.ts
|
|
2710
|
-
var formatInstalledAgentNames2 = (agents) => agents.map(
|
|
3052
|
+
var formatInstalledAgentNames2 = (agents) => agents.map(getAgentDisplayName).join(", ");
|
|
2711
3053
|
var applyTransformWithFeedback = (result, message) => {
|
|
2712
3054
|
const writeSpinner = spinner(
|
|
2713
3055
|
message ?? `Applying changes to ${result.filePath}.`
|
|
@@ -2760,7 +3102,7 @@ var uninstallPackagesWithFeedback = (packages, packageManager, projectRoot) => {
|
|
|
2760
3102
|
};
|
|
2761
3103
|
|
|
2762
3104
|
// src/commands/init.ts
|
|
2763
|
-
var VERSION3 = "0.1.
|
|
3105
|
+
var VERSION3 = "0.1.13";
|
|
2764
3106
|
var REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
2765
3107
|
var DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
2766
3108
|
var reportToCli = (type, config, error) => {
|
|
@@ -2796,12 +3138,7 @@ var UNSUPPORTED_FRAMEWORK_NAMES = {
|
|
|
2796
3138
|
sveltekit: "SvelteKit",
|
|
2797
3139
|
gatsby: "Gatsby"
|
|
2798
3140
|
};
|
|
2799
|
-
var getAgentName =
|
|
2800
|
-
if (agent in AGENT_NAMES) {
|
|
2801
|
-
return AGENT_NAMES[agent];
|
|
2802
|
-
}
|
|
2803
|
-
return agent;
|
|
2804
|
-
};
|
|
3141
|
+
var getAgentName = getAgentDisplayName;
|
|
2805
3142
|
var formatActivationKeyDisplay2 = (activationKey) => {
|
|
2806
3143
|
if (!activationKey) return "Default (Option/Alt)";
|
|
2807
3144
|
return activationKey.split("+").map((part) => {
|
|
@@ -2816,7 +3153,7 @@ var formatActivationKeyDisplay2 = (activationKey) => {
|
|
|
2816
3153
|
};
|
|
2817
3154
|
var init = new commander.Command().name("init").description("initialize React Grab in your project").option("-y, --yes", "skip confirmation prompts", false).option("-f, --force", "force overwrite existing config", false).option(
|
|
2818
3155
|
"-a, --agent <agent>",
|
|
2819
|
-
"agent
|
|
3156
|
+
"connect to your agent (claude-code, cursor, opencode, codex, gemini, amp, mcp)"
|
|
2820
3157
|
).option(
|
|
2821
3158
|
"-k, --key <key>",
|
|
2822
3159
|
"activation key (e.g., Meta+K, Ctrl+Shift+G, Space)"
|
|
@@ -3035,23 +3372,108 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
3035
3372
|
const availableAgents = AGENTS.filter(
|
|
3036
3373
|
(agent) => !projectInfo.installedAgents.includes(agent)
|
|
3037
3374
|
);
|
|
3038
|
-
|
|
3375
|
+
logger.break();
|
|
3376
|
+
const { wantAddAgent } = await prompts({
|
|
3377
|
+
type: "confirm",
|
|
3378
|
+
name: "wantAddAgent",
|
|
3379
|
+
message: `Would you like to ${highlighter.info("connect it to your agent")}?`,
|
|
3380
|
+
initial: false
|
|
3381
|
+
});
|
|
3382
|
+
if (wantAddAgent === void 0) {
|
|
3039
3383
|
logger.break();
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
});
|
|
3046
|
-
if (wantAddAgent === void 0) {
|
|
3384
|
+
process.exit(1);
|
|
3385
|
+
}
|
|
3386
|
+
if (wantAddAgent) {
|
|
3387
|
+
const connectionMode = await promptConnectionMode();
|
|
3388
|
+
if (connectionMode === void 0) {
|
|
3047
3389
|
logger.break();
|
|
3048
3390
|
process.exit(1);
|
|
3049
3391
|
}
|
|
3050
|
-
|
|
3392
|
+
let agentIntegration2;
|
|
3393
|
+
if (connectionMode === "mcp") {
|
|
3394
|
+
const didInstall = await promptMcpInstall();
|
|
3395
|
+
if (!didInstall) {
|
|
3396
|
+
logger.break();
|
|
3397
|
+
process.exit(0);
|
|
3398
|
+
}
|
|
3399
|
+
logger.break();
|
|
3400
|
+
logger.success("MCP server has been configured.");
|
|
3401
|
+
logger.log("Restart your agents to activate.");
|
|
3402
|
+
agentIntegration2 = "mcp";
|
|
3403
|
+
projectInfo.installedAgents = ["mcp"];
|
|
3404
|
+
const result2 = previewTransform(
|
|
3405
|
+
projectInfo.projectRoot,
|
|
3406
|
+
projectInfo.framework,
|
|
3407
|
+
projectInfo.nextRouterType,
|
|
3408
|
+
agentIntegration2,
|
|
3409
|
+
true
|
|
3410
|
+
);
|
|
3411
|
+
const packageJsonResult2 = previewPackageJsonTransform(
|
|
3412
|
+
projectInfo.projectRoot,
|
|
3413
|
+
agentIntegration2,
|
|
3414
|
+
projectInfo.installedAgents,
|
|
3415
|
+
projectInfo.packageManager
|
|
3416
|
+
);
|
|
3417
|
+
if (!result2.success) {
|
|
3418
|
+
logger.break();
|
|
3419
|
+
logger.error(result2.message);
|
|
3420
|
+
logger.break();
|
|
3421
|
+
process.exit(1);
|
|
3422
|
+
}
|
|
3423
|
+
const hasLayoutChanges2 = !result2.noChanges && result2.originalContent && result2.newContent;
|
|
3424
|
+
const hasPackageJsonChanges2 = packageJsonResult2.success && !packageJsonResult2.noChanges && packageJsonResult2.originalContent && packageJsonResult2.newContent;
|
|
3425
|
+
if (hasLayoutChanges2 || hasPackageJsonChanges2) {
|
|
3426
|
+
logger.break();
|
|
3427
|
+
if (hasLayoutChanges2) {
|
|
3428
|
+
printDiff(
|
|
3429
|
+
result2.filePath,
|
|
3430
|
+
result2.originalContent,
|
|
3431
|
+
result2.newContent
|
|
3432
|
+
);
|
|
3433
|
+
}
|
|
3434
|
+
if (hasPackageJsonChanges2) {
|
|
3435
|
+
if (hasLayoutChanges2) {
|
|
3436
|
+
logger.break();
|
|
3437
|
+
}
|
|
3438
|
+
printDiff(
|
|
3439
|
+
packageJsonResult2.filePath,
|
|
3440
|
+
packageJsonResult2.originalContent,
|
|
3441
|
+
packageJsonResult2.newContent
|
|
3442
|
+
);
|
|
3443
|
+
}
|
|
3444
|
+
logger.break();
|
|
3445
|
+
const { proceed } = await prompts({
|
|
3446
|
+
type: "confirm",
|
|
3447
|
+
name: "proceed",
|
|
3448
|
+
message: "Apply these changes?",
|
|
3449
|
+
initial: true
|
|
3450
|
+
});
|
|
3451
|
+
if (!proceed) {
|
|
3452
|
+
logger.break();
|
|
3453
|
+
logger.log("Agent addition cancelled.");
|
|
3454
|
+
} else {
|
|
3455
|
+
installPackagesWithFeedback(
|
|
3456
|
+
getPackagesToInstall(agentIntegration2, false),
|
|
3457
|
+
projectInfo.packageManager,
|
|
3458
|
+
projectInfo.projectRoot
|
|
3459
|
+
);
|
|
3460
|
+
if (hasLayoutChanges2) {
|
|
3461
|
+
applyTransformWithFeedback(result2);
|
|
3462
|
+
}
|
|
3463
|
+
if (hasPackageJsonChanges2) {
|
|
3464
|
+
applyPackageJsonWithFeedback(packageJsonResult2);
|
|
3465
|
+
}
|
|
3466
|
+
logger.break();
|
|
3467
|
+
logger.success(
|
|
3468
|
+
`${getAgentName(agentIntegration2)} has been added.`
|
|
3469
|
+
);
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
} else {
|
|
3051
3473
|
const { agent } = await prompts({
|
|
3052
3474
|
type: "select",
|
|
3053
3475
|
name: "agent",
|
|
3054
|
-
message: `Which ${highlighter.info("
|
|
3476
|
+
message: `Which ${highlighter.info("agent")} would you like to connect?`,
|
|
3055
3477
|
choices: [
|
|
3056
3478
|
...availableAgents.map((innerAgent) => ({
|
|
3057
3479
|
title: getAgentName(innerAgent),
|
|
@@ -3064,7 +3486,7 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
3064
3486
|
logger.break();
|
|
3065
3487
|
process.exit(0);
|
|
3066
3488
|
}
|
|
3067
|
-
|
|
3489
|
+
agentIntegration2 = agent;
|
|
3068
3490
|
let agentsToRemove2 = [];
|
|
3069
3491
|
if (projectInfo.installedAgents.length > 0) {
|
|
3070
3492
|
const installedNames = formatInstalledAgentNames2(
|
|
@@ -3362,7 +3784,7 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
3362
3784
|
const { wantAddAgent } = await prompts({
|
|
3363
3785
|
type: "confirm",
|
|
3364
3786
|
name: "wantAddAgent",
|
|
3365
|
-
message: `Would you like to
|
|
3787
|
+
message: `Would you like to ${highlighter.info("connect it to your agent")}?`,
|
|
3366
3788
|
initial: false
|
|
3367
3789
|
});
|
|
3368
3790
|
if (wantAddAgent === void 0) {
|
|
@@ -3370,24 +3792,42 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
3370
3792
|
process.exit(1);
|
|
3371
3793
|
}
|
|
3372
3794
|
if (wantAddAgent) {
|
|
3373
|
-
const
|
|
3374
|
-
|
|
3375
|
-
name: "agent",
|
|
3376
|
-
message: `Which ${highlighter.info("coding agent")} would you like to connect?`,
|
|
3377
|
-
choices: [
|
|
3378
|
-
...AGENTS.map((innerAgent) => ({
|
|
3379
|
-
title: getAgentName(innerAgent),
|
|
3380
|
-
value: innerAgent
|
|
3381
|
-
})),
|
|
3382
|
-
{ title: "Skip", value: "skip" }
|
|
3383
|
-
]
|
|
3384
|
-
});
|
|
3385
|
-
if (agent === void 0) {
|
|
3795
|
+
const connectionMode = await promptConnectionMode();
|
|
3796
|
+
if (connectionMode === void 0) {
|
|
3386
3797
|
logger.break();
|
|
3387
3798
|
process.exit(1);
|
|
3388
3799
|
}
|
|
3389
|
-
if (
|
|
3390
|
-
|
|
3800
|
+
if (connectionMode === "mcp") {
|
|
3801
|
+
const didInstall = await promptMcpInstall();
|
|
3802
|
+
if (!didInstall) {
|
|
3803
|
+
logger.break();
|
|
3804
|
+
process.exit(0);
|
|
3805
|
+
}
|
|
3806
|
+
logger.break();
|
|
3807
|
+
logger.success("MCP server has been configured.");
|
|
3808
|
+
logger.log("Continuing with React Grab installation...");
|
|
3809
|
+
logger.break();
|
|
3810
|
+
agentIntegration = "mcp";
|
|
3811
|
+
} else {
|
|
3812
|
+
const { agent } = await prompts({
|
|
3813
|
+
type: "select",
|
|
3814
|
+
name: "agent",
|
|
3815
|
+
message: `Which ${highlighter.info("agent")} would you like to connect?`,
|
|
3816
|
+
choices: [
|
|
3817
|
+
...AGENTS.map((innerAgent) => ({
|
|
3818
|
+
title: getAgentName(innerAgent),
|
|
3819
|
+
value: innerAgent
|
|
3820
|
+
})),
|
|
3821
|
+
{ title: "Skip", value: "skip" }
|
|
3822
|
+
]
|
|
3823
|
+
});
|
|
3824
|
+
if (agent === void 0) {
|
|
3825
|
+
logger.break();
|
|
3826
|
+
process.exit(1);
|
|
3827
|
+
}
|
|
3828
|
+
if (agent !== "skip") {
|
|
3829
|
+
agentIntegration = agent;
|
|
3830
|
+
}
|
|
3391
3831
|
}
|
|
3392
3832
|
}
|
|
3393
3833
|
}
|
|
@@ -3496,10 +3936,10 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
3496
3936
|
reportToCli("error", void 0, error);
|
|
3497
3937
|
}
|
|
3498
3938
|
});
|
|
3499
|
-
var VERSION4 = "0.1.
|
|
3500
|
-
var remove = new commander.Command().name("remove").description("
|
|
3939
|
+
var VERSION4 = "0.1.13";
|
|
3940
|
+
var remove = new commander.Command().name("remove").description("disconnect React Grab from your agent").argument(
|
|
3501
3941
|
"[agent]",
|
|
3502
|
-
"agent to remove (claude-code, cursor, opencode, codex, gemini, amp, ami)"
|
|
3942
|
+
"agent to remove (claude-code, cursor, opencode, codex, gemini, amp, ami, mcp)"
|
|
3503
3943
|
).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
3504
3944
|
"-c, --cwd <cwd>",
|
|
3505
3945
|
"working directory (defaults to current directory)",
|
|
@@ -3526,7 +3966,7 @@ var remove = new commander.Command().name("remove").description("remove an agent
|
|
|
3526
3966
|
if (projectInfo.installedAgents.length === 0) {
|
|
3527
3967
|
preflightSpinner.succeed();
|
|
3528
3968
|
logger.break();
|
|
3529
|
-
logger.warn("No agent
|
|
3969
|
+
logger.warn("No agent connections are installed.");
|
|
3530
3970
|
logger.break();
|
|
3531
3971
|
process.exit(0);
|
|
3532
3972
|
}
|
|
@@ -3537,7 +3977,7 @@ var remove = new commander.Command().name("remove").description("remove an agent
|
|
|
3537
3977
|
logger.break();
|
|
3538
3978
|
logger.error(`Agent ${highlighter.info(agentArg)} is not installed.`);
|
|
3539
3979
|
logger.log(
|
|
3540
|
-
`Installed agents: ${projectInfo.installedAgents.map(
|
|
3980
|
+
`Installed agents: ${projectInfo.installedAgents.map(getAgentDisplayName).join(", ")}`
|
|
3541
3981
|
);
|
|
3542
3982
|
logger.break();
|
|
3543
3983
|
process.exit(1);
|
|
@@ -3548,9 +3988,9 @@ var remove = new commander.Command().name("remove").description("remove an agent
|
|
|
3548
3988
|
const { agent } = await prompts({
|
|
3549
3989
|
type: "select",
|
|
3550
3990
|
name: "agent",
|
|
3551
|
-
message: `Which ${highlighter.info("agent
|
|
3991
|
+
message: `Which ${highlighter.info("agent")} would you like to disconnect?`,
|
|
3552
3992
|
choices: projectInfo.installedAgents.map((innerAgent) => ({
|
|
3553
|
-
title:
|
|
3993
|
+
title: getAgentDisplayName(innerAgent),
|
|
3554
3994
|
value: innerAgent
|
|
3555
3995
|
}))
|
|
3556
3996
|
});
|
|
@@ -3569,7 +4009,7 @@ var remove = new commander.Command().name("remove").description("remove an agent
|
|
|
3569
4009
|
process.exit(1);
|
|
3570
4010
|
}
|
|
3571
4011
|
const removingSpinner = spinner(
|
|
3572
|
-
`Preparing to remove ${
|
|
4012
|
+
`Preparing to remove ${getAgentDisplayName(agentToRemove)}.`
|
|
3573
4013
|
).start();
|
|
3574
4014
|
removingSpinner.succeed();
|
|
3575
4015
|
const result = previewAgentRemoval(
|
|
@@ -3666,7 +4106,7 @@ var remove = new commander.Command().name("remove").description("remove an agent
|
|
|
3666
4106
|
}
|
|
3667
4107
|
logger.break();
|
|
3668
4108
|
logger.log(
|
|
3669
|
-
`${highlighter.success("Success!")} ${
|
|
4109
|
+
`${highlighter.success("Success!")} ${getAgentDisplayName(agentToRemove)} has been removed.`
|
|
3670
4110
|
);
|
|
3671
4111
|
logger.break();
|
|
3672
4112
|
} catch (error) {
|
|
@@ -3675,7 +4115,7 @@ var remove = new commander.Command().name("remove").description("remove an agent
|
|
|
3675
4115
|
});
|
|
3676
4116
|
|
|
3677
4117
|
// src/cli.ts
|
|
3678
|
-
var VERSION5 = "0.1.
|
|
4118
|
+
var VERSION5 = "0.1.13";
|
|
3679
4119
|
var VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
3680
4120
|
process.on("SIGINT", () => process.exit(0));
|
|
3681
4121
|
process.on("SIGTERM", () => process.exit(0));
|