cursor-kit-cli 1.2.0-beta.2 → 1.2.0-beta.3

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.
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # OS guard – must be macOS
5
+ if [ "$(uname)" != "Darwin" ]; then
6
+ echo "This command only works on macOS." >&2
7
+ exit 1
8
+ fi
9
+
10
+ # === Parse arguments ===
11
+ SKIP_CONFIRM=false
12
+ NEW_APP_NAME=""
13
+
14
+ while [[ $# -gt 0 ]]; do
15
+ case "$1" in
16
+ -y|--yes|--force)
17
+ SKIP_CONFIRM=true
18
+ shift
19
+ ;;
20
+ *)
21
+ NEW_APP_NAME="$1"
22
+ shift
23
+ ;;
24
+ esac
25
+ done
26
+
27
+ if [ -z "$NEW_APP_NAME" ]; then
28
+ echo "Usage: $0 [-y|--yes] \"App Name (e.g. Cursor Enterprise)\"" >&2
29
+ exit 1
30
+ fi
31
+
32
+ APP_PATH="$HOME/Applications/$NEW_APP_NAME.app"
33
+
34
+ # Calculate slug and paths (must match cursor-new-instance logic)
35
+ SLUG="$(echo "$NEW_APP_NAME" | tr '[:upper:]' '[:lower:]' | tr -cd '[:alnum:]')"
36
+ [ -z "$SLUG" ] && SLUG="custom"
37
+
38
+ BUNDLE_ID="com.cursor.$SLUG"
39
+ DATA_DIR="$HOME/Library/Application Support/${NEW_APP_NAME// /}"
40
+
41
+ # Verify instance exists
42
+ if [ ! -d "$APP_PATH" ]; then
43
+ echo "❌ Instance not found at: $APP_PATH" >&2
44
+ exit 1
45
+ fi
46
+
47
+ echo "This will reinstall:"
48
+ echo " App bundle: $APP_PATH"
49
+ echo " Bundle ID: $BUNDLE_ID"
50
+ echo " Data dir: $DATA_DIR (preserved)"
51
+ echo
52
+
53
+ # Skip confirmation if --yes flag is provided
54
+ if [ "$SKIP_CONFIRM" = true ]; then
55
+ ans="y"
56
+ else
57
+ read -r -p "Are you sure? [y/N] " ans
58
+ fi
59
+
60
+ case "$ans" in
61
+ y|Y|yes|YES)
62
+ echo "🔄 Reinstalling $NEW_APP_NAME..."
63
+
64
+ # === Step 1: Remove the app bundle ===
65
+ echo "🗑️ Removing old app bundle..."
66
+ rm -rf "$APP_PATH"
67
+
68
+ # === Step 2: Copy the original app bundle ===
69
+ echo "📦 Copying fresh app bundle..."
70
+ if [ ! -d "/Applications/Cursor.app" ]; then
71
+ echo "❌ Original Cursor.app not found at /Applications/Cursor.app" >&2
72
+ exit 1
73
+ fi
74
+ cp -R "/Applications/Cursor.app" "$APP_PATH"
75
+
76
+ # === Step 3: Give the app its identity ===
77
+ APP="$APP_PATH"
78
+ PLIST="$APP/Contents/Info.plist"
79
+
80
+ echo "📝 Setting CFBundleIdentifier to $BUNDLE_ID..."
81
+ if /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_ID" "$PLIST"; then
82
+ echo "✅ CFBundleIdentifier updated."
83
+ else
84
+ echo "ℹ️ CFBundleIdentifier not found, adding..."
85
+ /usr/libexec/PlistBuddy -c "Add :CFBundleIdentifier string $BUNDLE_ID" "$PLIST"
86
+ echo "✅ CFBundleIdentifier added."
87
+ fi
88
+
89
+ echo "🔏 Re-signing app (ad-hoc signature)..."
90
+ codesign --force --deep --sign - "$APP"
91
+
92
+ # === Step 4: Launch with existing data ===
93
+ echo "🚀 Launching $NEW_APP_NAME with preserved data..."
94
+ open -n "$APP" --args --user-data-dir "$DATA_DIR"
95
+
96
+ echo "✅ Done."
97
+ ;;
98
+ *)
99
+ echo "Cancelled."
100
+ exit 0
101
+ ;;
102
+ esac
package/dist/cli.cjs CHANGED
@@ -1282,7 +1282,7 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1282
1282
  action: {
1283
1283
  type: "string",
1284
1284
  alias: "a",
1285
- description: "Action: 'create' or 'remove'"
1285
+ description: "Action: 'create', 'reinstall', or 'remove'"
1286
1286
  },
1287
1287
  name: {
1288
1288
  type: "string",
@@ -1331,7 +1331,8 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1331
1331
  const binPath = getBinPath();
1332
1332
  const createScript = (0, import_node_path7.join)(binPath, "cursor-new-instance");
1333
1333
  const removeScript = (0, import_node_path7.join)(binPath, "cursor-remove-instance");
1334
- const scriptsExist = (0, import_node_fs2.existsSync)(createScript) && (0, import_node_fs2.existsSync)(removeScript);
1334
+ const reinstallScript = (0, import_node_path7.join)(binPath, "cursor-reinstall-instance.sh");
1335
+ const scriptsExist = (0, import_node_fs2.existsSync)(createScript) && (0, import_node_fs2.existsSync)(removeScript) && (0, import_node_fs2.existsSync)(reinstallScript);
1335
1336
  if (!scriptsExist) {
1336
1337
  s.stop("Prerequisites check failed");
1337
1338
  console.log();
@@ -1355,7 +1356,7 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1355
1356
  const existingInstances = getExistingInstances();
1356
1357
  let action;
1357
1358
  let instanceName;
1358
- if (args.action && ["create", "remove"].includes(args.action)) {
1359
+ if (args.action && ["create", "remove", "reinstall"].includes(args.action)) {
1359
1360
  action = args.action;
1360
1361
  } else {
1361
1362
  const actionResult = await p6.select({
@@ -1366,6 +1367,11 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1366
1367
  label: "Create new instance",
1367
1368
  hint: "Clone Cursor with separate identity"
1368
1369
  },
1370
+ {
1371
+ value: "reinstall",
1372
+ label: "Reinstall instance",
1373
+ hint: existingInstances.length > 0 ? "Fix broken instance after Cursor update" : "No instances to reinstall"
1374
+ },
1369
1375
  {
1370
1376
  value: "remove",
1371
1377
  label: "Remove instance",
@@ -1381,9 +1387,10 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1381
1387
  }
1382
1388
  if (args.name) {
1383
1389
  instanceName = args.name;
1384
- } else if (action === "remove" && existingInstances.length > 0) {
1390
+ } else if ((action === "remove" || action === "reinstall") && existingInstances.length > 0) {
1391
+ const actionLabel2 = action === "remove" ? "remove" : "reinstall";
1385
1392
  const instanceResult = await p6.select({
1386
- message: "Select instance to remove:",
1393
+ message: `Select instance to ${actionLabel2}:`,
1387
1394
  options: existingInstances.map((inst) => ({
1388
1395
  value: inst.name,
1389
1396
  label: inst.name,
@@ -1395,9 +1402,9 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1395
1402
  process.exit(0);
1396
1403
  }
1397
1404
  instanceName = instanceResult;
1398
- } else if (action === "remove" && existingInstances.length === 0) {
1405
+ } else if ((action === "remove" || action === "reinstall") && existingInstances.length === 0) {
1399
1406
  console.log();
1400
- printInfo("No custom Cursor instances found to remove.");
1407
+ printInfo(`No custom Cursor instances found to ${action}.`);
1401
1408
  console.log();
1402
1409
  p6.outro(import_picocolors7.default.dim("Nothing to do"));
1403
1410
  return;
@@ -1425,12 +1432,18 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1425
1432
  console.log();
1426
1433
  console.log(import_picocolors7.default.bold(import_picocolors7.default.cyan(" \u{1F4CB} Summary")));
1427
1434
  console.log();
1428
- console.log(` ${import_picocolors7.default.dim("Action:")} ${action === "create" ? import_picocolors7.default.green("Create") : import_picocolors7.default.yellow("Remove")}`);
1435
+ const actionColor = action === "create" ? import_picocolors7.default.green : action === "reinstall" ? import_picocolors7.default.blue : import_picocolors7.default.yellow;
1436
+ const actionLabel = action === "create" ? "Create" : action === "reinstall" ? "Reinstall" : "Remove";
1437
+ console.log(` ${import_picocolors7.default.dim("Action:")} ${actionColor(actionLabel)}`);
1429
1438
  console.log(` ${import_picocolors7.default.dim("Instance:")} ${highlight(instanceName)}`);
1430
- if (action === "create") {
1439
+ if (action === "create" || action === "reinstall") {
1431
1440
  const slug = instanceName.toLowerCase().replace(/[^a-z0-9]/g, "");
1432
1441
  console.log(` ${import_picocolors7.default.dim("Bundle ID:")} ${import_picocolors7.default.dim("com.cursor.")}${highlight(slug)}`);
1433
1442
  console.log(` ${import_picocolors7.default.dim("Location:")} ${import_picocolors7.default.dim("~/Applications/")}${highlight(instanceName + ".app")}`);
1443
+ if (action === "reinstall") {
1444
+ const dataDir = (0, import_node_path7.join)(process.env.HOME ?? "", "Library", "Application Support", instanceName.replace(/ /g, ""));
1445
+ console.log(` ${import_picocolors7.default.dim("Data:")} ${import_picocolors7.default.green("\u2713")} ${import_picocolors7.default.dim("Preserved at")} ${import_picocolors7.default.dim(dataDir)}`);
1446
+ }
1434
1447
  } else {
1435
1448
  const targetPath = (0, import_node_path7.join)(process.env.HOME ?? "", "Applications", `${instanceName}.app`);
1436
1449
  console.log(` ${import_picocolors7.default.dim("Path:")} ${import_picocolors7.default.dim(targetPath)}`);
@@ -1439,8 +1452,8 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1439
1452
  printDivider();
1440
1453
  console.log();
1441
1454
  const shouldContinue = await p6.confirm({
1442
- message: action === "create" ? "Create this Cursor instance?" : "Remove this Cursor instance? This cannot be undone.",
1443
- initialValue: action === "create"
1455
+ message: action === "create" ? "Create this Cursor instance?" : action === "reinstall" ? "Reinstall this instance? (User data will be preserved)" : "Remove this Cursor instance? This cannot be undone.",
1456
+ initialValue: action !== "remove"
1444
1457
  });
1445
1458
  if (p6.isCancel(shouldContinue) || !shouldContinue) {
1446
1459
  p6.cancel("Operation cancelled");
@@ -1449,8 +1462,8 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1449
1462
  console.log();
1450
1463
  printDivider();
1451
1464
  console.log();
1452
- const scriptPath = action === "create" ? createScript : removeScript;
1453
- const scriptArgs = action === "remove" ? ["--yes", instanceName] : [instanceName];
1465
+ const scriptPath = action === "create" ? createScript : action === "reinstall" ? reinstallScript : removeScript;
1466
+ const scriptArgs = action === "remove" || action === "reinstall" ? ["--yes", instanceName] : [instanceName];
1454
1467
  const exitCode = await runScript(scriptPath, scriptArgs);
1455
1468
  console.log();
1456
1469
  printDivider();
@@ -1463,6 +1476,13 @@ var instanceCommand = (0, import_citty6.defineCommand)({
1463
1476
  console.log(import_picocolors7.default.dim(" \u2022 The new instance should launch automatically"));
1464
1477
  console.log(import_picocolors7.default.dim(" \u2022 Sign in with a different Cursor account"));
1465
1478
  console.log(import_picocolors7.default.dim(" \u2022 Find it in ~/Applications/"));
1479
+ } else if (action === "reinstall") {
1480
+ printSuccess(`Instance ${highlight(instanceName)} reinstalled successfully!`);
1481
+ console.log();
1482
+ console.log(import_picocolors7.default.dim(" The instance has been:"));
1483
+ console.log(import_picocolors7.default.dim(" \u2022 Refreshed with the latest Cursor version"));
1484
+ console.log(import_picocolors7.default.dim(" \u2022 Relaunched with your preserved data"));
1485
+ console.log(import_picocolors7.default.dim(" \u2022 Ready to use with your existing account"));
1466
1486
  } else {
1467
1487
  printSuccess(`Instance ${highlight(instanceName)} removed successfully!`);
1468
1488
  }