ai-common-skills 0.1.0

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.
Files changed (47) hide show
  1. package/README.md +66 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +17 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/info.d.ts +3 -0
  7. package/dist/commands/info.d.ts.map +1 -0
  8. package/dist/commands/info.js +36 -0
  9. package/dist/commands/info.js.map +1 -0
  10. package/dist/commands/install.d.ts +3 -0
  11. package/dist/commands/install.d.ts.map +1 -0
  12. package/dist/commands/install.js +119 -0
  13. package/dist/commands/install.js.map +1 -0
  14. package/dist/commands/list.d.ts +3 -0
  15. package/dist/commands/list.d.ts.map +1 -0
  16. package/dist/commands/list.js +30 -0
  17. package/dist/commands/list.js.map +1 -0
  18. package/dist/commands/search.d.ts +3 -0
  19. package/dist/commands/search.d.ts.map +1 -0
  20. package/dist/commands/search.js +27 -0
  21. package/dist/commands/search.js.map +1 -0
  22. package/dist/helpers.d.ts +12 -0
  23. package/dist/helpers.d.ts.map +1 -0
  24. package/dist/helpers.js +21 -0
  25. package/dist/helpers.js.map +1 -0
  26. package/dist/indexer.d.ts +4 -0
  27. package/dist/indexer.d.ts.map +1 -0
  28. package/dist/indexer.js +42 -0
  29. package/dist/indexer.js.map +1 -0
  30. package/dist/validate-all.d.ts +2 -0
  31. package/dist/validate-all.d.ts.map +1 -0
  32. package/dist/validate-all.js +35 -0
  33. package/dist/validate-all.js.map +1 -0
  34. package/dist/validator.d.ts +34 -0
  35. package/dist/validator.d.ts.map +1 -0
  36. package/dist/validator.js +105 -0
  37. package/dist/validator.js.map +1 -0
  38. package/package.json +39 -0
  39. package/skill-index.json +54 -0
  40. package/skills/openspec-apply-change/SKILL.md +156 -0
  41. package/skills/openspec-apply-change/metadata.json +6 -0
  42. package/skills/openspec-archive-change/SKILL.md +114 -0
  43. package/skills/openspec-archive-change/metadata.json +6 -0
  44. package/skills/openspec-explore/SKILL.md +288 -0
  45. package/skills/openspec-explore/metadata.json +6 -0
  46. package/skills/openspec-propose/SKILL.md +110 -0
  47. package/skills/openspec-propose/metadata.json +6 -0
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # ai-common-skills
2
+
3
+ A curated registry of AI agent skills for **Cursor** and **Claude Code**. Install skills to your project with a single command.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g ai-common-skills
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### List available skills
14
+
15
+ ```bash
16
+ ai-skills list
17
+ ai-skills list --tag openspec
18
+ ai-skills list --platform cursor
19
+ ```
20
+
21
+ ### Search skills
22
+
23
+ ```bash
24
+ ai-skills search "workflow"
25
+ ```
26
+
27
+ ### Show skill details
28
+
29
+ ```bash
30
+ ai-skills info openspec-propose
31
+ ```
32
+
33
+ ### Install skills to your project
34
+
35
+ Interactive mode — select tools and skills from a checklist:
36
+
37
+ ```bash
38
+ ai-skills install
39
+ ```
40
+
41
+ Direct mode — install a specific skill to one or more targets:
42
+
43
+ ```bash
44
+ ai-skills install openspec-propose --target cursor
45
+ ai-skills install openspec-propose --target cursor,claude-code
46
+ ```
47
+
48
+ ## Available Skills
49
+
50
+ | Skill | Description |
51
+ |-------|-------------|
52
+ | `openspec-propose` | Propose a new change with all artifacts in one step |
53
+ | `openspec-explore` | Explore ideas, investigate problems, clarify requirements |
54
+ | `openspec-apply-change` | Implement tasks from an OpenSpec change |
55
+ | `openspec-archive-change` | Archive a completed change after implementation |
56
+
57
+ ## Contributing
58
+
59
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for how to add new skills.
60
+
61
+ ## Development
62
+
63
+ ```bash
64
+ npm run build # Regenerate skill-index.json
65
+ npm run validate # Validate all skills
66
+ ```
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { registerListCommand } from './commands/list.js';
4
+ import { registerSearchCommand } from './commands/search.js';
5
+ import { registerInfoCommand } from './commands/info.js';
6
+ import { registerInstallCommand } from './commands/install.js';
7
+ const program = new Command();
8
+ program
9
+ .name('ai-skills')
10
+ .description('Install and manage AI agent skills for Cursor and Claude Code')
11
+ .version('0.1.0');
12
+ registerListCommand(program);
13
+ registerSearchCommand(program);
14
+ registerInfoCommand(program);
15
+ registerInstallCommand(program);
16
+ program.parse();
17
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,+DAA+D,CAAC;KAC5E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAEhC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerInfoCommand(program: Command): void;
3
+ //# sourceMappingURL=info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoC1D"}
@@ -0,0 +1,36 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import chalk from 'chalk';
4
+ import { loadIndex, getSkillSourceDir } from '../helpers.js';
5
+ export function registerInfoCommand(program) {
6
+ program
7
+ .command('info <skill-name>')
8
+ .description('Show detailed info about a skill')
9
+ .action((skillName) => {
10
+ const skills = loadIndex();
11
+ const skill = skills.find((s) => s.name === skillName);
12
+ if (!skill) {
13
+ console.log(chalk.red(`Skill "${skillName}" not found.`));
14
+ process.exit(1);
15
+ }
16
+ console.log(chalk.bold.cyan(`\n ${skill.name}\n`));
17
+ console.log(` ${chalk.bold('Description:')} ${skill.description}`);
18
+ console.log(` ${chalk.bold('Tags:')} ${skill.tags.length > 0 ? skill.tags.join(', ') : chalk.dim('none')}`);
19
+ console.log(` ${chalk.bold('Platforms:')} ${skill.platforms.join(', ')}`);
20
+ const skillMdPath = path.join(getSkillSourceDir(skillName), 'SKILL.md');
21
+ if (fs.existsSync(skillMdPath)) {
22
+ const content = fs.readFileSync(skillMdPath, 'utf-8');
23
+ const preview = content.split('\n').slice(0, 15).join('\n');
24
+ console.log(`\n${chalk.bold(' Preview:')}\n`);
25
+ console.log(preview
26
+ .split('\n')
27
+ .map((l) => ` ${chalk.dim(l)}`)
28
+ .join('\n'));
29
+ if (content.split('\n').length > 15) {
30
+ console.log(chalk.dim(' ...'));
31
+ }
32
+ }
33
+ console.log();
34
+ });
35
+ }
36
+ //# sourceMappingURL=info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE7D,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,CAAC,SAAiB,EAAE,EAAE;QAC5B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QAEvD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,SAAS,cAAc,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrH,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAE9E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,CAAC;QACxE,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CACT,OAAO;iBACJ,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;iBACjC,IAAI,CAAC,IAAI,CAAC,CACd,CAAC;YACF,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;gBACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerInstallCommand(program: Command): void;
3
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqEzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4D7D"}
@@ -0,0 +1,119 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { checkbox, confirm } from '@inquirer/prompts';
4
+ import chalk from 'chalk';
5
+ import fsExtra from 'fs-extra';
6
+ import { loadIndex, getSkillSourceDir, TOOL_TARGETS } from '../helpers.js';
7
+ async function selectTools() {
8
+ const toolKeys = Object.keys(TOOL_TARGETS);
9
+ const choices = [
10
+ { name: 'Select All', value: '__all__' },
11
+ ...toolKeys.map((key) => ({ name: TOOL_TARGETS[key].label, value: key })),
12
+ ];
13
+ const selected = await checkbox({
14
+ message: 'Select target tools:',
15
+ choices,
16
+ });
17
+ if (selected.includes('__all__')) {
18
+ return toolKeys;
19
+ }
20
+ return selected.filter((s) => s !== '__all__');
21
+ }
22
+ async function selectSkills(skills) {
23
+ const choices = [
24
+ { name: 'Select All', value: '__all__' },
25
+ ...skills.map((s) => ({
26
+ name: `${s.name} ${chalk.dim('- ' + s.description)}`,
27
+ value: s.name,
28
+ })),
29
+ ];
30
+ const selected = await checkbox({
31
+ message: 'Select skills to install:',
32
+ choices,
33
+ });
34
+ if (selected.includes('__all__')) {
35
+ return skills.map((s) => s.name);
36
+ }
37
+ return selected.filter((s) => s !== '__all__');
38
+ }
39
+ async function installSkill(skillName, targetDir) {
40
+ const sourceDir = getSkillSourceDir(skillName);
41
+ const destDir = path.join(process.cwd(), targetDir, skillName);
42
+ if (fs.existsSync(destDir)) {
43
+ const overwrite = await confirm({
44
+ message: `"${skillName}" already exists in ${targetDir}. Overwrite?`,
45
+ default: false,
46
+ });
47
+ if (!overwrite) {
48
+ return false;
49
+ }
50
+ }
51
+ await fsExtra.copy(sourceDir, destDir, { overwrite: true });
52
+ return true;
53
+ }
54
+ function parseTargets(targetStr) {
55
+ return targetStr
56
+ .split(',')
57
+ .map((t) => t.trim().toLowerCase())
58
+ .filter((t) => t in TOOL_TARGETS);
59
+ }
60
+ export function registerInstallCommand(program) {
61
+ program
62
+ .command('install [skill-name]')
63
+ .description('Install skills to your project')
64
+ .option('--target <tools>', 'Target tools, comma-separated (cursor, claude-code)')
65
+ .action(async (skillName, opts) => {
66
+ const allSkills = loadIndex();
67
+ if (allSkills.length === 0) {
68
+ console.log(chalk.yellow('No skills available. Run "npm run build" first.'));
69
+ return;
70
+ }
71
+ let targets;
72
+ if (opts.target) {
73
+ targets = parseTargets(opts.target);
74
+ if (targets.length === 0) {
75
+ console.log(chalk.red(`Invalid target "${opts.target}". Use: cursor, claude-code`));
76
+ return;
77
+ }
78
+ }
79
+ else {
80
+ targets = await selectTools();
81
+ if (targets.length === 0) {
82
+ console.log(chalk.yellow('No tools selected.'));
83
+ return;
84
+ }
85
+ }
86
+ let skillNames;
87
+ if (skillName) {
88
+ const exists = allSkills.find((s) => s.name === skillName);
89
+ if (!exists) {
90
+ console.log(chalk.red(`Skill "${skillName}" not found.`));
91
+ return;
92
+ }
93
+ skillNames = [skillName];
94
+ }
95
+ else {
96
+ skillNames = await selectSkills(allSkills);
97
+ if (skillNames.length === 0) {
98
+ console.log(chalk.yellow('No skills selected.'));
99
+ return;
100
+ }
101
+ }
102
+ for (const targetKey of targets) {
103
+ const { label, dir } = TOOL_TARGETS[targetKey];
104
+ let installed = 0;
105
+ for (const name of skillNames) {
106
+ const ok = await installSkill(name, dir);
107
+ if (ok)
108
+ installed++;
109
+ }
110
+ if (installed > 0) {
111
+ console.log(chalk.green(`✔ Installed ${installed} skill(s) to ${dir}/`));
112
+ }
113
+ else {
114
+ console.log(chalk.dim(` Skipped ${label} — no skills installed`));
115
+ }
116
+ }
117
+ });
118
+ }
119
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerListCommand(program: Command): void;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgC1D"}
@@ -0,0 +1,30 @@
1
+ import chalk from 'chalk';
2
+ import { loadIndex } from '../helpers.js';
3
+ export function registerListCommand(program) {
4
+ program
5
+ .command('list')
6
+ .description('List all available skills')
7
+ .option('--tag <tag>', 'Filter by tag')
8
+ .option('--platform <platform>', 'Filter by platform (cursor | claude-code)')
9
+ .action((opts) => {
10
+ let skills = loadIndex();
11
+ if (opts.tag) {
12
+ skills = skills.filter((s) => s.tags.includes(opts.tag));
13
+ }
14
+ if (opts.platform) {
15
+ skills = skills.filter((s) => s.platforms.includes(opts.platform));
16
+ }
17
+ if (skills.length === 0) {
18
+ console.log(chalk.yellow('No skills found.'));
19
+ return;
20
+ }
21
+ const nameWidth = Math.max(20, ...skills.map((s) => s.name.length)) + 2;
22
+ console.log(chalk.bold('Name'.padEnd(nameWidth) + 'Description'));
23
+ console.log('─'.repeat(nameWidth + 40));
24
+ for (const skill of skills) {
25
+ console.log(chalk.cyan(skill.name.padEnd(nameWidth)) + (skill.description || ''));
26
+ }
27
+ console.log(`\n${chalk.dim(`${skills.length} skill(s) available`)}`);
28
+ });
29
+ }
30
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,2BAA2B,CAAC;SACxC,MAAM,CAAC,aAAa,EAAE,eAAe,CAAC;SACtC,MAAM,CAAC,uBAAuB,EAAE,2CAA2C,CAAC;SAC5E,MAAM,CAAC,CAAC,IAAyC,EAAE,EAAE;QACpD,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC;QAEzB,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAI,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAS,CAAC,CAAC,CAAC;QACtE,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;QAExE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC;QAExC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;QACpF,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,qBAAqB,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerSearchCommand(program: Command): void;
3
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6B5D"}
@@ -0,0 +1,27 @@
1
+ import chalk from 'chalk';
2
+ import { loadIndex } from '../helpers.js';
3
+ export function registerSearchCommand(program) {
4
+ program
5
+ .command('search <query>')
6
+ .description('Search skills by keyword (name, description, tags)')
7
+ .action((query) => {
8
+ const skills = loadIndex();
9
+ const q = query.toLowerCase();
10
+ const matches = skills.filter((s) => {
11
+ const haystack = [s.name, s.description, ...(s.tags || [])].join(' ').toLowerCase();
12
+ return haystack.includes(q);
13
+ });
14
+ if (matches.length === 0) {
15
+ console.log(chalk.yellow(`No skills found matching "${query}"`));
16
+ return;
17
+ }
18
+ const nameWidth = Math.max(20, ...matches.map((s) => s.name.length)) + 2;
19
+ console.log(chalk.bold('Name'.padEnd(nameWidth) + 'Description'));
20
+ console.log('─'.repeat(nameWidth + 40));
21
+ for (const skill of matches) {
22
+ console.log(chalk.cyan(skill.name.padEnd(nameWidth)) + (skill.description || ''));
23
+ }
24
+ console.log(`\n${chalk.dim(`${matches.length} result(s)`)}`);
25
+ });
26
+ }
27
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,gBAAgB,CAAC;SACzB,WAAW,CAAC,oDAAoD,CAAC;SACjE,MAAM,CAAC,CAAC,KAAa,EAAE,EAAE;QACxB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAE9B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YAClC,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YACpF,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,6BAA6B,KAAK,GAAG,CAAC,CAAC,CAAC;YACjE,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;QAEzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC;QAExC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;QACpF,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { SkillMetadata } from './validator.js';
2
+ export declare const SKILLS_DIR: string;
3
+ export declare const INDEX_PATH: string;
4
+ export interface ToolTarget {
5
+ label: string;
6
+ dir: string;
7
+ }
8
+ export declare const TOOL_TARGETS: Record<string, ToolTarget>;
9
+ export type SkillIndexEntry = Pick<SkillMetadata, 'name' | 'description' | 'tags' | 'platforms'>;
10
+ export declare function loadIndex(): SkillIndexEntry[];
11
+ export declare function getSkillSourceDir(skillName: string): string;
12
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAKpD,eAAO,MAAM,UAAU,QAAoC,CAAC;AAC5D,eAAO,MAAM,UAAU,QAA8C,CAAC;AAEtE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAGnD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC;AAEjG,wBAAgB,SAAS,IAAI,eAAe,EAAE,CAK7C;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D"}
@@ -0,0 +1,21 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
+ const PROJECT_ROOT = path.resolve(__dirname, '..');
6
+ export const SKILLS_DIR = path.join(PROJECT_ROOT, 'skills');
7
+ export const INDEX_PATH = path.join(PROJECT_ROOT, 'skill-index.json');
8
+ export const TOOL_TARGETS = {
9
+ cursor: { label: 'Cursor', dir: '.cursor/skills' },
10
+ 'claude-code': { label: 'Claude Code', dir: '.claude/skills' },
11
+ };
12
+ export function loadIndex() {
13
+ if (!fs.existsSync(INDEX_PATH)) {
14
+ throw new Error('skill-index.json not found. Run "npm run build" first.');
15
+ }
16
+ return JSON.parse(fs.readFileSync(INDEX_PATH, 'utf-8'));
17
+ }
18
+ export function getSkillSourceDir(skillName) {
19
+ return path.join(SKILLS_DIR, skillName);
20
+ }
21
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEnD,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;AAOtE,MAAM,CAAC,MAAM,YAAY,GAA+B;IACtD,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,gBAAgB,EAAE;IAClD,aAAa,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,gBAAgB,EAAE;CAC/D,CAAC;AAIF,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SkillIndexEntry } from './helpers.js';
2
+ export declare function buildIndex(skillsDir?: string): SkillIndexEntry[];
3
+ export declare function writeIndex(outputPath?: string, skillsDir?: string): SkillIndexEntry[];
4
+ //# sourceMappingURL=indexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAOpD,wBAAgB,UAAU,CAAC,SAAS,GAAE,MAAmB,GAAG,eAAe,EAAE,CA2B5E;AAED,wBAAgB,UAAU,CAAC,UAAU,GAAE,MAAmB,EAAE,SAAS,GAAE,MAAmB,GAAG,eAAe,EAAE,CAI7G"}
@@ -0,0 +1,42 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { validateSkillDir } from './validator.js';
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+ const PROJECT_ROOT = path.resolve(__dirname, '..');
7
+ const SKILLS_DIR = path.join(PROJECT_ROOT, 'skills');
8
+ const INDEX_PATH = path.join(PROJECT_ROOT, 'skill-index.json');
9
+ export function buildIndex(skillsDir = SKILLS_DIR) {
10
+ if (!fs.existsSync(skillsDir)) {
11
+ return [];
12
+ }
13
+ const entries = fs.readdirSync(skillsDir, { withFileTypes: true })
14
+ .filter((d) => d.isDirectory())
15
+ .map((d) => d.name)
16
+ .sort();
17
+ const index = [];
18
+ for (const dirName of entries) {
19
+ const skillDir = path.join(skillsDir, dirName);
20
+ const result = validateSkillDir(skillDir);
21
+ if (!result.metadata)
22
+ continue;
23
+ index.push({
24
+ name: result.metadata.name,
25
+ description: result.metadata.description,
26
+ tags: result.metadata.tags || [],
27
+ platforms: result.metadata.platforms || ['cursor', 'claude-code'],
28
+ });
29
+ }
30
+ return index;
31
+ }
32
+ export function writeIndex(outputPath = INDEX_PATH, skillsDir = SKILLS_DIR) {
33
+ const index = buildIndex(skillsDir);
34
+ fs.writeFileSync(outputPath, JSON.stringify(index, null, 2) + '\n');
35
+ return index;
36
+ }
37
+ const isDirectRun = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
38
+ if (isDirectRun) {
39
+ const index = writeIndex();
40
+ console.log(`Generated skill-index.json with ${index.length} skill(s).`);
41
+ }
42
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AACnD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AACrD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;AAE/D,MAAM,UAAU,UAAU,CAAC,YAAoB,UAAU;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SAC/D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,IAAI,EAAE,CAAC;IAEV,MAAM,KAAK,GAAsB,EAAE,CAAC;IAEpC,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE1C,IAAI,CAAC,MAAM,CAAC,QAAQ;YAAE,SAAS;QAE/B,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;YAC1B,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW;YACxC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE;YAChC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC;SAClE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,aAAqB,UAAU,EAAE,YAAoB,UAAU;IACxF,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;IACpC,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACxG,IAAI,WAAW,EAAE,CAAC;IAChB,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,mCAAmC,KAAK,CAAC,MAAM,YAAY,CAAC,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validate-all.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-all.d.ts","sourceRoot":"","sources":["../src/validate-all.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { validateSkillDir } from './validator.js';
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+ const SKILLS_DIR = path.resolve(__dirname, '..', 'skills');
7
+ const entries = fs.readdirSync(SKILLS_DIR, { withFileTypes: true })
8
+ .filter((d) => d.isDirectory())
9
+ .map((d) => d.name)
10
+ .sort();
11
+ let hasErrors = false;
12
+ for (const dirName of entries) {
13
+ const skillDir = path.join(SKILLS_DIR, dirName);
14
+ const result = validateSkillDir(skillDir);
15
+ if (result.errors.length > 0) {
16
+ hasErrors = true;
17
+ console.error(`✗ ${dirName}`);
18
+ for (const e of result.errors)
19
+ console.error(` ERROR: ${e}`);
20
+ }
21
+ else {
22
+ console.log(`✓ ${dirName}`);
23
+ }
24
+ for (const w of result.warnings) {
25
+ console.warn(` WARN: ${w}`);
26
+ }
27
+ }
28
+ if (hasErrors) {
29
+ console.error('\nValidation failed.');
30
+ process.exit(1);
31
+ }
32
+ else {
33
+ console.log(`\nAll ${entries.length} skill(s) passed validation.`);
34
+ }
35
+ //# sourceMappingURL=validate-all.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-all.js","sourceRoot":"","sources":["../src/validate-all.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAE3D,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;KAChE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;KAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;KAClB,IAAI,EAAE,CAAC;AAEV,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE1C,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,SAAS,GAAG,IAAI,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,IAAI,SAAS,EAAE,CAAC;IACd,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,GAAG,CAAC,SAAS,OAAO,CAAC,MAAM,8BAA8B,CAAC,CAAC;AACrE,CAAC"}
@@ -0,0 +1,34 @@
1
+ export interface ValidationResult {
2
+ valid: boolean;
3
+ error?: string;
4
+ }
5
+ export interface SkillMdValidation {
6
+ valid: boolean;
7
+ warnings: string[];
8
+ }
9
+ export interface MetadataValidation {
10
+ valid: boolean;
11
+ errors: string[];
12
+ warnings: string[];
13
+ }
14
+ export interface SkillMetadata {
15
+ name: string;
16
+ description: string;
17
+ tags: string[];
18
+ platforms: string[];
19
+ author?: string;
20
+ version?: string;
21
+ }
22
+ export interface SkillDirValidation {
23
+ valid: boolean;
24
+ errors: string[];
25
+ warnings: string[];
26
+ metadata: SkillMetadata | null;
27
+ }
28
+ export declare function validateSkillName(name: string): ValidationResult;
29
+ export declare function validateSkillMd(content: string): SkillMdValidation;
30
+ export declare function parseSkillMdDescription(content: string): string;
31
+ export declare function validateMetadata(meta: Record<string, unknown>): MetadataValidation;
32
+ export declare function deriveMetadata(skillDir: string, skillMdContent: string): SkillMetadata;
33
+ export declare function validateSkillDir(skillDir: string): SkillDirValidation;
34
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;CAChC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAKhE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAYlE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAS/D;AAKD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,kBAAkB,CA2BlF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,aAAa,CAStF;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAqCrE"}