skiller 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/SkillsProcessor.js +80 -2
- package/dist/core/SkillsUtils.js +32 -2
- package/dist/lib.js +6 -8
- package/package.json +1 -1
|
@@ -38,8 +38,10 @@ exports.syncMdcToSkillMd = syncMdcToSkillMd;
|
|
|
38
38
|
exports.discoverSkills = discoverSkills;
|
|
39
39
|
exports.getSkillsGitignorePaths = getSkillsGitignorePaths;
|
|
40
40
|
exports.propagateSkills = propagateSkills;
|
|
41
|
+
exports.migrateRulesToSkills = migrateRulesToSkills;
|
|
41
42
|
exports.copySkillFoldersFromRules = copySkillFoldersFromRules;
|
|
42
43
|
exports.copyMdcFilesFromRules = copyMdcFilesFromRules;
|
|
44
|
+
exports.deleteRulesDir = deleteRulesDir;
|
|
43
45
|
const path = __importStar(require("path"));
|
|
44
46
|
const fs = __importStar(require("fs/promises"));
|
|
45
47
|
const yaml = __importStar(require("js-yaml"));
|
|
@@ -445,6 +447,27 @@ async function findSkillFoldersInRules(dir, depth = 0) {
|
|
|
445
447
|
}
|
|
446
448
|
return skillFolders;
|
|
447
449
|
}
|
|
450
|
+
/**
|
|
451
|
+
* Migrates all content from .claude/rules to .claude/skills and deletes the rules directory.
|
|
452
|
+
* This is the main entry point for rules migration - it only processes if rules directory exists.
|
|
453
|
+
*/
|
|
454
|
+
async function migrateRulesToSkills(skillerDir, verbose, dryRun) {
|
|
455
|
+
const rulesDir = path.join(skillerDir, 'rules');
|
|
456
|
+
// Check if rules directory exists - early exit if not
|
|
457
|
+
try {
|
|
458
|
+
await fs.access(rulesDir);
|
|
459
|
+
}
|
|
460
|
+
catch {
|
|
461
|
+
// No rules directory - nothing to migrate
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
// Copy skill folders (folders with SKILL.md)
|
|
465
|
+
await copySkillFoldersFromRules(skillerDir, verbose, dryRun);
|
|
466
|
+
// Copy standalone .mdc files
|
|
467
|
+
await copyMdcFilesFromRules(skillerDir, verbose, dryRun);
|
|
468
|
+
// Delete the rules directory after migration
|
|
469
|
+
await deleteRulesDir(skillerDir, verbose, dryRun);
|
|
470
|
+
}
|
|
448
471
|
/**
|
|
449
472
|
* Copies skill folders (folders containing SKILL.md) from .claude/rules to .claude/skills.
|
|
450
473
|
* This allows users to organize skills in the rules directory and have them automatically
|
|
@@ -507,13 +530,41 @@ async function copyMdcFilesFromRules(skillerDir, verbose, dryRun) {
|
|
|
507
530
|
const targetDir = path.join(skillsDir, skillName);
|
|
508
531
|
const targetPath = path.join(targetDir, mdcFile.name);
|
|
509
532
|
try {
|
|
533
|
+
const content = await fs.readFile(sourcePath, 'utf8');
|
|
534
|
+
// Parse and clean frontmatter - remove globs and alwaysApply: false
|
|
535
|
+
const { frontmatter, body } = (0, FrontmatterParser_1.parseFrontmatter)(content);
|
|
536
|
+
let cleanedContent;
|
|
537
|
+
if (frontmatter && Object.keys(frontmatter).length > 0) {
|
|
538
|
+
const cleanedFrontmatter = {};
|
|
539
|
+
// Only keep description and alwaysApply: true
|
|
540
|
+
if (frontmatter.description) {
|
|
541
|
+
cleanedFrontmatter.description = frontmatter.description;
|
|
542
|
+
}
|
|
543
|
+
if (frontmatter.alwaysApply === true) {
|
|
544
|
+
cleanedFrontmatter.alwaysApply = true;
|
|
545
|
+
}
|
|
546
|
+
// Note: globs and alwaysApply: false are intentionally omitted
|
|
547
|
+
if (Object.keys(cleanedFrontmatter).length > 0) {
|
|
548
|
+
cleanedContent = `---
|
|
549
|
+
${yaml.dump(cleanedFrontmatter, { lineWidth: -1, noRefs: true }).trim()}
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
${body}
|
|
553
|
+
`;
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
cleanedContent = body;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
cleanedContent = content;
|
|
561
|
+
}
|
|
510
562
|
if (dryRun) {
|
|
511
563
|
(0, constants_1.logVerboseInfo)(`DRY RUN: Would copy ${mdcFile.name} from rules to skills/${skillName}/${mdcFile.name}`, verbose, dryRun);
|
|
512
564
|
}
|
|
513
565
|
else {
|
|
514
566
|
await fs.mkdir(targetDir, { recursive: true });
|
|
515
|
-
|
|
516
|
-
await fs.writeFile(targetPath, content, 'utf8');
|
|
567
|
+
await fs.writeFile(targetPath, cleanedContent, 'utf8');
|
|
517
568
|
(0, constants_1.logVerboseInfo)(`Copied ${mdcFile.name} from rules to skills/${skillName}/${mdcFile.name}`, verbose, dryRun);
|
|
518
569
|
}
|
|
519
570
|
copiedNames.push(skillName);
|
|
@@ -527,3 +578,30 @@ async function copyMdcFilesFromRules(skillerDir, verbose, dryRun) {
|
|
|
527
578
|
}
|
|
528
579
|
return copiedNames;
|
|
529
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Deletes the .claude/rules directory after content has been migrated to .claude/skills.
|
|
583
|
+
* This completes the migration from the old rules-based structure to the new skills-based structure.
|
|
584
|
+
*/
|
|
585
|
+
async function deleteRulesDir(skillerDir, verbose, dryRun) {
|
|
586
|
+
const rulesDir = path.join(skillerDir, 'rules');
|
|
587
|
+
// Check if rules directory exists
|
|
588
|
+
try {
|
|
589
|
+
await fs.access(rulesDir);
|
|
590
|
+
}
|
|
591
|
+
catch {
|
|
592
|
+
return false; // No rules directory to delete
|
|
593
|
+
}
|
|
594
|
+
if (dryRun) {
|
|
595
|
+
(0, constants_1.logVerboseInfo)(`DRY RUN: Would delete .claude/rules directory after migration`, verbose, dryRun);
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
try {
|
|
599
|
+
await fs.rm(rulesDir, { recursive: true, force: true });
|
|
600
|
+
(0, constants_1.logVerboseInfo)(`Deleted .claude/rules directory after migration to .claude/skills`, verbose, dryRun);
|
|
601
|
+
return true;
|
|
602
|
+
}
|
|
603
|
+
catch (err) {
|
|
604
|
+
(0, constants_1.logWarn)(`Failed to delete .claude/rules: ${err.message}`, dryRun);
|
|
605
|
+
return false;
|
|
606
|
+
}
|
|
607
|
+
}
|
package/dist/core/SkillsUtils.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.hasSkillMd = hasSkillMd;
|
|
37
|
+
exports.hasAlwaysApplyMdc = hasAlwaysApplyMdc;
|
|
37
38
|
exports.isGroupingDir = isGroupingDir;
|
|
38
39
|
exports.walkSkillsTree = walkSkillsTree;
|
|
39
40
|
exports.formatValidationWarnings = formatValidationWarnings;
|
|
@@ -42,6 +43,7 @@ exports.copySkillsDirectoryWithTransform = copySkillsDirectoryWithTransform;
|
|
|
42
43
|
const path = __importStar(require("path"));
|
|
43
44
|
const fs = __importStar(require("fs/promises"));
|
|
44
45
|
const constants_1 = require("../constants");
|
|
46
|
+
const FrontmatterParser_1 = require("./FrontmatterParser");
|
|
45
47
|
/**
|
|
46
48
|
* Checks if a directory contains a SKILL.md file.
|
|
47
49
|
*/
|
|
@@ -55,6 +57,30 @@ async function hasSkillMd(dirPath) {
|
|
|
55
57
|
return false;
|
|
56
58
|
}
|
|
57
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Checks if a directory contains an .mdc file with alwaysApply: true.
|
|
62
|
+
* These directories are valid without SKILL.md since alwaysApply rules
|
|
63
|
+
* are Cursor-style rules, not Claude Code skills.
|
|
64
|
+
*/
|
|
65
|
+
async function hasAlwaysApplyMdc(dirPath) {
|
|
66
|
+
try {
|
|
67
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
68
|
+
for (const entry of entries) {
|
|
69
|
+
if (entry.isFile() && entry.name.endsWith('.mdc')) {
|
|
70
|
+
const mdcPath = path.join(dirPath, entry.name);
|
|
71
|
+
const content = await fs.readFile(mdcPath, 'utf8');
|
|
72
|
+
const { frontmatter } = (0, FrontmatterParser_1.parseFrontmatter)(content);
|
|
73
|
+
if (frontmatter?.alwaysApply === true) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
58
84
|
/**
|
|
59
85
|
* Checks if a directory is a grouping directory (contains subdirectories with SKILL.md).
|
|
60
86
|
*/
|
|
@@ -121,8 +147,12 @@ async function walkSkillsTree(root) {
|
|
|
121
147
|
await walk(entryPath, entryRelativePath, depth + 1);
|
|
122
148
|
}
|
|
123
149
|
else {
|
|
124
|
-
//
|
|
125
|
-
|
|
150
|
+
// Check if this is a valid alwaysApply directory (no SKILL.md expected)
|
|
151
|
+
const hasAlwaysApply = await hasAlwaysApplyMdc(entryPath);
|
|
152
|
+
if (!hasAlwaysApply) {
|
|
153
|
+
// This is neither a skill nor a grouping directory - warn about it
|
|
154
|
+
warnings.push(`Directory '${entryRelativePath}' in .claude/skills has no SKILL.md and contains no sub-skills. It may be malformed or stray.`);
|
|
155
|
+
}
|
|
126
156
|
}
|
|
127
157
|
}
|
|
128
158
|
}
|
package/dist/lib.js
CHANGED
|
@@ -102,12 +102,11 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
|
|
|
102
102
|
(0, constants_1.logVerbose)(`Selected ${selectedAgents.length} agents: ${selectedAgents.map((a) => a.getName()).join(', ')}`, verbose);
|
|
103
103
|
// Propagate skills (or cleanup if disabled) - do this for each nested directory
|
|
104
104
|
const skillsEnabledResolved = resolveSkillsEnabled(skillsEnabled, rootConfig.skills?.enabled);
|
|
105
|
-
const { propagateSkills,
|
|
106
|
-
//
|
|
105
|
+
const { propagateSkills, migrateRulesToSkills } = await Promise.resolve().then(() => __importStar(require('./core/SkillsProcessor')));
|
|
106
|
+
// Migrate content from .claude/rules to .claude/skills (only if rules exists)
|
|
107
107
|
if (skillsEnabledResolved) {
|
|
108
108
|
for (const configEntry of hierarchicalConfigs) {
|
|
109
|
-
await
|
|
110
|
-
await copyMdcFilesFromRules(configEntry.skillerDir, verbose, dryRun);
|
|
109
|
+
await migrateRulesToSkills(configEntry.skillerDir, verbose, dryRun);
|
|
111
110
|
}
|
|
112
111
|
}
|
|
113
112
|
// Propagate skills for each nested .claude directory (or cleanup if disabled)
|
|
@@ -131,11 +130,10 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
|
|
|
131
130
|
(0, constants_1.logVerbose)(`Selected ${selectedAgents.length} agents: ${selectedAgents.map((a) => a.getName()).join(', ')}`, verbose);
|
|
132
131
|
// Propagate skills (or cleanup if disabled)
|
|
133
132
|
const skillsEnabledResolved = resolveSkillsEnabled(skillsEnabled, singleConfig.config.skills?.enabled);
|
|
134
|
-
const { propagateSkills,
|
|
135
|
-
//
|
|
133
|
+
const { propagateSkills, migrateRulesToSkills } = await Promise.resolve().then(() => __importStar(require('./core/SkillsProcessor')));
|
|
134
|
+
// Migrate content from .claude/rules to .claude/skills (only if rules exists)
|
|
136
135
|
if (skillsEnabledResolved) {
|
|
137
|
-
await
|
|
138
|
-
await copyMdcFilesFromRules(singleConfig.skillerDir, verbose, dryRun);
|
|
136
|
+
await migrateRulesToSkills(singleConfig.skillerDir, verbose, dryRun);
|
|
139
137
|
}
|
|
140
138
|
// Always call propagateSkills - it handles cleanup when disabled
|
|
141
139
|
await propagateSkills(projectRoot, selectedAgents, skillsEnabledResolved, verbose, dryRun, singleConfig.skillerDir);
|