@react-grab/cli 0.0.71 → 0.0.73

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.
Files changed (3) hide show
  1. package/dist/cli.cjs +445 -504
  2. package/dist/cli.js +444 -503
  3. package/package.json +6 -5
package/dist/cli.cjs CHANGED
@@ -1,19 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var prompts = require('@inquirer/prompts');
5
- var pc = require('picocolors');
6
- var yargs = require('yargs');
7
- var helpers = require('yargs/helpers');
4
+ var commander = require('commander');
5
+ var prompts2 = require('prompts');
6
+ var child_process = require('child_process');
8
7
  var fs = require('fs');
9
8
  var path = require('path');
10
9
  var ni = require('@antfu/ni');
11
- var child_process = require('child_process');
10
+ var colors = require('kleur/colors');
11
+ var ora = require('ora');
12
12
 
13
13
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
14
14
 
15
- var pc__default = /*#__PURE__*/_interopDefault(pc);
16
- var yargs__default = /*#__PURE__*/_interopDefault(yargs);
15
+ var prompts2__default = /*#__PURE__*/_interopDefault(prompts2);
16
+ var ora__default = /*#__PURE__*/_interopDefault(ora);
17
17
 
18
18
  var detectPackageManager = async (projectRoot) => {
19
19
  const detected = await ni.detect({ cwd: projectRoot });
@@ -301,7 +301,7 @@ var detectProject = async (projectRoot = process.cwd()) => {
301
301
  };
302
302
  };
303
303
 
304
- // src/diff.ts
304
+ // src/utils/diff.ts
305
305
  var RED = "\x1B[31m";
306
306
  var GREEN = "\x1B[32m";
307
307
  var GRAY = "\x1B[90m";
@@ -388,6 +388,50 @@ ${BOLD}File: ${filePath}${RESET}`);
388
388
  console.log(formatDiff(diff));
389
389
  console.log("\u2500".repeat(60));
390
390
  };
391
+ var highlighter = {
392
+ error: colors.red,
393
+ warn: colors.yellow,
394
+ info: colors.cyan,
395
+ success: colors.green,
396
+ dim: colors.dim
397
+ };
398
+
399
+ // src/utils/logger.ts
400
+ var logger = {
401
+ error(...args) {
402
+ console.log(highlighter.error(args.join(" ")));
403
+ },
404
+ warn(...args) {
405
+ console.log(highlighter.warn(args.join(" ")));
406
+ },
407
+ info(...args) {
408
+ console.log(highlighter.info(args.join(" ")));
409
+ },
410
+ success(...args) {
411
+ console.log(highlighter.success(args.join(" ")));
412
+ },
413
+ log(...args) {
414
+ console.log(args.join(" "));
415
+ },
416
+ break() {
417
+ console.log("");
418
+ }
419
+ };
420
+
421
+ // src/utils/handle-error.ts
422
+ var handleError = (error) => {
423
+ logger.break();
424
+ logger.error(
425
+ "Something went wrong. Please check the error below for more details."
426
+ );
427
+ logger.error("If the problem persists, please open an issue on GitHub.");
428
+ logger.error("");
429
+ if (error instanceof Error) {
430
+ logger.error(error.message);
431
+ }
432
+ logger.break();
433
+ process.exit(1);
434
+ };
391
435
  var INSTALL_COMMANDS = {
392
436
  npm: "npm install",
393
437
  yarn: "yarn add",
@@ -418,8 +462,9 @@ var getPackagesToInstall = (agent, includeReactGrab = true) => {
418
462
  }
419
463
  return packages;
420
464
  };
465
+ var spinner = (text, options) => ora__default.default({ text, isSilent: options?.silent, stream: process.stdout });
421
466
 
422
- // src/templates.ts
467
+ // src/utils/templates.ts
423
468
  var NEXT_APP_ROUTER_SCRIPT = `{process.env.NODE_ENV === "development" && (
424
469
  <Script
425
470
  src="//unpkg.com/react-grab/dist/index.global.js"
@@ -492,7 +537,7 @@ var WEBPACK_IMPORT_WITH_AGENT = (agent) => {
492
537
  };
493
538
  var SCRIPT_IMPORT = 'import Script from "next/script";';
494
539
 
495
- // src/transform.ts
540
+ // src/utils/transform.ts
496
541
  var hasReactGrabCode = (content) => {
497
542
  const fuzzyPatterns = [
498
543
  /["'`][^"'`]*react-grab/,
@@ -648,11 +693,13 @@ var addAgentToExistingVite = (originalContent, agent, filePath) => {
648
693
  };
649
694
  }
650
695
  const agentImport = `import("${agentPackage}/client");`;
651
- const reactGrabImportMatch = originalContent.match(/import\s*\(\s*["']react-grab["']\s*\)/);
696
+ const reactGrabImportMatch = originalContent.match(/import\s*\(\s*["']react-grab["']\s*\);?/);
652
697
  if (reactGrabImportMatch) {
698
+ const matchedText = reactGrabImportMatch[0];
699
+ const hasSemicolon = matchedText.endsWith(";");
653
700
  const newContent = originalContent.replace(
654
- reactGrabImportMatch[0],
655
- `${reactGrabImportMatch[0]};
701
+ matchedText,
702
+ `${hasSemicolon ? matchedText.slice(0, -1) : matchedText};
656
703
  ${agentImport}`
657
704
  );
658
705
  return {
@@ -688,11 +735,13 @@ var addAgentToExistingWebpack = (originalContent, agent, filePath) => {
688
735
  };
689
736
  }
690
737
  const agentImport = `import("${agentPackage}/client");`;
691
- const reactGrabImportMatch = originalContent.match(/import\s*\(\s*["']react-grab["']\s*\)/);
738
+ const reactGrabImportMatch = originalContent.match(/import\s*\(\s*["']react-grab["']\s*\);?/);
692
739
  if (reactGrabImportMatch) {
740
+ const matchedText = reactGrabImportMatch[0];
741
+ const hasSemicolon = matchedText.endsWith(";");
693
742
  const newContent = originalContent.replace(
694
- reactGrabImportMatch[0],
695
- `${reactGrabImportMatch[0]};
743
+ matchedText,
744
+ `${hasSemicolon ? matchedText.slice(0, -1) : matchedText};
696
745
  ${agentImport}`
697
746
  );
698
747
  return {
@@ -1030,9 +1079,187 @@ var applyPackageJsonTransform = (result) => {
1030
1079
  return { success: true };
1031
1080
  };
1032
1081
 
1033
- // src/cli.ts
1034
- var VERSION = "0.0.71";
1035
- var REPORT_URL = "https://reactgrab.com/api/report-cli";
1082
+ // src/commands/add.ts
1083
+ var AGENT_NAMES = {
1084
+ "claude-code": "Claude Code",
1085
+ cursor: "Cursor",
1086
+ opencode: "Opencode"
1087
+ };
1088
+ var add = new commander.Command().name("add").description("add an agent integration").argument("[agent]", "agent to add (claude-code, cursor, opencode)").option("-y, --yes", "skip confirmation prompts", false).option(
1089
+ "-c, --cwd <cwd>",
1090
+ "working directory (defaults to current directory)",
1091
+ process.cwd()
1092
+ ).action(async (agentArg, opts) => {
1093
+ try {
1094
+ const cwd = opts.cwd;
1095
+ const isNonInteractive = opts.yes;
1096
+ logger.log(`\u269B ${highlighter.info("React Grab")}`);
1097
+ logger.break();
1098
+ const preflightSpinner = spinner("Preflight checks.").start();
1099
+ const projectInfo = await detectProject(cwd);
1100
+ if (!projectInfo.hasReactGrab) {
1101
+ preflightSpinner.fail("React Grab is not installed.");
1102
+ logger.break();
1103
+ logger.error(
1104
+ `Run ${highlighter.info("react-grab init")} first to install React Grab.`
1105
+ );
1106
+ logger.break();
1107
+ process.exit(1);
1108
+ }
1109
+ preflightSpinner.succeed();
1110
+ const availableAgents = ["claude-code", "cursor", "opencode"].filter((agent) => !projectInfo.installedAgents.includes(agent));
1111
+ if (availableAgents.length === 0) {
1112
+ logger.break();
1113
+ logger.success("All agent integrations are already installed.");
1114
+ logger.break();
1115
+ process.exit(0);
1116
+ }
1117
+ let agentIntegration;
1118
+ if (agentArg) {
1119
+ if (!["claude-code", "cursor", "opencode"].includes(agentArg)) {
1120
+ logger.break();
1121
+ logger.error(`Invalid agent: ${agentArg}`);
1122
+ logger.error("Available agents: claude-code, cursor, opencode");
1123
+ logger.break();
1124
+ process.exit(1);
1125
+ }
1126
+ if (projectInfo.installedAgents.includes(agentArg)) {
1127
+ logger.break();
1128
+ logger.warn(`${AGENT_NAMES[agentArg]} is already installed.`);
1129
+ logger.break();
1130
+ process.exit(0);
1131
+ }
1132
+ agentIntegration = agentArg;
1133
+ } else if (!isNonInteractive) {
1134
+ logger.break();
1135
+ const { agent } = await prompts2__default.default({
1136
+ type: "select",
1137
+ name: "agent",
1138
+ message: `Which ${highlighter.info("agent integration")} would you like to add?`,
1139
+ choices: availableAgents.map((innerAgent) => ({
1140
+ title: AGENT_NAMES[innerAgent],
1141
+ value: innerAgent
1142
+ }))
1143
+ });
1144
+ if (!agent) {
1145
+ logger.break();
1146
+ process.exit(1);
1147
+ }
1148
+ agentIntegration = agent;
1149
+ } else {
1150
+ logger.break();
1151
+ logger.error("Please specify an agent to add.");
1152
+ logger.error("Available agents: " + availableAgents.join(", "));
1153
+ logger.break();
1154
+ process.exit(1);
1155
+ }
1156
+ const addingSpinner = spinner(
1157
+ `Adding ${AGENT_NAMES[agentIntegration]}.`
1158
+ ).start();
1159
+ addingSpinner.succeed();
1160
+ const result = previewTransform(
1161
+ projectInfo.projectRoot,
1162
+ projectInfo.framework,
1163
+ projectInfo.nextRouterType,
1164
+ agentIntegration,
1165
+ true
1166
+ );
1167
+ const packageJsonResult = previewPackageJsonTransform(
1168
+ projectInfo.projectRoot,
1169
+ agentIntegration,
1170
+ projectInfo.installedAgents
1171
+ );
1172
+ if (!result.success) {
1173
+ logger.break();
1174
+ logger.error(result.message);
1175
+ logger.break();
1176
+ process.exit(1);
1177
+ }
1178
+ const hasLayoutChanges = !result.noChanges && result.originalContent && result.newContent;
1179
+ const hasPackageJsonChanges = packageJsonResult.success && !packageJsonResult.noChanges && packageJsonResult.originalContent && packageJsonResult.newContent;
1180
+ if (hasLayoutChanges || hasPackageJsonChanges) {
1181
+ logger.break();
1182
+ if (hasLayoutChanges) {
1183
+ printDiff(result.filePath, result.originalContent, result.newContent);
1184
+ }
1185
+ if (hasPackageJsonChanges) {
1186
+ if (hasLayoutChanges) {
1187
+ logger.break();
1188
+ }
1189
+ printDiff(
1190
+ packageJsonResult.filePath,
1191
+ packageJsonResult.originalContent,
1192
+ packageJsonResult.newContent
1193
+ );
1194
+ }
1195
+ if (!isNonInteractive) {
1196
+ logger.break();
1197
+ const { proceed } = await prompts2__default.default({
1198
+ type: "confirm",
1199
+ name: "proceed",
1200
+ message: "Apply these changes?",
1201
+ initial: true
1202
+ });
1203
+ if (!proceed) {
1204
+ logger.break();
1205
+ logger.log("Changes cancelled.");
1206
+ logger.break();
1207
+ process.exit(0);
1208
+ }
1209
+ }
1210
+ }
1211
+ const packages = getPackagesToInstall(agentIntegration, false);
1212
+ if (packages.length > 0) {
1213
+ const installSpinner = spinner(
1214
+ `Installing ${packages.join(", ")}.`
1215
+ ).start();
1216
+ try {
1217
+ installPackages(packages, projectInfo.packageManager, projectInfo.projectRoot);
1218
+ installSpinner.succeed();
1219
+ } catch (error) {
1220
+ installSpinner.fail();
1221
+ handleError(error);
1222
+ }
1223
+ }
1224
+ if (hasLayoutChanges) {
1225
+ const writeSpinner = spinner(`Applying changes to ${result.filePath}.`).start();
1226
+ const writeResult = applyTransform(result);
1227
+ if (!writeResult.success) {
1228
+ writeSpinner.fail();
1229
+ logger.break();
1230
+ logger.error(writeResult.error || "Failed to write file.");
1231
+ logger.break();
1232
+ process.exit(1);
1233
+ }
1234
+ writeSpinner.succeed();
1235
+ }
1236
+ if (hasPackageJsonChanges) {
1237
+ const packageJsonSpinner = spinner(
1238
+ `Applying changes to ${packageJsonResult.filePath}.`
1239
+ ).start();
1240
+ const packageJsonWriteResult = applyPackageJsonTransform(packageJsonResult);
1241
+ if (!packageJsonWriteResult.success) {
1242
+ packageJsonSpinner.fail();
1243
+ logger.break();
1244
+ logger.error(packageJsonWriteResult.error || "Failed to write file.");
1245
+ logger.break();
1246
+ process.exit(1);
1247
+ }
1248
+ packageJsonSpinner.succeed();
1249
+ }
1250
+ logger.break();
1251
+ logger.log(
1252
+ `${highlighter.success("Success!")} ${AGENT_NAMES[agentIntegration]} has been added.`
1253
+ );
1254
+ logger.log("Make sure to start the agent server before using it.");
1255
+ logger.break();
1256
+ } catch (error) {
1257
+ handleError(error);
1258
+ }
1259
+ });
1260
+ var VERSION = "0.0.73";
1261
+ var REPORT_URL = "https://react-grab.com/api/report-cli";
1262
+ var DOCS_URL = "https://github.com/aidenybai/react-grab";
1036
1263
  var reportToCli = async (type, config, error) => {
1037
1264
  try {
1038
1265
  await fetch(REPORT_URL, {
@@ -1062,416 +1289,144 @@ var PACKAGE_MANAGER_NAMES = {
1062
1289
  pnpm: "pnpm",
1063
1290
  bun: "Bun"
1064
1291
  };
1065
- var AGENT_NAMES = {
1066
- "claude-code": "Claude Code",
1067
- cursor: "Cursor",
1068
- opencode: "Opencode"
1069
- };
1070
1292
  var UNSUPPORTED_FRAMEWORK_NAMES = {
1071
1293
  remix: "Remix",
1072
1294
  astro: "Astro",
1073
1295
  sveltekit: "SvelteKit",
1074
1296
  gatsby: "Gatsby"
1075
1297
  };
1076
- var DOCS_URL = "https://github.com/aidenybai/react-grab";
1077
- var showDocsLink = () => {
1078
- console.log("\nFor manual installation instructions, visit:");
1079
- console.log(` ${pc__default.default.cyan(DOCS_URL)}
1080
- `);
1081
- };
1082
- var showManualInstructions = (framework, nextRouterType) => {
1083
- console.log(
1084
- `
1085
- ${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Manual Setup Instructions:")}
1086
- `
1087
- );
1088
- if (framework === "next" && nextRouterType === "app") {
1089
- console.log(`${pc__default.default.bold("Next.js App Router:")}`);
1090
- console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
1091
- console.log(` 2. Add to ${pc__default.default.cyan("app/layout.tsx")} inside <head>:`);
1092
- console.log(` ${pc__default.default.gray('import Script from "next/script";')}`);
1093
- console.log(
1094
- ` ${pc__default.default.gray('{process.env.NODE_ENV === "development" && (')}`
1095
- );
1096
- console.log(` ${pc__default.default.gray(" <Script")}`);
1097
- console.log(
1098
- ` ${pc__default.default.gray(' src="//unpkg.com/react-grab/dist/index.global.js"')}`
1099
- );
1100
- console.log(` ${pc__default.default.gray(' crossOrigin="anonymous"')}`);
1101
- console.log(` ${pc__default.default.gray(' strategy="beforeInteractive"')}`);
1102
- console.log(` ${pc__default.default.gray(" />")}`);
1103
- console.log(` ${pc__default.default.gray(")}")}`);
1104
- } else if (framework === "next" && nextRouterType === "pages") {
1105
- console.log(`${pc__default.default.bold("Next.js Pages Router:")}`);
1106
- console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
1107
- console.log(` 2. Add to ${pc__default.default.cyan("pages/_document.tsx")} inside <Head>:`);
1108
- console.log(` ${pc__default.default.gray('import Script from "next/script";')}`);
1109
- console.log(
1110
- ` ${pc__default.default.gray('{process.env.NODE_ENV === "development" && (')}`
1111
- );
1112
- console.log(` ${pc__default.default.gray(" <Script")}`);
1113
- console.log(
1114
- ` ${pc__default.default.gray(' src="//unpkg.com/react-grab/dist/index.global.js"')}`
1115
- );
1116
- console.log(` ${pc__default.default.gray(' crossOrigin="anonymous"')}`);
1117
- console.log(` ${pc__default.default.gray(' strategy="beforeInteractive"')}`);
1118
- console.log(` ${pc__default.default.gray(" />")}`);
1119
- console.log(` ${pc__default.default.gray(")}")}`);
1120
- } else if (framework === "vite") {
1121
- console.log(`${pc__default.default.bold("Vite:")}`);
1122
- console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
1123
- console.log(` 2. Add to ${pc__default.default.cyan("index.html")} inside <head>:`);
1124
- console.log(` ${pc__default.default.gray('<script type="module">')}`);
1125
- console.log(
1126
- ` ${pc__default.default.gray(' if (import.meta.env.DEV) { import("react-grab"); }')}`
1127
- );
1128
- console.log(` ${pc__default.default.gray("</script>")}`);
1129
- } else if (framework === "webpack") {
1130
- console.log(`${pc__default.default.bold("Webpack:")}`);
1131
- console.log(` 1. Install: ${pc__default.default.cyan("npm install -D react-grab")}`);
1132
- console.log(
1133
- ` 2. Add to your entry file (e.g., ${pc__default.default.cyan("src/index.tsx")}):`
1134
- );
1135
- console.log(
1136
- ` ${pc__default.default.gray('if (process.env.NODE_ENV === "development") {')}`
1137
- );
1138
- console.log(` ${pc__default.default.gray(' import("react-grab");')}`);
1139
- console.log(` ${pc__default.default.gray("}")}`);
1140
- } else {
1141
- console.log(
1142
- `${pc__default.default.bold("Next.js App Router:")} Add to ${pc__default.default.cyan("app/layout.tsx")} inside <head>:`
1143
- );
1144
- console.log(` ${pc__default.default.gray('import Script from "next/script";')}`);
1145
- console.log(
1146
- ` ${pc__default.default.gray('{process.env.NODE_ENV === "development" && (')}`
1147
- );
1148
- console.log(
1149
- ` ${pc__default.default.gray(' <Script src="//unpkg.com/react-grab/dist/index.global.js" strategy="beforeInteractive" />')}`
1150
- );
1151
- console.log(` ${pc__default.default.gray(")}")}`);
1152
- console.log("");
1153
- console.log(
1154
- `${pc__default.default.bold("Next.js Pages Router:")} Add to ${pc__default.default.cyan("pages/_document.tsx")} inside <Head>:`
1155
- );
1156
- console.log(` ${pc__default.default.gray('import Script from "next/script";')}`);
1157
- console.log(
1158
- ` ${pc__default.default.gray('{process.env.NODE_ENV === "development" && (')}`
1159
- );
1160
- console.log(
1161
- ` ${pc__default.default.gray(' <Script src="//unpkg.com/react-grab/dist/index.global.js" strategy="beforeInteractive" />')}`
1162
- );
1163
- console.log(` ${pc__default.default.gray(")}")}`);
1164
- console.log("");
1165
- console.log(
1166
- `${pc__default.default.bold("Vite:")} Add to ${pc__default.default.cyan("index.html")} inside <head>:`
1167
- );
1168
- console.log(` ${pc__default.default.gray('<script type="module">')}`);
1169
- console.log(
1170
- ` ${pc__default.default.gray(' if (import.meta.env.DEV) { import("react-grab"); }')}`
1171
- );
1172
- console.log(` ${pc__default.default.gray("</script>")}`);
1173
- console.log("");
1174
- console.log(
1175
- `${pc__default.default.bold("Webpack:")} Add to entry file (e.g., ${pc__default.default.cyan("src/index.tsx")}):`
1176
- );
1177
- console.log(
1178
- ` ${pc__default.default.gray('if (process.env.NODE_ENV === "development") {')}`
1179
- );
1180
- console.log(` ${pc__default.default.gray(' import("react-grab");')}`);
1181
- console.log(` ${pc__default.default.gray("}")}`);
1182
- console.log("");
1183
- console.log(`For full instructions, visit:`);
1184
- console.log(
1185
- ` ${pc__default.default.cyan("https://github.com/aidenybai/react-grab#readme")}`
1186
- );
1187
- return;
1188
- }
1189
- showDocsLink();
1190
- };
1191
- var showAccuracyWarning = () => {
1192
- console.log(
1193
- `
1194
- ${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Auto-detection may not be 100% accurate.")}`
1195
- );
1196
- console.log(
1197
- `${pc__default.default.yellow(" Please verify the changes in your file before committing.")}`
1198
- );
1199
- };
1200
- var parseArgs = async () => {
1201
- const argv = await yargs__default.default(helpers.hideBin(process.argv)).scriptName("react-grab").usage(
1202
- `${pc__default.default.magenta("\u269B")} ${pc__default.default.bold("React Grab CLI")} ${pc__default.default.gray(`v${VERSION}`)}
1203
-
1204
- ${pc__default.default.cyan("Usage:")} $0 [options]
1205
-
1206
- React Grab adds AI-powered context selection to your React application,
1207
- allowing you to select components and copy their context for AI assistants.
1208
-
1209
- The CLI auto-detects your project configuration (framework, package manager,
1210
- router type) and installs React Grab with optional agent integrations.`
1211
- ).option("framework", {
1212
- alias: "f",
1213
- type: "string",
1214
- choices: ["next", "vite", "webpack"],
1215
- description: "Override detected framework"
1216
- }).option("package-manager", {
1217
- alias: "p",
1218
- type: "string",
1219
- choices: ["npm", "yarn", "pnpm", "bun"],
1220
- description: "Override detected package manager"
1221
- }).option("router", {
1222
- alias: "r",
1223
- type: "string",
1224
- choices: ["app", "pages"],
1225
- description: "Next.js router type (only for Next.js projects)"
1226
- }).option("agent", {
1227
- alias: "a",
1228
- type: "string",
1229
- choices: ["claude-code", "cursor", "opencode", "none"],
1230
- description: "Agent integration to automatically forward selected elements to agent instead of copying to clipboard"
1231
- }).option("yes", {
1232
- alias: "y",
1233
- type: "boolean",
1234
- default: false,
1235
- description: "Skip all prompts and use auto-detected/default values"
1236
- }).option("skip-install", {
1237
- type: "boolean",
1238
- default: false,
1239
- description: "Only modify config files, skip npm/yarn/pnpm install"
1240
- }).help().alias("help", "h").version(VERSION).alias("version", "v").example("$0", "Run interactive setup with prompts").example("$0 -y", "Auto-detect everything and install without prompts").example("$0 -f next -r app", "Configure for Next.js App Router").example(
1241
- "$0 -a cursor -y",
1242
- "Add Cursor agent integration non-interactively"
1243
- ).example("$0 -p pnpm -a claude-code", "Use pnpm and add Claude Code agent").example(
1244
- "$0 --skip-install",
1245
- "Only modify files, install packages manually"
1246
- ).epilog(
1247
- `${pc__default.default.bold("Agent Integrations:")}
1248
- ${pc__default.default.cyan("claude-code")} Connect React Grab to Claude Code
1249
- ${pc__default.default.cyan("cursor")} Connect React Grab to Cursor IDE
1250
- ${pc__default.default.cyan("opencode")} Connect React Grab to Opencode
1251
-
1252
- ${pc__default.default.bold("Supported Frameworks:")}
1253
- ${pc__default.default.cyan("next")} Next.js (App Router & Pages Router)
1254
- ${pc__default.default.cyan("vite")} Vite-based React projects
1255
- ${pc__default.default.cyan("webpack")} Webpack-based React projects
1256
-
1257
- ${pc__default.default.bold("Documentation:")} ${pc__default.default.underline(DOCS_URL)}`
1258
- ).wrap(Math.min(100, process.stdout.columns || 80)).parse();
1259
- return {
1260
- framework: argv.framework,
1261
- packageManager: argv["package-manager"],
1262
- router: argv.router,
1263
- agent: argv.agent,
1264
- yes: argv.yes,
1265
- skipInstall: argv["skip-install"]
1266
- };
1267
- };
1268
- var main = async () => {
1269
- const args = await parseArgs();
1270
- const isNonInteractive = args.yes;
1271
- console.log(
1272
- `
1273
- ${pc__default.default.magenta("\u269B")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION)}`
1274
- );
1275
- const projectInfo = await detectProject(process.cwd());
1276
- console.log(
1277
- `- Framework: ${pc__default.default.cyan(FRAMEWORK_NAMES[projectInfo.framework])}`
1278
- );
1279
- console.log(
1280
- `- Package Manager: ${pc__default.default.cyan(PACKAGE_MANAGER_NAMES[projectInfo.packageManager])}`
1281
- );
1282
- if (projectInfo.framework === "next") {
1283
- console.log(
1284
- `- Router Type: ${pc__default.default.cyan(projectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}`
1285
- );
1286
- }
1287
- console.log(
1288
- `- Monorepo: ${pc__default.default.cyan(projectInfo.isMonorepo ? "Yes" : "No")}`
1289
- );
1290
- console.log(
1291
- `- React Grab: ${projectInfo.hasReactGrab ? pc__default.default.green("Installed") : pc__default.default.yellow("Not installed")}`
1292
- );
1293
- if (projectInfo.installedAgents.length > 0) {
1294
- console.log(
1295
- `- Agents: ${pc__default.default.cyan(projectInfo.installedAgents.map((agent) => AGENT_NAMES[agent] || agent).join(", "))}`
1296
- );
1297
- }
1298
- console.log("");
1299
- if (projectInfo.unsupportedFramework) {
1300
- const frameworkName = UNSUPPORTED_FRAMEWORK_NAMES[projectInfo.unsupportedFramework];
1301
- console.log(
1302
- `${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow(`Detected ${frameworkName} - this framework requires manual setup.`)}`
1303
- );
1304
- console.log(
1305
- `${pc__default.default.yellow(" React Grab may not work correctly with auto-configuration.")}
1306
- `
1307
- );
1308
- showManualInstructions(projectInfo.framework, projectInfo.nextRouterType);
1309
- process.exit(0);
1310
- }
1311
- if (projectInfo.framework === "unknown") {
1312
- if (projectInfo.isMonorepo && !isNonInteractive) {
1313
- const workspaceProjects = findWorkspaceProjects(projectInfo.projectRoot);
1314
- const reactProjects = workspaceProjects.filter(
1315
- (p) => p.hasReact || p.framework !== "unknown"
1298
+ 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(
1299
+ "-a, --agent <agent>",
1300
+ "agent integration (claude-code, cursor, opencode)"
1301
+ ).option("--skip-install", "skip package installation", false).option(
1302
+ "-c, --cwd <cwd>",
1303
+ "working directory (defaults to current directory)",
1304
+ process.cwd()
1305
+ ).action(async (opts) => {
1306
+ try {
1307
+ const cwd = opts.cwd;
1308
+ const isNonInteractive = opts.yes;
1309
+ logger.log(`\u269B ${highlighter.info("React Grab")}`);
1310
+ logger.break();
1311
+ const preflightSpinner = spinner("Preflight checks.").start();
1312
+ const projectInfo = await detectProject(cwd);
1313
+ if (projectInfo.hasReactGrab && !opts.force) {
1314
+ preflightSpinner.succeed();
1315
+ logger.break();
1316
+ logger.warn("React Grab is already installed.");
1317
+ logger.log(
1318
+ `Use ${highlighter.info("--force")} to reconfigure, or ${highlighter.info("react-grab add")} to add an agent.`
1316
1319
  );
1317
- if (reactProjects.length > 0) {
1318
- console.log(
1319
- `${pc__default.default.cyan("\u2139")} ${pc__default.default.cyan("Found React projects in this monorepo:")}
1320
- `
1321
- );
1322
- const selectedProject = await prompts.select({
1323
- message: "Select a project to install React Grab:",
1324
- choices: reactProjects.map((project) => ({
1325
- name: `${project.name} ${pc__default.default.gray(`(${FRAMEWORK_NAMES[project.framework] || "React"})`)}`,
1326
- value: project.path
1327
- }))
1328
- });
1329
- console.log(
1330
- `
1331
- ${pc__default.default.magenta("\u269B")} Switching to ${pc__default.default.cyan(selectedProject)}...
1332
- `
1333
- );
1334
- process.chdir(selectedProject);
1335
- const newProjectInfo = await detectProject(selectedProject);
1336
- projectInfo.framework = newProjectInfo.framework;
1337
- projectInfo.nextRouterType = newProjectInfo.nextRouterType;
1338
- projectInfo.hasReactGrab = newProjectInfo.hasReactGrab;
1339
- projectInfo.installedAgents = newProjectInfo.installedAgents;
1340
- projectInfo.projectRoot = newProjectInfo.projectRoot;
1341
- console.log(
1342
- `- Framework: ${pc__default.default.cyan(FRAMEWORK_NAMES[newProjectInfo.framework])}`
1320
+ logger.break();
1321
+ process.exit(0);
1322
+ }
1323
+ preflightSpinner.succeed();
1324
+ const frameworkSpinner = spinner("Verifying framework.").start();
1325
+ if (projectInfo.unsupportedFramework) {
1326
+ const frameworkName = UNSUPPORTED_FRAMEWORK_NAMES[projectInfo.unsupportedFramework];
1327
+ frameworkSpinner.fail(`Found ${highlighter.info(frameworkName)}.`);
1328
+ logger.break();
1329
+ logger.log(`${frameworkName} is not yet supported by automatic setup.`);
1330
+ logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
1331
+ logger.break();
1332
+ process.exit(1);
1333
+ }
1334
+ if (projectInfo.framework === "unknown") {
1335
+ if (projectInfo.isMonorepo && !isNonInteractive) {
1336
+ frameworkSpinner.info("Verifying framework. Found monorepo.");
1337
+ const workspaceProjects = findWorkspaceProjects(projectInfo.projectRoot);
1338
+ const reactProjects = workspaceProjects.filter(
1339
+ (project) => project.hasReact || project.framework !== "unknown"
1343
1340
  );
1344
- if (newProjectInfo.framework === "next") {
1345
- console.log(
1346
- `- Router Type: ${pc__default.default.cyan(newProjectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}`
1341
+ if (reactProjects.length > 0) {
1342
+ logger.break();
1343
+ const sortedProjects = [...reactProjects].sort((projectA, projectB) => {
1344
+ if (projectA.framework === "unknown" && projectB.framework !== "unknown") return 1;
1345
+ if (projectA.framework !== "unknown" && projectB.framework === "unknown") return -1;
1346
+ return 0;
1347
+ });
1348
+ const { selectedProject } = await prompts2__default.default({
1349
+ type: "select",
1350
+ name: "selectedProject",
1351
+ message: "Select a project to install React Grab:",
1352
+ choices: sortedProjects.map((project) => {
1353
+ const frameworkLabel = project.framework !== "unknown" ? ` ${highlighter.dim(`(${FRAMEWORK_NAMES[project.framework]})`)}` : "";
1354
+ return {
1355
+ title: `${project.name}${frameworkLabel}`,
1356
+ value: project.path
1357
+ };
1358
+ })
1359
+ });
1360
+ if (!selectedProject) {
1361
+ logger.break();
1362
+ process.exit(1);
1363
+ }
1364
+ process.chdir(selectedProject);
1365
+ const newProjectInfo = await detectProject(selectedProject);
1366
+ Object.assign(projectInfo, newProjectInfo);
1367
+ const newFrameworkSpinner = spinner("Verifying framework.").start();
1368
+ newFrameworkSpinner.succeed(
1369
+ `Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[newProjectInfo.framework])}.`
1347
1370
  );
1371
+ } else {
1372
+ frameworkSpinner.fail("Could not detect a supported framework.");
1373
+ logger.break();
1374
+ logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
1375
+ logger.break();
1376
+ process.exit(1);
1348
1377
  }
1349
- console.log(
1350
- `- React Grab: ${newProjectInfo.hasReactGrab ? pc__default.default.green("Installed") : pc__default.default.yellow("Not installed")}`
1351
- );
1352
- console.log("");
1353
1378
  } else {
1354
- console.log(
1355
- `${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Could not detect framework automatically.")}
1356
- `
1357
- );
1358
- showManualInstructions("unknown");
1359
- process.exit(0);
1379
+ frameworkSpinner.fail("Could not detect a supported framework.");
1380
+ logger.break();
1381
+ logger.log("React Grab supports Next.js, Vite, and Webpack projects.");
1382
+ logger.log(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
1383
+ logger.break();
1384
+ process.exit(1);
1360
1385
  }
1361
1386
  } else {
1362
- console.log(
1363
- `${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("Could not detect framework automatically.")}
1364
- `
1387
+ frameworkSpinner.succeed(
1388
+ `Verifying framework. Found ${highlighter.info(FRAMEWORK_NAMES[projectInfo.framework])}.`
1365
1389
  );
1366
- showManualInstructions("unknown");
1367
- process.exit(0);
1368
1390
  }
1369
- }
1370
- let action = "install-all";
1371
- if (projectInfo.hasReactGrab && !isNonInteractive) {
1372
- action = await prompts.select({
1373
- message: "React Grab is already installed. What would you like to do?",
1374
- choices: [
1375
- { name: "Add an agent integration", value: "add-agent" },
1376
- { name: "Reconfigure project files", value: "reconfigure" },
1377
- { name: "Reinstall everything", value: "install-all" }
1378
- ]
1379
- });
1380
- } else if (projectInfo.hasReactGrab && args.agent && args.agent !== "none") {
1381
- action = "add-agent";
1382
- } else if (projectInfo.hasReactGrab && isNonInteractive && !args.agent) {
1383
- console.log(
1384
- `${pc__default.default.yellow("\u26A0\uFE0F")} ${pc__default.default.yellow("React Grab is already installed.")}`
1385
- );
1386
- console.log(
1387
- `${pc__default.default.yellow(" Use --agent to add an agent, or run without -y for interactive mode.")}
1388
- `
1391
+ if (projectInfo.framework === "next") {
1392
+ const routerSpinner = spinner("Detecting router type.").start();
1393
+ routerSpinner.succeed(
1394
+ `Detecting router type. Found ${highlighter.info(projectInfo.nextRouterType === "app" ? "App Router" : "Pages Router")}.`
1395
+ );
1396
+ }
1397
+ const packageManagerSpinner = spinner("Detecting package manager.").start();
1398
+ packageManagerSpinner.succeed(
1399
+ `Detecting package manager. Found ${highlighter.info(PACKAGE_MANAGER_NAMES[projectInfo.packageManager])}.`
1389
1400
  );
1390
- action = "reconfigure";
1391
- }
1392
- let finalFramework = args.framework || projectInfo.framework;
1393
- let finalPackageManager = args.packageManager || projectInfo.packageManager;
1394
- let finalNextRouterType = args.router || projectInfo.nextRouterType;
1395
- if (!isNonInteractive && !args.framework) {
1396
- const confirmSettings = await prompts.confirm({
1397
- message: "Are these settings correct?",
1398
- default: true
1399
- });
1400
- if (!confirmSettings) {
1401
- finalFramework = await prompts.select({
1402
- message: "Select your framework:",
1403
- choices: [
1404
- { name: "Next.js", value: "next" },
1405
- { name: "Vite", value: "vite" },
1406
- { name: "Webpack", value: "webpack" }
1407
- ],
1408
- default: projectInfo.framework
1409
- });
1410
- finalPackageManager = await prompts.select({
1411
- message: "Select your package manager:",
1401
+ let finalFramework = projectInfo.framework;
1402
+ let finalPackageManager = projectInfo.packageManager;
1403
+ let finalNextRouterType = projectInfo.nextRouterType;
1404
+ let agentIntegration = opts.agent || "none";
1405
+ if (!isNonInteractive && !opts.agent) {
1406
+ logger.break();
1407
+ const { agent } = await prompts2__default.default({
1408
+ type: "select",
1409
+ name: "agent",
1410
+ message: `Would you like to add an ${highlighter.info("agent integration")}?`,
1412
1411
  choices: [
1413
- { name: "npm", value: "npm" },
1414
- { name: "Yarn", value: "yarn" },
1415
- { name: "pnpm", value: "pnpm" },
1416
- { name: "Bun", value: "bun" }
1417
- ],
1418
- default: projectInfo.packageManager
1412
+ { title: "None", value: "none" },
1413
+ { title: "Claude Code", value: "claude-code" },
1414
+ { title: "Cursor", value: "cursor" },
1415
+ { title: "Opencode", value: "opencode" }
1416
+ ]
1419
1417
  });
1420
- if (finalFramework === "next") {
1421
- finalNextRouterType = await prompts.select({
1422
- message: "Select your Next.js router type:",
1423
- choices: [
1424
- { name: "App Router", value: "app" },
1425
- { name: "Pages Router", value: "pages" }
1426
- ],
1427
- default: projectInfo.nextRouterType === "app" ? "app" : "pages"
1428
- });
1418
+ if (agent === void 0) {
1419
+ logger.break();
1420
+ process.exit(1);
1429
1421
  }
1422
+ agentIntegration = agent;
1430
1423
  }
1431
- }
1432
- let agentIntegration = args.agent || "none";
1433
- const shouldAskForAgent = (action === "install-all" || action === "add-agent") && !args.agent;
1434
- if (shouldAskForAgent && !isNonInteractive) {
1435
- const availableAgents = [
1436
- { name: "Claude Code", value: "claude-code" },
1437
- { name: "Cursor", value: "cursor" },
1438
- { name: "Opencode", value: "opencode" }
1439
- ].filter((agent) => !projectInfo.installedAgents.includes(agent.value));
1440
- if (availableAgents.length === 0) {
1441
- console.log(
1442
- `
1443
- ${pc__default.default.green("All agent integrations are already installed.")}
1444
- `
1445
- );
1446
- } else if (action === "add-agent") {
1447
- agentIntegration = await prompts.select({
1448
- message: "Select an agent integration to add:",
1449
- choices: availableAgents
1450
- });
1451
- } else {
1452
- const wantAgentIntegration = await prompts.confirm({
1453
- message: "Do you want to add an agent integration (Claude Code, Cursor, or Opencode)?",
1454
- default: false
1455
- });
1456
- if (wantAgentIntegration) {
1457
- agentIntegration = await prompts.select({
1458
- message: "Select an agent integration:",
1459
- choices: availableAgents
1460
- });
1461
- }
1462
- }
1463
- }
1464
- const shouldTransform = action === "reconfigure" || action === "install-all" || action === "add-agent" && agentIntegration !== "none";
1465
- if (shouldTransform) {
1466
- console.log(`
1467
- ${pc__default.default.magenta("\u269B")} Previewing changes...
1468
- `);
1469
1424
  const result = previewTransform(
1470
1425
  projectInfo.projectRoot,
1471
1426
  finalFramework,
1472
1427
  finalNextRouterType,
1473
1428
  agentIntegration,
1474
- projectInfo.hasReactGrab || action === "add-agent"
1429
+ false
1475
1430
  );
1476
1431
  const packageJsonResult = previewPackageJsonTransform(
1477
1432
  projectInfo.projectRoot,
@@ -1479,24 +1434,22 @@ ${pc__default.default.magenta("\u269B")} Previewing changes...
1479
1434
  projectInfo.installedAgents
1480
1435
  );
1481
1436
  if (!result.success) {
1482
- console.error(`${pc__default.default.red("Error:")} ${result.message}`);
1483
- showDocsLink();
1437
+ logger.break();
1438
+ logger.error(result.message);
1439
+ logger.error(`Visit ${highlighter.info(DOCS_URL)} for manual setup.`);
1440
+ logger.break();
1484
1441
  process.exit(1);
1485
1442
  }
1486
1443
  const hasLayoutChanges = !result.noChanges && result.originalContent && result.newContent;
1487
1444
  const hasPackageJsonChanges = packageJsonResult.success && !packageJsonResult.noChanges && packageJsonResult.originalContent && packageJsonResult.newContent;
1488
- if (result.noChanges && packageJsonResult.noChanges) {
1489
- console.log(`${pc__default.default.cyan("Info:")} ${result.message}`);
1490
- if (packageJsonResult.message) {
1491
- console.log(`${pc__default.default.cyan("Info:")} ${packageJsonResult.message}`);
1492
- }
1493
- } else {
1445
+ if (hasLayoutChanges || hasPackageJsonChanges) {
1446
+ logger.break();
1494
1447
  if (hasLayoutChanges) {
1495
1448
  printDiff(result.filePath, result.originalContent, result.newContent);
1496
1449
  }
1497
1450
  if (hasPackageJsonChanges) {
1498
1451
  if (hasLayoutChanges) {
1499
- console.log("");
1452
+ logger.break();
1500
1453
  }
1501
1454
  printDiff(
1502
1455
  packageJsonResult.filePath,
@@ -1504,104 +1457,92 @@ ${pc__default.default.magenta("\u269B")} Previewing changes...
1504
1457
  packageJsonResult.newContent
1505
1458
  );
1506
1459
  }
1507
- if (hasLayoutChanges || hasPackageJsonChanges) {
1508
- showAccuracyWarning();
1509
- if (!isNonInteractive) {
1510
- const confirmChanges = await prompts.confirm({
1511
- message: "Apply these changes?",
1512
- default: true
1513
- });
1514
- if (!confirmChanges) {
1515
- console.log(`
1516
- ${pc__default.default.yellow("Changes cancelled.")}
1517
- `);
1518
- process.exit(0);
1519
- }
1460
+ logger.break();
1461
+ logger.warn("Auto-detection may not be 100% accurate.");
1462
+ logger.warn("Please verify the changes before committing.");
1463
+ if (!isNonInteractive) {
1464
+ logger.break();
1465
+ const { proceed } = await prompts2__default.default({
1466
+ type: "confirm",
1467
+ name: "proceed",
1468
+ message: "Apply these changes?",
1469
+ initial: true
1470
+ });
1471
+ if (!proceed) {
1472
+ logger.break();
1473
+ logger.log("Changes cancelled.");
1474
+ logger.break();
1475
+ process.exit(0);
1520
1476
  }
1521
1477
  }
1522
- const shouldInstallReactGrab = (action === "install-all" || action === "add-agent") && !projectInfo.hasReactGrab;
1523
- const shouldInstallAgent = agentIntegration !== "none" && !projectInfo.installedAgents.includes(agentIntegration);
1524
- if (!args.skipInstall && (shouldInstallReactGrab || shouldInstallAgent)) {
1525
- const packages = getPackagesToInstall(
1526
- agentIntegration,
1527
- shouldInstallReactGrab
1528
- );
1529
- if (packages.length > 0) {
1530
- console.log(
1531
- `
1532
- ${pc__default.default.magenta("\u269B")} Installing: ${pc__default.default.cyan(packages.join(", "))}
1533
- `
1534
- );
1535
- try {
1536
- installPackages(
1537
- packages,
1538
- finalPackageManager,
1539
- projectInfo.projectRoot
1540
- );
1541
- console.log(`
1542
- ${pc__default.default.green("Packages installed successfully!")}
1543
- `);
1544
- } catch (error) {
1545
- console.error(`
1546
- ${pc__default.default.red("Failed to install packages:")}`, error);
1547
- showDocsLink();
1548
- process.exit(1);
1549
- }
1478
+ }
1479
+ const shouldInstallReactGrab = !projectInfo.hasReactGrab;
1480
+ const shouldInstallAgent = agentIntegration !== "none" && !projectInfo.installedAgents.includes(agentIntegration);
1481
+ if (!opts.skipInstall && (shouldInstallReactGrab || shouldInstallAgent)) {
1482
+ const packages = getPackagesToInstall(agentIntegration, shouldInstallReactGrab);
1483
+ if (packages.length > 0) {
1484
+ const installSpinner = spinner(
1485
+ `Installing ${packages.join(", ")}.`
1486
+ ).start();
1487
+ try {
1488
+ installPackages(packages, finalPackageManager, projectInfo.projectRoot);
1489
+ installSpinner.succeed();
1490
+ } catch (error) {
1491
+ installSpinner.fail();
1492
+ handleError(error);
1550
1493
  }
1551
1494
  }
1552
- if (hasLayoutChanges) {
1553
- const writeResult = applyTransform(result);
1554
- if (!writeResult.success) {
1555
- console.error(`
1556
- ${pc__default.default.red("Error:")} ${writeResult.error}`);
1557
- showDocsLink();
1558
- process.exit(1);
1559
- }
1560
- console.log(`
1561
- ${pc__default.default.green("Applied:")} ${result.filePath}`);
1495
+ }
1496
+ if (hasLayoutChanges) {
1497
+ const writeSpinner = spinner(`Applying changes to ${result.filePath}.`).start();
1498
+ const writeResult = applyTransform(result);
1499
+ if (!writeResult.success) {
1500
+ writeSpinner.fail();
1501
+ logger.break();
1502
+ logger.error(writeResult.error || "Failed to write file.");
1503
+ logger.break();
1504
+ process.exit(1);
1562
1505
  }
1563
- if (hasPackageJsonChanges) {
1564
- const packageJsonWriteResult = applyPackageJsonTransform(packageJsonResult);
1565
- if (!packageJsonWriteResult.success) {
1566
- console.error(
1567
- `
1568
- ${pc__default.default.red("Error:")} ${packageJsonWriteResult.error}`
1569
- );
1570
- showDocsLink();
1571
- process.exit(1);
1572
- }
1573
- console.log(`${pc__default.default.green("Applied:")} ${packageJsonResult.filePath}`);
1506
+ writeSpinner.succeed();
1507
+ }
1508
+ if (hasPackageJsonChanges) {
1509
+ const packageJsonSpinner = spinner(
1510
+ `Applying changes to ${packageJsonResult.filePath}.`
1511
+ ).start();
1512
+ const packageJsonWriteResult = applyPackageJsonTransform(packageJsonResult);
1513
+ if (!packageJsonWriteResult.success) {
1514
+ packageJsonSpinner.fail();
1515
+ logger.break();
1516
+ logger.error(packageJsonWriteResult.error || "Failed to write file.");
1517
+ logger.break();
1518
+ process.exit(1);
1574
1519
  }
1520
+ packageJsonSpinner.succeed();
1575
1521
  }
1576
- }
1577
- console.log(`
1578
- ${pc__default.default.green("Done!")}`);
1579
- console.log(`
1580
- Next steps:`);
1581
- console.log(`- Start your development server`);
1582
- console.log(`- Select an element to copy its context`);
1583
- console.log(`- Learn more at ${pc__default.default.cyan(DOCS_URL)}
1584
- `);
1585
- if (agentIntegration !== "none") {
1586
- console.log(
1587
- `${pc__default.default.magenta("\u269B")} Agent: ${pc__default.default.cyan(AGENT_NAMES[agentIntegration])}`
1522
+ logger.break();
1523
+ logger.log(
1524
+ `${highlighter.success("Success!")} React Grab has been installed.`
1588
1525
  );
1589
- console.log(` Make sure to start the agent server before using it.
1590
- `);
1526
+ logger.log("You may now start your development server.");
1527
+ logger.break();
1528
+ await reportToCli("completed", {
1529
+ framework: finalFramework,
1530
+ packageManager: finalPackageManager,
1531
+ router: finalNextRouterType,
1532
+ agent: agentIntegration !== "none" ? agentIntegration : void 0,
1533
+ isMonorepo: projectInfo.isMonorepo
1534
+ });
1535
+ } catch (error) {
1536
+ handleError(error);
1537
+ await reportToCli("error", void 0, error);
1591
1538
  }
1592
- await reportToCli("completed", {
1593
- framework: finalFramework,
1594
- packageManager: finalPackageManager,
1595
- router: finalNextRouterType,
1596
- agent: agentIntegration !== "none" ? agentIntegration : void 0,
1597
- isMonorepo: projectInfo.isMonorepo
1598
- });
1599
- };
1600
- main().catch(async (error) => {
1601
- console.error(`${pc__default.default.red("Error:")}`, error);
1602
- console.log("\nFor manual installation instructions, visit:");
1603
- console.log(` ${DOCS_URL}
1604
- `);
1605
- await reportToCli("error", void 0, error);
1606
- process.exit(1);
1607
1539
  });
1540
+
1541
+ // src/cli.ts
1542
+ var VERSION2 = "0.0.73";
1543
+ process.on("SIGINT", () => process.exit(0));
1544
+ process.on("SIGTERM", () => process.exit(0));
1545
+ var program = new commander.Command().name("react-grab").description("add React Grab to your project").version(VERSION2, "-v, --version", "display the version number");
1546
+ program.addCommand(init);
1547
+ program.addCommand(add);
1548
+ program.parse();