cursor-kit-cli 1.2.0-beta → 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/dist/cli.cjs +333 -56
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +334 -57
- 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 +1 -1
- 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
|
@@ -102,6 +102,9 @@ function removeFile(path) {
|
|
|
102
102
|
(0, import_node_fs.rmSync)(path, { recursive: true });
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
+
function copyDir(src, dest) {
|
|
106
|
+
(0, import_node_fs.cpSync)(src, dest, { recursive: true });
|
|
107
|
+
}
|
|
105
108
|
function listFiles(dir, extension) {
|
|
106
109
|
if (!dirExists(dir)) return [];
|
|
107
110
|
const files = (0, import_node_fs.readdirSync)(dir);
|
|
@@ -110,6 +113,13 @@ function listFiles(dir, extension) {
|
|
|
110
113
|
}
|
|
111
114
|
return files;
|
|
112
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
|
+
}
|
|
113
123
|
function getCursorDir(cwd = process.cwd()) {
|
|
114
124
|
return (0, import_node_path.join)(cwd, ".cursor");
|
|
115
125
|
}
|
|
@@ -119,10 +129,17 @@ function getCommandsDir(cwd = process.cwd()) {
|
|
|
119
129
|
function getRulesDir(cwd = process.cwd()) {
|
|
120
130
|
return (0, import_node_path.join)(getCursorDir(cwd), "rules");
|
|
121
131
|
}
|
|
132
|
+
function getSkillsDir(cwd = process.cwd()) {
|
|
133
|
+
return (0, import_node_path.join)(getCursorDir(cwd), "skills");
|
|
134
|
+
}
|
|
122
135
|
function getConflictingFiles(dir, files) {
|
|
123
136
|
if (!dirExists(dir)) return [];
|
|
124
137
|
return files.filter((file) => fileExists((0, import_node_path.join)(dir, file)));
|
|
125
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
|
+
}
|
|
126
143
|
|
|
127
144
|
// src/utils/templates.ts
|
|
128
145
|
var import_node_path2 = require("path");
|
|
@@ -134,7 +151,8 @@ var REPO_REF = "master";
|
|
|
134
151
|
var REPO_RAW_URL = "https://raw.githubusercontent.com/duongductrong/cursor-kit/master";
|
|
135
152
|
var TEMPLATE_PATHS = {
|
|
136
153
|
commands: "templates/commands",
|
|
137
|
-
rules: "templates/rules"
|
|
154
|
+
rules: "templates/rules",
|
|
155
|
+
skills: "templates/skills"
|
|
138
156
|
};
|
|
139
157
|
|
|
140
158
|
// src/utils/templates.ts
|
|
@@ -154,12 +172,14 @@ function getLocalManifest() {
|
|
|
154
172
|
}
|
|
155
173
|
const commandsDir = (0, import_node_path2.join)(templatesDir, "commands");
|
|
156
174
|
const rulesDir = (0, import_node_path2.join)(templatesDir, "rules");
|
|
157
|
-
|
|
175
|
+
const skillsDir = (0, import_node_path2.join)(templatesDir, "skills");
|
|
176
|
+
if (!dirExists(commandsDir) && !dirExists(rulesDir) && !dirExists(skillsDir)) {
|
|
158
177
|
return null;
|
|
159
178
|
}
|
|
160
179
|
return {
|
|
161
180
|
commands: dirExists(commandsDir) ? listFiles(commandsDir, ".md") : [],
|
|
162
|
-
rules: dirExists(rulesDir) ? listFiles(rulesDir, ".mdc") : []
|
|
181
|
+
rules: dirExists(rulesDir) ? listFiles(rulesDir, ".mdc") : [],
|
|
182
|
+
skills: dirExists(skillsDir) ? listDirs(skillsDir) : []
|
|
163
183
|
};
|
|
164
184
|
}
|
|
165
185
|
function getLocalTemplateContent(type, filename) {
|
|
@@ -170,6 +190,22 @@ function getLocalTemplateContent(type, filename) {
|
|
|
170
190
|
}
|
|
171
191
|
return null;
|
|
172
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
|
+
}
|
|
173
209
|
async function fetchTemplateManifest() {
|
|
174
210
|
const localManifest = getLocalManifest();
|
|
175
211
|
if (localManifest) {
|
|
@@ -213,9 +249,13 @@ function getTemplateLabel(filename) {
|
|
|
213
249
|
const nameWithoutExt = filename.replace(/\.(md|mdc)$/, "");
|
|
214
250
|
return nameWithoutExt.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
215
251
|
}
|
|
252
|
+
function getSkillLabel(skillName) {
|
|
253
|
+
return skillName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
254
|
+
}
|
|
216
255
|
|
|
217
256
|
// src/commands/init.ts
|
|
218
257
|
async function selectTemplates(type, availableTemplates) {
|
|
258
|
+
const labelFn = type === "skills" ? getSkillLabel : getTemplateLabel;
|
|
219
259
|
const selectionMode = await p.select({
|
|
220
260
|
message: `How would you like to add ${type}?`,
|
|
221
261
|
options: [
|
|
@@ -239,7 +279,7 @@ async function selectTemplates(type, availableTemplates) {
|
|
|
239
279
|
message: `Select ${type} to add:`,
|
|
240
280
|
options: availableTemplates.map((template) => ({
|
|
241
281
|
value: template,
|
|
242
|
-
label:
|
|
282
|
+
label: labelFn(template),
|
|
243
283
|
hint: template
|
|
244
284
|
})),
|
|
245
285
|
required: true
|
|
@@ -303,10 +343,36 @@ async function installTemplates(type, targetDir, selectedTemplates, conflictStra
|
|
|
303
343
|
}
|
|
304
344
|
return result;
|
|
305
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
|
+
}
|
|
306
372
|
var initCommand = (0, import_citty.defineCommand)({
|
|
307
373
|
meta: {
|
|
308
374
|
name: "init",
|
|
309
|
-
description: "Initialize .cursor/commands and .cursor/
|
|
375
|
+
description: "Initialize .cursor/commands, .cursor/rules, and .cursor/skills in your project"
|
|
310
376
|
},
|
|
311
377
|
args: {
|
|
312
378
|
force: {
|
|
@@ -327,6 +393,12 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
327
393
|
description: "Only initialize rules",
|
|
328
394
|
default: false
|
|
329
395
|
},
|
|
396
|
+
skills: {
|
|
397
|
+
type: "boolean",
|
|
398
|
+
alias: "s",
|
|
399
|
+
description: "Only initialize skills",
|
|
400
|
+
default: false
|
|
401
|
+
},
|
|
330
402
|
all: {
|
|
331
403
|
type: "boolean",
|
|
332
404
|
alias: "a",
|
|
@@ -339,9 +411,11 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
339
411
|
const cursorDir = getCursorDir(cwd);
|
|
340
412
|
const commandsDir = getCommandsDir(cwd);
|
|
341
413
|
const rulesDir = getRulesDir(cwd);
|
|
342
|
-
const
|
|
343
|
-
const
|
|
344
|
-
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;
|
|
345
419
|
p.intro(import_picocolors2.default.bgCyan(import_picocolors2.default.black(" cursor-kit init ")));
|
|
346
420
|
const s = p.spinner();
|
|
347
421
|
let manifest;
|
|
@@ -424,6 +498,36 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
424
498
|
);
|
|
425
499
|
s.stop("Rules installed");
|
|
426
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
|
+
}
|
|
427
531
|
printDivider();
|
|
428
532
|
console.log();
|
|
429
533
|
if (results.commands) {
|
|
@@ -454,8 +558,22 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
454
558
|
}
|
|
455
559
|
}
|
|
456
560
|
}
|
|
457
|
-
|
|
458
|
-
|
|
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);
|
|
459
577
|
if (totalAdded === 0 && totalSkipped > 0) {
|
|
460
578
|
console.log();
|
|
461
579
|
p.outro(import_picocolors2.default.yellow("No new templates added (all selected files already exist)"));
|
|
@@ -474,10 +592,10 @@ var initCommand = (0, import_citty.defineCommand)({
|
|
|
474
592
|
});
|
|
475
593
|
|
|
476
594
|
// src/commands/add.ts
|
|
477
|
-
var import_citty2 = require("citty");
|
|
478
595
|
var p2 = __toESM(require("@clack/prompts"), 1);
|
|
479
|
-
var
|
|
596
|
+
var import_citty2 = require("citty");
|
|
480
597
|
var import_node_path4 = require("path");
|
|
598
|
+
var import_picocolors3 = __toESM(require("picocolors"), 1);
|
|
481
599
|
var COMMAND_TEMPLATE = `You are a helpful assistant. Describe what this command does.
|
|
482
600
|
|
|
483
601
|
## Instructions
|
|
@@ -504,31 +622,69 @@ Describe the rule behavior here.
|
|
|
504
622
|
- Guideline 1
|
|
505
623
|
- Guideline 2
|
|
506
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
|
+
`;
|
|
507
663
|
function generateSlug(name) {
|
|
508
664
|
return name.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
|
|
509
665
|
}
|
|
510
666
|
var addCommand = (0, import_citty2.defineCommand)({
|
|
511
667
|
meta: {
|
|
512
668
|
name: "add",
|
|
513
|
-
description: "Add a new command or
|
|
669
|
+
description: "Add a new command, rule, or skill"
|
|
514
670
|
},
|
|
515
671
|
args: {
|
|
516
672
|
type: {
|
|
517
673
|
type: "string",
|
|
518
674
|
alias: "t",
|
|
519
|
-
description: "Type: 'command' or '
|
|
675
|
+
description: "Type: 'command', 'rule', or 'skill'"
|
|
520
676
|
},
|
|
521
677
|
name: {
|
|
522
678
|
type: "string",
|
|
523
679
|
alias: "n",
|
|
524
|
-
description: "Name of the command or
|
|
680
|
+
description: "Name of the command, rule, or skill"
|
|
525
681
|
}
|
|
526
682
|
},
|
|
527
683
|
async run({ args }) {
|
|
528
684
|
p2.intro(import_picocolors3.default.bgCyan(import_picocolors3.default.black(" cursor-kit add ")));
|
|
529
685
|
let itemType;
|
|
530
686
|
let itemName;
|
|
531
|
-
if (args.type && ["command", "rule"].includes(args.type)) {
|
|
687
|
+
if (args.type && ["command", "rule", "skill"].includes(args.type)) {
|
|
532
688
|
itemType = args.type;
|
|
533
689
|
} else {
|
|
534
690
|
const typeResult = await p2.select({
|
|
@@ -543,6 +699,11 @@ var addCommand = (0, import_citty2.defineCommand)({
|
|
|
543
699
|
value: "rule",
|
|
544
700
|
label: "Rule",
|
|
545
701
|
hint: "Project-specific AI behavior rules"
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
value: "skill",
|
|
705
|
+
label: "Skill",
|
|
706
|
+
hint: "Comprehensive guide with references"
|
|
546
707
|
}
|
|
547
708
|
]
|
|
548
709
|
});
|
|
@@ -557,7 +718,7 @@ var addCommand = (0, import_citty2.defineCommand)({
|
|
|
557
718
|
} else {
|
|
558
719
|
const nameResult = await p2.text({
|
|
559
720
|
message: `Enter ${itemType} name:`,
|
|
560
|
-
placeholder: itemType === "command" ? "my-command" : "my-rule",
|
|
721
|
+
placeholder: itemType === "command" ? "my-command" : itemType === "rule" ? "my-rule" : "my-skill",
|
|
561
722
|
validate: (value) => {
|
|
562
723
|
if (!value.trim()) return "Name is required";
|
|
563
724
|
if (value.length < 2) return "Name must be at least 2 characters";
|
|
@@ -572,12 +733,22 @@ var addCommand = (0, import_citty2.defineCommand)({
|
|
|
572
733
|
}
|
|
573
734
|
const slug = generateSlug(itemName);
|
|
574
735
|
const isCommand = itemType === "command";
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
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)) {
|
|
579
750
|
const shouldOverwrite = await p2.confirm({
|
|
580
|
-
message: `${highlight(slug +
|
|
751
|
+
message: `${highlight(isSkill ? slug : slug + (isCommand ? ".md" : ".mdc"))} already exists. Overwrite?`,
|
|
581
752
|
initialValue: false
|
|
582
753
|
});
|
|
583
754
|
if (p2.isCancel(shouldOverwrite) || !shouldOverwrite) {
|
|
@@ -588,12 +759,25 @@ var addCommand = (0, import_citty2.defineCommand)({
|
|
|
588
759
|
const s = p2.spinner();
|
|
589
760
|
s.start(`Creating ${itemType}...`);
|
|
590
761
|
try {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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
|
+
}
|
|
594
773
|
s.stop(`${itemType.charAt(0).toUpperCase() + itemType.slice(1)} created`);
|
|
595
774
|
console.log();
|
|
596
|
-
|
|
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
|
+
}
|
|
597
781
|
console.log();
|
|
598
782
|
p2.outro(
|
|
599
783
|
import_picocolors3.default.green(`\u2728 ${itemType.charAt(0).toUpperCase() + itemType.slice(1)} created! Edit the file to customize it.`)
|
|
@@ -629,6 +813,12 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
629
813
|
description: "Only pull rules",
|
|
630
814
|
default: false
|
|
631
815
|
},
|
|
816
|
+
skills: {
|
|
817
|
+
type: "boolean",
|
|
818
|
+
alias: "s",
|
|
819
|
+
description: "Only pull skills",
|
|
820
|
+
default: false
|
|
821
|
+
},
|
|
632
822
|
force: {
|
|
633
823
|
type: "boolean",
|
|
634
824
|
alias: "f",
|
|
@@ -637,15 +827,18 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
637
827
|
}
|
|
638
828
|
},
|
|
639
829
|
async run({ args }) {
|
|
640
|
-
const
|
|
641
|
-
const shouldPullCommands =
|
|
642
|
-
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;
|
|
643
834
|
p3.intro(import_picocolors4.default.bgCyan(import_picocolors4.default.black(" cursor-kit pull ")));
|
|
644
835
|
const commandsDir = getCommandsDir();
|
|
645
836
|
const rulesDir = getRulesDir();
|
|
837
|
+
const skillsDir = getSkillsDir();
|
|
646
838
|
const existingCommands = listFiles(commandsDir, ".md");
|
|
647
839
|
const existingRules = listFiles(rulesDir, ".mdc");
|
|
648
|
-
const
|
|
840
|
+
const existingSkills = listDirs(skillsDir);
|
|
841
|
+
const hasExisting = existingCommands.length > 0 || existingRules.length > 0 || existingSkills.length > 0;
|
|
649
842
|
if (hasExisting && !args.force) {
|
|
650
843
|
printInfo("Current status:");
|
|
651
844
|
if (existingCommands.length > 0) {
|
|
@@ -654,6 +847,9 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
654
847
|
if (existingRules.length > 0) {
|
|
655
848
|
console.log(import_picocolors4.default.dim(` Rules: ${existingRules.length} files`));
|
|
656
849
|
}
|
|
850
|
+
if (existingSkills.length > 0) {
|
|
851
|
+
console.log(import_picocolors4.default.dim(` Skills: ${existingSkills.length} directories`));
|
|
852
|
+
}
|
|
657
853
|
console.log();
|
|
658
854
|
const shouldContinue = await p3.confirm({
|
|
659
855
|
message: "This will merge with existing files. Continue?",
|
|
@@ -683,10 +879,19 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
683
879
|
});
|
|
684
880
|
s.stop("Rules updated");
|
|
685
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
|
+
}
|
|
686
890
|
printDivider();
|
|
687
891
|
console.log();
|
|
688
892
|
const newCommands = listFiles(commandsDir, ".md");
|
|
689
893
|
const newRules = listFiles(rulesDir, ".mdc");
|
|
894
|
+
const newSkills = listDirs(skillsDir);
|
|
690
895
|
if (shouldPullCommands) {
|
|
691
896
|
const added = newCommands.length - existingCommands.length;
|
|
692
897
|
printSuccess(
|
|
@@ -699,6 +904,12 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
699
904
|
`Rules: ${highlight(newRules.length.toString())} total` + (added > 0 ? import_picocolors4.default.green(` (+${added} new)`) : "")
|
|
700
905
|
);
|
|
701
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
|
+
}
|
|
702
913
|
console.log();
|
|
703
914
|
p3.outro(import_picocolors4.default.green("\u2728 Successfully pulled latest updates!"));
|
|
704
915
|
} catch (error) {
|
|
@@ -710,10 +921,10 @@ var pullCommand = (0, import_citty3.defineCommand)({
|
|
|
710
921
|
});
|
|
711
922
|
|
|
712
923
|
// src/commands/list.ts
|
|
713
|
-
var import_citty4 = require("citty");
|
|
714
924
|
var p4 = __toESM(require("@clack/prompts"), 1);
|
|
715
|
-
var
|
|
925
|
+
var import_citty4 = require("citty");
|
|
716
926
|
var import_node_path5 = require("path");
|
|
927
|
+
var import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
717
928
|
function extractDescription(content, isCommand) {
|
|
718
929
|
if (isCommand) {
|
|
719
930
|
const firstLine = content.trim().split("\n")[0];
|
|
@@ -740,10 +951,31 @@ function getItems(dir, extension, isCommand) {
|
|
|
740
951
|
};
|
|
741
952
|
});
|
|
742
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
|
+
}
|
|
743
975
|
var listCommand = (0, import_citty4.defineCommand)({
|
|
744
976
|
meta: {
|
|
745
977
|
name: "list",
|
|
746
|
-
description: "List all commands and
|
|
978
|
+
description: "List all commands, rules, and skills"
|
|
747
979
|
},
|
|
748
980
|
args: {
|
|
749
981
|
commands: {
|
|
@@ -758,6 +990,12 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
758
990
|
description: "Only list rules",
|
|
759
991
|
default: false
|
|
760
992
|
},
|
|
993
|
+
skills: {
|
|
994
|
+
type: "boolean",
|
|
995
|
+
alias: "s",
|
|
996
|
+
description: "Only list skills",
|
|
997
|
+
default: false
|
|
998
|
+
},
|
|
761
999
|
verbose: {
|
|
762
1000
|
type: "boolean",
|
|
763
1001
|
alias: "v",
|
|
@@ -766,18 +1004,23 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
766
1004
|
}
|
|
767
1005
|
},
|
|
768
1006
|
async run({ args }) {
|
|
769
|
-
const
|
|
770
|
-
const shouldListCommands =
|
|
771
|
-
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;
|
|
772
1011
|
p4.intro(import_picocolors5.default.bgCyan(import_picocolors5.default.black(" cursor-kit list ")));
|
|
773
1012
|
const commandsDir = getCommandsDir();
|
|
774
1013
|
const rulesDir = getRulesDir();
|
|
1014
|
+
const skillsDir = getSkillsDir();
|
|
775
1015
|
const commands = shouldListCommands ? getItems(commandsDir, ".md", true) : [];
|
|
776
1016
|
const rules = shouldListRules ? getItems(rulesDir, ".mdc", false) : [];
|
|
777
|
-
|
|
1017
|
+
const skills = shouldListSkills ? getSkills(skillsDir) : [];
|
|
1018
|
+
if (commands.length === 0 && rules.length === 0 && skills.length === 0) {
|
|
778
1019
|
console.log();
|
|
779
|
-
console.log(import_picocolors5.default.yellow(" No commands or
|
|
780
|
-
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
|
+
);
|
|
781
1024
|
console.log();
|
|
782
1025
|
p4.outro(import_picocolors5.default.dim("Nothing to show"));
|
|
783
1026
|
return;
|
|
@@ -785,7 +1028,9 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
785
1028
|
printDivider();
|
|
786
1029
|
if (shouldListCommands && commands.length > 0) {
|
|
787
1030
|
console.log();
|
|
788
|
-
console.log(
|
|
1031
|
+
console.log(
|
|
1032
|
+
import_picocolors5.default.bold(import_picocolors5.default.cyan(" \u{1F4DC} Commands")) + import_picocolors5.default.dim(` (${commands.length})`)
|
|
1033
|
+
);
|
|
789
1034
|
console.log();
|
|
790
1035
|
commands.forEach((cmd) => {
|
|
791
1036
|
console.log(` ${import_picocolors5.default.green("\u25CF")} ${highlight(cmd.name)}`);
|
|
@@ -799,7 +1044,9 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
799
1044
|
}
|
|
800
1045
|
if (shouldListRules && rules.length > 0) {
|
|
801
1046
|
console.log();
|
|
802
|
-
console.log(
|
|
1047
|
+
console.log(
|
|
1048
|
+
import_picocolors5.default.bold(import_picocolors5.default.cyan(" \u{1F4CB} Rules")) + import_picocolors5.default.dim(` (${rules.length})`)
|
|
1049
|
+
);
|
|
803
1050
|
console.log();
|
|
804
1051
|
rules.forEach((rule) => {
|
|
805
1052
|
console.log(` ${import_picocolors5.default.green("\u25CF")} ${highlight(rule.name)}`);
|
|
@@ -811,9 +1058,25 @@ var listCommand = (0, import_citty4.defineCommand)({
|
|
|
811
1058
|
}
|
|
812
1059
|
});
|
|
813
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
|
+
}
|
|
814
1077
|
console.log();
|
|
815
1078
|
printDivider();
|
|
816
|
-
const total = commands.length + rules.length;
|
|
1079
|
+
const total = commands.length + rules.length + skills.length;
|
|
817
1080
|
p4.outro(import_picocolors5.default.dim(`Total: ${total} item${total !== 1 ? "s" : ""}`));
|
|
818
1081
|
}
|
|
819
1082
|
});
|
|
@@ -826,18 +1089,18 @@ var import_node_path6 = require("path");
|
|
|
826
1089
|
var removeCommand = (0, import_citty5.defineCommand)({
|
|
827
1090
|
meta: {
|
|
828
1091
|
name: "remove",
|
|
829
|
-
description: "Remove a command or
|
|
1092
|
+
description: "Remove a command, rule, or skill"
|
|
830
1093
|
},
|
|
831
1094
|
args: {
|
|
832
1095
|
type: {
|
|
833
1096
|
type: "string",
|
|
834
1097
|
alias: "t",
|
|
835
|
-
description: "Type: 'command' or '
|
|
1098
|
+
description: "Type: 'command', 'rule', or 'skill'"
|
|
836
1099
|
},
|
|
837
1100
|
name: {
|
|
838
1101
|
type: "string",
|
|
839
1102
|
alias: "n",
|
|
840
|
-
description: "Name of the command or
|
|
1103
|
+
description: "Name of the command, rule, or skill to remove"
|
|
841
1104
|
},
|
|
842
1105
|
force: {
|
|
843
1106
|
type: "boolean",
|
|
@@ -850,18 +1113,20 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
850
1113
|
p5.intro(import_picocolors6.default.bgCyan(import_picocolors6.default.black(" cursor-kit remove ")));
|
|
851
1114
|
const commandsDir = getCommandsDir();
|
|
852
1115
|
const rulesDir = getRulesDir();
|
|
1116
|
+
const skillsDir = getSkillsDir();
|
|
853
1117
|
const commands = listFiles(commandsDir, ".md").map((f) => f.replace(".md", ""));
|
|
854
1118
|
const rules = listFiles(rulesDir, ".mdc").map((f) => f.replace(".mdc", ""));
|
|
855
|
-
|
|
1119
|
+
const skills = listDirs(skillsDir);
|
|
1120
|
+
if (commands.length === 0 && rules.length === 0 && skills.length === 0) {
|
|
856
1121
|
console.log();
|
|
857
|
-
console.log(import_picocolors6.default.yellow(" No commands or
|
|
1122
|
+
console.log(import_picocolors6.default.yellow(" No commands, rules, or skills to remove."));
|
|
858
1123
|
console.log();
|
|
859
1124
|
p5.outro(import_picocolors6.default.dim("Nothing to do"));
|
|
860
1125
|
return;
|
|
861
1126
|
}
|
|
862
1127
|
let itemType;
|
|
863
1128
|
let itemName;
|
|
864
|
-
if (args.type && ["command", "rule"].includes(args.type)) {
|
|
1129
|
+
if (args.type && ["command", "rule", "skill"].includes(args.type)) {
|
|
865
1130
|
itemType = args.type;
|
|
866
1131
|
} else {
|
|
867
1132
|
const typeOptions = [];
|
|
@@ -879,6 +1144,13 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
879
1144
|
hint: `${rules.length} available`
|
|
880
1145
|
});
|
|
881
1146
|
}
|
|
1147
|
+
if (skills.length > 0) {
|
|
1148
|
+
typeOptions.push({
|
|
1149
|
+
value: "skill",
|
|
1150
|
+
label: "Skill",
|
|
1151
|
+
hint: `${skills.length} available`
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
882
1154
|
const typeResult = await p5.select({
|
|
883
1155
|
message: "What do you want to remove?",
|
|
884
1156
|
options: typeOptions
|
|
@@ -890,9 +1162,11 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
890
1162
|
itemType = typeResult;
|
|
891
1163
|
}
|
|
892
1164
|
const isCommand = itemType === "command";
|
|
893
|
-
const
|
|
894
|
-
const
|
|
895
|
-
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" : "";
|
|
896
1170
|
if (items.length === 0) {
|
|
897
1171
|
p5.cancel(`No ${itemType}s found`);
|
|
898
1172
|
process.exit(0);
|
|
@@ -914,14 +1188,16 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
914
1188
|
}
|
|
915
1189
|
itemName = nameResult;
|
|
916
1190
|
}
|
|
917
|
-
const
|
|
918
|
-
|
|
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) {
|
|
919
1194
|
p5.cancel(`${itemType} '${itemName}' not found`);
|
|
920
1195
|
process.exit(1);
|
|
921
1196
|
}
|
|
922
1197
|
if (!args.force) {
|
|
1198
|
+
const displayName = isSkill ? itemName : itemName + extension;
|
|
923
1199
|
const shouldDelete = await p5.confirm({
|
|
924
|
-
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)" : ""}`,
|
|
925
1201
|
initialValue: false
|
|
926
1202
|
});
|
|
927
1203
|
if (p5.isCancel(shouldDelete) || !shouldDelete) {
|
|
@@ -930,9 +1206,10 @@ var removeCommand = (0, import_citty5.defineCommand)({
|
|
|
930
1206
|
}
|
|
931
1207
|
}
|
|
932
1208
|
try {
|
|
933
|
-
removeFile(
|
|
1209
|
+
removeFile(targetPath);
|
|
1210
|
+
const displayName = isSkill ? itemName : itemName + extension;
|
|
934
1211
|
console.log();
|
|
935
|
-
printSuccess(`Removed ${highlight(
|
|
1212
|
+
printSuccess(`Removed ${highlight(displayName)}`);
|
|
936
1213
|
console.log();
|
|
937
1214
|
p5.outro(import_picocolors6.default.green("\u2728 Done!"));
|
|
938
1215
|
} catch (error) {
|