skiller 0.9.0 → 0.9.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.
@@ -16,6 +16,42 @@ function skillsArgsBuilder(y) {
16
16
  description: 'Arguments passed through to the local skills CLI',
17
17
  });
18
18
  }
19
+ function migrateClaudePluginsArgsBuilder(y) {
20
+ return y
21
+ .option('project-root', {
22
+ type: 'string',
23
+ description: 'Project root directory',
24
+ default: process.cwd(),
25
+ })
26
+ .option('execute', {
27
+ type: 'boolean',
28
+ description: 'Actually install the resolved repos through the local skills CLI',
29
+ default: false,
30
+ });
31
+ }
32
+ function migrateRulesToSkillsArgsBuilder(y) {
33
+ return y
34
+ .option('project-root', {
35
+ type: 'string',
36
+ description: 'Project root directory',
37
+ default: process.cwd(),
38
+ })
39
+ .option('execute', {
40
+ type: 'boolean',
41
+ description: 'Actually replace selected local rules after detection',
42
+ default: false,
43
+ })
44
+ .option('yes', {
45
+ type: 'boolean',
46
+ description: 'Auto-replace only unambiguous exact matches without prompting',
47
+ default: false,
48
+ })
49
+ .positional('rules', {
50
+ type: 'string',
51
+ array: true,
52
+ description: 'Specific rule names or .mdc files to check (default: all .agents/rules/*.mdc)',
53
+ });
54
+ }
19
55
  /**
20
56
  * Sets up and parses CLI commands.
21
57
  */
@@ -110,42 +146,13 @@ async function run() {
110
146
  default: false,
111
147
  });
112
148
  }, handlers_1.initHandler)
113
- .command('migrate claude-plugins', 'Plan or execute a one-shot migration from legacy Claude plugins to skills installs', (y) => {
114
- return y
115
- .option('project-root', {
116
- type: 'string',
117
- description: 'Project root directory',
118
- default: process.cwd(),
119
- })
120
- .option('execute', {
121
- type: 'boolean',
122
- description: 'Actually install the resolved repos through the local skills CLI',
123
- default: false,
124
- });
125
- }, handlers_1.migrateClaudePluginsHandler)
126
- .command('migrate rules-to-skills [rules..]', 'Detect local .agents/rules .mdc files that already exist on skills.sh and optionally replace them', (y) => {
149
+ .command('migrate', 'Migration utilities', (y) => {
127
150
  return y
128
- .option('project-root', {
129
- type: 'string',
130
- description: 'Project root directory',
131
- default: process.cwd(),
132
- })
133
- .option('execute', {
134
- type: 'boolean',
135
- description: 'Actually replace selected local rules after detection',
136
- default: false,
137
- })
138
- .option('yes', {
139
- type: 'boolean',
140
- description: 'Auto-replace only unambiguous exact matches without prompting',
141
- default: false,
142
- })
143
- .positional('rules', {
144
- type: 'string',
145
- array: true,
146
- description: 'Specific rule names or .mdc files to check (default: all .agents/rules/*.mdc)',
147
- });
148
- }, handlers_1.migrateRulesToSkillsHandler)
151
+ .command('claude-plugins', 'Plan or execute a one-shot migration from legacy Claude plugins to skills installs', migrateClaudePluginsArgsBuilder, handlers_1.migrateClaudePluginsHandler)
152
+ .command('rules-to-skills [rules..]', 'Detect local .agents/rules .mdc files that already exist on skills.sh and optionally replace them', migrateRulesToSkillsArgsBuilder, handlers_1.migrateRulesToSkillsHandler)
153
+ .demandCommand(1, 'You need to specify a migrate subcommand')
154
+ .strict();
155
+ }, () => undefined)
149
156
  .command('revert', 'Revert skiller configurations from supported AI agents', (y) => {
150
157
  return y
151
158
  .option('project-root', {
@@ -38,6 +38,7 @@ exports.getCanonicalRulesDir = getCanonicalRulesDir;
38
38
  exports.readUpstreamOwnedSkillNames = readUpstreamOwnedSkillNames;
39
39
  exports.resolveSkillOwnership = resolveSkillOwnership;
40
40
  exports.adoptSkillerOwnedSkillNames = adoptSkillerOwnedSkillNames;
41
+ exports.syncSkillerOwnedSkillNamesFromRules = syncSkillerOwnedSkillNamesFromRules;
41
42
  exports.migrateLegacyProjectState = migrateLegacyProjectState;
42
43
  const fs = __importStar(require("fs/promises"));
43
44
  const path = __importStar(require("path"));
@@ -351,6 +352,26 @@ async function adoptSkillerOwnedSkillNames(projectRoot, skillNames, dryRun) {
351
352
  }
352
353
  await (0, SkillsManifest_1.writeLocalSkillNames)(projectRoot, [...next], dryRun);
353
354
  }
355
+ async function syncSkillerOwnedSkillNamesFromRules(projectRoot, dryRun) {
356
+ const rulesDir = path.join(projectRoot, project_paths_1.CANONICAL_SKILLER_DIR, 'rules');
357
+ let ruleNames = [];
358
+ try {
359
+ const entries = await fs.readdir(rulesDir, { withFileTypes: true });
360
+ ruleNames = entries
361
+ .filter((entry) => entry.isFile() && entry.name.endsWith('.mdc'))
362
+ .map((entry) => path.basename(entry.name, '.mdc'))
363
+ .sort((a, b) => a.localeCompare(b));
364
+ }
365
+ catch {
366
+ ruleNames = [];
367
+ }
368
+ const upstreamOwned = await readUpstreamOwnedSkillNames(projectRoot);
369
+ const nextLocalSkillNames = ruleNames.filter((name) => {
370
+ return !upstreamOwned.has(name);
371
+ });
372
+ await (0, SkillsManifest_1.writeLocalSkillNames)(projectRoot, nextLocalSkillNames, dryRun);
373
+ return nextLocalSkillNames;
374
+ }
354
375
  async function migrateLegacyProjectState(projectRoot, dryRun) {
355
376
  const legacyDir = path.join(projectRoot, project_paths_1.LEGACY_SKILLER_DIR);
356
377
  const canonicalDir = path.join(projectRoot, project_paths_1.CANONICAL_SKILLER_DIR);
@@ -383,7 +383,7 @@ async function writeSkillsManifestEntries(projectRoot, targetSkillsDir, entries,
383
383
  // Ensure `.claude` exists since the manifest lives there.
384
384
  await fs.mkdir(projectClaudeDir, { recursive: true });
385
385
  const targetKeys = Object.keys(existingTargets).sort((a, b) => a.localeCompare(b));
386
- if (targetKeys.length === 0) {
386
+ if (targetKeys.length === 0 && existingLocalSkills.length === 0) {
387
387
  await Promise.allSettled([fs.unlink(projectManifestPath)]);
388
388
  }
389
389
  else {
@@ -875,6 +875,7 @@ async function propagateSkills(projectRoot, agents, skillsEnabled, verbose, dryR
875
875
  for (const warning of compileResult.warnings) {
876
876
  (0, constants_1.logWarn)(warning, dryRun);
877
877
  }
878
+ await (0, SkillOwnership_1.syncSkillerOwnedSkillNamesFromRules)(projectRoot, dryRun);
878
879
  }
879
880
  // Determine canonical skills directory, with legacy fallback for migration.
880
881
  const skillsDir = await resolveProjectSkillsDir(projectRoot, skillerDir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skiller",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "Skiller — apply the same rules to all coding agents",
5
5
  "main": "dist/lib.js",
6
6
  "publishConfig": {