@react-grab/cli 0.1.15 → 0.1.17
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 +103 -141
- package/dist/cli.js +83 -141
- package/package.json +4 -2
package/dist/cli.cjs
CHANGED
|
@@ -11,10 +11,30 @@ var ni = require('@antfu/ni');
|
|
|
11
11
|
var ignore = require('ignore');
|
|
12
12
|
var os = require('os');
|
|
13
13
|
var process2 = require('process');
|
|
14
|
+
var jsonc = require('jsonc-parser');
|
|
15
|
+
var TOML = require('smol-toml');
|
|
14
16
|
var ora = require('ora');
|
|
15
17
|
|
|
16
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
19
|
|
|
20
|
+
function _interopNamespace(e) {
|
|
21
|
+
if (e && e.__esModule) return e;
|
|
22
|
+
var n = Object.create(null);
|
|
23
|
+
if (e) {
|
|
24
|
+
Object.keys(e).forEach(function (k) {
|
|
25
|
+
if (k !== 'default') {
|
|
26
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
27
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function () { return e[k]; }
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
n.default = e;
|
|
35
|
+
return Object.freeze(n);
|
|
36
|
+
}
|
|
37
|
+
|
|
18
38
|
var pc__default = /*#__PURE__*/_interopDefault(pc);
|
|
19
39
|
var basePrompts__default = /*#__PURE__*/_interopDefault(basePrompts);
|
|
20
40
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
@@ -22,17 +42,22 @@ var path__default = /*#__PURE__*/_interopDefault(path);
|
|
|
22
42
|
var ignore__default = /*#__PURE__*/_interopDefault(ignore);
|
|
23
43
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
24
44
|
var process2__default = /*#__PURE__*/_interopDefault(process2);
|
|
45
|
+
var jsonc__namespace = /*#__PURE__*/_interopNamespace(jsonc);
|
|
46
|
+
var TOML__namespace = /*#__PURE__*/_interopNamespace(TOML);
|
|
25
47
|
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
26
48
|
|
|
27
49
|
// src/utils/is-non-interactive.ts
|
|
28
|
-
var
|
|
50
|
+
var AGENT_ENVIRONMENT_VARIABLES = [
|
|
29
51
|
"CI",
|
|
30
52
|
"CLAUDECODE",
|
|
53
|
+
"CURSOR_AGENT",
|
|
54
|
+
"CODEX_CI",
|
|
55
|
+
"OPENCODE",
|
|
56
|
+
"AMP_HOME",
|
|
31
57
|
"AMI"
|
|
32
58
|
];
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
) || !process.stdin.isTTY;
|
|
59
|
+
var isEnvironmentVariableSet = (variable) => Boolean(process.env[variable]);
|
|
60
|
+
var detectNonInteractive = (yesFlag) => yesFlag || AGENT_ENVIRONMENT_VARIABLES.some(isEnvironmentVariableSet) || !process.stdin.isTTY;
|
|
36
61
|
var highlighter = {
|
|
37
62
|
error: pc__default.default.red,
|
|
38
63
|
warn: pc__default.default.yellow,
|
|
@@ -390,6 +415,8 @@ var AGENT_PACKAGES = [
|
|
|
390
415
|
"@react-grab/gemini",
|
|
391
416
|
"@react-grab/amp",
|
|
392
417
|
"@react-grab/ami",
|
|
418
|
+
"@react-grab/droid",
|
|
419
|
+
"@react-grab/copilot",
|
|
393
420
|
"@react-grab/mcp"
|
|
394
421
|
];
|
|
395
422
|
var detectUnsupportedFramework = (projectRoot) => {
|
|
@@ -624,6 +651,7 @@ var spinner = (text, options) => ora__default.default({ text, isSilent: options?
|
|
|
624
651
|
// src/utils/install-mcp.ts
|
|
625
652
|
var SERVER_NAME = "react-grab-mcp";
|
|
626
653
|
var PACKAGE_NAME = "@react-grab/mcp";
|
|
654
|
+
var getXdgConfigHome = () => process2__default.default.env.XDG_CONFIG_HOME || path__default.default.join(os__default.default.homedir(), ".config");
|
|
627
655
|
var getBaseDir = () => {
|
|
628
656
|
const homeDir = os__default.default.homedir();
|
|
629
657
|
if (process2__default.default.platform === "win32") {
|
|
@@ -632,15 +660,13 @@ var getBaseDir = () => {
|
|
|
632
660
|
if (process2__default.default.platform === "darwin") {
|
|
633
661
|
return path__default.default.join(homeDir, "Library", "Application Support");
|
|
634
662
|
}
|
|
635
|
-
return
|
|
663
|
+
return getXdgConfigHome();
|
|
636
664
|
};
|
|
637
665
|
var getZedConfigPath = () => {
|
|
638
|
-
const homeDir = os__default.default.homedir();
|
|
639
666
|
if (process2__default.default.platform === "win32") {
|
|
640
|
-
|
|
641
|
-
return path__default.default.join(appData, "Zed", "settings.json");
|
|
667
|
+
return path__default.default.join(getBaseDir(), "Zed", "settings.json");
|
|
642
668
|
}
|
|
643
|
-
return path__default.default.join(
|
|
669
|
+
return path__default.default.join(os__default.default.homedir(), ".config", "zed", "settings.json");
|
|
644
670
|
};
|
|
645
671
|
var getClients = () => {
|
|
646
672
|
const homeDir = os__default.default.homedir();
|
|
@@ -650,6 +676,23 @@ var getClients = () => {
|
|
|
650
676
|
args: ["-y", PACKAGE_NAME, "--stdio"]
|
|
651
677
|
};
|
|
652
678
|
return [
|
|
679
|
+
{
|
|
680
|
+
name: "Claude Code",
|
|
681
|
+
configPath: path__default.default.join(homeDir, ".claude.json"),
|
|
682
|
+
configKey: "mcpServers",
|
|
683
|
+
format: "json",
|
|
684
|
+
serverConfig: stdioConfig
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
name: "Codex",
|
|
688
|
+
configPath: path__default.default.join(
|
|
689
|
+
process2__default.default.env.CODEX_HOME || path__default.default.join(homeDir, ".codex"),
|
|
690
|
+
"config.toml"
|
|
691
|
+
),
|
|
692
|
+
configKey: "mcp_servers",
|
|
693
|
+
format: "toml",
|
|
694
|
+
serverConfig: stdioConfig
|
|
695
|
+
},
|
|
653
696
|
{
|
|
654
697
|
name: "Cursor",
|
|
655
698
|
configPath: path__default.default.join(homeDir, ".cursor", "mcp.json"),
|
|
@@ -657,6 +700,16 @@ var getClients = () => {
|
|
|
657
700
|
format: "json",
|
|
658
701
|
serverConfig: stdioConfig
|
|
659
702
|
},
|
|
703
|
+
{
|
|
704
|
+
name: "OpenCode",
|
|
705
|
+
configPath: path__default.default.join(getXdgConfigHome(), "opencode", "opencode.json"),
|
|
706
|
+
configKey: "mcp",
|
|
707
|
+
format: "json",
|
|
708
|
+
serverConfig: {
|
|
709
|
+
type: "local",
|
|
710
|
+
command: ["npx", "-y", PACKAGE_NAME, "--stdio"]
|
|
711
|
+
}
|
|
712
|
+
},
|
|
660
713
|
{
|
|
661
714
|
name: "VS Code",
|
|
662
715
|
configPath: path__default.default.join(baseDir, "Code", "User", "mcp.json"),
|
|
@@ -664,13 +717,6 @@ var getClients = () => {
|
|
|
664
717
|
format: "json",
|
|
665
718
|
serverConfig: { type: "stdio", ...stdioConfig }
|
|
666
719
|
},
|
|
667
|
-
{
|
|
668
|
-
name: "Claude Code",
|
|
669
|
-
configPath: path__default.default.join(homeDir, ".claude.json"),
|
|
670
|
-
configKey: "mcpServers",
|
|
671
|
-
format: "json",
|
|
672
|
-
serverConfig: stdioConfig
|
|
673
|
-
},
|
|
674
720
|
{
|
|
675
721
|
name: "Amp",
|
|
676
722
|
configPath: path__default.default.join(homeDir, ".config", "amp", "settings.json"),
|
|
@@ -686,13 +732,10 @@ var getClients = () => {
|
|
|
686
732
|
serverConfig: { type: "stdio", ...stdioConfig }
|
|
687
733
|
},
|
|
688
734
|
{
|
|
689
|
-
name: "
|
|
690
|
-
configPath: path__default.default.join(
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
),
|
|
694
|
-
configKey: "mcp_servers",
|
|
695
|
-
format: "toml",
|
|
735
|
+
name: "Windsurf",
|
|
736
|
+
configPath: path__default.default.join(homeDir, ".codeium", "windsurf", "mcp_config.json"),
|
|
737
|
+
configKey: "mcpServers",
|
|
738
|
+
format: "json",
|
|
696
739
|
serverConfig: stdioConfig
|
|
697
740
|
},
|
|
698
741
|
{
|
|
@@ -701,13 +744,6 @@ var getClients = () => {
|
|
|
701
744
|
configKey: "context_servers",
|
|
702
745
|
format: "json",
|
|
703
746
|
serverConfig: { source: "custom", ...stdioConfig, env: {} }
|
|
704
|
-
},
|
|
705
|
-
{
|
|
706
|
-
name: "Windsurf",
|
|
707
|
-
configPath: path__default.default.join(homeDir, ".codeium", "windsurf", "mcp_config.json"),
|
|
708
|
-
configKey: "mcpServers",
|
|
709
|
-
format: "json",
|
|
710
|
-
serverConfig: stdioConfig
|
|
711
747
|
}
|
|
712
748
|
];
|
|
713
749
|
};
|
|
@@ -717,113 +753,36 @@ var ensureDirectory = (filePath) => {
|
|
|
717
753
|
fs__default.default.mkdirSync(directory, { recursive: true });
|
|
718
754
|
}
|
|
719
755
|
};
|
|
720
|
-
var
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
const keyMatch = keyPattern.exec(content);
|
|
730
|
-
if (keyMatch) {
|
|
731
|
-
const insertPosition = keyMatch.index + keyMatch[0].length;
|
|
732
|
-
const entry = `
|
|
733
|
-
"${serverName}": ${serverJson},`;
|
|
734
|
-
fs__default.default.writeFileSync(
|
|
735
|
-
filePath,
|
|
736
|
-
content.slice(0, insertPosition) + entry + content.slice(insertPosition)
|
|
737
|
-
);
|
|
738
|
-
return;
|
|
739
|
-
}
|
|
740
|
-
const lastBrace = content.lastIndexOf("}");
|
|
741
|
-
if (lastBrace === -1) return;
|
|
742
|
-
const beforeBrace = content.slice(0, lastBrace).trimEnd();
|
|
743
|
-
const withoutComments = beforeBrace.replace(/\/\/.*$/, "").trimEnd();
|
|
744
|
-
const lastChar = withoutComments[withoutComments.length - 1];
|
|
745
|
-
const needsComma = lastChar !== void 0 && lastChar !== "{" && lastChar !== ",";
|
|
746
|
-
const section = `${needsComma ? "," : ""}
|
|
747
|
-
"${configKey}": {
|
|
748
|
-
"${serverName}": ${serverJson}
|
|
749
|
-
}`;
|
|
750
|
-
fs__default.default.writeFileSync(filePath, beforeBrace + section + "\n}\n");
|
|
756
|
+
var JSONC_FORMAT_OPTIONS = {
|
|
757
|
+
tabSize: 2,
|
|
758
|
+
insertSpaces: true
|
|
759
|
+
};
|
|
760
|
+
var upsertIntoJsonc = (filePath, content, configKey, serverName, serverConfig) => {
|
|
761
|
+
const edits = jsonc__namespace.modify(content, [configKey, serverName], serverConfig, {
|
|
762
|
+
formattingOptions: JSONC_FORMAT_OPTIONS
|
|
763
|
+
});
|
|
764
|
+
fs__default.default.writeFileSync(filePath, jsonc__namespace.applyEdits(content, edits));
|
|
751
765
|
};
|
|
752
766
|
var installJsonClient = (client) => {
|
|
753
767
|
ensureDirectory(client.configPath);
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
try {
|
|
763
|
-
const config = JSON.parse(content);
|
|
764
|
-
const servers = config[client.configKey] ?? {};
|
|
765
|
-
servers[SERVER_NAME] = client.serverConfig;
|
|
766
|
-
config[client.configKey] = servers;
|
|
767
|
-
fs__default.default.writeFileSync(client.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
768
|
-
} catch {
|
|
769
|
-
insertIntoJsonc(
|
|
770
|
-
client.configPath,
|
|
771
|
-
content,
|
|
772
|
-
client.configKey,
|
|
773
|
-
SERVER_NAME,
|
|
774
|
-
client.serverConfig
|
|
775
|
-
);
|
|
776
|
-
}
|
|
777
|
-
};
|
|
778
|
-
var buildTomlSection = (configKey, serverConfig) => {
|
|
779
|
-
const lines = [`[${configKey}.${SERVER_NAME}]`];
|
|
780
|
-
for (const [key, value] of Object.entries(serverConfig)) {
|
|
781
|
-
if (typeof value === "string") {
|
|
782
|
-
lines.push(`${key} = "${value}"`);
|
|
783
|
-
} else if (Array.isArray(value)) {
|
|
784
|
-
const items = value.map((item) => `"${item}"`).join(", ");
|
|
785
|
-
lines.push(`${key} = [${items}]`);
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
return lines.join("\n");
|
|
768
|
+
const content = fs__default.default.existsSync(client.configPath) ? fs__default.default.readFileSync(client.configPath, "utf8") : "{}";
|
|
769
|
+
upsertIntoJsonc(
|
|
770
|
+
client.configPath,
|
|
771
|
+
content,
|
|
772
|
+
client.configKey,
|
|
773
|
+
SERVER_NAME,
|
|
774
|
+
client.serverConfig
|
|
775
|
+
);
|
|
789
776
|
};
|
|
790
777
|
var installTomlClient = (client) => {
|
|
791
778
|
ensureDirectory(client.configPath);
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
if (!content.includes(sectionHeader)) {
|
|
800
|
-
fs__default.default.writeFileSync(
|
|
801
|
-
client.configPath,
|
|
802
|
-
content.trimEnd() + "\n\n" + newSection + "\n"
|
|
803
|
-
);
|
|
804
|
-
return;
|
|
805
|
-
}
|
|
806
|
-
const lines = content.split("\n");
|
|
807
|
-
const resultLines = [];
|
|
808
|
-
let isInsideOurSection = false;
|
|
809
|
-
let didInsertReplacement = false;
|
|
810
|
-
for (const line of lines) {
|
|
811
|
-
if (line.trim() === sectionHeader) {
|
|
812
|
-
isInsideOurSection = true;
|
|
813
|
-
if (!didInsertReplacement) {
|
|
814
|
-
resultLines.push(newSection);
|
|
815
|
-
didInsertReplacement = true;
|
|
816
|
-
}
|
|
817
|
-
continue;
|
|
818
|
-
}
|
|
819
|
-
if (isInsideOurSection && line.startsWith("[")) {
|
|
820
|
-
isInsideOurSection = false;
|
|
821
|
-
}
|
|
822
|
-
if (!isInsideOurSection) {
|
|
823
|
-
resultLines.push(line);
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
fs__default.default.writeFileSync(client.configPath, resultLines.join("\n"));
|
|
779
|
+
const existingConfig = fs__default.default.existsSync(
|
|
780
|
+
client.configPath
|
|
781
|
+
) ? TOML__namespace.parse(fs__default.default.readFileSync(client.configPath, "utf8")) : {};
|
|
782
|
+
const serverSection = existingConfig[client.configKey] ?? {};
|
|
783
|
+
serverSection[SERVER_NAME] = client.serverConfig;
|
|
784
|
+
existingConfig[client.configKey] = serverSection;
|
|
785
|
+
fs__default.default.writeFileSync(client.configPath, TOML__namespace.stringify(existingConfig));
|
|
827
786
|
};
|
|
828
787
|
var getMcpClientNames = () => getClients().map((client) => client.name);
|
|
829
788
|
var installMcpServers = (selectedClients) => {
|
|
@@ -854,8 +813,7 @@ var installMcpServers = (selectedClients) => {
|
|
|
854
813
|
}
|
|
855
814
|
}
|
|
856
815
|
const successCount = results.filter((result) => result.success).length;
|
|
857
|
-
|
|
858
|
-
if (failedCount > 0) {
|
|
816
|
+
if (successCount < results.length) {
|
|
859
817
|
installSpinner.warn(
|
|
860
818
|
`Installed to ${successCount}/${results.length} agents.`
|
|
861
819
|
);
|
|
@@ -925,7 +883,8 @@ var AGENTS = [
|
|
|
925
883
|
"gemini",
|
|
926
884
|
"amp",
|
|
927
885
|
"ami",
|
|
928
|
-
"droid"
|
|
886
|
+
"droid",
|
|
887
|
+
"copilot"
|
|
929
888
|
];
|
|
930
889
|
var AGENT_NAMES = {
|
|
931
890
|
"claude-code": "Claude Code",
|
|
@@ -935,7 +894,8 @@ var AGENT_NAMES = {
|
|
|
935
894
|
gemini: "Gemini",
|
|
936
895
|
amp: "Amp",
|
|
937
896
|
ami: "Ami",
|
|
938
|
-
droid: "Droid"
|
|
897
|
+
droid: "Droid",
|
|
898
|
+
copilot: "Copilot"
|
|
939
899
|
};
|
|
940
900
|
var getAgentDisplayName = (agent) => {
|
|
941
901
|
if (agent === "mcp") return "MCP";
|
|
@@ -1670,7 +1630,9 @@ var AGENT_PACKAGES2 = {
|
|
|
1670
1630
|
opencode: "@react-grab/opencode@latest",
|
|
1671
1631
|
codex: "@react-grab/codex@latest",
|
|
1672
1632
|
gemini: "@react-grab/gemini@latest",
|
|
1673
|
-
amp: "@react-grab/amp@latest"
|
|
1633
|
+
amp: "@react-grab/amp@latest",
|
|
1634
|
+
droid: "@react-grab/droid@latest",
|
|
1635
|
+
copilot: "@react-grab/copilot@latest"
|
|
1674
1636
|
};
|
|
1675
1637
|
var getAgentPrefix = (agent, packageManager) => {
|
|
1676
1638
|
const agentPackage = AGENT_PACKAGES2[agent];
|
|
@@ -2266,7 +2228,7 @@ var previewCdnTransform = (projectRoot, framework, nextRouterType, targetCdnDoma
|
|
|
2266
2228
|
};
|
|
2267
2229
|
|
|
2268
2230
|
// src/commands/add.ts
|
|
2269
|
-
var VERSION = "0.1.
|
|
2231
|
+
var VERSION = "0.1.17";
|
|
2270
2232
|
var formatInstalledAgentNames = (agents) => agents.map((agent) => AGENT_NAMES[agent] || agent).join(", ");
|
|
2271
2233
|
var add = new commander.Command().name("add").alias("install").description("connect React Grab to your agent").argument("[agent]", `agent to connect (${AGENTS.join(", ")}, mcp)`).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
2272
2234
|
"-c, --cwd <cwd>",
|
|
@@ -2627,7 +2589,7 @@ var MAX_KEY_HOLD_DURATION_MS = 2e3;
|
|
|
2627
2589
|
var MAX_CONTEXT_LINES = 50;
|
|
2628
2590
|
|
|
2629
2591
|
// src/commands/configure.ts
|
|
2630
|
-
var VERSION2 = "0.1.
|
|
2592
|
+
var VERSION2 = "0.1.17";
|
|
2631
2593
|
var isMac = process.platform === "darwin";
|
|
2632
2594
|
var META_LABEL = isMac ? "Cmd" : "Win";
|
|
2633
2595
|
var ALT_LABEL = isMac ? "Option" : "Alt";
|
|
@@ -3183,7 +3145,7 @@ var uninstallPackagesWithFeedback = (packages, packageManager, projectRoot) => {
|
|
|
3183
3145
|
};
|
|
3184
3146
|
|
|
3185
3147
|
// src/commands/init.ts
|
|
3186
|
-
var VERSION3 = "0.1.
|
|
3148
|
+
var VERSION3 = "0.1.17";
|
|
3187
3149
|
var REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
3188
3150
|
var DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
3189
3151
|
var reportToCli = (type, config, error) => {
|
|
@@ -4041,7 +4003,7 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
4041
4003
|
reportToCli("error", void 0, error);
|
|
4042
4004
|
}
|
|
4043
4005
|
});
|
|
4044
|
-
var VERSION4 = "0.1.
|
|
4006
|
+
var VERSION4 = "0.1.17";
|
|
4045
4007
|
var remove = new commander.Command().name("remove").description("disconnect React Grab from your agent").argument("[agent]", `agent to disconnect (${AGENTS.join(", ")}, mcp)`).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
4046
4008
|
"-c, --cwd <cwd>",
|
|
4047
4009
|
"working directory (defaults to current directory)",
|
|
@@ -4217,7 +4179,7 @@ var remove = new commander.Command().name("remove").description("disconnect Reac
|
|
|
4217
4179
|
});
|
|
4218
4180
|
|
|
4219
4181
|
// src/cli.ts
|
|
4220
|
-
var VERSION5 = "0.1.
|
|
4182
|
+
var VERSION5 = "0.1.17";
|
|
4221
4183
|
var VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
4222
4184
|
process.on("SIGINT", () => process.exit(0));
|
|
4223
4185
|
process.on("SIGTERM", () => process.exit(0));
|
package/dist/cli.js
CHANGED
|
@@ -9,17 +9,22 @@ import { detect } from '@antfu/ni';
|
|
|
9
9
|
import ignore from 'ignore';
|
|
10
10
|
import os from 'os';
|
|
11
11
|
import process2 from 'process';
|
|
12
|
+
import * as jsonc from 'jsonc-parser';
|
|
13
|
+
import * as TOML from 'smol-toml';
|
|
12
14
|
import ora from 'ora';
|
|
13
15
|
|
|
14
16
|
// src/utils/is-non-interactive.ts
|
|
15
|
-
var
|
|
17
|
+
var AGENT_ENVIRONMENT_VARIABLES = [
|
|
16
18
|
"CI",
|
|
17
19
|
"CLAUDECODE",
|
|
20
|
+
"CURSOR_AGENT",
|
|
21
|
+
"CODEX_CI",
|
|
22
|
+
"OPENCODE",
|
|
23
|
+
"AMP_HOME",
|
|
18
24
|
"AMI"
|
|
19
25
|
];
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
) || !process.stdin.isTTY;
|
|
26
|
+
var isEnvironmentVariableSet = (variable) => Boolean(process.env[variable]);
|
|
27
|
+
var detectNonInteractive = (yesFlag) => yesFlag || AGENT_ENVIRONMENT_VARIABLES.some(isEnvironmentVariableSet) || !process.stdin.isTTY;
|
|
23
28
|
var highlighter = {
|
|
24
29
|
error: pc.red,
|
|
25
30
|
warn: pc.yellow,
|
|
@@ -377,6 +382,8 @@ var AGENT_PACKAGES = [
|
|
|
377
382
|
"@react-grab/gemini",
|
|
378
383
|
"@react-grab/amp",
|
|
379
384
|
"@react-grab/ami",
|
|
385
|
+
"@react-grab/droid",
|
|
386
|
+
"@react-grab/copilot",
|
|
380
387
|
"@react-grab/mcp"
|
|
381
388
|
];
|
|
382
389
|
var detectUnsupportedFramework = (projectRoot) => {
|
|
@@ -611,6 +618,7 @@ var spinner = (text, options) => ora({ text, isSilent: options?.silent });
|
|
|
611
618
|
// src/utils/install-mcp.ts
|
|
612
619
|
var SERVER_NAME = "react-grab-mcp";
|
|
613
620
|
var PACKAGE_NAME = "@react-grab/mcp";
|
|
621
|
+
var getXdgConfigHome = () => process2.env.XDG_CONFIG_HOME || path.join(os.homedir(), ".config");
|
|
614
622
|
var getBaseDir = () => {
|
|
615
623
|
const homeDir = os.homedir();
|
|
616
624
|
if (process2.platform === "win32") {
|
|
@@ -619,15 +627,13 @@ var getBaseDir = () => {
|
|
|
619
627
|
if (process2.platform === "darwin") {
|
|
620
628
|
return path.join(homeDir, "Library", "Application Support");
|
|
621
629
|
}
|
|
622
|
-
return
|
|
630
|
+
return getXdgConfigHome();
|
|
623
631
|
};
|
|
624
632
|
var getZedConfigPath = () => {
|
|
625
|
-
const homeDir = os.homedir();
|
|
626
633
|
if (process2.platform === "win32") {
|
|
627
|
-
|
|
628
|
-
return path.join(appData, "Zed", "settings.json");
|
|
634
|
+
return path.join(getBaseDir(), "Zed", "settings.json");
|
|
629
635
|
}
|
|
630
|
-
return path.join(
|
|
636
|
+
return path.join(os.homedir(), ".config", "zed", "settings.json");
|
|
631
637
|
};
|
|
632
638
|
var getClients = () => {
|
|
633
639
|
const homeDir = os.homedir();
|
|
@@ -637,6 +643,23 @@ var getClients = () => {
|
|
|
637
643
|
args: ["-y", PACKAGE_NAME, "--stdio"]
|
|
638
644
|
};
|
|
639
645
|
return [
|
|
646
|
+
{
|
|
647
|
+
name: "Claude Code",
|
|
648
|
+
configPath: path.join(homeDir, ".claude.json"),
|
|
649
|
+
configKey: "mcpServers",
|
|
650
|
+
format: "json",
|
|
651
|
+
serverConfig: stdioConfig
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
name: "Codex",
|
|
655
|
+
configPath: path.join(
|
|
656
|
+
process2.env.CODEX_HOME || path.join(homeDir, ".codex"),
|
|
657
|
+
"config.toml"
|
|
658
|
+
),
|
|
659
|
+
configKey: "mcp_servers",
|
|
660
|
+
format: "toml",
|
|
661
|
+
serverConfig: stdioConfig
|
|
662
|
+
},
|
|
640
663
|
{
|
|
641
664
|
name: "Cursor",
|
|
642
665
|
configPath: path.join(homeDir, ".cursor", "mcp.json"),
|
|
@@ -644,6 +667,16 @@ var getClients = () => {
|
|
|
644
667
|
format: "json",
|
|
645
668
|
serverConfig: stdioConfig
|
|
646
669
|
},
|
|
670
|
+
{
|
|
671
|
+
name: "OpenCode",
|
|
672
|
+
configPath: path.join(getXdgConfigHome(), "opencode", "opencode.json"),
|
|
673
|
+
configKey: "mcp",
|
|
674
|
+
format: "json",
|
|
675
|
+
serverConfig: {
|
|
676
|
+
type: "local",
|
|
677
|
+
command: ["npx", "-y", PACKAGE_NAME, "--stdio"]
|
|
678
|
+
}
|
|
679
|
+
},
|
|
647
680
|
{
|
|
648
681
|
name: "VS Code",
|
|
649
682
|
configPath: path.join(baseDir, "Code", "User", "mcp.json"),
|
|
@@ -651,13 +684,6 @@ var getClients = () => {
|
|
|
651
684
|
format: "json",
|
|
652
685
|
serverConfig: { type: "stdio", ...stdioConfig }
|
|
653
686
|
},
|
|
654
|
-
{
|
|
655
|
-
name: "Claude Code",
|
|
656
|
-
configPath: path.join(homeDir, ".claude.json"),
|
|
657
|
-
configKey: "mcpServers",
|
|
658
|
-
format: "json",
|
|
659
|
-
serverConfig: stdioConfig
|
|
660
|
-
},
|
|
661
687
|
{
|
|
662
688
|
name: "Amp",
|
|
663
689
|
configPath: path.join(homeDir, ".config", "amp", "settings.json"),
|
|
@@ -673,13 +699,10 @@ var getClients = () => {
|
|
|
673
699
|
serverConfig: { type: "stdio", ...stdioConfig }
|
|
674
700
|
},
|
|
675
701
|
{
|
|
676
|
-
name: "
|
|
677
|
-
configPath: path.join(
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
),
|
|
681
|
-
configKey: "mcp_servers",
|
|
682
|
-
format: "toml",
|
|
702
|
+
name: "Windsurf",
|
|
703
|
+
configPath: path.join(homeDir, ".codeium", "windsurf", "mcp_config.json"),
|
|
704
|
+
configKey: "mcpServers",
|
|
705
|
+
format: "json",
|
|
683
706
|
serverConfig: stdioConfig
|
|
684
707
|
},
|
|
685
708
|
{
|
|
@@ -688,13 +711,6 @@ var getClients = () => {
|
|
|
688
711
|
configKey: "context_servers",
|
|
689
712
|
format: "json",
|
|
690
713
|
serverConfig: { source: "custom", ...stdioConfig, env: {} }
|
|
691
|
-
},
|
|
692
|
-
{
|
|
693
|
-
name: "Windsurf",
|
|
694
|
-
configPath: path.join(homeDir, ".codeium", "windsurf", "mcp_config.json"),
|
|
695
|
-
configKey: "mcpServers",
|
|
696
|
-
format: "json",
|
|
697
|
-
serverConfig: stdioConfig
|
|
698
714
|
}
|
|
699
715
|
];
|
|
700
716
|
};
|
|
@@ -704,113 +720,36 @@ var ensureDirectory = (filePath) => {
|
|
|
704
720
|
fs.mkdirSync(directory, { recursive: true });
|
|
705
721
|
}
|
|
706
722
|
};
|
|
707
|
-
var
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
const keyMatch = keyPattern.exec(content);
|
|
717
|
-
if (keyMatch) {
|
|
718
|
-
const insertPosition = keyMatch.index + keyMatch[0].length;
|
|
719
|
-
const entry = `
|
|
720
|
-
"${serverName}": ${serverJson},`;
|
|
721
|
-
fs.writeFileSync(
|
|
722
|
-
filePath,
|
|
723
|
-
content.slice(0, insertPosition) + entry + content.slice(insertPosition)
|
|
724
|
-
);
|
|
725
|
-
return;
|
|
726
|
-
}
|
|
727
|
-
const lastBrace = content.lastIndexOf("}");
|
|
728
|
-
if (lastBrace === -1) return;
|
|
729
|
-
const beforeBrace = content.slice(0, lastBrace).trimEnd();
|
|
730
|
-
const withoutComments = beforeBrace.replace(/\/\/.*$/, "").trimEnd();
|
|
731
|
-
const lastChar = withoutComments[withoutComments.length - 1];
|
|
732
|
-
const needsComma = lastChar !== void 0 && lastChar !== "{" && lastChar !== ",";
|
|
733
|
-
const section = `${needsComma ? "," : ""}
|
|
734
|
-
"${configKey}": {
|
|
735
|
-
"${serverName}": ${serverJson}
|
|
736
|
-
}`;
|
|
737
|
-
fs.writeFileSync(filePath, beforeBrace + section + "\n}\n");
|
|
723
|
+
var JSONC_FORMAT_OPTIONS = {
|
|
724
|
+
tabSize: 2,
|
|
725
|
+
insertSpaces: true
|
|
726
|
+
};
|
|
727
|
+
var upsertIntoJsonc = (filePath, content, configKey, serverName, serverConfig) => {
|
|
728
|
+
const edits = jsonc.modify(content, [configKey, serverName], serverConfig, {
|
|
729
|
+
formattingOptions: JSONC_FORMAT_OPTIONS
|
|
730
|
+
});
|
|
731
|
+
fs.writeFileSync(filePath, jsonc.applyEdits(content, edits));
|
|
738
732
|
};
|
|
739
733
|
var installJsonClient = (client) => {
|
|
740
734
|
ensureDirectory(client.configPath);
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
try {
|
|
750
|
-
const config = JSON.parse(content);
|
|
751
|
-
const servers = config[client.configKey] ?? {};
|
|
752
|
-
servers[SERVER_NAME] = client.serverConfig;
|
|
753
|
-
config[client.configKey] = servers;
|
|
754
|
-
fs.writeFileSync(client.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
755
|
-
} catch {
|
|
756
|
-
insertIntoJsonc(
|
|
757
|
-
client.configPath,
|
|
758
|
-
content,
|
|
759
|
-
client.configKey,
|
|
760
|
-
SERVER_NAME,
|
|
761
|
-
client.serverConfig
|
|
762
|
-
);
|
|
763
|
-
}
|
|
764
|
-
};
|
|
765
|
-
var buildTomlSection = (configKey, serverConfig) => {
|
|
766
|
-
const lines = [`[${configKey}.${SERVER_NAME}]`];
|
|
767
|
-
for (const [key, value] of Object.entries(serverConfig)) {
|
|
768
|
-
if (typeof value === "string") {
|
|
769
|
-
lines.push(`${key} = "${value}"`);
|
|
770
|
-
} else if (Array.isArray(value)) {
|
|
771
|
-
const items = value.map((item) => `"${item}"`).join(", ");
|
|
772
|
-
lines.push(`${key} = [${items}]`);
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
return lines.join("\n");
|
|
735
|
+
const content = fs.existsSync(client.configPath) ? fs.readFileSync(client.configPath, "utf8") : "{}";
|
|
736
|
+
upsertIntoJsonc(
|
|
737
|
+
client.configPath,
|
|
738
|
+
content,
|
|
739
|
+
client.configKey,
|
|
740
|
+
SERVER_NAME,
|
|
741
|
+
client.serverConfig
|
|
742
|
+
);
|
|
776
743
|
};
|
|
777
744
|
var installTomlClient = (client) => {
|
|
778
745
|
ensureDirectory(client.configPath);
|
|
779
|
-
const
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
if (!content.includes(sectionHeader)) {
|
|
787
|
-
fs.writeFileSync(
|
|
788
|
-
client.configPath,
|
|
789
|
-
content.trimEnd() + "\n\n" + newSection + "\n"
|
|
790
|
-
);
|
|
791
|
-
return;
|
|
792
|
-
}
|
|
793
|
-
const lines = content.split("\n");
|
|
794
|
-
const resultLines = [];
|
|
795
|
-
let isInsideOurSection = false;
|
|
796
|
-
let didInsertReplacement = false;
|
|
797
|
-
for (const line of lines) {
|
|
798
|
-
if (line.trim() === sectionHeader) {
|
|
799
|
-
isInsideOurSection = true;
|
|
800
|
-
if (!didInsertReplacement) {
|
|
801
|
-
resultLines.push(newSection);
|
|
802
|
-
didInsertReplacement = true;
|
|
803
|
-
}
|
|
804
|
-
continue;
|
|
805
|
-
}
|
|
806
|
-
if (isInsideOurSection && line.startsWith("[")) {
|
|
807
|
-
isInsideOurSection = false;
|
|
808
|
-
}
|
|
809
|
-
if (!isInsideOurSection) {
|
|
810
|
-
resultLines.push(line);
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
fs.writeFileSync(client.configPath, resultLines.join("\n"));
|
|
746
|
+
const existingConfig = fs.existsSync(
|
|
747
|
+
client.configPath
|
|
748
|
+
) ? TOML.parse(fs.readFileSync(client.configPath, "utf8")) : {};
|
|
749
|
+
const serverSection = existingConfig[client.configKey] ?? {};
|
|
750
|
+
serverSection[SERVER_NAME] = client.serverConfig;
|
|
751
|
+
existingConfig[client.configKey] = serverSection;
|
|
752
|
+
fs.writeFileSync(client.configPath, TOML.stringify(existingConfig));
|
|
814
753
|
};
|
|
815
754
|
var getMcpClientNames = () => getClients().map((client) => client.name);
|
|
816
755
|
var installMcpServers = (selectedClients) => {
|
|
@@ -841,8 +780,7 @@ var installMcpServers = (selectedClients) => {
|
|
|
841
780
|
}
|
|
842
781
|
}
|
|
843
782
|
const successCount = results.filter((result) => result.success).length;
|
|
844
|
-
|
|
845
|
-
if (failedCount > 0) {
|
|
783
|
+
if (successCount < results.length) {
|
|
846
784
|
installSpinner.warn(
|
|
847
785
|
`Installed to ${successCount}/${results.length} agents.`
|
|
848
786
|
);
|
|
@@ -912,7 +850,8 @@ var AGENTS = [
|
|
|
912
850
|
"gemini",
|
|
913
851
|
"amp",
|
|
914
852
|
"ami",
|
|
915
|
-
"droid"
|
|
853
|
+
"droid",
|
|
854
|
+
"copilot"
|
|
916
855
|
];
|
|
917
856
|
var AGENT_NAMES = {
|
|
918
857
|
"claude-code": "Claude Code",
|
|
@@ -922,7 +861,8 @@ var AGENT_NAMES = {
|
|
|
922
861
|
gemini: "Gemini",
|
|
923
862
|
amp: "Amp",
|
|
924
863
|
ami: "Ami",
|
|
925
|
-
droid: "Droid"
|
|
864
|
+
droid: "Droid",
|
|
865
|
+
copilot: "Copilot"
|
|
926
866
|
};
|
|
927
867
|
var getAgentDisplayName = (agent) => {
|
|
928
868
|
if (agent === "mcp") return "MCP";
|
|
@@ -1657,7 +1597,9 @@ var AGENT_PACKAGES2 = {
|
|
|
1657
1597
|
opencode: "@react-grab/opencode@latest",
|
|
1658
1598
|
codex: "@react-grab/codex@latest",
|
|
1659
1599
|
gemini: "@react-grab/gemini@latest",
|
|
1660
|
-
amp: "@react-grab/amp@latest"
|
|
1600
|
+
amp: "@react-grab/amp@latest",
|
|
1601
|
+
droid: "@react-grab/droid@latest",
|
|
1602
|
+
copilot: "@react-grab/copilot@latest"
|
|
1661
1603
|
};
|
|
1662
1604
|
var getAgentPrefix = (agent, packageManager) => {
|
|
1663
1605
|
const agentPackage = AGENT_PACKAGES2[agent];
|
|
@@ -2253,7 +2195,7 @@ var previewCdnTransform = (projectRoot, framework, nextRouterType, targetCdnDoma
|
|
|
2253
2195
|
};
|
|
2254
2196
|
|
|
2255
2197
|
// src/commands/add.ts
|
|
2256
|
-
var VERSION = "0.1.
|
|
2198
|
+
var VERSION = "0.1.17";
|
|
2257
2199
|
var formatInstalledAgentNames = (agents) => agents.map((agent) => AGENT_NAMES[agent] || agent).join(", ");
|
|
2258
2200
|
var add = new Command().name("add").alias("install").description("connect React Grab to your agent").argument("[agent]", `agent to connect (${AGENTS.join(", ")}, mcp)`).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
2259
2201
|
"-c, --cwd <cwd>",
|
|
@@ -2614,7 +2556,7 @@ var MAX_KEY_HOLD_DURATION_MS = 2e3;
|
|
|
2614
2556
|
var MAX_CONTEXT_LINES = 50;
|
|
2615
2557
|
|
|
2616
2558
|
// src/commands/configure.ts
|
|
2617
|
-
var VERSION2 = "0.1.
|
|
2559
|
+
var VERSION2 = "0.1.17";
|
|
2618
2560
|
var isMac = process.platform === "darwin";
|
|
2619
2561
|
var META_LABEL = isMac ? "Cmd" : "Win";
|
|
2620
2562
|
var ALT_LABEL = isMac ? "Option" : "Alt";
|
|
@@ -3170,7 +3112,7 @@ var uninstallPackagesWithFeedback = (packages, packageManager, projectRoot) => {
|
|
|
3170
3112
|
};
|
|
3171
3113
|
|
|
3172
3114
|
// src/commands/init.ts
|
|
3173
|
-
var VERSION3 = "0.1.
|
|
3115
|
+
var VERSION3 = "0.1.17";
|
|
3174
3116
|
var REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
3175
3117
|
var DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
3176
3118
|
var reportToCli = (type, config, error) => {
|
|
@@ -4028,7 +3970,7 @@ var init = new Command().name("init").description("initialize React Grab in your
|
|
|
4028
3970
|
reportToCli("error", void 0, error);
|
|
4029
3971
|
}
|
|
4030
3972
|
});
|
|
4031
|
-
var VERSION4 = "0.1.
|
|
3973
|
+
var VERSION4 = "0.1.17";
|
|
4032
3974
|
var remove = new Command().name("remove").description("disconnect React Grab from your agent").argument("[agent]", `agent to disconnect (${AGENTS.join(", ")}, mcp)`).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
4033
3975
|
"-c, --cwd <cwd>",
|
|
4034
3976
|
"working directory (defaults to current directory)",
|
|
@@ -4204,7 +4146,7 @@ var remove = new Command().name("remove").description("disconnect React Grab fro
|
|
|
4204
4146
|
});
|
|
4205
4147
|
|
|
4206
4148
|
// src/cli.ts
|
|
4207
|
-
var VERSION5 = "0.1.
|
|
4149
|
+
var VERSION5 = "0.1.17";
|
|
4208
4150
|
var VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
4209
4151
|
process.on("SIGINT", () => process.exit(0));
|
|
4210
4152
|
process.on("SIGTERM", () => process.exit(0));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-grab/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"bin": {
|
|
5
5
|
"react-grab": "./dist/cli.js"
|
|
6
6
|
},
|
|
@@ -19,9 +19,11 @@
|
|
|
19
19
|
"@antfu/ni": "^0.23.0",
|
|
20
20
|
"commander": "^14.0.0",
|
|
21
21
|
"ignore": "^7.0.5",
|
|
22
|
+
"jsonc-parser": "^3.3.1",
|
|
22
23
|
"ora": "^8.2.0",
|
|
23
24
|
"picocolors": "^1.1.1",
|
|
24
|
-
"prompts": "^2.4.2"
|
|
25
|
+
"prompts": "^2.4.2",
|
|
26
|
+
"smol-toml": "^1.6.0"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
27
29
|
"@types/prompts": "^2.4.9",
|