cursor-kit-cli 1.5.0 → 1.6.0-beta.1
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/README.md +86 -5
- package/dist/cli.cjs +597 -26
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +604 -25
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1535,8 +1535,8 @@ async function convertPulledFilesForTarget(target, directories) {
|
|
|
1535
1535
|
const skillPath = join6(skillsDir, skillDir);
|
|
1536
1536
|
const skillMdPath = join6(skillPath, "SKILL.md");
|
|
1537
1537
|
const skillMdcPath = join6(skillPath, "SKILL.mdc");
|
|
1538
|
-
const { existsSync:
|
|
1539
|
-
if (
|
|
1538
|
+
const { existsSync: existsSync4 } = await import("fs");
|
|
1539
|
+
if (existsSync4(skillMdPath)) {
|
|
1540
1540
|
const content = readFile(skillMdPath);
|
|
1541
1541
|
writeFile(skillMdcPath, content);
|
|
1542
1542
|
const { rmSync: rmSync2 } = await import("fs");
|
|
@@ -2033,17 +2033,313 @@ import { defineCommand as defineCommand6 } from "citty";
|
|
|
2033
2033
|
import * as p8 from "@clack/prompts";
|
|
2034
2034
|
import pc8 from "picocolors";
|
|
2035
2035
|
import { spawn } from "child_process";
|
|
2036
|
-
import { join as
|
|
2036
|
+
import { join as join10, dirname as dirname3 } from "path";
|
|
2037
2037
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2038
|
-
import { existsSync as
|
|
2038
|
+
import { existsSync as existsSync3, chmodSync as chmodSync2, readdirSync as readdirSync2 } from "fs";
|
|
2039
|
+
|
|
2040
|
+
// src/utils/alias.ts
|
|
2041
|
+
import {
|
|
2042
|
+
appendFileSync,
|
|
2043
|
+
chmodSync,
|
|
2044
|
+
existsSync as existsSync2,
|
|
2045
|
+
mkdirSync as mkdirSync2,
|
|
2046
|
+
readFileSync as readFileSync2,
|
|
2047
|
+
unlinkSync,
|
|
2048
|
+
writeFileSync as writeFileSync2
|
|
2049
|
+
} from "fs";
|
|
2050
|
+
import { homedir } from "os";
|
|
2051
|
+
import { join as join9 } from "path";
|
|
2052
|
+
var CURSOR_KIT_DIR = ".cursor-kit";
|
|
2053
|
+
var ALIASES_FILE = "aliases.json";
|
|
2054
|
+
function getAliasConfigDir() {
|
|
2055
|
+
return join9(homedir(), CURSOR_KIT_DIR);
|
|
2056
|
+
}
|
|
2057
|
+
function getAliasConfigPath() {
|
|
2058
|
+
return join9(getAliasConfigDir(), ALIASES_FILE);
|
|
2059
|
+
}
|
|
2060
|
+
function ensureConfigDir() {
|
|
2061
|
+
const configDir = getAliasConfigDir();
|
|
2062
|
+
if (!existsSync2(configDir)) {
|
|
2063
|
+
mkdirSync2(configDir, { recursive: true });
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
function loadAliasConfig() {
|
|
2067
|
+
const configPath = getAliasConfigPath();
|
|
2068
|
+
if (!existsSync2(configPath)) {
|
|
2069
|
+
return { aliases: {} };
|
|
2070
|
+
}
|
|
2071
|
+
try {
|
|
2072
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
2073
|
+
return JSON.parse(content);
|
|
2074
|
+
} catch {
|
|
2075
|
+
return { aliases: {} };
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
function saveAliasConfig(config) {
|
|
2079
|
+
ensureConfigDir();
|
|
2080
|
+
const configPath = getAliasConfigPath();
|
|
2081
|
+
writeFileSync2(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
2082
|
+
}
|
|
2083
|
+
function getInstanceDataDir(instanceName) {
|
|
2084
|
+
return join9(
|
|
2085
|
+
homedir(),
|
|
2086
|
+
"Library",
|
|
2087
|
+
"Application Support",
|
|
2088
|
+
instanceName.replace(/ /g, "")
|
|
2089
|
+
);
|
|
2090
|
+
}
|
|
2091
|
+
function getInstanceAppPath(instanceName) {
|
|
2092
|
+
return join9(homedir(), "Applications", `${instanceName}.app`);
|
|
2093
|
+
}
|
|
2094
|
+
function generateScriptContent(instanceName) {
|
|
2095
|
+
const dataDir = getInstanceDataDir(instanceName);
|
|
2096
|
+
const appPath = getInstanceAppPath(instanceName);
|
|
2097
|
+
return `#!/usr/bin/env bash
|
|
2098
|
+
# Generated by cursor-kit for instance: ${instanceName}
|
|
2099
|
+
# This script opens the specified directory (or current directory) in the Cursor instance
|
|
2100
|
+
|
|
2101
|
+
set -euo pipefail
|
|
2102
|
+
|
|
2103
|
+
DIR="\${1:-.}"
|
|
2104
|
+
|
|
2105
|
+
# Resolve to absolute path if relative
|
|
2106
|
+
if [[ "$DIR" != /* ]]; then
|
|
2107
|
+
DIR="$(cd "$DIR" 2>/dev/null && pwd)"
|
|
2108
|
+
fi
|
|
2109
|
+
|
|
2110
|
+
DATA_DIR="${dataDir}"
|
|
2111
|
+
APP_PATH="${appPath}"
|
|
2112
|
+
|
|
2113
|
+
if [ ! -d "$APP_PATH" ]; then
|
|
2114
|
+
echo "Error: Cursor instance not found at $APP_PATH" >&2
|
|
2115
|
+
echo "The instance may have been removed. Run 'cursor-kit instance -l' to see available instances." >&2
|
|
2116
|
+
exit 1
|
|
2117
|
+
fi
|
|
2118
|
+
|
|
2119
|
+
open -n "$APP_PATH" --args --user-data-dir "$DATA_DIR" "$DIR"
|
|
2120
|
+
`;
|
|
2121
|
+
}
|
|
2122
|
+
function generateShellFunction(aliasName, instanceName) {
|
|
2123
|
+
const dataDir = getInstanceDataDir(instanceName);
|
|
2124
|
+
const appPath = getInstanceAppPath(instanceName);
|
|
2125
|
+
return `
|
|
2126
|
+
# cursor-kit alias: ${aliasName} -> ${instanceName}
|
|
2127
|
+
${aliasName}() {
|
|
2128
|
+
local DIR="\${1:-.}"
|
|
2129
|
+
if [[ "$DIR" != /* ]]; then
|
|
2130
|
+
DIR="$(cd "$DIR" 2>/dev/null && pwd)"
|
|
2131
|
+
fi
|
|
2132
|
+
local DATA_DIR="${dataDir}"
|
|
2133
|
+
local APP_PATH="${appPath}"
|
|
2134
|
+
if [ ! -d "$APP_PATH" ]; then
|
|
2135
|
+
echo "Error: Cursor instance not found at $APP_PATH" >&2
|
|
2136
|
+
return 1
|
|
2137
|
+
fi
|
|
2138
|
+
open -n "$APP_PATH" --args --user-data-dir "$DATA_DIR" "$DIR"
|
|
2139
|
+
}
|
|
2140
|
+
# end cursor-kit alias: ${aliasName}
|
|
2141
|
+
`;
|
|
2142
|
+
}
|
|
2143
|
+
function detectShellConfigPath() {
|
|
2144
|
+
const home = homedir();
|
|
2145
|
+
const shell = process.env.SHELL ?? "/bin/zsh";
|
|
2146
|
+
if (shell.includes("zsh")) {
|
|
2147
|
+
return join9(home, ".zshrc");
|
|
2148
|
+
}
|
|
2149
|
+
if (shell.includes("bash")) {
|
|
2150
|
+
const bashProfile = join9(home, ".bash_profile");
|
|
2151
|
+
if (existsSync2(bashProfile)) {
|
|
2152
|
+
return bashProfile;
|
|
2153
|
+
}
|
|
2154
|
+
return join9(home, ".bashrc");
|
|
2155
|
+
}
|
|
2156
|
+
return join9(home, ".zshrc");
|
|
2157
|
+
}
|
|
2158
|
+
function getHomeBinDir() {
|
|
2159
|
+
return join9(homedir(), "bin");
|
|
2160
|
+
}
|
|
2161
|
+
function getUsrLocalBinDir() {
|
|
2162
|
+
return "/usr/local/bin";
|
|
2163
|
+
}
|
|
2164
|
+
function ensureBinDir(binDir) {
|
|
2165
|
+
if (!existsSync2(binDir)) {
|
|
2166
|
+
mkdirSync2(binDir, { recursive: true });
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
function createExecutableScript(aliasName, instanceName, targetDir) {
|
|
2170
|
+
ensureBinDir(targetDir);
|
|
2171
|
+
const scriptPath = join9(targetDir, aliasName);
|
|
2172
|
+
const scriptContent = generateScriptContent(instanceName);
|
|
2173
|
+
writeFileSync2(scriptPath, scriptContent, "utf-8");
|
|
2174
|
+
chmodSync(scriptPath, 493);
|
|
2175
|
+
return scriptPath;
|
|
2176
|
+
}
|
|
2177
|
+
function createShellAlias(aliasName, instanceName, shellConfigPath) {
|
|
2178
|
+
const functionContent = generateShellFunction(aliasName, instanceName);
|
|
2179
|
+
if (!existsSync2(shellConfigPath)) {
|
|
2180
|
+
writeFileSync2(shellConfigPath, "", "utf-8");
|
|
2181
|
+
}
|
|
2182
|
+
const existingContent = readFileSync2(shellConfigPath, "utf-8");
|
|
2183
|
+
if (existingContent.includes(`# cursor-kit alias: ${aliasName}`)) {
|
|
2184
|
+
removeShellAlias(aliasName, shellConfigPath);
|
|
2185
|
+
}
|
|
2186
|
+
appendFileSync(shellConfigPath, functionContent, "utf-8");
|
|
2187
|
+
}
|
|
2188
|
+
function removeShellAlias(aliasName, shellConfigPath) {
|
|
2189
|
+
if (!existsSync2(shellConfigPath)) {
|
|
2190
|
+
return false;
|
|
2191
|
+
}
|
|
2192
|
+
const content = readFileSync2(shellConfigPath, "utf-8");
|
|
2193
|
+
const startMarker = `# cursor-kit alias: ${aliasName}`;
|
|
2194
|
+
const endMarker = `# end cursor-kit alias: ${aliasName}`;
|
|
2195
|
+
const startIndex = content.indexOf(startMarker);
|
|
2196
|
+
if (startIndex === -1) {
|
|
2197
|
+
return false;
|
|
2198
|
+
}
|
|
2199
|
+
const endIndex = content.indexOf(endMarker);
|
|
2200
|
+
if (endIndex === -1) {
|
|
2201
|
+
return false;
|
|
2202
|
+
}
|
|
2203
|
+
const before = content.slice(0, startIndex);
|
|
2204
|
+
const after = content.slice(endIndex + endMarker.length);
|
|
2205
|
+
const newContent = (before + after).replace(/\n{3,}/g, "\n\n");
|
|
2206
|
+
writeFileSync2(shellConfigPath, newContent, "utf-8");
|
|
2207
|
+
return true;
|
|
2208
|
+
}
|
|
2209
|
+
function removeExecutableScript(scriptPath) {
|
|
2210
|
+
if (!existsSync2(scriptPath)) {
|
|
2211
|
+
return false;
|
|
2212
|
+
}
|
|
2213
|
+
try {
|
|
2214
|
+
unlinkSync(scriptPath);
|
|
2215
|
+
return true;
|
|
2216
|
+
} catch {
|
|
2217
|
+
return false;
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
function createAlias(options) {
|
|
2221
|
+
const { aliasName, instanceName, storageLocation } = options;
|
|
2222
|
+
try {
|
|
2223
|
+
let scriptPath;
|
|
2224
|
+
let shellConfigPath;
|
|
2225
|
+
switch (storageLocation) {
|
|
2226
|
+
case "shell-config": {
|
|
2227
|
+
shellConfigPath = detectShellConfigPath();
|
|
2228
|
+
createShellAlias(aliasName, instanceName, shellConfigPath);
|
|
2229
|
+
break;
|
|
2230
|
+
}
|
|
2231
|
+
case "usr-local-bin": {
|
|
2232
|
+
scriptPath = createExecutableScript(
|
|
2233
|
+
aliasName,
|
|
2234
|
+
instanceName,
|
|
2235
|
+
getUsrLocalBinDir()
|
|
2236
|
+
);
|
|
2237
|
+
break;
|
|
2238
|
+
}
|
|
2239
|
+
case "home-bin": {
|
|
2240
|
+
scriptPath = createExecutableScript(
|
|
2241
|
+
aliasName,
|
|
2242
|
+
instanceName,
|
|
2243
|
+
getHomeBinDir()
|
|
2244
|
+
);
|
|
2245
|
+
break;
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
const config = loadAliasConfig();
|
|
2249
|
+
config.aliases[aliasName] = {
|
|
2250
|
+
instanceName,
|
|
2251
|
+
aliasName,
|
|
2252
|
+
storageLocation,
|
|
2253
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2254
|
+
scriptPath
|
|
2255
|
+
};
|
|
2256
|
+
saveAliasConfig(config);
|
|
2257
|
+
return { success: true, scriptPath, shellConfigPath };
|
|
2258
|
+
} catch (error) {
|
|
2259
|
+
return {
|
|
2260
|
+
success: false,
|
|
2261
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
2262
|
+
};
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
function removeAlias(aliasName) {
|
|
2266
|
+
const config = loadAliasConfig();
|
|
2267
|
+
const entry = config.aliases[aliasName];
|
|
2268
|
+
if (!entry) {
|
|
2269
|
+
return false;
|
|
2270
|
+
}
|
|
2271
|
+
let removed = false;
|
|
2272
|
+
switch (entry.storageLocation) {
|
|
2273
|
+
case "shell-config": {
|
|
2274
|
+
const shellConfigPath = detectShellConfigPath();
|
|
2275
|
+
removed = removeShellAlias(aliasName, shellConfigPath);
|
|
2276
|
+
break;
|
|
2277
|
+
}
|
|
2278
|
+
case "usr-local-bin": {
|
|
2279
|
+
const scriptPath = join9(getUsrLocalBinDir(), aliasName);
|
|
2280
|
+
removed = removeExecutableScript(scriptPath);
|
|
2281
|
+
break;
|
|
2282
|
+
}
|
|
2283
|
+
case "home-bin": {
|
|
2284
|
+
const scriptPath = join9(getHomeBinDir(), aliasName);
|
|
2285
|
+
removed = removeExecutableScript(scriptPath);
|
|
2286
|
+
break;
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
delete config.aliases[aliasName];
|
|
2290
|
+
saveAliasConfig(config);
|
|
2291
|
+
return removed;
|
|
2292
|
+
}
|
|
2293
|
+
function getAliasForInstance(instanceName) {
|
|
2294
|
+
const config = loadAliasConfig();
|
|
2295
|
+
for (const entry of Object.values(config.aliases)) {
|
|
2296
|
+
if (entry.instanceName === instanceName) {
|
|
2297
|
+
return entry;
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
return null;
|
|
2301
|
+
}
|
|
2302
|
+
function aliasExists(aliasName) {
|
|
2303
|
+
const config = loadAliasConfig();
|
|
2304
|
+
return aliasName in config.aliases;
|
|
2305
|
+
}
|
|
2306
|
+
function generateAliasName(instanceName) {
|
|
2307
|
+
return instanceName.toLowerCase().replace(/^cursor\s*/i, "cursor-").replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
2308
|
+
}
|
|
2309
|
+
function getStorageLocationLabel(location) {
|
|
2310
|
+
switch (location) {
|
|
2311
|
+
case "shell-config":
|
|
2312
|
+
return "Shell config (~/.zshrc or ~/.bashrc)";
|
|
2313
|
+
case "usr-local-bin":
|
|
2314
|
+
return "/usr/local/bin (system-wide)";
|
|
2315
|
+
case "home-bin":
|
|
2316
|
+
return "~/bin (user-local)";
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
function isHomeBinInPath() {
|
|
2320
|
+
const pathEnv = process.env.PATH ?? "";
|
|
2321
|
+
const homeBin = getHomeBinDir();
|
|
2322
|
+
return pathEnv.split(":").some((p9) => p9 === homeBin || p9 === "~/bin" || p9 === "$HOME/bin");
|
|
2323
|
+
}
|
|
2324
|
+
function getPathSetupInstructions() {
|
|
2325
|
+
const shell = process.env.SHELL ?? "/bin/zsh";
|
|
2326
|
+
const configFile = shell.includes("zsh") ? "~/.zshrc" : "~/.bashrc";
|
|
2327
|
+
return `Add the following to your ${configFile}:
|
|
2328
|
+
|
|
2329
|
+
export PATH="$HOME/bin:$PATH"
|
|
2330
|
+
|
|
2331
|
+
Then restart your terminal or run: source ${configFile}`;
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
// src/commands/instance.ts
|
|
2039
2335
|
function getBinPath() {
|
|
2040
2336
|
const currentDir = dirname3(fileURLToPath2(import.meta.url));
|
|
2041
2337
|
const possiblePaths = [
|
|
2042
|
-
|
|
2043
|
-
|
|
2338
|
+
join10(currentDir, "..", "..", "bin"),
|
|
2339
|
+
join10(currentDir, "..", "bin")
|
|
2044
2340
|
];
|
|
2045
2341
|
for (const binPath of possiblePaths) {
|
|
2046
|
-
if (
|
|
2342
|
+
if (existsSync3(binPath)) {
|
|
2047
2343
|
return binPath;
|
|
2048
2344
|
}
|
|
2049
2345
|
}
|
|
@@ -2051,19 +2347,24 @@ function getBinPath() {
|
|
|
2051
2347
|
}
|
|
2052
2348
|
function ensureExecutable(scriptPath) {
|
|
2053
2349
|
try {
|
|
2054
|
-
|
|
2350
|
+
chmodSync2(scriptPath, 493);
|
|
2055
2351
|
} catch {
|
|
2056
2352
|
}
|
|
2057
2353
|
}
|
|
2058
2354
|
function getExistingInstances() {
|
|
2059
|
-
const userAppsDir =
|
|
2060
|
-
if (!
|
|
2355
|
+
const userAppsDir = join10(process.env.HOME ?? "", "Applications");
|
|
2356
|
+
if (!existsSync3(userAppsDir)) return [];
|
|
2061
2357
|
try {
|
|
2062
2358
|
const apps = readdirSync2(userAppsDir);
|
|
2063
|
-
return apps.filter((app) => app.startsWith("Cursor") && app.endsWith(".app") && app !== "Cursor.app").map((app) =>
|
|
2064
|
-
name
|
|
2065
|
-
|
|
2066
|
-
|
|
2359
|
+
return apps.filter((app) => app.startsWith("Cursor") && app.endsWith(".app") && app !== "Cursor.app").map((app) => {
|
|
2360
|
+
const name = app.replace(".app", "");
|
|
2361
|
+
const aliasEntry = getAliasForInstance(name);
|
|
2362
|
+
return {
|
|
2363
|
+
name,
|
|
2364
|
+
path: join10(userAppsDir, app),
|
|
2365
|
+
alias: aliasEntry?.aliasName
|
|
2366
|
+
};
|
|
2367
|
+
});
|
|
2067
2368
|
} catch {
|
|
2068
2369
|
return [];
|
|
2069
2370
|
}
|
|
@@ -2082,6 +2383,180 @@ function runScript(scriptPath, args) {
|
|
|
2082
2383
|
});
|
|
2083
2384
|
});
|
|
2084
2385
|
}
|
|
2386
|
+
async function promptAliasCreation(instanceName, providedAlias, providedLocation, skipConfirmation) {
|
|
2387
|
+
if (!skipConfirmation) {
|
|
2388
|
+
const shouldCreateAlias = await p8.confirm({
|
|
2389
|
+
message: "Would you like to create a shell alias for this instance?",
|
|
2390
|
+
initialValue: true
|
|
2391
|
+
});
|
|
2392
|
+
if (p8.isCancel(shouldCreateAlias) || !shouldCreateAlias) {
|
|
2393
|
+
return null;
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
let aliasName;
|
|
2397
|
+
const suggestedAlias = generateAliasName(instanceName);
|
|
2398
|
+
if (providedAlias) {
|
|
2399
|
+
aliasName = providedAlias;
|
|
2400
|
+
} else {
|
|
2401
|
+
const aliasResult = await p8.text({
|
|
2402
|
+
message: "Enter alias name:",
|
|
2403
|
+
placeholder: suggestedAlias,
|
|
2404
|
+
initialValue: suggestedAlias,
|
|
2405
|
+
validate: (value) => {
|
|
2406
|
+
if (!value.trim()) return "Alias name is required";
|
|
2407
|
+
if (!/^[a-z0-9-]+$/.test(value)) return "Alias must contain only lowercase letters, numbers, and hyphens";
|
|
2408
|
+
if (aliasExists(value)) return `Alias "${value}" already exists`;
|
|
2409
|
+
return void 0;
|
|
2410
|
+
}
|
|
2411
|
+
});
|
|
2412
|
+
if (p8.isCancel(aliasResult)) {
|
|
2413
|
+
return null;
|
|
2414
|
+
}
|
|
2415
|
+
aliasName = aliasResult;
|
|
2416
|
+
}
|
|
2417
|
+
let location;
|
|
2418
|
+
if (providedLocation && ["shell-config", "usr-local-bin", "home-bin"].includes(providedLocation)) {
|
|
2419
|
+
location = providedLocation;
|
|
2420
|
+
} else {
|
|
2421
|
+
const locationResult = await p8.select({
|
|
2422
|
+
message: "Where should the alias be stored?",
|
|
2423
|
+
options: [
|
|
2424
|
+
{
|
|
2425
|
+
value: "shell-config",
|
|
2426
|
+
label: "Shell config",
|
|
2427
|
+
hint: detectShellConfigPath()
|
|
2428
|
+
},
|
|
2429
|
+
{
|
|
2430
|
+
value: "home-bin",
|
|
2431
|
+
label: "~/bin",
|
|
2432
|
+
hint: "User-local executable scripts"
|
|
2433
|
+
},
|
|
2434
|
+
{
|
|
2435
|
+
value: "usr-local-bin",
|
|
2436
|
+
label: "/usr/local/bin",
|
|
2437
|
+
hint: "System-wide (may require sudo)"
|
|
2438
|
+
}
|
|
2439
|
+
]
|
|
2440
|
+
});
|
|
2441
|
+
if (p8.isCancel(locationResult)) {
|
|
2442
|
+
return null;
|
|
2443
|
+
}
|
|
2444
|
+
location = locationResult;
|
|
2445
|
+
}
|
|
2446
|
+
return { aliasName, location };
|
|
2447
|
+
}
|
|
2448
|
+
async function handleAliasCreation(instanceName, aliasName, location) {
|
|
2449
|
+
const result = createAlias({
|
|
2450
|
+
aliasName,
|
|
2451
|
+
instanceName,
|
|
2452
|
+
storageLocation: location
|
|
2453
|
+
});
|
|
2454
|
+
if (!result.success) {
|
|
2455
|
+
printWarning(`Failed to create alias: ${result.error}`);
|
|
2456
|
+
return false;
|
|
2457
|
+
}
|
|
2458
|
+
console.log();
|
|
2459
|
+
printSuccess(`Alias ${highlight(aliasName)} created!`);
|
|
2460
|
+
console.log(pc8.dim(` \u2514\u2500 Location: ${getStorageLocationLabel(location)}`));
|
|
2461
|
+
if (location === "home-bin" && !isHomeBinInPath()) {
|
|
2462
|
+
console.log();
|
|
2463
|
+
printWarning("~/bin is not in your PATH");
|
|
2464
|
+
console.log(pc8.dim(getPathSetupInstructions()));
|
|
2465
|
+
}
|
|
2466
|
+
if (location === "shell-config") {
|
|
2467
|
+
console.log();
|
|
2468
|
+
console.log(pc8.dim(" Restart your terminal or run:"));
|
|
2469
|
+
console.log(pc8.dim(` source ${detectShellConfigPath()}`));
|
|
2470
|
+
}
|
|
2471
|
+
console.log();
|
|
2472
|
+
console.log(pc8.dim(" Usage:"));
|
|
2473
|
+
console.log(pc8.dim(` ${aliasName} . # Open current directory`));
|
|
2474
|
+
console.log(pc8.dim(` ${aliasName} /path/to/dir # Open specific directory`));
|
|
2475
|
+
return true;
|
|
2476
|
+
}
|
|
2477
|
+
async function handleAliasRemoval(instanceName) {
|
|
2478
|
+
const aliasEntry = getAliasForInstance(instanceName);
|
|
2479
|
+
if (!aliasEntry) {
|
|
2480
|
+
return;
|
|
2481
|
+
}
|
|
2482
|
+
const shouldRemove = await p8.confirm({
|
|
2483
|
+
message: `Remove associated alias "${aliasEntry.aliasName}"?`,
|
|
2484
|
+
initialValue: true
|
|
2485
|
+
});
|
|
2486
|
+
if (p8.isCancel(shouldRemove) || !shouldRemove) {
|
|
2487
|
+
return;
|
|
2488
|
+
}
|
|
2489
|
+
const removed = removeAlias(aliasEntry.aliasName);
|
|
2490
|
+
if (removed) {
|
|
2491
|
+
printSuccess(`Alias ${highlight(aliasEntry.aliasName)} removed`);
|
|
2492
|
+
} else {
|
|
2493
|
+
printWarning(`Could not remove alias ${aliasEntry.aliasName}`);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
async function handleAliasAction(instanceName, providedAlias, providedLocation) {
|
|
2497
|
+
const existingAlias = getAliasForInstance(instanceName);
|
|
2498
|
+
if (existingAlias) {
|
|
2499
|
+
console.log();
|
|
2500
|
+
printInfo(`Instance ${highlight(instanceName)} already has alias: ${highlight(existingAlias.aliasName)}`);
|
|
2501
|
+
console.log(pc8.dim(` \u2514\u2500 Location: ${getStorageLocationLabel(existingAlias.storageLocation)}`));
|
|
2502
|
+
console.log();
|
|
2503
|
+
const updateChoice = await p8.select({
|
|
2504
|
+
message: "What would you like to do?",
|
|
2505
|
+
options: [
|
|
2506
|
+
{
|
|
2507
|
+
value: "update",
|
|
2508
|
+
label: "Update alias",
|
|
2509
|
+
hint: "Change alias name or location"
|
|
2510
|
+
},
|
|
2511
|
+
{
|
|
2512
|
+
value: "remove",
|
|
2513
|
+
label: "Remove alias",
|
|
2514
|
+
hint: "Delete the existing alias"
|
|
2515
|
+
},
|
|
2516
|
+
{
|
|
2517
|
+
value: "keep",
|
|
2518
|
+
label: "Keep current alias",
|
|
2519
|
+
hint: "No changes"
|
|
2520
|
+
}
|
|
2521
|
+
]
|
|
2522
|
+
});
|
|
2523
|
+
if (p8.isCancel(updateChoice) || updateChoice === "keep") {
|
|
2524
|
+
p8.outro(pc8.dim("No changes made"));
|
|
2525
|
+
return;
|
|
2526
|
+
}
|
|
2527
|
+
if (updateChoice === "remove") {
|
|
2528
|
+
const removed = removeAlias(existingAlias.aliasName);
|
|
2529
|
+
if (removed) {
|
|
2530
|
+
console.log();
|
|
2531
|
+
printSuccess(`Alias ${highlight(existingAlias.aliasName)} removed`);
|
|
2532
|
+
console.log();
|
|
2533
|
+
p8.outro(pc8.green("\u2728 Done!"));
|
|
2534
|
+
} else {
|
|
2535
|
+
printWarning(`Could not remove alias ${existingAlias.aliasName}`);
|
|
2536
|
+
p8.outro(pc8.yellow("Check file permissions"));
|
|
2537
|
+
}
|
|
2538
|
+
return;
|
|
2539
|
+
}
|
|
2540
|
+
removeAlias(existingAlias.aliasName);
|
|
2541
|
+
}
|
|
2542
|
+
const aliasConfig = await promptAliasCreation(
|
|
2543
|
+
instanceName,
|
|
2544
|
+
providedAlias,
|
|
2545
|
+
providedLocation,
|
|
2546
|
+
true
|
|
2547
|
+
);
|
|
2548
|
+
if (!aliasConfig) {
|
|
2549
|
+
p8.outro(pc8.dim("Alias creation cancelled"));
|
|
2550
|
+
return;
|
|
2551
|
+
}
|
|
2552
|
+
const success = await handleAliasCreation(instanceName, aliasConfig.aliasName, aliasConfig.location);
|
|
2553
|
+
if (success) {
|
|
2554
|
+
console.log();
|
|
2555
|
+
p8.outro(pc8.green("\u2728 Done!"));
|
|
2556
|
+
} else {
|
|
2557
|
+
p8.outro(pc8.yellow("Alias creation failed"));
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2085
2560
|
var instanceCommand = defineCommand6({
|
|
2086
2561
|
meta: {
|
|
2087
2562
|
name: "instance",
|
|
@@ -2091,7 +2566,7 @@ var instanceCommand = defineCommand6({
|
|
|
2091
2566
|
action: {
|
|
2092
2567
|
type: "string",
|
|
2093
2568
|
alias: "a",
|
|
2094
|
-
description: "Action: 'create', 'reinstall', or '
|
|
2569
|
+
description: "Action: 'create', 'reinstall', 'remove', or 'alias'"
|
|
2095
2570
|
},
|
|
2096
2571
|
name: {
|
|
2097
2572
|
type: "string",
|
|
@@ -2103,6 +2578,20 @@ var instanceCommand = defineCommand6({
|
|
|
2103
2578
|
alias: "l",
|
|
2104
2579
|
description: "List existing Cursor instances",
|
|
2105
2580
|
default: false
|
|
2581
|
+
},
|
|
2582
|
+
alias: {
|
|
2583
|
+
type: "string",
|
|
2584
|
+
alias: "A",
|
|
2585
|
+
description: "Shell alias name for the instance (e.g. 'cursor-work')"
|
|
2586
|
+
},
|
|
2587
|
+
aliasLocation: {
|
|
2588
|
+
type: "string",
|
|
2589
|
+
description: "Alias storage location: 'shell-config', 'usr-local-bin', or 'home-bin'"
|
|
2590
|
+
},
|
|
2591
|
+
skipAlias: {
|
|
2592
|
+
type: "boolean",
|
|
2593
|
+
description: "Skip alias creation prompt",
|
|
2594
|
+
default: false
|
|
2106
2595
|
}
|
|
2107
2596
|
},
|
|
2108
2597
|
async run({ args }) {
|
|
@@ -2126,7 +2615,8 @@ var instanceCommand = defineCommand6({
|
|
|
2126
2615
|
console.log(pc8.bold(pc8.cyan(" \u{1F5A5} Cursor Instances")) + pc8.dim(` (${instances.length})`));
|
|
2127
2616
|
console.log();
|
|
2128
2617
|
for (const instance of instances) {
|
|
2129
|
-
|
|
2618
|
+
const aliasInfo = instance.alias ? pc8.dim(` (alias: ${pc8.cyan(instance.alias)})`) : "";
|
|
2619
|
+
console.log(` ${pc8.green("\u25CF")} ${highlight(instance.name)}${aliasInfo}`);
|
|
2130
2620
|
console.log(pc8.dim(` \u2514\u2500 ${instance.path}`));
|
|
2131
2621
|
}
|
|
2132
2622
|
}
|
|
@@ -2135,13 +2625,55 @@ var instanceCommand = defineCommand6({
|
|
|
2135
2625
|
p8.outro(pc8.dim(`Total: ${instances.length} instance${instances.length !== 1 ? "s" : ""}`));
|
|
2136
2626
|
return;
|
|
2137
2627
|
}
|
|
2628
|
+
const existingInstances = getExistingInstances();
|
|
2629
|
+
if (args.action === "alias") {
|
|
2630
|
+
if (existingInstances.length === 0) {
|
|
2631
|
+
console.log();
|
|
2632
|
+
printInfo("No custom Cursor instances found.");
|
|
2633
|
+
console.log(pc8.dim(" Create an instance first with: ") + highlight("cursor-kit instance -a create"));
|
|
2634
|
+
console.log();
|
|
2635
|
+
p8.outro(pc8.dim("Nothing to do"));
|
|
2636
|
+
return;
|
|
2637
|
+
}
|
|
2638
|
+
let instanceName2;
|
|
2639
|
+
if (args.name) {
|
|
2640
|
+
const found = existingInstances.find((i) => i.name === args.name);
|
|
2641
|
+
if (!found) {
|
|
2642
|
+
printWarning(`Instance "${args.name}" not found.`);
|
|
2643
|
+
console.log(pc8.dim(" Available instances:"));
|
|
2644
|
+
for (const inst of existingInstances) {
|
|
2645
|
+
console.log(pc8.dim(` \u2022 ${inst.name}`));
|
|
2646
|
+
}
|
|
2647
|
+
console.log();
|
|
2648
|
+
p8.outro(pc8.dim("Nothing to do"));
|
|
2649
|
+
return;
|
|
2650
|
+
}
|
|
2651
|
+
instanceName2 = args.name;
|
|
2652
|
+
} else {
|
|
2653
|
+
const instanceResult = await p8.select({
|
|
2654
|
+
message: "Select instance to manage alias:",
|
|
2655
|
+
options: existingInstances.map((inst) => ({
|
|
2656
|
+
value: inst.name,
|
|
2657
|
+
label: inst.alias ? `${inst.name} (alias: ${inst.alias})` : inst.name,
|
|
2658
|
+
hint: inst.alias ? "Has alias" : "No alias"
|
|
2659
|
+
}))
|
|
2660
|
+
});
|
|
2661
|
+
if (p8.isCancel(instanceResult)) {
|
|
2662
|
+
p8.cancel("Operation cancelled");
|
|
2663
|
+
process.exit(0);
|
|
2664
|
+
}
|
|
2665
|
+
instanceName2 = instanceResult;
|
|
2666
|
+
}
|
|
2667
|
+
await handleAliasAction(instanceName2, args.alias, args.aliasLocation);
|
|
2668
|
+
return;
|
|
2669
|
+
}
|
|
2138
2670
|
const s = p8.spinner();
|
|
2139
2671
|
s.start("Checking prerequisites...");
|
|
2140
2672
|
const binPath = getBinPath();
|
|
2141
|
-
const createScript =
|
|
2142
|
-
const removeScript =
|
|
2143
|
-
const reinstallScript =
|
|
2144
|
-
const scriptsExist =
|
|
2673
|
+
const createScript = join10(binPath, "cursor-new-instance");
|
|
2674
|
+
const removeScript = join10(binPath, "cursor-remove-instance");
|
|
2675
|
+
const reinstallScript = join10(binPath, "cursor-reinstall-instance.sh");
|
|
2676
|
+
const scriptsExist = existsSync3(createScript) && existsSync3(removeScript) && existsSync3(reinstallScript);
|
|
2145
2677
|
if (!scriptsExist) {
|
|
2146
2678
|
s.stop("Prerequisites check failed");
|
|
2147
2679
|
console.log();
|
|
@@ -2152,7 +2684,7 @@ var instanceCommand = defineCommand6({
|
|
|
2152
2684
|
process.exit(1);
|
|
2153
2685
|
}
|
|
2154
2686
|
const originalCursor = "/Applications/Cursor.app";
|
|
2155
|
-
if (!
|
|
2687
|
+
if (!existsSync3(originalCursor)) {
|
|
2156
2688
|
s.stop("Prerequisites check failed");
|
|
2157
2689
|
console.log();
|
|
2158
2690
|
printWarning("Cursor.app not found in /Applications");
|
|
@@ -2162,7 +2694,6 @@ var instanceCommand = defineCommand6({
|
|
|
2162
2694
|
process.exit(1);
|
|
2163
2695
|
}
|
|
2164
2696
|
s.stop("Prerequisites verified");
|
|
2165
|
-
const existingInstances = getExistingInstances();
|
|
2166
2697
|
let action;
|
|
2167
2698
|
let instanceName;
|
|
2168
2699
|
if (args.action && ["create", "remove", "reinstall"].includes(args.action)) {
|
|
@@ -2176,6 +2707,11 @@ var instanceCommand = defineCommand6({
|
|
|
2176
2707
|
label: "Create new instance",
|
|
2177
2708
|
hint: "Clone Cursor with separate identity"
|
|
2178
2709
|
},
|
|
2710
|
+
{
|
|
2711
|
+
value: "alias",
|
|
2712
|
+
label: "Manage alias",
|
|
2713
|
+
hint: existingInstances.length > 0 ? "Add or update shell alias for instance" : "No instances available"
|
|
2714
|
+
},
|
|
2179
2715
|
{
|
|
2180
2716
|
value: "reinstall",
|
|
2181
2717
|
label: "Reinstall instance",
|
|
@@ -2193,6 +2729,30 @@ var instanceCommand = defineCommand6({
|
|
|
2193
2729
|
process.exit(0);
|
|
2194
2730
|
}
|
|
2195
2731
|
action = actionResult;
|
|
2732
|
+
if (action === "alias") {
|
|
2733
|
+
if (existingInstances.length === 0) {
|
|
2734
|
+
console.log();
|
|
2735
|
+
printInfo("No custom Cursor instances found.");
|
|
2736
|
+
console.log(pc8.dim(" Create an instance first."));
|
|
2737
|
+
console.log();
|
|
2738
|
+
p8.outro(pc8.dim("Nothing to do"));
|
|
2739
|
+
return;
|
|
2740
|
+
}
|
|
2741
|
+
const instanceResult = await p8.select({
|
|
2742
|
+
message: "Select instance to manage alias:",
|
|
2743
|
+
options: existingInstances.map((inst) => ({
|
|
2744
|
+
value: inst.name,
|
|
2745
|
+
label: inst.alias ? `${inst.name} (alias: ${inst.alias})` : inst.name,
|
|
2746
|
+
hint: inst.alias ? "Has alias" : "No alias"
|
|
2747
|
+
}))
|
|
2748
|
+
});
|
|
2749
|
+
if (p8.isCancel(instanceResult)) {
|
|
2750
|
+
p8.cancel("Operation cancelled");
|
|
2751
|
+
process.exit(0);
|
|
2752
|
+
}
|
|
2753
|
+
await handleAliasAction(instanceResult, args.alias, args.aliasLocation);
|
|
2754
|
+
return;
|
|
2755
|
+
}
|
|
2196
2756
|
}
|
|
2197
2757
|
if (args.name) {
|
|
2198
2758
|
instanceName = args.name;
|
|
@@ -2202,7 +2762,7 @@ var instanceCommand = defineCommand6({
|
|
|
2202
2762
|
message: `Select instance to ${actionLabel2}:`,
|
|
2203
2763
|
options: existingInstances.map((inst) => ({
|
|
2204
2764
|
value: inst.name,
|
|
2205
|
-
label: inst.name,
|
|
2765
|
+
label: inst.alias ? `${inst.name} (alias: ${inst.alias})` : inst.name,
|
|
2206
2766
|
hint: inst.path
|
|
2207
2767
|
}))
|
|
2208
2768
|
});
|
|
@@ -2250,12 +2810,16 @@ var instanceCommand = defineCommand6({
|
|
|
2250
2810
|
console.log(` ${pc8.dim("Bundle ID:")} ${pc8.dim("com.cursor.")}${highlight(slug)}`);
|
|
2251
2811
|
console.log(` ${pc8.dim("Location:")} ${pc8.dim("~/Applications/")}${highlight(instanceName + ".app")}`);
|
|
2252
2812
|
if (action === "reinstall") {
|
|
2253
|
-
const dataDir =
|
|
2813
|
+
const dataDir = join10(process.env.HOME ?? "", "Library", "Application Support", instanceName.replace(/ /g, ""));
|
|
2254
2814
|
console.log(` ${pc8.dim("Data:")} ${pc8.green("\u2713")} ${pc8.dim("Preserved at")} ${pc8.dim(dataDir)}`);
|
|
2255
2815
|
}
|
|
2256
2816
|
} else {
|
|
2257
|
-
const targetPath =
|
|
2817
|
+
const targetPath = join10(process.env.HOME ?? "", "Applications", `${instanceName}.app`);
|
|
2258
2818
|
console.log(` ${pc8.dim("Path:")} ${pc8.dim(targetPath)}`);
|
|
2819
|
+
const aliasEntry = getAliasForInstance(instanceName);
|
|
2820
|
+
if (aliasEntry) {
|
|
2821
|
+
console.log(` ${pc8.dim("Alias:")} ${pc8.yellow(aliasEntry.aliasName)} ${pc8.dim("(will be removed)")}`);
|
|
2822
|
+
}
|
|
2259
2823
|
}
|
|
2260
2824
|
console.log();
|
|
2261
2825
|
printDivider();
|
|
@@ -2280,6 +2844,20 @@ var instanceCommand = defineCommand6({
|
|
|
2280
2844
|
if (exitCode === 0) {
|
|
2281
2845
|
if (action === "create") {
|
|
2282
2846
|
printSuccess(`Instance ${highlight(instanceName)} created successfully!`);
|
|
2847
|
+
if (!args.skipAlias) {
|
|
2848
|
+
console.log();
|
|
2849
|
+
const aliasConfig = await promptAliasCreation(
|
|
2850
|
+
instanceName,
|
|
2851
|
+
args.alias,
|
|
2852
|
+
args.aliasLocation
|
|
2853
|
+
);
|
|
2854
|
+
if (aliasConfig) {
|
|
2855
|
+
await handleAliasCreation(instanceName, aliasConfig.aliasName, aliasConfig.location);
|
|
2856
|
+
}
|
|
2857
|
+
} else if (args.alias) {
|
|
2858
|
+
const location = args.aliasLocation ?? "shell-config";
|
|
2859
|
+
await handleAliasCreation(instanceName, args.alias, location);
|
|
2860
|
+
}
|
|
2283
2861
|
console.log();
|
|
2284
2862
|
console.log(pc8.dim(" Next steps:"));
|
|
2285
2863
|
console.log(pc8.dim(" \u2022 The new instance should launch automatically"));
|
|
@@ -2293,6 +2871,7 @@ var instanceCommand = defineCommand6({
|
|
|
2293
2871
|
console.log(pc8.dim(" \u2022 Relaunched with your preserved data"));
|
|
2294
2872
|
console.log(pc8.dim(" \u2022 Ready to use with your existing account"));
|
|
2295
2873
|
} else {
|
|
2874
|
+
await handleAliasRemoval(instanceName);
|
|
2296
2875
|
printSuccess(`Instance ${highlight(instanceName)} removed successfully!`);
|
|
2297
2876
|
}
|
|
2298
2877
|
console.log();
|