@react-grab/cli 0.1.13 → 0.1.15
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 +196 -94
- package/dist/cli.js +197 -96
- package/package.json +2 -1
package/dist/cli.cjs
CHANGED
|
@@ -8,6 +8,7 @@ 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 ignore = require('ignore');
|
|
11
12
|
var os = require('os');
|
|
12
13
|
var process2 = require('process');
|
|
13
14
|
var ora = require('ora');
|
|
@@ -18,10 +19,20 @@ var pc__default = /*#__PURE__*/_interopDefault(pc);
|
|
|
18
19
|
var basePrompts__default = /*#__PURE__*/_interopDefault(basePrompts);
|
|
19
20
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
20
21
|
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
22
|
+
var ignore__default = /*#__PURE__*/_interopDefault(ignore);
|
|
21
23
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
22
24
|
var process2__default = /*#__PURE__*/_interopDefault(process2);
|
|
23
25
|
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
24
26
|
|
|
27
|
+
// src/utils/is-non-interactive.ts
|
|
28
|
+
var NON_INTERACTIVE_ENVIRONMENT_VARIABLES = [
|
|
29
|
+
"CI",
|
|
30
|
+
"CLAUDECODE",
|
|
31
|
+
"AMI"
|
|
32
|
+
];
|
|
33
|
+
var detectNonInteractive = (yesFlag) => yesFlag || NON_INTERACTIVE_ENVIRONMENT_VARIABLES.some(
|
|
34
|
+
(variable) => process.env[variable] === "true"
|
|
35
|
+
) || !process.stdin.isTTY;
|
|
25
36
|
var highlighter = {
|
|
26
37
|
error: pc__default.default.red,
|
|
27
38
|
warn: pc__default.default.yellow,
|
|
@@ -65,10 +76,19 @@ var onCancel = () => {
|
|
|
65
76
|
var prompts = (questions) => {
|
|
66
77
|
return basePrompts__default.default(questions, { onCancel });
|
|
67
78
|
};
|
|
79
|
+
var VALID_PACKAGE_MANAGERS = /* @__PURE__ */ new Set([
|
|
80
|
+
"npm",
|
|
81
|
+
"yarn",
|
|
82
|
+
"pnpm",
|
|
83
|
+
"bun"
|
|
84
|
+
]);
|
|
68
85
|
var detectPackageManager = async (projectRoot) => {
|
|
69
86
|
const detected = await ni.detect({ cwd: projectRoot });
|
|
70
|
-
if (detected
|
|
71
|
-
|
|
87
|
+
if (detected) {
|
|
88
|
+
const managerName = detected.split("@")[0];
|
|
89
|
+
if (VALID_PACKAGE_MANAGERS.has(managerName)) {
|
|
90
|
+
return managerName;
|
|
91
|
+
}
|
|
72
92
|
}
|
|
73
93
|
return "npm";
|
|
74
94
|
};
|
|
@@ -182,18 +202,22 @@ var getWorkspacePatterns = (projectRoot) => {
|
|
|
182
202
|
return [...new Set(patterns)];
|
|
183
203
|
};
|
|
184
204
|
var expandWorkspacePattern = (projectRoot, pattern) => {
|
|
185
|
-
const
|
|
205
|
+
const isGlob = pattern.endsWith("/*");
|
|
186
206
|
const cleanPattern = pattern.replace(/\/\*$/, "");
|
|
187
207
|
const basePath = path.join(projectRoot, cleanPattern);
|
|
188
|
-
if (!fs.existsSync(basePath)) return
|
|
208
|
+
if (!fs.existsSync(basePath)) return [];
|
|
209
|
+
if (!isGlob) {
|
|
210
|
+
const hasPackageJson = fs.existsSync(path.join(basePath, "package.json"));
|
|
211
|
+
return hasPackageJson ? [basePath] : [];
|
|
212
|
+
}
|
|
213
|
+
const results = [];
|
|
189
214
|
try {
|
|
190
215
|
const entries = fs.readdirSync(basePath, { withFileTypes: true });
|
|
191
216
|
for (const entry of entries) {
|
|
192
|
-
if (entry.isDirectory())
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
217
|
+
if (!entry.isDirectory()) continue;
|
|
218
|
+
const packageJsonPath = path.join(basePath, entry.name, "package.json");
|
|
219
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
220
|
+
results.push(path.join(basePath, entry.name));
|
|
197
221
|
}
|
|
198
222
|
}
|
|
199
223
|
} catch {
|
|
@@ -215,35 +239,92 @@ var hasReactDependency = (projectPath) => {
|
|
|
215
239
|
return false;
|
|
216
240
|
}
|
|
217
241
|
};
|
|
242
|
+
var buildReactProject = (projectPath) => {
|
|
243
|
+
const framework = detectFramework(projectPath);
|
|
244
|
+
const hasReact = hasReactDependency(projectPath);
|
|
245
|
+
if (!hasReact && framework === "unknown") return null;
|
|
246
|
+
let name = path.basename(projectPath);
|
|
247
|
+
const packageJsonPath = path.join(projectPath, "package.json");
|
|
248
|
+
try {
|
|
249
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
250
|
+
name = packageJson.name || name;
|
|
251
|
+
} catch {
|
|
252
|
+
}
|
|
253
|
+
return { name, path: projectPath, framework, hasReact };
|
|
254
|
+
};
|
|
218
255
|
var findWorkspaceProjects = (projectRoot) => {
|
|
219
256
|
const patterns = getWorkspacePatterns(projectRoot);
|
|
220
257
|
const projects = [];
|
|
221
258
|
for (const pattern of patterns) {
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
259
|
+
for (const projectPath of expandWorkspacePattern(projectRoot, pattern)) {
|
|
260
|
+
const project = buildReactProject(projectPath);
|
|
261
|
+
if (project) projects.push(project);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return projects;
|
|
265
|
+
};
|
|
266
|
+
var ALWAYS_IGNORED_DIRECTORIES = [
|
|
267
|
+
"node_modules",
|
|
268
|
+
".git",
|
|
269
|
+
".next",
|
|
270
|
+
".cache",
|
|
271
|
+
".turbo",
|
|
272
|
+
"dist",
|
|
273
|
+
"build",
|
|
274
|
+
"coverage",
|
|
275
|
+
"test-results"
|
|
276
|
+
];
|
|
277
|
+
var loadGitignore = (projectRoot) => {
|
|
278
|
+
const ignorer = ignore__default.default().add(ALWAYS_IGNORED_DIRECTORIES);
|
|
279
|
+
const gitignorePath = path.join(projectRoot, ".gitignore");
|
|
280
|
+
if (fs.existsSync(gitignorePath)) {
|
|
281
|
+
try {
|
|
282
|
+
ignorer.add(fs.readFileSync(gitignorePath, "utf-8"));
|
|
283
|
+
} catch {
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return ignorer;
|
|
287
|
+
};
|
|
288
|
+
var scanDirectoryForProjects = (rootDirectory, ignorer, maxDepth, currentDepth = 0) => {
|
|
289
|
+
if (currentDepth >= maxDepth) return [];
|
|
290
|
+
if (!fs.existsSync(rootDirectory)) return [];
|
|
291
|
+
const projects = [];
|
|
292
|
+
try {
|
|
293
|
+
const entries = fs.readdirSync(rootDirectory, { withFileTypes: true });
|
|
294
|
+
for (const entry of entries) {
|
|
295
|
+
if (!entry.isDirectory()) continue;
|
|
296
|
+
if (ignorer.ignores(entry.name)) continue;
|
|
297
|
+
const entryPath = path.join(rootDirectory, entry.name);
|
|
298
|
+
const hasPackageJson = fs.existsSync(path.join(entryPath, "package.json"));
|
|
299
|
+
if (hasPackageJson) {
|
|
300
|
+
const project = buildReactProject(entryPath);
|
|
301
|
+
if (project) {
|
|
302
|
+
projects.push(project);
|
|
303
|
+
continue;
|
|
235
304
|
}
|
|
236
|
-
projects.push({
|
|
237
|
-
name,
|
|
238
|
-
path: projectPath,
|
|
239
|
-
framework,
|
|
240
|
-
hasReact
|
|
241
|
-
});
|
|
242
305
|
}
|
|
306
|
+
projects.push(
|
|
307
|
+
...scanDirectoryForProjects(
|
|
308
|
+
entryPath,
|
|
309
|
+
ignorer,
|
|
310
|
+
maxDepth,
|
|
311
|
+
currentDepth + 1
|
|
312
|
+
)
|
|
313
|
+
);
|
|
243
314
|
}
|
|
315
|
+
} catch {
|
|
316
|
+
return projects;
|
|
244
317
|
}
|
|
245
318
|
return projects;
|
|
246
319
|
};
|
|
320
|
+
var MAX_SCAN_DEPTH = 2;
|
|
321
|
+
var findReactProjects = (projectRoot) => {
|
|
322
|
+
if (detectMonorepo(projectRoot)) {
|
|
323
|
+
return findWorkspaceProjects(projectRoot);
|
|
324
|
+
}
|
|
325
|
+
const ignorer = loadGitignore(projectRoot);
|
|
326
|
+
return scanDirectoryForProjects(projectRoot, ignorer, MAX_SCAN_DEPTH);
|
|
327
|
+
};
|
|
247
328
|
var hasReactGrabInFile = (filePath) => {
|
|
248
329
|
if (!fs.existsSync(filePath)) return false;
|
|
249
330
|
try {
|
|
@@ -2185,9 +2266,9 @@ var previewCdnTransform = (projectRoot, framework, nextRouterType, targetCdnDoma
|
|
|
2185
2266
|
};
|
|
2186
2267
|
|
|
2187
2268
|
// src/commands/add.ts
|
|
2188
|
-
var VERSION = "0.1.
|
|
2269
|
+
var VERSION = "0.1.15";
|
|
2189
2270
|
var formatInstalledAgentNames = (agents) => agents.map((agent) => AGENT_NAMES[agent] || agent).join(", ");
|
|
2190
|
-
var add = new commander.Command().name("add").alias("install").description("connect React Grab to your agent").argument("[agent]", `agent to
|
|
2271
|
+
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(
|
|
2191
2272
|
"-c, --cwd <cwd>",
|
|
2192
2273
|
"working directory (defaults to current directory)",
|
|
2193
2274
|
process.cwd()
|
|
@@ -2198,7 +2279,7 @@ var add = new commander.Command().name("add").alias("install").description("conn
|
|
|
2198
2279
|
console.log();
|
|
2199
2280
|
try {
|
|
2200
2281
|
const cwd = opts.cwd;
|
|
2201
|
-
const isNonInteractive = opts.yes;
|
|
2282
|
+
const isNonInteractive = detectNonInteractive(opts.yes);
|
|
2202
2283
|
const preflightSpinner = spinner("Preflight checks.").start();
|
|
2203
2284
|
const projectInfo = await detectProject(cwd);
|
|
2204
2285
|
if (!projectInfo.hasReactGrab) {
|
|
@@ -2349,7 +2430,7 @@ var add = new commander.Command().name("add").alias("install").description("conn
|
|
|
2349
2430
|
}
|
|
2350
2431
|
} else {
|
|
2351
2432
|
logger.break();
|
|
2352
|
-
logger.error("Please specify an agent to
|
|
2433
|
+
logger.error("Please specify an agent to connect.");
|
|
2353
2434
|
logger.error("Available agents: " + availableAgents.join(", "));
|
|
2354
2435
|
logger.break();
|
|
2355
2436
|
process.exit(1);
|
|
@@ -2546,7 +2627,7 @@ var MAX_KEY_HOLD_DURATION_MS = 2e3;
|
|
|
2546
2627
|
var MAX_CONTEXT_LINES = 50;
|
|
2547
2628
|
|
|
2548
2629
|
// src/commands/configure.ts
|
|
2549
|
-
var VERSION2 = "0.1.
|
|
2630
|
+
var VERSION2 = "0.1.15";
|
|
2550
2631
|
var isMac = process.platform === "darwin";
|
|
2551
2632
|
var META_LABEL = isMac ? "Cmd" : "Win";
|
|
2552
2633
|
var ALT_LABEL = isMac ? "Option" : "Alt";
|
|
@@ -3102,7 +3183,7 @@ var uninstallPackagesWithFeedback = (packages, packageManager, projectRoot) => {
|
|
|
3102
3183
|
};
|
|
3103
3184
|
|
|
3104
3185
|
// src/commands/init.ts
|
|
3105
|
-
var VERSION3 = "0.1.
|
|
3186
|
+
var VERSION3 = "0.1.15";
|
|
3106
3187
|
var REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
3107
3188
|
var DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
3108
3189
|
var reportToCli = (type, config, error) => {
|
|
@@ -3139,6 +3220,34 @@ var UNSUPPORTED_FRAMEWORK_NAMES = {
|
|
|
3139
3220
|
gatsby: "Gatsby"
|
|
3140
3221
|
};
|
|
3141
3222
|
var getAgentName = getAgentDisplayName;
|
|
3223
|
+
var sortProjectsByFramework = (projects) => [...projects].sort((projectA, projectB) => {
|
|
3224
|
+
if (projectA.framework === "unknown" && projectB.framework !== "unknown")
|
|
3225
|
+
return 1;
|
|
3226
|
+
if (projectA.framework !== "unknown" && projectB.framework === "unknown")
|
|
3227
|
+
return -1;
|
|
3228
|
+
return 0;
|
|
3229
|
+
});
|
|
3230
|
+
var printSubprojects = (searchRoot, sortedProjects) => {
|
|
3231
|
+
logger.break();
|
|
3232
|
+
logger.log("Found the following projects:");
|
|
3233
|
+
logger.break();
|
|
3234
|
+
for (const project of sortedProjects) {
|
|
3235
|
+
const frameworkLabel = project.framework !== "unknown" ? ` ${highlighter.dim(`(${FRAMEWORK_NAMES[project.framework]})`)}` : "";
|
|
3236
|
+
const relativePath = path.relative(searchRoot, project.path);
|
|
3237
|
+
logger.log(
|
|
3238
|
+
` ${highlighter.info(project.name)}${frameworkLabel} ${highlighter.dim(relativePath)}`
|
|
3239
|
+
);
|
|
3240
|
+
}
|
|
3241
|
+
logger.break();
|
|
3242
|
+
logger.log(
|
|
3243
|
+
`Re-run with ${highlighter.info("-c <path>")} to specify a project:`
|
|
3244
|
+
);
|
|
3245
|
+
logger.break();
|
|
3246
|
+
logger.log(
|
|
3247
|
+
` ${highlighter.dim("$")} npx -y grab@latest init -c ${path.relative(searchRoot, sortedProjects[0].path)}`
|
|
3248
|
+
);
|
|
3249
|
+
logger.break();
|
|
3250
|
+
};
|
|
3142
3251
|
var formatActivationKeyDisplay2 = (activationKey) => {
|
|
3143
3252
|
if (!activationKey) return "Default (Option/Alt)";
|
|
3144
3253
|
return activationKey.split("+").map((part) => {
|
|
@@ -3153,7 +3262,7 @@ var formatActivationKeyDisplay2 = (activationKey) => {
|
|
|
3153
3262
|
};
|
|
3154
3263
|
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(
|
|
3155
3264
|
"-a, --agent <agent>",
|
|
3156
|
-
|
|
3265
|
+
`connect to your agent (${AGENTS.join(", ")}, mcp)`
|
|
3157
3266
|
).option(
|
|
3158
3267
|
"-k, --key <key>",
|
|
3159
3268
|
"activation key (e.g., Meta+K, Ctrl+Shift+G, Space)"
|
|
@@ -3167,8 +3276,14 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
3167
3276
|
);
|
|
3168
3277
|
console.log();
|
|
3169
3278
|
try {
|
|
3170
|
-
const cwd = opts.cwd;
|
|
3171
|
-
const isNonInteractive = opts.yes;
|
|
3279
|
+
const cwd = path.resolve(opts.cwd);
|
|
3280
|
+
const isNonInteractive = detectNonInteractive(opts.yes);
|
|
3281
|
+
if (!fs.existsSync(cwd)) {
|
|
3282
|
+
logger.break();
|
|
3283
|
+
logger.error(`Directory does not exist: ${highlighter.info(cwd)}`);
|
|
3284
|
+
logger.break();
|
|
3285
|
+
process.exit(1);
|
|
3286
|
+
}
|
|
3172
3287
|
const preflightSpinner = spinner("Preflight checks.").start();
|
|
3173
3288
|
const projectInfo = await detectProject(cwd);
|
|
3174
3289
|
const removeAgents = async (agentsToRemove2, skipInstall = false) => {
|
|
@@ -3695,58 +3810,48 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
3695
3810
|
process.exit(1);
|
|
3696
3811
|
}
|
|
3697
3812
|
if (projectInfo.framework === "unknown") {
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
);
|
|
3703
|
-
|
|
3704
|
-
|
|
3813
|
+
let searchRoot = cwd;
|
|
3814
|
+
let reactProjects = findReactProjects(searchRoot);
|
|
3815
|
+
if (reactProjects.length === 0 && cwd !== process.cwd()) {
|
|
3816
|
+
searchRoot = process.cwd();
|
|
3817
|
+
reactProjects = findReactProjects(searchRoot);
|
|
3818
|
+
}
|
|
3819
|
+
if (reactProjects.length > 0) {
|
|
3820
|
+
frameworkSpinner.info(
|
|
3821
|
+
`Verifying framework. Found ${reactProjects.length} project${reactProjects.length === 1 ? "" : "s"}.`
|
|
3705
3822
|
);
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
(projectA, projectB) => {
|
|
3710
|
-
if (projectA.framework === "unknown" && projectB.framework !== "unknown")
|
|
3711
|
-
return 1;
|
|
3712
|
-
if (projectA.framework !== "unknown" && projectB.framework === "unknown")
|
|
3713
|
-
return -1;
|
|
3714
|
-
return 0;
|
|
3715
|
-
}
|
|
3716
|
-
);
|
|
3717
|
-
const { selectedProject } = await prompts({
|
|
3718
|
-
type: "select",
|
|
3719
|
-
name: "selectedProject",
|
|
3720
|
-
message: "Select a project to install React Grab:",
|
|
3721
|
-
choices: [
|
|
3722
|
-
...sortedProjects.map((project) => {
|
|
3723
|
-
const frameworkLabel = project.framework !== "unknown" ? ` ${highlighter.dim(`(${FRAMEWORK_NAMES[project.framework]})`)}` : "";
|
|
3724
|
-
return {
|
|
3725
|
-
title: `${project.name}${frameworkLabel}`,
|
|
3726
|
-
value: project.path
|
|
3727
|
-
};
|
|
3728
|
-
}),
|
|
3729
|
-
{ title: "Skip", value: "skip" }
|
|
3730
|
-
]
|
|
3731
|
-
});
|
|
3732
|
-
if (!selectedProject || selectedProject === "skip") {
|
|
3733
|
-
logger.break();
|
|
3734
|
-
process.exit(0);
|
|
3735
|
-
}
|
|
3736
|
-
process.chdir(selectedProject);
|
|
3737
|
-
const newProjectInfo = await detectProject(selectedProject);
|
|
3738
|
-
Object.assign(projectInfo, newProjectInfo);
|
|
3739
|
-
const newFrameworkSpinner = spinner("Verifying framework.").start();
|
|
3740
|
-
newFrameworkSpinner.succeed(
|
|
3741
|
-
`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[newProjectInfo.framework])}.`
|
|
3742
|
-
);
|
|
3743
|
-
} else {
|
|
3744
|
-
frameworkSpinner.fail("Could not detect a supported framework.");
|
|
3745
|
-
logger.break();
|
|
3746
|
-
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
3747
|
-
logger.break();
|
|
3823
|
+
const sortedProjects = sortProjectsByFramework(reactProjects);
|
|
3824
|
+
if (isNonInteractive) {
|
|
3825
|
+
printSubprojects(searchRoot, sortedProjects);
|
|
3748
3826
|
process.exit(1);
|
|
3749
3827
|
}
|
|
3828
|
+
logger.break();
|
|
3829
|
+
const { selectedProject } = await prompts({
|
|
3830
|
+
type: "select",
|
|
3831
|
+
name: "selectedProject",
|
|
3832
|
+
message: "Select a project to install React Grab:",
|
|
3833
|
+
choices: [
|
|
3834
|
+
...sortedProjects.map((project) => {
|
|
3835
|
+
const frameworkLabel = project.framework !== "unknown" ? ` ${highlighter.dim(`(${FRAMEWORK_NAMES[project.framework]})`)}` : "";
|
|
3836
|
+
return {
|
|
3837
|
+
title: `${project.name}${frameworkLabel}`,
|
|
3838
|
+
value: project.path
|
|
3839
|
+
};
|
|
3840
|
+
}),
|
|
3841
|
+
{ title: "Skip", value: "skip" }
|
|
3842
|
+
]
|
|
3843
|
+
});
|
|
3844
|
+
if (!selectedProject || selectedProject === "skip") {
|
|
3845
|
+
logger.break();
|
|
3846
|
+
process.exit(0);
|
|
3847
|
+
}
|
|
3848
|
+
process.chdir(selectedProject);
|
|
3849
|
+
const newProjectInfo = await detectProject(selectedProject);
|
|
3850
|
+
Object.assign(projectInfo, newProjectInfo);
|
|
3851
|
+
const newFrameworkSpinner = spinner("Verifying framework.").start();
|
|
3852
|
+
newFrameworkSpinner.succeed(
|
|
3853
|
+
`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[newProjectInfo.framework])}.`
|
|
3854
|
+
);
|
|
3750
3855
|
} else {
|
|
3751
3856
|
frameworkSpinner.fail("Could not detect a supported framework.");
|
|
3752
3857
|
logger.break();
|
|
@@ -3936,11 +4041,8 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
3936
4041
|
reportToCli("error", void 0, error);
|
|
3937
4042
|
}
|
|
3938
4043
|
});
|
|
3939
|
-
var VERSION4 = "0.1.
|
|
3940
|
-
var remove = new commander.Command().name("remove").description("disconnect React Grab from your agent").argument(
|
|
3941
|
-
"[agent]",
|
|
3942
|
-
"agent to remove (claude-code, cursor, opencode, codex, gemini, amp, ami, mcp)"
|
|
3943
|
-
).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
4044
|
+
var VERSION4 = "0.1.15";
|
|
4045
|
+
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(
|
|
3944
4046
|
"-c, --cwd <cwd>",
|
|
3945
4047
|
"working directory (defaults to current directory)",
|
|
3946
4048
|
process.cwd()
|
|
@@ -3951,7 +4053,7 @@ var remove = new commander.Command().name("remove").description("disconnect Reac
|
|
|
3951
4053
|
console.log();
|
|
3952
4054
|
try {
|
|
3953
4055
|
const cwd = opts.cwd;
|
|
3954
|
-
const isNonInteractive = opts.yes;
|
|
4056
|
+
const isNonInteractive = detectNonInteractive(opts.yes);
|
|
3955
4057
|
const preflightSpinner = spinner("Preflight checks.").start();
|
|
3956
4058
|
const projectInfo = await detectProject(cwd);
|
|
3957
4059
|
if (!projectInfo.hasReactGrab) {
|
|
@@ -4001,7 +4103,7 @@ var remove = new commander.Command().name("remove").description("disconnect Reac
|
|
|
4001
4103
|
agentToRemove = agent;
|
|
4002
4104
|
} else {
|
|
4003
4105
|
logger.break();
|
|
4004
|
-
logger.error("Please specify an agent to
|
|
4106
|
+
logger.error("Please specify an agent to disconnect.");
|
|
4005
4107
|
logger.error(
|
|
4006
4108
|
"Installed agents: " + projectInfo.installedAgents.join(", ")
|
|
4007
4109
|
);
|
|
@@ -4115,7 +4217,7 @@ var remove = new commander.Command().name("remove").description("disconnect Reac
|
|
|
4115
4217
|
});
|
|
4116
4218
|
|
|
4117
4219
|
// src/cli.ts
|
|
4118
|
-
var VERSION5 = "0.1.
|
|
4220
|
+
var VERSION5 = "0.1.15";
|
|
4119
4221
|
var VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
4120
4222
|
process.on("SIGINT", () => process.exit(0));
|
|
4121
4223
|
process.on("SIGTERM", () => process.exit(0));
|
package/dist/cli.js
CHANGED
|
@@ -3,13 +3,23 @@ import { Command } from 'commander';
|
|
|
3
3
|
import pc from 'picocolors';
|
|
4
4
|
import basePrompts from 'prompts';
|
|
5
5
|
import { execSync } from 'child_process';
|
|
6
|
-
import fs, {
|
|
7
|
-
import path, { join, basename } from 'path';
|
|
6
|
+
import fs, { existsSync, readFileSync, writeFileSync, accessSync, constants, readdirSync } from 'fs';
|
|
7
|
+
import path, { resolve, join, relative, basename } from 'path';
|
|
8
8
|
import { detect } from '@antfu/ni';
|
|
9
|
+
import ignore from 'ignore';
|
|
9
10
|
import os from 'os';
|
|
10
11
|
import process2 from 'process';
|
|
11
12
|
import ora from 'ora';
|
|
12
13
|
|
|
14
|
+
// src/utils/is-non-interactive.ts
|
|
15
|
+
var NON_INTERACTIVE_ENVIRONMENT_VARIABLES = [
|
|
16
|
+
"CI",
|
|
17
|
+
"CLAUDECODE",
|
|
18
|
+
"AMI"
|
|
19
|
+
];
|
|
20
|
+
var detectNonInteractive = (yesFlag) => yesFlag || NON_INTERACTIVE_ENVIRONMENT_VARIABLES.some(
|
|
21
|
+
(variable) => process.env[variable] === "true"
|
|
22
|
+
) || !process.stdin.isTTY;
|
|
13
23
|
var highlighter = {
|
|
14
24
|
error: pc.red,
|
|
15
25
|
warn: pc.yellow,
|
|
@@ -53,10 +63,19 @@ var onCancel = () => {
|
|
|
53
63
|
var prompts = (questions) => {
|
|
54
64
|
return basePrompts(questions, { onCancel });
|
|
55
65
|
};
|
|
66
|
+
var VALID_PACKAGE_MANAGERS = /* @__PURE__ */ new Set([
|
|
67
|
+
"npm",
|
|
68
|
+
"yarn",
|
|
69
|
+
"pnpm",
|
|
70
|
+
"bun"
|
|
71
|
+
]);
|
|
56
72
|
var detectPackageManager = async (projectRoot) => {
|
|
57
73
|
const detected = await detect({ cwd: projectRoot });
|
|
58
|
-
if (detected
|
|
59
|
-
|
|
74
|
+
if (detected) {
|
|
75
|
+
const managerName = detected.split("@")[0];
|
|
76
|
+
if (VALID_PACKAGE_MANAGERS.has(managerName)) {
|
|
77
|
+
return managerName;
|
|
78
|
+
}
|
|
60
79
|
}
|
|
61
80
|
return "npm";
|
|
62
81
|
};
|
|
@@ -170,18 +189,22 @@ var getWorkspacePatterns = (projectRoot) => {
|
|
|
170
189
|
return [...new Set(patterns)];
|
|
171
190
|
};
|
|
172
191
|
var expandWorkspacePattern = (projectRoot, pattern) => {
|
|
173
|
-
const
|
|
192
|
+
const isGlob = pattern.endsWith("/*");
|
|
174
193
|
const cleanPattern = pattern.replace(/\/\*$/, "");
|
|
175
194
|
const basePath = join(projectRoot, cleanPattern);
|
|
176
|
-
if (!existsSync(basePath)) return
|
|
195
|
+
if (!existsSync(basePath)) return [];
|
|
196
|
+
if (!isGlob) {
|
|
197
|
+
const hasPackageJson = existsSync(join(basePath, "package.json"));
|
|
198
|
+
return hasPackageJson ? [basePath] : [];
|
|
199
|
+
}
|
|
200
|
+
const results = [];
|
|
177
201
|
try {
|
|
178
202
|
const entries = readdirSync(basePath, { withFileTypes: true });
|
|
179
203
|
for (const entry of entries) {
|
|
180
|
-
if (entry.isDirectory())
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
204
|
+
if (!entry.isDirectory()) continue;
|
|
205
|
+
const packageJsonPath = join(basePath, entry.name, "package.json");
|
|
206
|
+
if (existsSync(packageJsonPath)) {
|
|
207
|
+
results.push(join(basePath, entry.name));
|
|
185
208
|
}
|
|
186
209
|
}
|
|
187
210
|
} catch {
|
|
@@ -203,35 +226,92 @@ var hasReactDependency = (projectPath) => {
|
|
|
203
226
|
return false;
|
|
204
227
|
}
|
|
205
228
|
};
|
|
229
|
+
var buildReactProject = (projectPath) => {
|
|
230
|
+
const framework = detectFramework(projectPath);
|
|
231
|
+
const hasReact = hasReactDependency(projectPath);
|
|
232
|
+
if (!hasReact && framework === "unknown") return null;
|
|
233
|
+
let name = basename(projectPath);
|
|
234
|
+
const packageJsonPath = join(projectPath, "package.json");
|
|
235
|
+
try {
|
|
236
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
237
|
+
name = packageJson.name || name;
|
|
238
|
+
} catch {
|
|
239
|
+
}
|
|
240
|
+
return { name, path: projectPath, framework, hasReact };
|
|
241
|
+
};
|
|
206
242
|
var findWorkspaceProjects = (projectRoot) => {
|
|
207
243
|
const patterns = getWorkspacePatterns(projectRoot);
|
|
208
244
|
const projects = [];
|
|
209
245
|
for (const pattern of patterns) {
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
246
|
+
for (const projectPath of expandWorkspacePattern(projectRoot, pattern)) {
|
|
247
|
+
const project = buildReactProject(projectPath);
|
|
248
|
+
if (project) projects.push(project);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return projects;
|
|
252
|
+
};
|
|
253
|
+
var ALWAYS_IGNORED_DIRECTORIES = [
|
|
254
|
+
"node_modules",
|
|
255
|
+
".git",
|
|
256
|
+
".next",
|
|
257
|
+
".cache",
|
|
258
|
+
".turbo",
|
|
259
|
+
"dist",
|
|
260
|
+
"build",
|
|
261
|
+
"coverage",
|
|
262
|
+
"test-results"
|
|
263
|
+
];
|
|
264
|
+
var loadGitignore = (projectRoot) => {
|
|
265
|
+
const ignorer = ignore().add(ALWAYS_IGNORED_DIRECTORIES);
|
|
266
|
+
const gitignorePath = join(projectRoot, ".gitignore");
|
|
267
|
+
if (existsSync(gitignorePath)) {
|
|
268
|
+
try {
|
|
269
|
+
ignorer.add(readFileSync(gitignorePath, "utf-8"));
|
|
270
|
+
} catch {
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return ignorer;
|
|
274
|
+
};
|
|
275
|
+
var scanDirectoryForProjects = (rootDirectory, ignorer, maxDepth, currentDepth = 0) => {
|
|
276
|
+
if (currentDepth >= maxDepth) return [];
|
|
277
|
+
if (!existsSync(rootDirectory)) return [];
|
|
278
|
+
const projects = [];
|
|
279
|
+
try {
|
|
280
|
+
const entries = readdirSync(rootDirectory, { withFileTypes: true });
|
|
281
|
+
for (const entry of entries) {
|
|
282
|
+
if (!entry.isDirectory()) continue;
|
|
283
|
+
if (ignorer.ignores(entry.name)) continue;
|
|
284
|
+
const entryPath = join(rootDirectory, entry.name);
|
|
285
|
+
const hasPackageJson = existsSync(join(entryPath, "package.json"));
|
|
286
|
+
if (hasPackageJson) {
|
|
287
|
+
const project = buildReactProject(entryPath);
|
|
288
|
+
if (project) {
|
|
289
|
+
projects.push(project);
|
|
290
|
+
continue;
|
|
223
291
|
}
|
|
224
|
-
projects.push({
|
|
225
|
-
name,
|
|
226
|
-
path: projectPath,
|
|
227
|
-
framework,
|
|
228
|
-
hasReact
|
|
229
|
-
});
|
|
230
292
|
}
|
|
293
|
+
projects.push(
|
|
294
|
+
...scanDirectoryForProjects(
|
|
295
|
+
entryPath,
|
|
296
|
+
ignorer,
|
|
297
|
+
maxDepth,
|
|
298
|
+
currentDepth + 1
|
|
299
|
+
)
|
|
300
|
+
);
|
|
231
301
|
}
|
|
302
|
+
} catch {
|
|
303
|
+
return projects;
|
|
232
304
|
}
|
|
233
305
|
return projects;
|
|
234
306
|
};
|
|
307
|
+
var MAX_SCAN_DEPTH = 2;
|
|
308
|
+
var findReactProjects = (projectRoot) => {
|
|
309
|
+
if (detectMonorepo(projectRoot)) {
|
|
310
|
+
return findWorkspaceProjects(projectRoot);
|
|
311
|
+
}
|
|
312
|
+
const ignorer = loadGitignore(projectRoot);
|
|
313
|
+
return scanDirectoryForProjects(projectRoot, ignorer, MAX_SCAN_DEPTH);
|
|
314
|
+
};
|
|
235
315
|
var hasReactGrabInFile = (filePath) => {
|
|
236
316
|
if (!existsSync(filePath)) return false;
|
|
237
317
|
try {
|
|
@@ -2173,9 +2253,9 @@ var previewCdnTransform = (projectRoot, framework, nextRouterType, targetCdnDoma
|
|
|
2173
2253
|
};
|
|
2174
2254
|
|
|
2175
2255
|
// src/commands/add.ts
|
|
2176
|
-
var VERSION = "0.1.
|
|
2256
|
+
var VERSION = "0.1.15";
|
|
2177
2257
|
var formatInstalledAgentNames = (agents) => agents.map((agent) => AGENT_NAMES[agent] || agent).join(", ");
|
|
2178
|
-
var add = new Command().name("add").alias("install").description("connect React Grab to your agent").argument("[agent]", `agent to
|
|
2258
|
+
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(
|
|
2179
2259
|
"-c, --cwd <cwd>",
|
|
2180
2260
|
"working directory (defaults to current directory)",
|
|
2181
2261
|
process.cwd()
|
|
@@ -2186,7 +2266,7 @@ var add = new Command().name("add").alias("install").description("connect React
|
|
|
2186
2266
|
console.log();
|
|
2187
2267
|
try {
|
|
2188
2268
|
const cwd = opts.cwd;
|
|
2189
|
-
const isNonInteractive = opts.yes;
|
|
2269
|
+
const isNonInteractive = detectNonInteractive(opts.yes);
|
|
2190
2270
|
const preflightSpinner = spinner("Preflight checks.").start();
|
|
2191
2271
|
const projectInfo = await detectProject(cwd);
|
|
2192
2272
|
if (!projectInfo.hasReactGrab) {
|
|
@@ -2337,7 +2417,7 @@ var add = new Command().name("add").alias("install").description("connect React
|
|
|
2337
2417
|
}
|
|
2338
2418
|
} else {
|
|
2339
2419
|
logger.break();
|
|
2340
|
-
logger.error("Please specify an agent to
|
|
2420
|
+
logger.error("Please specify an agent to connect.");
|
|
2341
2421
|
logger.error("Available agents: " + availableAgents.join(", "));
|
|
2342
2422
|
logger.break();
|
|
2343
2423
|
process.exit(1);
|
|
@@ -2534,7 +2614,7 @@ var MAX_KEY_HOLD_DURATION_MS = 2e3;
|
|
|
2534
2614
|
var MAX_CONTEXT_LINES = 50;
|
|
2535
2615
|
|
|
2536
2616
|
// src/commands/configure.ts
|
|
2537
|
-
var VERSION2 = "0.1.
|
|
2617
|
+
var VERSION2 = "0.1.15";
|
|
2538
2618
|
var isMac = process.platform === "darwin";
|
|
2539
2619
|
var META_LABEL = isMac ? "Cmd" : "Win";
|
|
2540
2620
|
var ALT_LABEL = isMac ? "Option" : "Alt";
|
|
@@ -3090,7 +3170,7 @@ var uninstallPackagesWithFeedback = (packages, packageManager, projectRoot) => {
|
|
|
3090
3170
|
};
|
|
3091
3171
|
|
|
3092
3172
|
// src/commands/init.ts
|
|
3093
|
-
var VERSION3 = "0.1.
|
|
3173
|
+
var VERSION3 = "0.1.15";
|
|
3094
3174
|
var REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
3095
3175
|
var DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
3096
3176
|
var reportToCli = (type, config, error) => {
|
|
@@ -3127,6 +3207,34 @@ var UNSUPPORTED_FRAMEWORK_NAMES = {
|
|
|
3127
3207
|
gatsby: "Gatsby"
|
|
3128
3208
|
};
|
|
3129
3209
|
var getAgentName = getAgentDisplayName;
|
|
3210
|
+
var sortProjectsByFramework = (projects) => [...projects].sort((projectA, projectB) => {
|
|
3211
|
+
if (projectA.framework === "unknown" && projectB.framework !== "unknown")
|
|
3212
|
+
return 1;
|
|
3213
|
+
if (projectA.framework !== "unknown" && projectB.framework === "unknown")
|
|
3214
|
+
return -1;
|
|
3215
|
+
return 0;
|
|
3216
|
+
});
|
|
3217
|
+
var printSubprojects = (searchRoot, sortedProjects) => {
|
|
3218
|
+
logger.break();
|
|
3219
|
+
logger.log("Found the following projects:");
|
|
3220
|
+
logger.break();
|
|
3221
|
+
for (const project of sortedProjects) {
|
|
3222
|
+
const frameworkLabel = project.framework !== "unknown" ? ` ${highlighter.dim(`(${FRAMEWORK_NAMES[project.framework]})`)}` : "";
|
|
3223
|
+
const relativePath = relative(searchRoot, project.path);
|
|
3224
|
+
logger.log(
|
|
3225
|
+
` ${highlighter.info(project.name)}${frameworkLabel} ${highlighter.dim(relativePath)}`
|
|
3226
|
+
);
|
|
3227
|
+
}
|
|
3228
|
+
logger.break();
|
|
3229
|
+
logger.log(
|
|
3230
|
+
`Re-run with ${highlighter.info("-c <path>")} to specify a project:`
|
|
3231
|
+
);
|
|
3232
|
+
logger.break();
|
|
3233
|
+
logger.log(
|
|
3234
|
+
` ${highlighter.dim("$")} npx -y grab@latest init -c ${relative(searchRoot, sortedProjects[0].path)}`
|
|
3235
|
+
);
|
|
3236
|
+
logger.break();
|
|
3237
|
+
};
|
|
3130
3238
|
var formatActivationKeyDisplay2 = (activationKey) => {
|
|
3131
3239
|
if (!activationKey) return "Default (Option/Alt)";
|
|
3132
3240
|
return activationKey.split("+").map((part) => {
|
|
@@ -3141,7 +3249,7 @@ var formatActivationKeyDisplay2 = (activationKey) => {
|
|
|
3141
3249
|
};
|
|
3142
3250
|
var init = new 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(
|
|
3143
3251
|
"-a, --agent <agent>",
|
|
3144
|
-
|
|
3252
|
+
`connect to your agent (${AGENTS.join(", ")}, mcp)`
|
|
3145
3253
|
).option(
|
|
3146
3254
|
"-k, --key <key>",
|
|
3147
3255
|
"activation key (e.g., Meta+K, Ctrl+Shift+G, Space)"
|
|
@@ -3155,8 +3263,14 @@ var init = new Command().name("init").description("initialize React Grab in your
|
|
|
3155
3263
|
);
|
|
3156
3264
|
console.log();
|
|
3157
3265
|
try {
|
|
3158
|
-
const cwd = opts.cwd;
|
|
3159
|
-
const isNonInteractive = opts.yes;
|
|
3266
|
+
const cwd = resolve(opts.cwd);
|
|
3267
|
+
const isNonInteractive = detectNonInteractive(opts.yes);
|
|
3268
|
+
if (!existsSync(cwd)) {
|
|
3269
|
+
logger.break();
|
|
3270
|
+
logger.error(`Directory does not exist: ${highlighter.info(cwd)}`);
|
|
3271
|
+
logger.break();
|
|
3272
|
+
process.exit(1);
|
|
3273
|
+
}
|
|
3160
3274
|
const preflightSpinner = spinner("Preflight checks.").start();
|
|
3161
3275
|
const projectInfo = await detectProject(cwd);
|
|
3162
3276
|
const removeAgents = async (agentsToRemove2, skipInstall = false) => {
|
|
@@ -3683,58 +3797,48 @@ var init = new Command().name("init").description("initialize React Grab in your
|
|
|
3683
3797
|
process.exit(1);
|
|
3684
3798
|
}
|
|
3685
3799
|
if (projectInfo.framework === "unknown") {
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
);
|
|
3691
|
-
|
|
3692
|
-
|
|
3800
|
+
let searchRoot = cwd;
|
|
3801
|
+
let reactProjects = findReactProjects(searchRoot);
|
|
3802
|
+
if (reactProjects.length === 0 && cwd !== process.cwd()) {
|
|
3803
|
+
searchRoot = process.cwd();
|
|
3804
|
+
reactProjects = findReactProjects(searchRoot);
|
|
3805
|
+
}
|
|
3806
|
+
if (reactProjects.length > 0) {
|
|
3807
|
+
frameworkSpinner.info(
|
|
3808
|
+
`Verifying framework. Found ${reactProjects.length} project${reactProjects.length === 1 ? "" : "s"}.`
|
|
3693
3809
|
);
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
(projectA, projectB) => {
|
|
3698
|
-
if (projectA.framework === "unknown" && projectB.framework !== "unknown")
|
|
3699
|
-
return 1;
|
|
3700
|
-
if (projectA.framework !== "unknown" && projectB.framework === "unknown")
|
|
3701
|
-
return -1;
|
|
3702
|
-
return 0;
|
|
3703
|
-
}
|
|
3704
|
-
);
|
|
3705
|
-
const { selectedProject } = await prompts({
|
|
3706
|
-
type: "select",
|
|
3707
|
-
name: "selectedProject",
|
|
3708
|
-
message: "Select a project to install React Grab:",
|
|
3709
|
-
choices: [
|
|
3710
|
-
...sortedProjects.map((project) => {
|
|
3711
|
-
const frameworkLabel = project.framework !== "unknown" ? ` ${highlighter.dim(`(${FRAMEWORK_NAMES[project.framework]})`)}` : "";
|
|
3712
|
-
return {
|
|
3713
|
-
title: `${project.name}${frameworkLabel}`,
|
|
3714
|
-
value: project.path
|
|
3715
|
-
};
|
|
3716
|
-
}),
|
|
3717
|
-
{ title: "Skip", value: "skip" }
|
|
3718
|
-
]
|
|
3719
|
-
});
|
|
3720
|
-
if (!selectedProject || selectedProject === "skip") {
|
|
3721
|
-
logger.break();
|
|
3722
|
-
process.exit(0);
|
|
3723
|
-
}
|
|
3724
|
-
process.chdir(selectedProject);
|
|
3725
|
-
const newProjectInfo = await detectProject(selectedProject);
|
|
3726
|
-
Object.assign(projectInfo, newProjectInfo);
|
|
3727
|
-
const newFrameworkSpinner = spinner("Verifying framework.").start();
|
|
3728
|
-
newFrameworkSpinner.succeed(
|
|
3729
|
-
`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[newProjectInfo.framework])}.`
|
|
3730
|
-
);
|
|
3731
|
-
} else {
|
|
3732
|
-
frameworkSpinner.fail("Could not detect a supported framework.");
|
|
3733
|
-
logger.break();
|
|
3734
|
-
logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
|
|
3735
|
-
logger.break();
|
|
3810
|
+
const sortedProjects = sortProjectsByFramework(reactProjects);
|
|
3811
|
+
if (isNonInteractive) {
|
|
3812
|
+
printSubprojects(searchRoot, sortedProjects);
|
|
3736
3813
|
process.exit(1);
|
|
3737
3814
|
}
|
|
3815
|
+
logger.break();
|
|
3816
|
+
const { selectedProject } = await prompts({
|
|
3817
|
+
type: "select",
|
|
3818
|
+
name: "selectedProject",
|
|
3819
|
+
message: "Select a project to install React Grab:",
|
|
3820
|
+
choices: [
|
|
3821
|
+
...sortedProjects.map((project) => {
|
|
3822
|
+
const frameworkLabel = project.framework !== "unknown" ? ` ${highlighter.dim(`(${FRAMEWORK_NAMES[project.framework]})`)}` : "";
|
|
3823
|
+
return {
|
|
3824
|
+
title: `${project.name}${frameworkLabel}`,
|
|
3825
|
+
value: project.path
|
|
3826
|
+
};
|
|
3827
|
+
}),
|
|
3828
|
+
{ title: "Skip", value: "skip" }
|
|
3829
|
+
]
|
|
3830
|
+
});
|
|
3831
|
+
if (!selectedProject || selectedProject === "skip") {
|
|
3832
|
+
logger.break();
|
|
3833
|
+
process.exit(0);
|
|
3834
|
+
}
|
|
3835
|
+
process.chdir(selectedProject);
|
|
3836
|
+
const newProjectInfo = await detectProject(selectedProject);
|
|
3837
|
+
Object.assign(projectInfo, newProjectInfo);
|
|
3838
|
+
const newFrameworkSpinner = spinner("Verifying framework.").start();
|
|
3839
|
+
newFrameworkSpinner.succeed(
|
|
3840
|
+
`Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[newProjectInfo.framework])}.`
|
|
3841
|
+
);
|
|
3738
3842
|
} else {
|
|
3739
3843
|
frameworkSpinner.fail("Could not detect a supported framework.");
|
|
3740
3844
|
logger.break();
|
|
@@ -3924,11 +4028,8 @@ var init = new Command().name("init").description("initialize React Grab in your
|
|
|
3924
4028
|
reportToCli("error", void 0, error);
|
|
3925
4029
|
}
|
|
3926
4030
|
});
|
|
3927
|
-
var VERSION4 = "0.1.
|
|
3928
|
-
var remove = new Command().name("remove").description("disconnect React Grab from your agent").argument(
|
|
3929
|
-
"[agent]",
|
|
3930
|
-
"agent to remove (claude-code, cursor, opencode, codex, gemini, amp, ami, mcp)"
|
|
3931
|
-
).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
4031
|
+
var VERSION4 = "0.1.15";
|
|
4032
|
+
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(
|
|
3932
4033
|
"-c, --cwd <cwd>",
|
|
3933
4034
|
"working directory (defaults to current directory)",
|
|
3934
4035
|
process.cwd()
|
|
@@ -3939,7 +4040,7 @@ var remove = new Command().name("remove").description("disconnect React Grab fro
|
|
|
3939
4040
|
console.log();
|
|
3940
4041
|
try {
|
|
3941
4042
|
const cwd = opts.cwd;
|
|
3942
|
-
const isNonInteractive = opts.yes;
|
|
4043
|
+
const isNonInteractive = detectNonInteractive(opts.yes);
|
|
3943
4044
|
const preflightSpinner = spinner("Preflight checks.").start();
|
|
3944
4045
|
const projectInfo = await detectProject(cwd);
|
|
3945
4046
|
if (!projectInfo.hasReactGrab) {
|
|
@@ -3989,7 +4090,7 @@ var remove = new Command().name("remove").description("disconnect React Grab fro
|
|
|
3989
4090
|
agentToRemove = agent;
|
|
3990
4091
|
} else {
|
|
3991
4092
|
logger.break();
|
|
3992
|
-
logger.error("Please specify an agent to
|
|
4093
|
+
logger.error("Please specify an agent to disconnect.");
|
|
3993
4094
|
logger.error(
|
|
3994
4095
|
"Installed agents: " + projectInfo.installedAgents.join(", ")
|
|
3995
4096
|
);
|
|
@@ -4103,7 +4204,7 @@ var remove = new Command().name("remove").description("disconnect React Grab fro
|
|
|
4103
4204
|
});
|
|
4104
4205
|
|
|
4105
4206
|
// src/cli.ts
|
|
4106
|
-
var VERSION5 = "0.1.
|
|
4207
|
+
var VERSION5 = "0.1.15";
|
|
4107
4208
|
var VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
4108
4209
|
process.on("SIGINT", () => process.exit(0));
|
|
4109
4210
|
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.15",
|
|
4
4
|
"bin": {
|
|
5
5
|
"react-grab": "./dist/cli.js"
|
|
6
6
|
},
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@antfu/ni": "^0.23.0",
|
|
20
20
|
"commander": "^14.0.0",
|
|
21
|
+
"ignore": "^7.0.5",
|
|
21
22
|
"ora": "^8.2.0",
|
|
22
23
|
"picocolors": "^1.1.1",
|
|
23
24
|
"prompts": "^2.4.2"
|