cursor-kit-cli 1.1.1 → 1.2.0-beta.2
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 +36 -0
- package/bin/cursor-new-instance +74 -0
- package/bin/cursor-remove-instance +69 -0
- package/dist/cli.cjs +601 -62
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +601 -62
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +39 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +33 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/templates/commands/docs.md +5 -3
- package/templates/commands/explain.md +5 -3
- package/templates/commands/fix.md +5 -3
- package/templates/commands/implement.md +5 -3
- package/templates/commands/refactor.md +5 -3
- package/templates/commands/review.md +5 -3
- package/templates/commands/test.md +5 -3
- package/templates/manifest.json +11 -8
- package/templates/rules/git.mdc +0 -2
- package/templates/rules/toc.mdc +17 -9
- package/templates/skills/aesthetic/SKILL.md +121 -0
- package/templates/skills/aesthetic/assets/design-guideline-template.md +163 -0
- package/templates/skills/aesthetic/assets/design-story-template.md +135 -0
- package/templates/skills/aesthetic/references/design-principles.md +62 -0
- package/templates/skills/aesthetic/references/design-resources.md +75 -0
- package/templates/skills/aesthetic/references/micro-interactions.md +53 -0
- package/templates/skills/aesthetic/references/storytelling-design.md +50 -0
- package/templates/skills/backend-development/SKILL.mdc +95 -0
- package/templates/skills/backend-development/references/backend-api-design.md +495 -0
- package/templates/skills/backend-development/references/backend-architecture.md +454 -0
- package/templates/skills/backend-development/references/backend-authentication.md +338 -0
- package/templates/skills/backend-development/references/backend-code-quality.md +659 -0
- package/templates/skills/backend-development/references/backend-debugging.md +904 -0
- package/templates/skills/backend-development/references/backend-devops.md +494 -0
- package/templates/skills/backend-development/references/backend-mindset.md +387 -0
- package/templates/skills/backend-development/references/backend-performance.md +397 -0
- package/templates/skills/backend-development/references/backend-security.md +290 -0
- package/templates/skills/backend-development/references/backend-technologies.md +256 -0
- package/templates/skills/backend-development/references/backend-testing.md +429 -0
- package/templates/skills/frontend-design/SKILL.mdc +41 -0
- package/templates/skills/frontend-design/references/animejs.md +396 -0
- package/templates/skills/frontend-development/SKILL.mdc +399 -0
- package/templates/skills/frontend-development/resources/common-patterns.md +331 -0
- package/templates/skills/frontend-development/resources/complete-examples.md +872 -0
- package/templates/skills/frontend-development/resources/component-patterns.md +502 -0
- package/templates/skills/frontend-development/resources/data-fetching.md +767 -0
- package/templates/skills/frontend-development/resources/file-organization.md +502 -0
- package/templates/skills/frontend-development/resources/loading-and-error-states.md +501 -0
- package/templates/skills/frontend-development/resources/performance.md +406 -0
- package/templates/skills/frontend-development/resources/routing-guide.md +364 -0
- package/templates/skills/frontend-development/resources/styling-guide.md +428 -0
- package/templates/skills/frontend-development/resources/typescript-standards.md +418 -0
- package/templates/skills/problem-solving/SKILL.mdc +96 -0
- package/templates/skills/problem-solving/references/attribution.md +69 -0
- package/templates/skills/problem-solving/references/collision-zone-thinking.md +79 -0
- package/templates/skills/problem-solving/references/inversion-exercise.md +91 -0
- package/templates/skills/problem-solving/references/meta-pattern-recognition.md +87 -0
- package/templates/skills/problem-solving/references/scale-game.md +95 -0
- package/templates/skills/problem-solving/references/simplification-cascades.md +80 -0
- package/templates/skills/problem-solving/references/when-stuck.md +72 -0
- package/templates/skills/research/SKILL.mdc +168 -0
- package/templates/skills/sequential-thinking/.env.example +8 -0
- package/templates/skills/sequential-thinking/README.md +183 -0
- package/templates/skills/sequential-thinking/SKILL.mdc +94 -0
- package/templates/skills/sequential-thinking/package.json +31 -0
- package/templates/skills/sequential-thinking/references/advanced-strategies.md +79 -0
- package/templates/skills/sequential-thinking/references/advanced-techniques.md +76 -0
- package/templates/skills/sequential-thinking/references/core-patterns.md +95 -0
- package/templates/skills/sequential-thinking/references/examples-api.md +88 -0
- package/templates/skills/sequential-thinking/references/examples-architecture.md +94 -0
- package/templates/skills/sequential-thinking/references/examples-debug.md +90 -0
- package/templates/skills/sequential-thinking/scripts/format-thought.js +159 -0
- package/templates/skills/sequential-thinking/scripts/process-thought.js +236 -0
- package/templates/skills/sequential-thinking/tests/format-thought.test.js +133 -0
- package/templates/skills/sequential-thinking/tests/process-thought.test.js +215 -0
- package/templates/skills/ui-styling/LICENSE.txt +202 -0
- package/templates/skills/ui-styling/SKILL.mdc +321 -0
- package/templates/skills/ui-styling/references/canvas-design-system.md +320 -0
- package/templates/skills/ui-styling/references/shadcn-accessibility.md +471 -0
- package/templates/skills/ui-styling/references/shadcn-components.md +424 -0
- package/templates/skills/ui-styling/references/shadcn-theming.md +373 -0
- package/templates/skills/ui-styling/references/tailwind-customization.md +483 -0
- package/templates/skills/ui-styling/references/tailwind-responsive.md +382 -0
- package/templates/skills/ui-styling/references/tailwind-utilities.md +455 -0
- package/templates/rules/frontend-design.mdc +0 -48
- package/templates/rules/performance.mdc +0 -54
- package/templates/rules/react.mdc +0 -58
- package/templates/rules/security.mdc +0 -50
- package/templates/rules/testing.mdc +0 -54
- package/templates/rules/typescript.mdc +0 -36
package/dist/cli.cjs
CHANGED
|
@@ -28,7 +28,7 @@ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${_
|
|
|
28
28
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
29
29
|
|
|
30
30
|
// src/cli.ts
|
|
31
|
-
var
|
|
31
|
+
var import_citty7 = require("citty");
|
|
32
32
|
var import_node_module = require("module");
|
|
33
33
|
|
|
34
34
|
// src/utils/branding.ts
|
|
@@ -54,6 +54,9 @@ function printSuccess(message) {
|
|
|
54
54
|
function printInfo(message) {
|
|
55
55
|
console.log(import_picocolors.default.cyan("\u2139") + import_picocolors.default.dim(" ") + message);
|
|
56
56
|
}
|
|
57
|
+
function printWarning(message) {
|
|
58
|
+
console.log(import_picocolors.default.yellow("\u26A0") + import_picocolors.default.dim(" ") + message);
|
|
59
|
+
}
|
|
57
60
|
function printDivider() {
|
|
58
61
|
console.log(import_picocolors.default.dim("\u2500".repeat(50)));
|
|
59
62
|
}
|
|
@@ -63,8 +66,8 @@ function printVersion(version) {
|
|
|
63
66
|
);
|
|
64
67
|
console.log();
|
|
65
68
|
}
|
|
66
|
-
function highlight(
|
|
67
|
-
return import_picocolors.default.cyan(
|
|
69
|
+
function highlight(text3) {
|
|
70
|
+
return import_picocolors.default.cyan(text3);
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
// src/commands/init.ts
|
|
@@ -99,6 +102,9 @@ function removeFile(path) {
|
|
|
99
102
|
(0, import_node_fs.rmSync)(path, { recursive: true });
|
|
100
103
|
}
|
|
101
104
|
}
|
|
105
|
+
function copyDir(src, dest) {
|
|
106
|
+
(0, import_node_fs.cpSync)(src, dest, { recursive: true });
|
|
107
|
+
}
|
|
102
108
|
function listFiles(dir, extension) {
|
|
103
109
|
if (!dirExists(dir)) return [];
|
|
104
110
|
const files = (0, import_node_fs.readdirSync)(dir);
|
|
@@ -107,6 +113,13 @@ function listFiles(dir, extension) {
|
|
|
107
113
|
}
|
|
108
114
|
return files;
|
|
109
115
|
}
|
|
116
|
+
function listDirs(dir) {
|
|
117
|
+
if (!dirExists(dir)) return [];
|
|
118
|
+
return (0, import_node_fs.readdirSync)(dir).filter((item) => {
|
|
119
|
+
const itemPath = (0, import_node_path.join)(dir, item);
|
|
120
|
+
return (0, import_node_fs.statSync)(itemPath).isDirectory();
|
|
121
|
+
});
|
|
122
|
+
}
|
|
110
123
|
function getCursorDir(cwd = process.cwd()) {
|
|
111
124
|
return (0, import_node_path.join)(cwd, ".cursor");
|
|
112
125
|
}
|
|
@@ -116,10 +129,17 @@ function getCommandsDir(cwd = process.cwd()) {
|
|
|
116
129
|
function getRulesDir(cwd = process.cwd()) {
|
|
117
130
|
return (0, import_node_path.join)(getCursorDir(cwd), "rules");
|
|
118
131
|
}
|
|
132
|
+
function getSkillsDir(cwd = process.cwd()) {
|
|
133
|
+
return (0, import_node_path.join)(getCursorDir(cwd), "skills");
|
|
134
|
+
}
|
|
119
135
|
function getConflictingFiles(dir, files) {
|
|
120
136
|
if (!dirExists(dir)) return [];
|
|
121
137
|
return files.filter((file) => fileExists((0, import_node_path.join)(dir, file)));
|
|
122
138
|
}
|
|
139
|
+
function getConflictingDirs(dir, dirs) {
|
|
140
|
+
if (!dirExists(dir)) return [];
|
|
141
|
+
return dirs.filter((d) => dirExists((0, import_node_path.join)(dir, d)));
|
|
142
|
+
}
|
|
123
143
|
|
|
124
144
|
// src/utils/templates.ts
|
|
125
145
|
var import_node_path2 = require("path");
|
|
@@ -131,7 +151,8 @@ var REPO_REF = "master";
|
|
|
131
151
|
var REPO_RAW_URL = "https://raw.githubusercontent.com/duongductrong/cursor-kit/master";
|
|
132
152
|
var TEMPLATE_PATHS = {
|
|
133
153
|
commands: "templates/commands",
|
|
134
|
-
rules: "templates/rules"
|
|
154
|
+
rules: "templates/rules",
|
|
155
|
+
skills: "templates/skills"
|
|
135
156
|
};
|
|
136
157
|
|
|
137
158
|
// src/utils/templates.ts
|
|
@@ -151,12 +172,14 @@ function getLocalManifest() {
|
|
|
151
172
|
}
|
|
152
173
|
const commandsDir = (0, import_node_path2.join)(templatesDir, "commands");
|
|
153
174
|
const rulesDir = (0, import_node_path2.join)(templatesDir, "rules");
|
|
154
|
-
|
|
175
|
+
const skillsDir = (0, import_node_path2.join)(templatesDir, "skills");
|
|
176
|
+
if (!dirExists(commandsDir) && !dirExists(rulesDir) && !dirExists(skillsDir)) {
|
|
155
177
|
return null;
|
|
156
178
|
}
|
|
157
179
|
return {
|
|
158
180
|
commands: dirExists(commandsDir) ? listFiles(commandsDir, ".md") : [],
|
|
159
|
-
rules: dirExists(rulesDir) ? listFiles(rulesDir, ".mdc") : []
|
|
181
|
+
rules: dirExists(rulesDir) ? listFiles(rulesDir, ".mdc") : [],
|
|
182
|
+
skills: dirExists(skillsDir) ? listDirs(skillsDir) : []
|
|
160
183
|
};
|
|
161
184
|
}
|
|
162
185
|
function getLocalTemplateContent(type, filename) {
|
|
@@ -167,6 +190,22 @@ function getLocalTemplateContent(type, filename) {
|
|
|
167
190
|
}
|
|
168
191
|
return null;
|
|
169
192
|
}
|
|
193
|
+
function getLocalSkillDir(skillName) {
|
|
194
|
+
const templatesDir = getLocalTemplatesDir();
|
|
195
|
+
const skillPath = (0, import_node_path2.join)(templatesDir, "skills", skillName);
|
|
196
|
+
if (dirExists(skillPath)) {
|
|
197
|
+
return skillPath;
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
function copyLocalSkill(skillName, targetDir) {
|
|
202
|
+
const sourcePath = getLocalSkillDir(skillName);
|
|
203
|
+
if (!sourcePath) return false;
|
|
204
|
+
const destPath = (0, import_node_path2.join)(targetDir, skillName);
|
|
205
|
+
ensureDir(destPath);
|
|
206
|
+
copyDir(sourcePath, destPath);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
170
209
|
async function fetchTemplateManifest() {
|
|
171
210
|
const localManifest = getLocalManifest();
|
|
172
211
|
if (localManifest) {
|
|
@@ -210,9 +249,13 @@ function getTemplateLabel(filename) {
|
|
|
210
249
|
const nameWithoutExt = filename.replace(/\.(md|mdc)$/, "");
|
|
211
250
|
return nameWithoutExt.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
212
251
|
}
|
|
252
|
+
function getSkillLabel(skillName) {
|
|
253
|
+
return skillName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
254
|
+
}
|
|
213
255
|
|
|
214
256
|
// src/commands/init.ts
|
|
215
257
|
async function selectTemplates(type, availableTemplates) {
|
|
258
|
+
const labelFn = type === "skills" ? getSkillLabel : getTemplateLabel;
|
|
216
259
|
const selectionMode = await p.select({
|
|
217
260
|
message: `How would you like to add ${type}?`,
|
|
218
261
|
options: [
|
|
@@ -236,7 +279,7 @@ async function selectTemplates(type, availableTemplates) {
|
|
|
236
279
|
message: `Select ${type} to add:`,
|
|
237
280
|
options: availableTemplates.map((template) => ({
|
|
238
281
|
value: template,
|
|
239
|
-
label:
|
|
282
|
+
label: labelFn(template),
|
|
240
283
|
hint: template
|
|
241
284
|
})),
|
|
242
285
|
required: true
|
|
@@ -300,10 +343,36 @@ async function installTemplates(type, targetDir, selectedTemplates, conflictStra
|
|
|
300
343
|
}
|
|
301
344
|
return result;
|
|
302
345
|
}
|
|
346
|
+
async function installSkills(targetDir, selectedSkills, conflictStrategy) {
|
|
347
|
+
const result = { added: [], skipped: [] };
|
|
348
|
+
const conflictingDirs = getConflictingDirs(targetDir, selectedSkills);
|
|
349
|
+
let skillsToInstall;
|
|
350
|
+
if (conflictStrategy === "merge") {
|
|
351
|
+
skillsToInstall = selectedSkills.filter(
|
|
352
|
+
(s) => !conflictingDirs.includes(s)
|
|
353
|
+
);
|
|
354
|
+
result.skipped = conflictingDirs.filter(
|
|
355
|
+
(d) => selectedSkills.includes(d)
|
|
356
|
+
);
|
|
357
|
+
} else {
|
|
358
|
+
skillsToInstall = selectedSkills;
|
|
359
|
+
}
|
|
360
|
+
if (skillsToInstall.length === 0) {
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
ensureDir(targetDir);
|
|
364
|
+
for (const skillName of skillsToInstall) {
|
|
365
|
+
const success = copyLocalSkill(skillName, targetDir);
|
|
366
|
+
if (success) {
|
|
367
|
+
result.added.push(skillName);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return result;
|
|
371
|
+
}
|
|
303
372
|
var initCommand = (0, import_citty.defineCommand)({
|
|
304
373
|
meta: {
|
|
305
374
|
name: "init",
|
|
306
|
-
description: "Initialize .cursor/commands and .cursor/
|
|
375
|
+
description: "Initialize .cursor/commands, .cursor/rules, and .cursor/skills in your project"
|
|
307
376
|
},
|
|
308
377
|
args: {
|
|
309
378
|
force: {
|
|
@@ -324,6 +393,12 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
324
393
|
description: "Only initialize rules",
|
|
325
394
|
default: false
|
|
326
395
|
},
|
|
396
|
+
skills: {
|
|
397
|
+
type: "boolean",
|
|
398
|
+
alias: "s",
|
|
399
|
+
description: "Only initialize skills",
|
|
400
|
+
default: false
|
|
401
|
+
},
|
|
327
402
|
all: {
|
|
328
403
|
type: "boolean",
|
|
329
404
|
alias: "a",
|
|
@@ -336,9 +411,11 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
336
411
|
const cursorDir = getCursorDir(cwd);
|
|
337
412
|
const commandsDir = getCommandsDir(cwd);
|
|
338
413
|
const rulesDir = getRulesDir(cwd);
|
|
339
|
-
const
|
|
340
|
-
const
|
|
341
|
-
const
|
|
414
|
+
const skillsDir = getSkillsDir(cwd);
|
|
415
|
+
const initAll = !args.commands && !args.rules && !args.skills;
|
|
416
|
+
const shouldInitCommands = initAll || args.commands;
|
|
417
|
+
const shouldInitRules = initAll || args.rules;
|
|
418
|
+
const shouldInitSkills = initAll || args.skills;
|
|
342
419
|
p.intro(import_picocolors2.default.bgCyan(import_picocolors2.default.black(" cursor-kit init ")));
|
|
343
420
|
const s = p.spinner();
|
|
344
421
|
let manifest;
|
|
@@ -421,6 +498,36 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
421
498
|
);
|
|
422
499
|
s.stop("Rules installed");
|
|
423
500
|
}
|
|
501
|
+
if (shouldInitSkills) {
|
|
502
|
+
let selectedSkills;
|
|
503
|
+
if (args.all) {
|
|
504
|
+
selectedSkills = manifest.skills;
|
|
505
|
+
} else {
|
|
506
|
+
const selection = await selectTemplates("skills", manifest.skills);
|
|
507
|
+
if (p.isCancel(selection)) {
|
|
508
|
+
p.cancel("Operation cancelled");
|
|
509
|
+
process.exit(0);
|
|
510
|
+
}
|
|
511
|
+
selectedSkills = selection;
|
|
512
|
+
}
|
|
513
|
+
const conflictingSkills = getConflictingDirs(skillsDir, selectedSkills);
|
|
514
|
+
let skillStrategy = "overwrite";
|
|
515
|
+
if (conflictingSkills.length > 0 && !args.force) {
|
|
516
|
+
const strategy = await handleConflicts("skills", conflictingSkills);
|
|
517
|
+
if (p.isCancel(strategy) || strategy === "cancel") {
|
|
518
|
+
p.cancel("Operation cancelled");
|
|
519
|
+
process.exit(0);
|
|
520
|
+
}
|
|
521
|
+
skillStrategy = strategy;
|
|
522
|
+
}
|
|
523
|
+
s.start("Installing skills...");
|
|
524
|
+
results.skills = await installSkills(
|
|
525
|
+
skillsDir,
|
|
526
|
+
selectedSkills,
|
|
527
|
+
skillStrategy
|
|
528
|
+
);
|
|
529
|
+
s.stop("Skills installed");
|
|
530
|
+
}
|
|
424
531
|
printDivider();
|
|
425
532
|
console.log();
|
|
426
533
|
if (results.commands) {
|
|
@@ -451,8 +558,22 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
451
558
|
}
|
|
452
559
|
}
|
|
453
560
|
}
|
|
454
|
-
|
|
455
|
-
|
|
561
|
+
if (results.skills) {
|
|
562
|
+
const { added, skipped } = results.skills;
|
|
563
|
+
if (added.length > 0 || skipped.length > 0) {
|
|
564
|
+
printSuccess(
|
|
565
|
+
`Skills: ${highlight(added.length.toString())} added${skipped.length > 0 ? `, ${import_picocolors2.default.yellow(skipped.length.toString())} skipped` : ""}`
|
|
566
|
+
);
|
|
567
|
+
for (const f of added) {
|
|
568
|
+
console.log(import_picocolors2.default.dim(` \u2514\u2500 ${import_picocolors2.default.green("+")} ${f}`));
|
|
569
|
+
}
|
|
570
|
+
for (const f of skipped) {
|
|
571
|
+
console.log(import_picocolors2.default.dim(` \u2514\u2500 ${import_picocolors2.default.yellow("\u25CB")} ${f} (kept existing)`));
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
const totalAdded = (results.commands?.added.length ?? 0) + (results.rules?.added.length ?? 0) + (results.skills?.added.length ?? 0);
|
|
576
|
+
const totalSkipped = (results.commands?.skipped.length ?? 0) + (results.rules?.skipped.length ?? 0) + (results.skills?.skipped.length ?? 0);
|
|
456
577
|
if (totalAdded === 0 && totalSkipped > 0) {
|
|
457
578
|
console.log();
|
|
458
579
|
p.outro(import_picocolors2.default.yellow("No new templates added (all selected files already exist)"));
|
|
@@ -471,10 +592,10 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
471
592
|
});
|
|
472
593
|
|
|
473
594
|
// src/commands/add.ts
|
|
474
|
-
var import_citty2 = require("citty");
|
|
475
595
|
var p2 = __toESM(require("@clack/prompts"), 1);
|
|
476
|
-
var
|
|
596
|
+
var import_citty2 = require("citty");
|
|
477
597
|
var import_node_path4 = require("path");
|
|
598
|
+
var import_picocolors3 = __toESM(require("picocolors"), 1);
|
|
478
599
|
var COMMAND_TEMPLATE = `You are a helpful assistant. Describe what this command does.
|
|
479
600
|
|
|
480
601
|
## Instructions
|
|
@@ -501,31 +622,69 @@ Describe the rule behavior here.
|
|
|
501
622
|
- Guideline 1
|
|
502
623
|
- Guideline 2
|
|
503
624
|
`;
|
|
625
|
+
var SKILL_TEMPLATE = `---
|
|
626
|
+
description: Describe when this skill should be activated
|
|
627
|
+
globs:
|
|
628
|
+
alwaysApply: false
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
# Skill Name
|
|
632
|
+
|
|
633
|
+
Brief description of what this skill enables.
|
|
634
|
+
|
|
635
|
+
## Core Capabilities
|
|
636
|
+
|
|
637
|
+
- Capability 1
|
|
638
|
+
- Capability 2
|
|
639
|
+
|
|
640
|
+
## When to Use
|
|
641
|
+
|
|
642
|
+
Use this skill when:
|
|
643
|
+
- Condition 1
|
|
644
|
+
- Condition 2
|
|
645
|
+
|
|
646
|
+
## References
|
|
647
|
+
|
|
648
|
+
For detailed guidance, see the references folder:
|
|
649
|
+
- [Reference 1](./references/example.md) - Description
|
|
650
|
+
`;
|
|
651
|
+
var SKILL_REFERENCE_TEMPLATE = `# Reference Title
|
|
652
|
+
|
|
653
|
+
Detailed reference content goes here.
|
|
654
|
+
|
|
655
|
+
## Section 1
|
|
656
|
+
|
|
657
|
+
Content...
|
|
658
|
+
|
|
659
|
+
## Section 2
|
|
660
|
+
|
|
661
|
+
Content...
|
|
662
|
+
`;
|
|
504
663
|
function generateSlug(name) {
|
|
505
664
|
return name.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
|
|
506
665
|
}
|
|
507
666
|
var addCommand = (0, import_citty2.defineCommand)({
|
|
508
667
|
meta: {
|
|
509
668
|
name: "add",
|
|
510
|
-
description: "Add a new command or
|
|
669
|
+
description: "Add a new command, rule, or skill"
|
|
511
670
|
},
|
|
512
671
|
args: {
|
|
513
672
|
type: {
|
|
514
673
|
type: "string",
|
|
515
674
|
alias: "t",
|
|
516
|
-
description: "Type: 'command' or '
|
|
675
|
+
description: "Type: 'command', 'rule', or 'skill'"
|
|
517
676
|
},
|
|
518
677
|
name: {
|
|
519
678
|
type: "string",
|
|
520
679
|
alias: "n",
|
|
521
|
-
description: "Name of the command or
|
|
680
|
+
description: "Name of the command, rule, or skill"
|
|
522
681
|
}
|
|
523
682
|
},
|
|
524
683
|
async run({ args }) {
|
|
525
684
|
p2.intro(import_picocolors3.default.bgCyan(import_picocolors3.default.black(" cursor-kit add ")));
|
|
526
685
|
let itemType;
|
|
527
686
|
let itemName;
|
|
528
|
-
if (args.type && ["command", "rule"].includes(args.type)) {
|
|
687
|
+
if (args.type && ["command", "rule", "skill"].includes(args.type)) {
|
|
529
688
|
itemType = args.type;
|
|
530
689
|
} else {
|
|
531
690
|
const typeResult = await p2.select({
|
|
@@ -540,6 +699,11 @@ var addCommand = (0, import_citty2.defineCommand)({
|
|
|
540
699
|
value: "rule",
|
|
541
700
|
label: "Rule",
|
|
542
701
|
hint: "Project-specific AI behavior rules"
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
value: "skill",
|
|
705
|
+
label: "Skill",
|
|
706
|
+
hint: "Comprehensive guide with references"
|
|
543
707
|
}
|
|
544
708
|
]
|
|
545
709
|
});
|
|
@@ -554,7 +718,7 @@ var addCommand = (0, import_citty2.defineCommand)({
|
|
|
554
718
|
} else {
|
|
555
719
|
const nameResult = await p2.text({
|
|
556
720
|
message: `Enter ${itemType} name:`,
|
|
557
|
-
placeholder: itemType === "command" ? "my-command" : "my-rule",
|
|
721
|
+
placeholder: itemType === "command" ? "my-command" : itemType === "rule" ? "my-rule" : "my-skill",
|
|
558
722
|
validate: (value) => {
|
|
559
723
|
if (!value.trim()) return "Name is required";
|
|
560
724
|
if (value.length < 2) return "Name must be at least 2 characters";
|
|
@@ -569,12 +733,22 @@ var addCommand = (0, import_citty2.defineCommand)({
|
|
|
569
733
|
}
|
|
570
734
|
const slug = generateSlug(itemName);
|
|
571
735
|
const isCommand = itemType === "command";
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
if (
|
|
736
|
+
const isSkill = itemType === "skill";
|
|
737
|
+
let targetPath;
|
|
738
|
+
let displayPath;
|
|
739
|
+
if (isSkill) {
|
|
740
|
+
const skillsDir = getSkillsDir();
|
|
741
|
+
targetPath = (0, import_node_path4.join)(skillsDir, slug);
|
|
742
|
+
displayPath = targetPath;
|
|
743
|
+
} else {
|
|
744
|
+
const targetDir = isCommand ? getCommandsDir() : getRulesDir();
|
|
745
|
+
const extension = isCommand ? ".md" : ".mdc";
|
|
746
|
+
targetPath = (0, import_node_path4.join)(targetDir, `${slug}${extension}`);
|
|
747
|
+
displayPath = targetPath;
|
|
748
|
+
}
|
|
749
|
+
if (isSkill ? dirExists(targetPath) : fileExists(targetPath)) {
|
|
576
750
|
const shouldOverwrite = await p2.confirm({
|
|
577
|
-
message: `${highlight(slug +
|
|
751
|
+
message: `${highlight(isSkill ? slug : slug + (isCommand ? ".md" : ".mdc"))} already exists. Overwrite?`,
|
|
578
752
|
initialValue: false
|
|
579
753
|
});
|
|
580
754
|
if (p2.isCancel(shouldOverwrite) || !shouldOverwrite) {
|
|
@@ -585,12 +759,25 @@ var addCommand = (0, import_citty2.defineCommand)({
|
|
|
585
759
|
const s = p2.spinner();
|
|
586
760
|
s.start(`Creating ${itemType}...`);
|
|
587
761
|
try {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
762
|
+
if (isSkill) {
|
|
763
|
+
ensureDir(targetPath);
|
|
764
|
+
ensureDir((0, import_node_path4.join)(targetPath, "references"));
|
|
765
|
+
writeFile((0, import_node_path4.join)(targetPath, "SKILL.mdc"), SKILL_TEMPLATE);
|
|
766
|
+
writeFile((0, import_node_path4.join)(targetPath, "references", "example.md"), SKILL_REFERENCE_TEMPLATE);
|
|
767
|
+
} else {
|
|
768
|
+
const targetDir = isCommand ? getCommandsDir() : getRulesDir();
|
|
769
|
+
ensureDir(targetDir);
|
|
770
|
+
const template = isCommand ? COMMAND_TEMPLATE : RULE_TEMPLATE;
|
|
771
|
+
writeFile(targetPath, template);
|
|
772
|
+
}
|
|
591
773
|
s.stop(`${itemType.charAt(0).toUpperCase() + itemType.slice(1)} created`);
|
|
592
774
|
console.log();
|
|
593
|
-
|
|
775
|
+
if (isSkill) {
|
|
776
|
+
console.log(import_picocolors3.default.dim(" Directory: ") + highlight(displayPath));
|
|
777
|
+
console.log(import_picocolors3.default.dim(" Main file: ") + highlight((0, import_node_path4.join)(displayPath, "SKILL.mdc")));
|
|
778
|
+
} else {
|
|
779
|
+
console.log(import_picocolors3.default.dim(" File: ") + highlight(displayPath));
|
|
780
|
+
}
|
|
594
781
|
console.log();
|
|
595
782
|
p2.outro(
|
|
596
783
|
import_picocolors3.default.green(`\u2728 ${itemType.charAt(0).toUpperCase() + itemType.slice(1)} created! Edit the file to customize it.`)
|
|
@@ -626,6 +813,12 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
626
813
|
description: "Only pull rules",
|
|
627
814
|
default: false
|
|
628
815
|
},
|
|
816
|
+
skills: {
|
|
817
|
+
type: "boolean",
|
|
818
|
+
alias: "s",
|
|
819
|
+
description: "Only pull skills",
|
|
820
|
+
default: false
|
|
821
|
+
},
|
|
629
822
|
force: {
|
|
630
823
|
type: "boolean",
|
|
631
824
|
alias: "f",
|
|
@@ -634,15 +827,18 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
634
827
|
}
|
|
635
828
|
},
|
|
636
829
|
async run({ args }) {
|
|
637
|
-
const
|
|
638
|
-
const shouldPullCommands =
|
|
639
|
-
const shouldPullRules =
|
|
830
|
+
const pullAll = !args.commands && !args.rules && !args.skills;
|
|
831
|
+
const shouldPullCommands = pullAll || args.commands;
|
|
832
|
+
const shouldPullRules = pullAll || args.rules;
|
|
833
|
+
const shouldPullSkills = pullAll || args.skills;
|
|
640
834
|
p3.intro(import_picocolors4.default.bgCyan(import_picocolors4.default.black(" cursor-kit pull ")));
|
|
641
835
|
const commandsDir = getCommandsDir();
|
|
642
836
|
const rulesDir = getRulesDir();
|
|
837
|
+
const skillsDir = getSkillsDir();
|
|
643
838
|
const existingCommands = listFiles(commandsDir, ".md");
|
|
644
839
|
const existingRules = listFiles(rulesDir, ".mdc");
|
|
645
|
-
const
|
|
840
|
+
const existingSkills = listDirs(skillsDir);
|
|
841
|
+
const hasExisting = existingCommands.length > 0 || existingRules.length > 0 || existingSkills.length > 0;
|
|
646
842
|
if (hasExisting && !args.force) {
|
|
647
843
|
printInfo("Current status:");
|
|
648
844
|
if (existingCommands.length > 0) {
|
|
@@ -651,6 +847,9 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
651
847
|
if (existingRules.length > 0) {
|
|
652
848
|
console.log(import_picocolors4.default.dim(` Rules: ${existingRules.length} files`));
|
|
653
849
|
}
|
|
850
|
+
if (existingSkills.length > 0) {
|
|
851
|
+
console.log(import_picocolors4.default.dim(` Skills: ${existingSkills.length} directories`));
|
|
852
|
+
}
|
|
654
853
|
console.log();
|
|
655
854
|
const shouldContinue = await p3.confirm({
|
|
656
855
|
message: "This will merge with existing files. Continue?",
|
|
@@ -680,10 +879,19 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
680
879
|
});
|
|
681
880
|
s.stop("Rules updated");
|
|
682
881
|
}
|
|
882
|
+
if (shouldPullSkills) {
|
|
883
|
+
s.start("Pulling skills...");
|
|
884
|
+
await (0, import_giget.downloadTemplate)(`${REPO_URL}/templates/skills#${REPO_REF}`, {
|
|
885
|
+
dir: skillsDir,
|
|
886
|
+
force: true
|
|
887
|
+
});
|
|
888
|
+
s.stop("Skills updated");
|
|
889
|
+
}
|
|
683
890
|
printDivider();
|
|
684
891
|
console.log();
|
|
685
892
|
const newCommands = listFiles(commandsDir, ".md");
|
|
686
893
|
const newRules = listFiles(rulesDir, ".mdc");
|
|
894
|
+
const newSkills = listDirs(skillsDir);
|
|
687
895
|
if (shouldPullCommands) {
|
|
688
896
|
const added = newCommands.length - existingCommands.length;
|
|
689
897
|
printSuccess(
|
|
@@ -696,6 +904,12 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
696
904
|
`Rules: ${highlight(newRules.length.toString())} total` + (added > 0 ? import_picocolors4.default.green(` (+${added} new)`) : "")
|
|
697
905
|
);
|
|
698
906
|
}
|
|
907
|
+
if (shouldPullSkills) {
|
|
908
|
+
const added = newSkills.length - existingSkills.length;
|
|
909
|
+
printSuccess(
|
|
910
|
+
`Skills: ${highlight(newSkills.length.toString())} total` + (added > 0 ? import_picocolors4.default.green(` (+${added} new)`) : "")
|
|
911
|
+
);
|
|
912
|
+
}
|
|
699
913
|
console.log();
|
|
700
914
|
p3.outro(import_picocolors4.default.green("\u2728 Successfully pulled latest updates!"));
|
|
701
915
|
} catch (error) {
|
|
@@ -707,10 +921,10 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
707
921
|
});
|
|
708
922
|
|
|
709
923
|
// src/commands/list.ts
|
|
710
|
-
var import_citty4 = require("citty");
|
|
711
924
|
var p4 = __toESM(require("@clack/prompts"), 1);
|
|
712
|
-
var
|
|
925
|
+
var import_citty4 = require("citty");
|
|
713
926
|
var import_node_path5 = require("path");
|
|
927
|
+
var import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
714
928
|
function extractDescription(content, isCommand) {
|
|
715
929
|
if (isCommand) {
|
|
716
930
|
const firstLine = content.trim().split("\n")[0];
|
|
@@ -737,10 +951,31 @@ function getItems(dir, extension, isCommand) {
|
|
|
737
951
|
};
|
|
738
952
|
});
|
|
739
953
|
}
|
|
954
|
+
function getSkills(dir) {
|
|
955
|
+
const skillDirs = listDirs(dir);
|
|
956
|
+
return skillDirs.map((skillName) => {
|
|
957
|
+
const skillPath = (0, import_node_path5.join)(dir, skillName);
|
|
958
|
+
const skillFile = (0, import_node_path5.join)(skillPath, "SKILL.mdc");
|
|
959
|
+
const altSkillFile = (0, import_node_path5.join)(skillPath, "SKILL.md");
|
|
960
|
+
let description;
|
|
961
|
+
if (fileExists(skillFile)) {
|
|
962
|
+
const content = readFile(skillFile);
|
|
963
|
+
description = extractDescription(content, false);
|
|
964
|
+
} else if (fileExists(altSkillFile)) {
|
|
965
|
+
const content = readFile(altSkillFile);
|
|
966
|
+
description = extractDescription(content, false);
|
|
967
|
+
}
|
|
968
|
+
return {
|
|
969
|
+
name: skillName,
|
|
970
|
+
path: skillPath,
|
|
971
|
+
description
|
|
972
|
+
};
|
|
973
|
+
});
|
|
974
|
+
}
|
|
740
975
|
var listCommand = (0, import_citty4.defineCommand)({
|
|
741
976
|
meta: {
|
|
742
977
|
name: "list",
|
|
743
|
-
description: "List all commands and
|
|
978
|
+
description: "List all commands, rules, and skills"
|
|
744
979
|
},
|
|
745
980
|
args: {
|
|
746
981
|
commands: {
|
|
@@ -755,6 +990,12 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
755
990
|
description: "Only list rules",
|
|
756
991
|
default: false
|
|
757
992
|
},
|
|
993
|
+
skills: {
|
|
994
|
+
type: "boolean",
|
|
995
|
+
alias: "s",
|
|
996
|
+
description: "Only list skills",
|
|
997
|
+
default: false
|
|
998
|
+
},
|
|
758
999
|
verbose: {
|
|
759
1000
|
type: "boolean",
|
|
760
1001
|
alias: "v",
|
|
@@ -763,18 +1004,23 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
763
1004
|
}
|
|
764
1005
|
},
|
|
765
1006
|
async run({ args }) {
|
|
766
|
-
const
|
|
767
|
-
const shouldListCommands =
|
|
768
|
-
const shouldListRules =
|
|
1007
|
+
const listAll = !args.commands && !args.rules && !args.skills;
|
|
1008
|
+
const shouldListCommands = listAll || args.commands;
|
|
1009
|
+
const shouldListRules = listAll || args.rules;
|
|
1010
|
+
const shouldListSkills = listAll || args.skills;
|
|
769
1011
|
p4.intro(import_picocolors5.default.bgCyan(import_picocolors5.default.black(" cursor-kit list ")));
|
|
770
1012
|
const commandsDir = getCommandsDir();
|
|
771
1013
|
const rulesDir = getRulesDir();
|
|
1014
|
+
const skillsDir = getSkillsDir();
|
|
772
1015
|
const commands = shouldListCommands ? getItems(commandsDir, ".md", true) : [];
|
|
773
1016
|
const rules = shouldListRules ? getItems(rulesDir, ".mdc", false) : [];
|
|
774
|
-
|
|
1017
|
+
const skills = shouldListSkills ? getSkills(skillsDir) : [];
|
|
1018
|
+
if (commands.length === 0 && rules.length === 0 && skills.length === 0) {
|
|
775
1019
|
console.log();
|
|
776
|
-
console.log(import_picocolors5.default.yellow(" No commands or
|
|
777
|
-
console.log(
|
|
1020
|
+
console.log(import_picocolors5.default.yellow(" No commands, rules, or skills found."));
|
|
1021
|
+
console.log(
|
|
1022
|
+
import_picocolors5.default.dim(" Run ") + highlight("cursor-kit init") + import_picocolors5.default.dim(" to get started.")
|
|
1023
|
+
);
|
|
778
1024
|
console.log();
|
|
779
1025
|
p4.outro(import_picocolors5.default.dim("Nothing to show"));
|
|
780
1026
|
return;
|
|
@@ -782,7 +1028,9 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
782
1028
|
printDivider();
|
|
783
1029
|
if (shouldListCommands && commands.length > 0) {
|
|
784
1030
|
console.log();
|
|
785
|
-
console.log(
|
|
1031
|
+
console.log(
|
|
1032
|
+
import_picocolors5.default.bold(import_picocolors5.default.cyan(" \u{1F4DC} Commands")) + import_picocolors5.default.dim(` (${commands.length})`)
|
|
1033
|
+
);
|
|
786
1034
|
console.log();
|
|
787
1035
|
commands.forEach((cmd) => {
|
|
788
1036
|
console.log(` ${import_picocolors5.default.green("\u25CF")} ${highlight(cmd.name)}`);
|
|
@@ -796,7 +1044,9 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
796
1044
|
}
|
|
797
1045
|
if (shouldListRules && rules.length > 0) {
|
|
798
1046
|
console.log();
|
|
799
|
-
console.log(
|
|
1047
|
+
console.log(
|
|
1048
|
+
import_picocolors5.default.bold(import_picocolors5.default.cyan(" \u{1F4CB} Rules")) + import_picocolors5.default.dim(` (${rules.length})`)
|
|
1049
|
+
);
|
|
800
1050
|
console.log();
|
|
801
1051
|
rules.forEach((rule) => {
|
|
802
1052
|
console.log(` ${import_picocolors5.default.green("\u25CF")} ${highlight(rule.name)}`);
|
|
@@ -808,9 +1058,25 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
808
1058
|
}
|
|
809
1059
|
});
|
|
810
1060
|
}
|
|
1061
|
+
if (shouldListSkills && skills.length > 0) {
|
|
1062
|
+
console.log();
|
|
1063
|
+
console.log(
|
|
1064
|
+
import_picocolors5.default.bold(import_picocolors5.default.cyan(" \u{1F3AF} Skills")) + import_picocolors5.default.dim(` (${skills.length})`)
|
|
1065
|
+
);
|
|
1066
|
+
console.log();
|
|
1067
|
+
skills.forEach((skill) => {
|
|
1068
|
+
console.log(` ${import_picocolors5.default.green("\u25CF")} ${highlight(skill.name)}`);
|
|
1069
|
+
if (skill.description) {
|
|
1070
|
+
console.log(import_picocolors5.default.dim(` ${skill.description}`));
|
|
1071
|
+
}
|
|
1072
|
+
if (args.verbose) {
|
|
1073
|
+
console.log(import_picocolors5.default.dim(` ${skill.path}`));
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
811
1077
|
console.log();
|
|
812
1078
|
printDivider();
|
|
813
|
-
const total = commands.length + rules.length;
|
|
1079
|
+
const total = commands.length + rules.length + skills.length;
|
|
814
1080
|
p4.outro(import_picocolors5.default.dim(`Total: ${total} item${total !== 1 ? "s" : ""}`));
|
|
815
1081
|
}
|
|
816
1082
|
});
|
|
@@ -823,18 +1089,18 @@ var import_node_path6 = require("path");
|
|
|
823
1089
|
var removeCommand = (0, import_citty5.defineCommand)({
|
|
824
1090
|
meta: {
|
|
825
1091
|
name: "remove",
|
|
826
|
-
description: "Remove a command or
|
|
1092
|
+
description: "Remove a command, rule, or skill"
|
|
827
1093
|
},
|
|
828
1094
|
args: {
|
|
829
1095
|
type: {
|
|
830
1096
|
type: "string",
|
|
831
1097
|
alias: "t",
|
|
832
|
-
description: "Type: 'command' or '
|
|
1098
|
+
description: "Type: 'command', 'rule', or 'skill'"
|
|
833
1099
|
},
|
|
834
1100
|
name: {
|
|
835
1101
|
type: "string",
|
|
836
1102
|
alias: "n",
|
|
837
|
-
description: "Name of the command or
|
|
1103
|
+
description: "Name of the command, rule, or skill to remove"
|
|
838
1104
|
},
|
|
839
1105
|
force: {
|
|
840
1106
|
type: "boolean",
|
|
@@ -847,18 +1113,20 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
847
1113
|
p5.intro(import_picocolors6.default.bgCyan(import_picocolors6.default.black(" cursor-kit remove ")));
|
|
848
1114
|
const commandsDir = getCommandsDir();
|
|
849
1115
|
const rulesDir = getRulesDir();
|
|
1116
|
+
const skillsDir = getSkillsDir();
|
|
850
1117
|
const commands = listFiles(commandsDir, ".md").map((f) => f.replace(".md", ""));
|
|
851
1118
|
const rules = listFiles(rulesDir, ".mdc").map((f) => f.replace(".mdc", ""));
|
|
852
|
-
|
|
1119
|
+
const skills = listDirs(skillsDir);
|
|
1120
|
+
if (commands.length === 0 && rules.length === 0 && skills.length === 0) {
|
|
853
1121
|
console.log();
|
|
854
|
-
console.log(import_picocolors6.default.yellow(" No commands or
|
|
1122
|
+
console.log(import_picocolors6.default.yellow(" No commands, rules, or skills to remove."));
|
|
855
1123
|
console.log();
|
|
856
1124
|
p5.outro(import_picocolors6.default.dim("Nothing to do"));
|
|
857
1125
|
return;
|
|
858
1126
|
}
|
|
859
1127
|
let itemType;
|
|
860
1128
|
let itemName;
|
|
861
|
-
if (args.type && ["command", "rule"].includes(args.type)) {
|
|
1129
|
+
if (args.type && ["command", "rule", "skill"].includes(args.type)) {
|
|
862
1130
|
itemType = args.type;
|
|
863
1131
|
} else {
|
|
864
1132
|
const typeOptions = [];
|
|
@@ -876,6 +1144,13 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
876
1144
|
hint: `${rules.length} available`
|
|
877
1145
|
});
|
|
878
1146
|
}
|
|
1147
|
+
if (skills.length > 0) {
|
|
1148
|
+
typeOptions.push({
|
|
1149
|
+
value: "skill",
|
|
1150
|
+
label: "Skill",
|
|
1151
|
+
hint: `${skills.length} available`
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
879
1154
|
const typeResult = await p5.select({
|
|
880
1155
|
message: "What do you want to remove?",
|
|
881
1156
|
options: typeOptions
|
|
@@ -887,9 +1162,11 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
887
1162
|
itemType = typeResult;
|
|
888
1163
|
}
|
|
889
1164
|
const isCommand = itemType === "command";
|
|
890
|
-
const
|
|
891
|
-
const
|
|
892
|
-
const
|
|
1165
|
+
const isRule = itemType === "rule";
|
|
1166
|
+
const isSkill = itemType === "skill";
|
|
1167
|
+
const items = isCommand ? commands : isRule ? rules : skills;
|
|
1168
|
+
const dir = isCommand ? commandsDir : isRule ? rulesDir : skillsDir;
|
|
1169
|
+
const extension = isCommand ? ".md" : isRule ? ".mdc" : "";
|
|
893
1170
|
if (items.length === 0) {
|
|
894
1171
|
p5.cancel(`No ${itemType}s found`);
|
|
895
1172
|
process.exit(0);
|
|
@@ -911,14 +1188,16 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
911
1188
|
}
|
|
912
1189
|
itemName = nameResult;
|
|
913
1190
|
}
|
|
914
|
-
const
|
|
915
|
-
|
|
1191
|
+
const targetPath = isSkill ? (0, import_node_path6.join)(dir, itemName) : (0, import_node_path6.join)(dir, `${itemName}${extension}`);
|
|
1192
|
+
const exists = isSkill ? dirExists(targetPath) : fileExists(targetPath);
|
|
1193
|
+
if (!exists) {
|
|
916
1194
|
p5.cancel(`${itemType} '${itemName}' not found`);
|
|
917
1195
|
process.exit(1);
|
|
918
1196
|
}
|
|
919
1197
|
if (!args.force) {
|
|
1198
|
+
const displayName = isSkill ? itemName : itemName + extension;
|
|
920
1199
|
const shouldDelete = await p5.confirm({
|
|
921
|
-
message: `Are you sure you want to delete ${highlight(
|
|
1200
|
+
message: `Are you sure you want to delete ${highlight(displayName)}?${isSkill ? " (This will remove the entire skill directory)" : ""}`,
|
|
922
1201
|
initialValue: false
|
|
923
1202
|
});
|
|
924
1203
|
if (p5.isCancel(shouldDelete) || !shouldDelete) {
|
|
@@ -927,9 +1206,10 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
927
1206
|
}
|
|
928
1207
|
}
|
|
929
1208
|
try {
|
|
930
|
-
removeFile(
|
|
1209
|
+
removeFile(targetPath);
|
|
1210
|
+
const displayName = isSkill ? itemName : itemName + extension;
|
|
931
1211
|
console.log();
|
|
932
|
-
printSuccess(`Removed ${highlight(
|
|
1212
|
+
printSuccess(`Removed ${highlight(displayName)}`);
|
|
933
1213
|
console.log();
|
|
934
1214
|
p5.outro(import_picocolors6.default.green("\u2728 Done!"));
|
|
935
1215
|
} catch (error) {
|
|
@@ -939,10 +1219,268 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
939
1219
|
}
|
|
940
1220
|
});
|
|
941
1221
|
|
|
1222
|
+
// src/commands/instance.ts
|
|
1223
|
+
var import_citty6 = require("citty");
|
|
1224
|
+
var p6 = __toESM(require("@clack/prompts"), 1);
|
|
1225
|
+
var import_picocolors7 = __toESM(require("picocolors"), 1);
|
|
1226
|
+
var import_node_child_process = require("child_process");
|
|
1227
|
+
var import_node_path7 = require("path");
|
|
1228
|
+
var import_node_url2 = require("url");
|
|
1229
|
+
var import_node_fs2 = require("fs");
|
|
1230
|
+
function getBinPath() {
|
|
1231
|
+
const currentDir = (0, import_node_path7.dirname)((0, import_node_url2.fileURLToPath)(importMetaUrl));
|
|
1232
|
+
const possiblePaths = [
|
|
1233
|
+
(0, import_node_path7.join)(currentDir, "..", "..", "bin"),
|
|
1234
|
+
(0, import_node_path7.join)(currentDir, "..", "bin")
|
|
1235
|
+
];
|
|
1236
|
+
for (const binPath of possiblePaths) {
|
|
1237
|
+
if ((0, import_node_fs2.existsSync)(binPath)) {
|
|
1238
|
+
return binPath;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
return possiblePaths[0];
|
|
1242
|
+
}
|
|
1243
|
+
function ensureExecutable(scriptPath) {
|
|
1244
|
+
try {
|
|
1245
|
+
(0, import_node_fs2.chmodSync)(scriptPath, 493);
|
|
1246
|
+
} catch {
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
function getExistingInstances() {
|
|
1250
|
+
const userAppsDir = (0, import_node_path7.join)(process.env.HOME ?? "", "Applications");
|
|
1251
|
+
if (!(0, import_node_fs2.existsSync)(userAppsDir)) return [];
|
|
1252
|
+
try {
|
|
1253
|
+
const apps = (0, import_node_fs2.readdirSync)(userAppsDir);
|
|
1254
|
+
return apps.filter((app) => app.startsWith("Cursor") && app.endsWith(".app") && app !== "Cursor.app").map((app) => ({
|
|
1255
|
+
name: app.replace(".app", ""),
|
|
1256
|
+
path: (0, import_node_path7.join)(userAppsDir, app)
|
|
1257
|
+
}));
|
|
1258
|
+
} catch {
|
|
1259
|
+
return [];
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
function runScript(scriptPath, args) {
|
|
1263
|
+
return new Promise((resolve2) => {
|
|
1264
|
+
ensureExecutable(scriptPath);
|
|
1265
|
+
const child = (0, import_node_child_process.spawn)(scriptPath, args, {
|
|
1266
|
+
stdio: "inherit"
|
|
1267
|
+
});
|
|
1268
|
+
child.on("close", (code) => {
|
|
1269
|
+
resolve2(code ?? 1);
|
|
1270
|
+
});
|
|
1271
|
+
child.on("error", () => {
|
|
1272
|
+
resolve2(1);
|
|
1273
|
+
});
|
|
1274
|
+
});
|
|
1275
|
+
}
|
|
1276
|
+
var instanceCommand = (0, import_citty6.defineCommand)({
|
|
1277
|
+
meta: {
|
|
1278
|
+
name: "instance",
|
|
1279
|
+
description: "Manage Cursor IDE instances for multi-account login (macOS only)"
|
|
1280
|
+
},
|
|
1281
|
+
args: {
|
|
1282
|
+
action: {
|
|
1283
|
+
type: "string",
|
|
1284
|
+
alias: "a",
|
|
1285
|
+
description: "Action: 'create' or 'remove'"
|
|
1286
|
+
},
|
|
1287
|
+
name: {
|
|
1288
|
+
type: "string",
|
|
1289
|
+
alias: "n",
|
|
1290
|
+
description: "Name of the instance (e.g. 'Cursor Enterprise')"
|
|
1291
|
+
},
|
|
1292
|
+
list: {
|
|
1293
|
+
type: "boolean",
|
|
1294
|
+
alias: "l",
|
|
1295
|
+
description: "List existing Cursor instances",
|
|
1296
|
+
default: false
|
|
1297
|
+
}
|
|
1298
|
+
},
|
|
1299
|
+
async run({ args }) {
|
|
1300
|
+
p6.intro(import_picocolors7.default.bgCyan(import_picocolors7.default.black(" cursor-kit instance ")));
|
|
1301
|
+
if (process.platform !== "darwin") {
|
|
1302
|
+
console.log();
|
|
1303
|
+
printWarning("This command only works on macOS.");
|
|
1304
|
+
console.log(import_picocolors7.default.dim(" Cursor instance management requires macOS-specific features."));
|
|
1305
|
+
console.log();
|
|
1306
|
+
p6.outro(import_picocolors7.default.dim("Exiting"));
|
|
1307
|
+
process.exit(1);
|
|
1308
|
+
}
|
|
1309
|
+
if (args.list) {
|
|
1310
|
+
const instances = getExistingInstances();
|
|
1311
|
+
printDivider();
|
|
1312
|
+
console.log();
|
|
1313
|
+
if (instances.length === 0) {
|
|
1314
|
+
printInfo("No custom Cursor instances found.");
|
|
1315
|
+
console.log(import_picocolors7.default.dim(" Run ") + highlight("cursor-kit instance") + import_picocolors7.default.dim(" to create one."));
|
|
1316
|
+
} else {
|
|
1317
|
+
console.log(import_picocolors7.default.bold(import_picocolors7.default.cyan(" \u{1F5A5} Cursor Instances")) + import_picocolors7.default.dim(` (${instances.length})`));
|
|
1318
|
+
console.log();
|
|
1319
|
+
for (const instance of instances) {
|
|
1320
|
+
console.log(` ${import_picocolors7.default.green("\u25CF")} ${highlight(instance.name)}`);
|
|
1321
|
+
console.log(import_picocolors7.default.dim(` \u2514\u2500 ${instance.path}`));
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
console.log();
|
|
1325
|
+
printDivider();
|
|
1326
|
+
p6.outro(import_picocolors7.default.dim(`Total: ${instances.length} instance${instances.length !== 1 ? "s" : ""}`));
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
const s = p6.spinner();
|
|
1330
|
+
s.start("Checking prerequisites...");
|
|
1331
|
+
const binPath = getBinPath();
|
|
1332
|
+
const createScript = (0, import_node_path7.join)(binPath, "cursor-new-instance");
|
|
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);
|
|
1335
|
+
if (!scriptsExist) {
|
|
1336
|
+
s.stop("Prerequisites check failed");
|
|
1337
|
+
console.log();
|
|
1338
|
+
printWarning("Required scripts not found.");
|
|
1339
|
+
console.log(import_picocolors7.default.dim(` Expected at: ${binPath}`));
|
|
1340
|
+
console.log();
|
|
1341
|
+
p6.outro(import_picocolors7.default.red("Installation may be corrupted"));
|
|
1342
|
+
process.exit(1);
|
|
1343
|
+
}
|
|
1344
|
+
const originalCursor = "/Applications/Cursor.app";
|
|
1345
|
+
if (!(0, import_node_fs2.existsSync)(originalCursor)) {
|
|
1346
|
+
s.stop("Prerequisites check failed");
|
|
1347
|
+
console.log();
|
|
1348
|
+
printWarning("Cursor.app not found in /Applications");
|
|
1349
|
+
console.log(import_picocolors7.default.dim(" Please install Cursor IDE first."));
|
|
1350
|
+
console.log();
|
|
1351
|
+
p6.outro(import_picocolors7.default.red("Cursor IDE required"));
|
|
1352
|
+
process.exit(1);
|
|
1353
|
+
}
|
|
1354
|
+
s.stop("Prerequisites verified");
|
|
1355
|
+
const existingInstances = getExistingInstances();
|
|
1356
|
+
let action;
|
|
1357
|
+
let instanceName;
|
|
1358
|
+
if (args.action && ["create", "remove"].includes(args.action)) {
|
|
1359
|
+
action = args.action;
|
|
1360
|
+
} else {
|
|
1361
|
+
const actionResult = await p6.select({
|
|
1362
|
+
message: "What would you like to do?",
|
|
1363
|
+
options: [
|
|
1364
|
+
{
|
|
1365
|
+
value: "create",
|
|
1366
|
+
label: "Create new instance",
|
|
1367
|
+
hint: "Clone Cursor with separate identity"
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
value: "remove",
|
|
1371
|
+
label: "Remove instance",
|
|
1372
|
+
hint: existingInstances.length > 0 ? `${existingInstances.length} instance${existingInstances.length !== 1 ? "s" : ""} available` : "No instances to remove"
|
|
1373
|
+
}
|
|
1374
|
+
]
|
|
1375
|
+
});
|
|
1376
|
+
if (p6.isCancel(actionResult)) {
|
|
1377
|
+
p6.cancel("Operation cancelled");
|
|
1378
|
+
process.exit(0);
|
|
1379
|
+
}
|
|
1380
|
+
action = actionResult;
|
|
1381
|
+
}
|
|
1382
|
+
if (args.name) {
|
|
1383
|
+
instanceName = args.name;
|
|
1384
|
+
} else if (action === "remove" && existingInstances.length > 0) {
|
|
1385
|
+
const instanceResult = await p6.select({
|
|
1386
|
+
message: "Select instance to remove:",
|
|
1387
|
+
options: existingInstances.map((inst) => ({
|
|
1388
|
+
value: inst.name,
|
|
1389
|
+
label: inst.name,
|
|
1390
|
+
hint: inst.path
|
|
1391
|
+
}))
|
|
1392
|
+
});
|
|
1393
|
+
if (p6.isCancel(instanceResult)) {
|
|
1394
|
+
p6.cancel("Operation cancelled");
|
|
1395
|
+
process.exit(0);
|
|
1396
|
+
}
|
|
1397
|
+
instanceName = instanceResult;
|
|
1398
|
+
} else if (action === "remove" && existingInstances.length === 0) {
|
|
1399
|
+
console.log();
|
|
1400
|
+
printInfo("No custom Cursor instances found to remove.");
|
|
1401
|
+
console.log();
|
|
1402
|
+
p6.outro(import_picocolors7.default.dim("Nothing to do"));
|
|
1403
|
+
return;
|
|
1404
|
+
} else {
|
|
1405
|
+
const nameResult = await p6.text({
|
|
1406
|
+
message: "Enter a name for the new instance:",
|
|
1407
|
+
placeholder: "Cursor Enterprise",
|
|
1408
|
+
validate: (value) => {
|
|
1409
|
+
if (!value.trim()) return "Instance name is required";
|
|
1410
|
+
if (value.length < 2) return "Name must be at least 2 characters";
|
|
1411
|
+
const existing = existingInstances.find(
|
|
1412
|
+
(i) => i.name.toLowerCase() === value.toLowerCase()
|
|
1413
|
+
);
|
|
1414
|
+
if (existing) return `Instance "${value}" already exists`;
|
|
1415
|
+
return void 0;
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
if (p6.isCancel(nameResult)) {
|
|
1419
|
+
p6.cancel("Operation cancelled");
|
|
1420
|
+
process.exit(0);
|
|
1421
|
+
}
|
|
1422
|
+
instanceName = nameResult;
|
|
1423
|
+
}
|
|
1424
|
+
printDivider();
|
|
1425
|
+
console.log();
|
|
1426
|
+
console.log(import_picocolors7.default.bold(import_picocolors7.default.cyan(" \u{1F4CB} Summary")));
|
|
1427
|
+
console.log();
|
|
1428
|
+
console.log(` ${import_picocolors7.default.dim("Action:")} ${action === "create" ? import_picocolors7.default.green("Create") : import_picocolors7.default.yellow("Remove")}`);
|
|
1429
|
+
console.log(` ${import_picocolors7.default.dim("Instance:")} ${highlight(instanceName)}`);
|
|
1430
|
+
if (action === "create") {
|
|
1431
|
+
const slug = instanceName.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1432
|
+
console.log(` ${import_picocolors7.default.dim("Bundle ID:")} ${import_picocolors7.default.dim("com.cursor.")}${highlight(slug)}`);
|
|
1433
|
+
console.log(` ${import_picocolors7.default.dim("Location:")} ${import_picocolors7.default.dim("~/Applications/")}${highlight(instanceName + ".app")}`);
|
|
1434
|
+
} else {
|
|
1435
|
+
const targetPath = (0, import_node_path7.join)(process.env.HOME ?? "", "Applications", `${instanceName}.app`);
|
|
1436
|
+
console.log(` ${import_picocolors7.default.dim("Path:")} ${import_picocolors7.default.dim(targetPath)}`);
|
|
1437
|
+
}
|
|
1438
|
+
console.log();
|
|
1439
|
+
printDivider();
|
|
1440
|
+
console.log();
|
|
1441
|
+
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"
|
|
1444
|
+
});
|
|
1445
|
+
if (p6.isCancel(shouldContinue) || !shouldContinue) {
|
|
1446
|
+
p6.cancel("Operation cancelled");
|
|
1447
|
+
process.exit(0);
|
|
1448
|
+
}
|
|
1449
|
+
console.log();
|
|
1450
|
+
printDivider();
|
|
1451
|
+
console.log();
|
|
1452
|
+
const scriptPath = action === "create" ? createScript : removeScript;
|
|
1453
|
+
const scriptArgs = action === "remove" ? ["--yes", instanceName] : [instanceName];
|
|
1454
|
+
const exitCode = await runScript(scriptPath, scriptArgs);
|
|
1455
|
+
console.log();
|
|
1456
|
+
printDivider();
|
|
1457
|
+
console.log();
|
|
1458
|
+
if (exitCode === 0) {
|
|
1459
|
+
if (action === "create") {
|
|
1460
|
+
printSuccess(`Instance ${highlight(instanceName)} created successfully!`);
|
|
1461
|
+
console.log();
|
|
1462
|
+
console.log(import_picocolors7.default.dim(" Next steps:"));
|
|
1463
|
+
console.log(import_picocolors7.default.dim(" \u2022 The new instance should launch automatically"));
|
|
1464
|
+
console.log(import_picocolors7.default.dim(" \u2022 Sign in with a different Cursor account"));
|
|
1465
|
+
console.log(import_picocolors7.default.dim(" \u2022 Find it in ~/Applications/"));
|
|
1466
|
+
} else {
|
|
1467
|
+
printSuccess(`Instance ${highlight(instanceName)} removed successfully!`);
|
|
1468
|
+
}
|
|
1469
|
+
console.log();
|
|
1470
|
+
p6.outro(import_picocolors7.default.green("\u2728 Done!"));
|
|
1471
|
+
} else {
|
|
1472
|
+
printWarning(`Operation completed with exit code ${exitCode}`);
|
|
1473
|
+
console.log();
|
|
1474
|
+
p6.outro(import_picocolors7.default.yellow("Check the output above for details"));
|
|
1475
|
+
process.exit(exitCode);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1479
|
+
|
|
942
1480
|
// src/cli.ts
|
|
943
1481
|
var require2 = (0, import_node_module.createRequire)(importMetaUrl);
|
|
944
1482
|
var pkg = require2("../package.json");
|
|
945
|
-
var main = (0,
|
|
1483
|
+
var main = (0, import_citty7.defineCommand)({
|
|
946
1484
|
meta: {
|
|
947
1485
|
name: "cursor-kit",
|
|
948
1486
|
version: pkg.version,
|
|
@@ -957,8 +1495,9 @@ var main = (0, import_citty6.defineCommand)({
|
|
|
957
1495
|
add: addCommand,
|
|
958
1496
|
pull: pullCommand,
|
|
959
1497
|
list: listCommand,
|
|
960
|
-
remove: removeCommand
|
|
1498
|
+
remove: removeCommand,
|
|
1499
|
+
instance: instanceCommand
|
|
961
1500
|
}
|
|
962
1501
|
});
|
|
963
|
-
(0,
|
|
1502
|
+
(0, import_citty7.runMain)(main);
|
|
964
1503
|
//# sourceMappingURL=cli.cjs.map
|