skilldex-cli 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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +318 -0
  3. package/dist/cli/commands/install-action.d.ts +7 -0
  4. package/dist/cli/commands/install-action.d.ts.map +1 -0
  5. package/dist/cli/commands/install-action.js +85 -0
  6. package/dist/cli/commands/install-action.js.map +1 -0
  7. package/dist/cli/commands/install.d.ts +3 -0
  8. package/dist/cli/commands/install.d.ts.map +1 -0
  9. package/dist/cli/commands/install.js +13 -0
  10. package/dist/cli/commands/install.js.map +1 -0
  11. package/dist/cli/commands/list-action.d.ts +6 -0
  12. package/dist/cli/commands/list-action.d.ts.map +1 -0
  13. package/dist/cli/commands/list-action.js +46 -0
  14. package/dist/cli/commands/list-action.js.map +1 -0
  15. package/dist/cli/commands/list.d.ts +3 -0
  16. package/dist/cli/commands/list.d.ts.map +1 -0
  17. package/dist/cli/commands/list.js +12 -0
  18. package/dist/cli/commands/list.js.map +1 -0
  19. package/dist/cli/commands/publish.d.ts +3 -0
  20. package/dist/cli/commands/publish.d.ts.map +1 -0
  21. package/dist/cli/commands/publish.js +10 -0
  22. package/dist/cli/commands/publish.js.map +1 -0
  23. package/dist/cli/commands/suggest-action.d.ts +6 -0
  24. package/dist/cli/commands/suggest-action.d.ts.map +1 -0
  25. package/dist/cli/commands/suggest-action.js +51 -0
  26. package/dist/cli/commands/suggest-action.js.map +1 -0
  27. package/dist/cli/commands/suggest.d.ts +3 -0
  28. package/dist/cli/commands/suggest.d.ts.map +1 -0
  29. package/dist/cli/commands/suggest.js +13 -0
  30. package/dist/cli/commands/suggest.js.map +1 -0
  31. package/dist/cli/commands/uninstall-action.d.ts +6 -0
  32. package/dist/cli/commands/uninstall-action.d.ts.map +1 -0
  33. package/dist/cli/commands/uninstall-action.js +21 -0
  34. package/dist/cli/commands/uninstall-action.js.map +1 -0
  35. package/dist/cli/commands/uninstall.d.ts +3 -0
  36. package/dist/cli/commands/uninstall.d.ts.map +1 -0
  37. package/dist/cli/commands/uninstall.js +12 -0
  38. package/dist/cli/commands/uninstall.js.map +1 -0
  39. package/dist/cli/commands/validate-action.d.ts +4 -0
  40. package/dist/cli/commands/validate-action.d.ts.map +1 -0
  41. package/dist/cli/commands/validate-action.js +22 -0
  42. package/dist/cli/commands/validate-action.js.map +1 -0
  43. package/dist/cli/commands/validate.d.ts +3 -0
  44. package/dist/cli/commands/validate.d.ts.map +1 -0
  45. package/dist/cli/commands/validate.js +11 -0
  46. package/dist/cli/commands/validate.js.map +1 -0
  47. package/dist/cli/index.d.ts +3 -0
  48. package/dist/cli/index.d.ts.map +1 -0
  49. package/dist/cli/index.js +31 -0
  50. package/dist/cli/index.js.map +1 -0
  51. package/dist/cli/ui/output.d.ts +9 -0
  52. package/dist/cli/ui/output.d.ts.map +1 -0
  53. package/dist/cli/ui/output.js +43 -0
  54. package/dist/cli/ui/output.js.map +1 -0
  55. package/dist/cli/ui/prompts.d.ts +8 -0
  56. package/dist/cli/ui/prompts.d.ts.map +1 -0
  57. package/dist/cli/ui/prompts.js +28 -0
  58. package/dist/cli/ui/prompts.js.map +1 -0
  59. package/dist/core/installer.d.ts +18 -0
  60. package/dist/core/installer.d.ts.map +1 -0
  61. package/dist/core/installer.js +68 -0
  62. package/dist/core/installer.js.map +1 -0
  63. package/dist/core/manifest.d.ts +8 -0
  64. package/dist/core/manifest.d.ts.map +1 -0
  65. package/dist/core/manifest.js +62 -0
  66. package/dist/core/manifest.js.map +1 -0
  67. package/dist/core/resolver.d.ts +5 -0
  68. package/dist/core/resolver.d.ts.map +1 -0
  69. package/dist/core/resolver.js +68 -0
  70. package/dist/core/resolver.js.map +1 -0
  71. package/dist/core/suggest-agent.d.ts +10 -0
  72. package/dist/core/suggest-agent.d.ts.map +1 -0
  73. package/dist/core/suggest-agent.js +108 -0
  74. package/dist/core/suggest-agent.js.map +1 -0
  75. package/dist/core/validator.d.ts +4 -0
  76. package/dist/core/validator.d.ts.map +1 -0
  77. package/dist/core/validator.js +347 -0
  78. package/dist/core/validator.js.map +1 -0
  79. package/dist/index.d.ts +3 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +5 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/mcp/server.d.ts +2 -0
  84. package/dist/mcp/server.d.ts.map +1 -0
  85. package/dist/mcp/server.js +109 -0
  86. package/dist/mcp/server.js.map +1 -0
  87. package/dist/registry/index.d.ts +2 -0
  88. package/dist/registry/index.d.ts.map +1 -0
  89. package/dist/registry/index.js +4 -0
  90. package/dist/registry/index.js.map +1 -0
  91. package/dist/registry/sources/github.d.ts +10 -0
  92. package/dist/registry/sources/github.d.ts.map +1 -0
  93. package/dist/registry/sources/github.js +78 -0
  94. package/dist/registry/sources/github.js.map +1 -0
  95. package/dist/types/manifest.d.ts +19 -0
  96. package/dist/types/manifest.d.ts.map +1 -0
  97. package/dist/types/manifest.js +2 -0
  98. package/dist/types/manifest.js.map +1 -0
  99. package/dist/types/registry.d.ts +17 -0
  100. package/dist/types/registry.d.ts.map +1 -0
  101. package/dist/types/registry.js +2 -0
  102. package/dist/types/registry.js.map +1 -0
  103. package/dist/types/scope.d.ts +8 -0
  104. package/dist/types/scope.d.ts.map +1 -0
  105. package/dist/types/scope.js +2 -0
  106. package/dist/types/scope.js.map +1 -0
  107. package/dist/types/skill.d.ts +34 -0
  108. package/dist/types/skill.d.ts.map +1 -0
  109. package/dist/types/skill.js +2 -0
  110. package/dist/types/skill.js.map +1 -0
  111. package/package.json +56 -0
@@ -0,0 +1,108 @@
1
+ import { readFile, readdir } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import Anthropic from '@anthropic-ai/sdk';
4
+ export async function gatherProjectContext(projectRoot) {
5
+ const parts = [];
6
+ // README
7
+ for (const name of ['README.md', 'README.txt', 'readme.md']) {
8
+ try {
9
+ const content = await readFile(path.join(projectRoot, name), 'utf8');
10
+ const excerpt = content.split('\n').slice(0, 100).join('\n');
11
+ parts.push(`## README (first 100 lines)\n${excerpt}`);
12
+ break;
13
+ }
14
+ catch {
15
+ // file not found
16
+ }
17
+ }
18
+ // package.json
19
+ try {
20
+ const pkgRaw = await readFile(path.join(projectRoot, 'package.json'), 'utf8');
21
+ const pkg = JSON.parse(pkgRaw);
22
+ const summary = {
23
+ name: pkg.name,
24
+ description: pkg.description,
25
+ scripts: pkg.scripts,
26
+ dependencies: Object.keys(pkg.dependencies ?? {}),
27
+ devDependencies: Object.keys(pkg.devDependencies ?? {}),
28
+ };
29
+ parts.push(`## package.json summary\n${JSON.stringify(summary, null, 2)}`);
30
+ }
31
+ catch {
32
+ // not a Node project
33
+ }
34
+ // .claude directory listing
35
+ try {
36
+ const claudeDir = path.join(projectRoot, '.claude');
37
+ const entries = await readdir(claudeDir);
38
+ parts.push(`## .claude/ directory\n${entries.join('\n')}`);
39
+ }
40
+ catch {
41
+ // no .claude dir
42
+ }
43
+ // Existing skills manifest
44
+ try {
45
+ const manifestPath = path.join(projectRoot, '.skilldex', 'skilldex.json');
46
+ const manifestRaw = await readFile(manifestPath, 'utf8');
47
+ const manifest = JSON.parse(manifestRaw);
48
+ const installedNames = Object.keys(manifest.skills ?? {});
49
+ if (installedNames.length > 0) {
50
+ parts.push(`## Already installed skills\n${installedNames.join(', ')}`);
51
+ }
52
+ }
53
+ catch {
54
+ // no manifest yet
55
+ }
56
+ return parts.join('\n\n');
57
+ }
58
+ export async function generateProposals(context) {
59
+ const apiKey = process.env.ANTHROPIC_API_KEY;
60
+ if (!apiKey) {
61
+ throw new Error('ANTHROPIC_API_KEY environment variable is required for the suggest command');
62
+ }
63
+ const client = new Anthropic({ apiKey });
64
+ const systemPrompt = `You are a Claude skill recommender for the Skilldex package manager.
65
+ Skills are Claude Code skill packages (SKILL.md files) that give Claude specialized capabilities.
66
+ Given a project context, suggest relevant skills the user might want to install.
67
+
68
+ Respond ONLY with valid JSON matching this schema:
69
+ {
70
+ "proposals": [
71
+ {
72
+ "skillName": "kebab-case-skill-name",
73
+ "reason": "one sentence explaining why this skill fits this project",
74
+ "suggestedScope": "project" | "shared" | "global"
75
+ }
76
+ ]
77
+ }
78
+
79
+ Rules:
80
+ - Suggest 3-7 skills maximum
81
+ - suggestedScope should be "project" unless there is a clear reason for global/shared
82
+ - Do not suggest skills that are already installed (listed in context)
83
+ - Only suggest skills that would realistically exist as Claude Code skills
84
+ - Keep reasons concise (one sentence)`;
85
+ const message = await client.messages.create({
86
+ model: 'claude-sonnet-4-6',
87
+ max_tokens: 1024,
88
+ messages: [
89
+ {
90
+ role: 'user',
91
+ content: `Here is the project context:\n\n${context}\n\nPlease suggest relevant Claude Code skills for this project.`,
92
+ },
93
+ ],
94
+ system: systemPrompt,
95
+ });
96
+ const textContent = message.content.find((c) => c.type === 'text');
97
+ if (!textContent || textContent.type !== 'text') {
98
+ throw new Error('No text response from AI');
99
+ }
100
+ // Extract JSON from response (handle potential markdown code blocks)
101
+ const jsonMatch = textContent.text.match(/\{[\s\S]*\}/);
102
+ if (!jsonMatch) {
103
+ throw new Error('Could not parse AI response as JSON');
104
+ }
105
+ const parsed = JSON.parse(jsonMatch[0]);
106
+ return parsed.proposals.map((p) => ({ ...p, available: true }));
107
+ }
108
+ //# sourceMappingURL=suggest-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggest-agent.js","sourceRoot":"","sources":["../../src/core/suggest-agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ValidationResult } from '../types/skill.js';
2
+ export declare const SPEC_VERSION = "1.0";
3
+ export declare function validateSkill(skillPath: string): Promise<ValidationResult>;
4
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAA0C,MAAM,mBAAmB,CAAA;AAEjG,eAAO,MAAM,YAAY,QAAQ,CAAA;AAmBjC,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsMhF"}
@@ -0,0 +1,347 @@
1
+ import { readFile, stat, readdir } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { parseDocument } from 'yaml';
4
+ export const SPEC_VERSION = '1.0';
5
+ const SKILL_MD = 'SKILL.md';
6
+ const ALLOWED_SUBDIRS = new Set(['scripts', 'references', 'assets']);
7
+ const MAX_LINES = 500;
8
+ const WARN_LINES = 400;
9
+ const MIN_DESCRIPTION_WORDS = 30;
10
+ // Scoring weights
11
+ const WEIGHTS = {
12
+ frontmatterParseable: 25,
13
+ namePresent: 10,
14
+ descriptionPresent: 10,
15
+ descriptionLength: 10,
16
+ lineCount: 15,
17
+ allowedSubdirs: 10,
18
+ referencedResourcesExist: 15,
19
+ bundledResourcesCorrect: 5,
20
+ };
21
+ export async function validateSkill(skillPath) {
22
+ const diagnostics = [];
23
+ let score = 0;
24
+ const absPath = path.resolve(skillPath);
25
+ // Check that path exists and is a directory
26
+ try {
27
+ const s = await stat(absPath);
28
+ if (!s.isDirectory()) {
29
+ return fatal(skillPath, `Path is not a directory: ${absPath}`);
30
+ }
31
+ }
32
+ catch {
33
+ return fatal(skillPath, `Path does not exist: ${absPath}`);
34
+ }
35
+ // Check SKILL.md exists
36
+ const skillMdPath = path.join(absPath, SKILL_MD);
37
+ let content;
38
+ try {
39
+ content = await readFile(skillMdPath, 'utf8');
40
+ }
41
+ catch {
42
+ return fatal(skillPath, `SKILL.md not found in ${absPath}`);
43
+ }
44
+ const lines = content.split('\n');
45
+ const lineCount = lines.length;
46
+ // --- Check: YAML frontmatter parseable (25 pts) ---
47
+ const { frontmatter, frontmatterEndLine, parseError } = extractFrontmatter(content, lines);
48
+ if (parseError || frontmatter === null) {
49
+ // Frontmatter is fatal — no other checks make sense without it
50
+ return {
51
+ skill: path.basename(absPath),
52
+ score: 0,
53
+ diagnostics: [
54
+ {
55
+ severity: 'error',
56
+ line: 1,
57
+ message: parseError ?? 'Missing YAML frontmatter — file must start with ---',
58
+ check: 'yaml-frontmatter',
59
+ },
60
+ ],
61
+ specVersion: SPEC_VERSION,
62
+ passCount: 0,
63
+ warnCount: 0,
64
+ errorCount: 1,
65
+ };
66
+ }
67
+ else {
68
+ score += WEIGHTS.frontmatterParseable;
69
+ diagnostics.push({
70
+ severity: 'pass',
71
+ message: 'YAML frontmatter valid',
72
+ check: 'yaml-frontmatter',
73
+ });
74
+ // --- Check: name present (10 pts) ---
75
+ if (!frontmatter.name || String(frontmatter.name).trim() === '') {
76
+ diagnostics.push({
77
+ severity: 'error',
78
+ line: findFieldLine(lines, 'name', frontmatterEndLine),
79
+ message: 'Required field "name" is missing or empty',
80
+ check: 'name-present',
81
+ });
82
+ }
83
+ else {
84
+ score += WEIGHTS.namePresent;
85
+ diagnostics.push({
86
+ severity: 'pass',
87
+ message: 'name field present',
88
+ check: 'name-present',
89
+ });
90
+ }
91
+ // --- Check: description present + length (20 pts total) ---
92
+ if (!frontmatter.description || String(frontmatter.description).trim() === '') {
93
+ diagnostics.push({
94
+ severity: 'error',
95
+ line: findFieldLine(lines, 'description', frontmatterEndLine),
96
+ message: 'Required field "description" is missing or empty',
97
+ check: 'description-length',
98
+ });
99
+ }
100
+ else {
101
+ score += WEIGHTS.descriptionPresent;
102
+ const wordCount = String(frontmatter.description).trim().split(/\s+/).length;
103
+ if (wordCount < MIN_DESCRIPTION_WORDS) {
104
+ diagnostics.push({
105
+ severity: 'error',
106
+ line: findFieldLine(lines, 'description', frontmatterEndLine),
107
+ message: `description too short (current: ${wordCount} words, recommended: ${MIN_DESCRIPTION_WORDS}+)`,
108
+ check: 'description-length',
109
+ });
110
+ }
111
+ else {
112
+ score += WEIGHTS.descriptionLength;
113
+ diagnostics.push({
114
+ severity: 'pass',
115
+ message: `description meets length requirement (${wordCount} words)`,
116
+ check: 'description-length',
117
+ });
118
+ }
119
+ }
120
+ }
121
+ // --- Check: SKILL.md line count (15 pts) ---
122
+ if (lineCount > MAX_LINES) {
123
+ diagnostics.push({
124
+ severity: 'error',
125
+ message: `SKILL.md is ${lineCount} lines — exceeds ${MAX_LINES} line limit`,
126
+ check: 'line-count',
127
+ });
128
+ }
129
+ else if (lineCount > WARN_LINES) {
130
+ score += WEIGHTS.lineCount;
131
+ diagnostics.push({
132
+ severity: 'warning',
133
+ message: `SKILL.md is ${lineCount} lines — approaching ${MAX_LINES} line limit`,
134
+ check: 'line-count',
135
+ });
136
+ }
137
+ else {
138
+ score += WEIGHTS.lineCount;
139
+ diagnostics.push({
140
+ severity: 'pass',
141
+ message: `SKILL.md line count OK (${lineCount} lines)`,
142
+ check: 'line-count',
143
+ });
144
+ }
145
+ // --- Check: allowed subdirectories (10 pts) ---
146
+ const subDirResult = await checkSubdirectories(absPath);
147
+ if (subDirResult.unknownDirs.length > 0) {
148
+ for (const dir of subDirResult.unknownDirs) {
149
+ diagnostics.push({
150
+ severity: 'warning',
151
+ message: `Unknown subdirectory "${dir}" — only scripts/, references/, assets/ are allowed`,
152
+ check: 'allowed-subdirs',
153
+ });
154
+ }
155
+ // Partial credit: deduct per unknown dir but don't go below 0
156
+ const deduction = Math.min(WEIGHTS.allowedSubdirs, subDirResult.unknownDirs.length * 3);
157
+ score += Math.max(0, WEIGHTS.allowedSubdirs - deduction);
158
+ }
159
+ else {
160
+ score += WEIGHTS.allowedSubdirs;
161
+ diagnostics.push({
162
+ severity: 'pass',
163
+ message: 'Folder structure matches convention',
164
+ check: 'allowed-subdirs',
165
+ });
166
+ }
167
+ // --- Check: referenced resources exist (15 pts) ---
168
+ const brokenRefs = await checkBrokenReferences(content, absPath, lines);
169
+ if (brokenRefs.length > 0) {
170
+ for (const ref of brokenRefs) {
171
+ diagnostics.push({
172
+ severity: 'error',
173
+ line: ref.line,
174
+ message: `references ${ref.ref} but ${ref.reason}`,
175
+ check: 'referenced-resources',
176
+ });
177
+ }
178
+ }
179
+ else {
180
+ score += WEIGHTS.referencedResourcesExist;
181
+ diagnostics.push({
182
+ severity: 'pass',
183
+ message: 'All referenced resources exist',
184
+ check: 'referenced-resources',
185
+ });
186
+ }
187
+ // --- Check: bundled resources in correct subdirs (5 pts) ---
188
+ const misplacedFiles = await checkBundledResourceStructure(absPath);
189
+ if (misplacedFiles.length > 0) {
190
+ for (const f of misplacedFiles) {
191
+ diagnostics.push({
192
+ severity: 'warning',
193
+ message: `File "${f}" appears to be misplaced — check it belongs in scripts/, references/, or assets/`,
194
+ check: 'bundled-resources',
195
+ });
196
+ }
197
+ }
198
+ else {
199
+ score += WEIGHTS.bundledResourcesCorrect;
200
+ diagnostics.push({
201
+ severity: 'pass',
202
+ message: 'Bundled resources in correct subdirectories',
203
+ check: 'bundled-resources',
204
+ });
205
+ }
206
+ score = Math.min(100, Math.max(0, Math.round(score)));
207
+ return {
208
+ skill: path.basename(absPath),
209
+ score,
210
+ diagnostics,
211
+ specVersion: SPEC_VERSION,
212
+ passCount: diagnostics.filter((d) => d.severity === 'pass').length,
213
+ warnCount: diagnostics.filter((d) => d.severity === 'warning').length,
214
+ errorCount: diagnostics.filter((d) => d.severity === 'error').length,
215
+ };
216
+ }
217
+ // --- Helpers ---
218
+ function fatal(skillPath, message) {
219
+ return {
220
+ skill: path.basename(skillPath),
221
+ score: 0,
222
+ diagnostics: [{ severity: 'error', message, check: 'skill-exists' }],
223
+ specVersion: SPEC_VERSION,
224
+ passCount: 0,
225
+ warnCount: 0,
226
+ errorCount: 1,
227
+ };
228
+ }
229
+ function extractFrontmatter(content, lines) {
230
+ if (!lines[0]?.trimEnd().startsWith('---')) {
231
+ return { frontmatter: null, frontmatterEndLine: 0, parseError: 'Missing YAML frontmatter — file must start with ---' };
232
+ }
233
+ let endIndex = -1;
234
+ for (let i = 1; i < lines.length; i++) {
235
+ if (lines[i].trimEnd() === '---') {
236
+ endIndex = i;
237
+ break;
238
+ }
239
+ }
240
+ if (endIndex === -1) {
241
+ return { frontmatter: null, frontmatterEndLine: 0, parseError: 'Unclosed YAML frontmatter — missing closing ---' };
242
+ }
243
+ const yamlContent = lines.slice(1, endIndex).join('\n');
244
+ try {
245
+ const doc = parseDocument(yamlContent);
246
+ if (doc.errors.length > 0) {
247
+ const err = doc.errors[0];
248
+ return {
249
+ frontmatter: null,
250
+ frontmatterEndLine: endIndex,
251
+ parseError: `YAML parse error: ${err.message}`,
252
+ };
253
+ }
254
+ const fm = doc.toJS();
255
+ return { frontmatter: fm, frontmatterEndLine: endIndex, parseError: null };
256
+ }
257
+ catch (e) {
258
+ return {
259
+ frontmatter: null,
260
+ frontmatterEndLine: endIndex,
261
+ parseError: `YAML parse error: ${e instanceof Error ? e.message : String(e)}`,
262
+ };
263
+ }
264
+ }
265
+ function findFieldLine(lines, field, maxLine) {
266
+ for (let i = 0; i < Math.min(maxLine, lines.length); i++) {
267
+ if (lines[i].trimStart().startsWith(`${field}:`)) {
268
+ return i + 1; // 1-indexed
269
+ }
270
+ }
271
+ return undefined;
272
+ }
273
+ async function checkSubdirectories(skillPath) {
274
+ const unknownDirs = [];
275
+ try {
276
+ const entries = await readdir(skillPath, { withFileTypes: true });
277
+ for (const entry of entries) {
278
+ if (entry.isDirectory() && !ALLOWED_SUBDIRS.has(entry.name)) {
279
+ unknownDirs.push(entry.name);
280
+ }
281
+ }
282
+ }
283
+ catch {
284
+ // ignore readdir errors
285
+ }
286
+ return { unknownDirs };
287
+ }
288
+ async function checkBrokenReferences(content, skillPath, lines) {
289
+ const broken = [];
290
+ // Match markdown links, image refs, and plain relative paths referencing known dirs
291
+ const refPattern = /(?:(?:\[.*?\]\()|(?:!\[.*?\]\())([^)#\s]+)\)|(?:^|\s)((?:scripts|references|assets)\/[^\s)]+)/gm;
292
+ let match;
293
+ while ((match = refPattern.exec(content)) !== null) {
294
+ const ref = (match[1] ?? match[2])?.trim();
295
+ if (!ref || ref.startsWith('http://') || ref.startsWith('https://'))
296
+ continue;
297
+ const refPath = path.resolve(skillPath, ref);
298
+ try {
299
+ await stat(refPath);
300
+ }
301
+ catch {
302
+ // Find line number
303
+ const lineIndex = findLineNumber(lines, match.index, content);
304
+ broken.push({
305
+ line: lineIndex,
306
+ ref,
307
+ reason: `${ref} not found`,
308
+ });
309
+ }
310
+ }
311
+ return broken;
312
+ }
313
+ function findLineNumber(lines, charIndex, content) {
314
+ let count = 0;
315
+ for (let i = 0; i < lines.length; i++) {
316
+ count += lines[i].length + 1; // +1 for \n
317
+ if (count > charIndex)
318
+ return i + 1;
319
+ }
320
+ return lines.length;
321
+ }
322
+ async function checkBundledResourceStructure(skillPath) {
323
+ const misplaced = [];
324
+ // Check for executable-looking files in references/ (should be in scripts/)
325
+ // Check for .md files in scripts/ (should be in references/)
326
+ const checks = [
327
+ { dir: 'scripts', badExtensions: ['.md', '.txt', '.pdf'], reason: 'docs should go in references/' },
328
+ { dir: 'references', badExtensions: ['.sh', '.py', '.js', '.ts', '.rb'], reason: 'scripts should go in scripts/' },
329
+ ];
330
+ for (const check of checks) {
331
+ const dirPath = path.join(skillPath, check.dir);
332
+ try {
333
+ const entries = await readdir(dirPath);
334
+ for (const entry of entries) {
335
+ const ext = path.extname(entry).toLowerCase();
336
+ if (check.badExtensions.includes(ext)) {
337
+ misplaced.push(`${check.dir}/${entry} (${check.reason})`);
338
+ }
339
+ }
340
+ }
341
+ catch {
342
+ // Directory doesn't exist, that's fine
343
+ }
344
+ }
345
+ return misplaced;
346
+ }
347
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { createCli } from './cli/index.js';
3
+ const program = createCli();
4
+ program.parse(process.argv);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,OAAO,GAAG,SAAS,EAAE,CAAA;AAC3B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare function startMcpServer(): Promise<void>;
2
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AASA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAuIpD"}
@@ -0,0 +1,109 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { z } from 'zod';
4
+ import { validateSkill } from '../core/validator.js';
5
+ import { installFromPath, uninstallSkill } from '../core/installer.js';
6
+ import { resolveScope, resolveAllScopes } from '../core/resolver.js';
7
+ import { readManifest } from '../core/manifest.js';
8
+ import { installFromGitUrl } from '../registry/sources/github.js';
9
+ export async function startMcpServer() {
10
+ const server = new McpServer({
11
+ name: 'skilldex',
12
+ version: '0.1.0',
13
+ });
14
+ // skilldex_validate
15
+ server.tool('skilldex_validate', 'Validate a skill folder and return its format conformance score', {
16
+ path: z.string().describe('Absolute or relative path to the skill folder'),
17
+ }, async ({ path: skillPath }) => {
18
+ const result = await validateSkill(skillPath);
19
+ return {
20
+ content: [{ type: 'text', text: JSON.stringify(result) }],
21
+ };
22
+ });
23
+ // skilldex_install
24
+ server.tool('skilldex_install', 'Install a skill from a local path or git+https:// URL', {
25
+ source: z.string().describe('Local path or git+https:// URL'),
26
+ scope: z.enum(['global', 'shared', 'project']).default('project'),
27
+ force: z.boolean().default(false),
28
+ }, async ({ source, scope, force }) => {
29
+ let result;
30
+ if (source.startsWith('git+')) {
31
+ const scopeConfig = await resolveScope(scope);
32
+ result = await installFromGitUrl(source, scopeConfig, { scope, force, sourceUrl: source });
33
+ }
34
+ else {
35
+ result = await installFromPath(source, { scope, force });
36
+ }
37
+ return {
38
+ content: [
39
+ {
40
+ type: 'text',
41
+ text: JSON.stringify({
42
+ installed: true,
43
+ skillName: result.skillName,
44
+ scope: result.scope,
45
+ score: result.validation.score,
46
+ diagnostics: result.validation.diagnostics,
47
+ }),
48
+ },
49
+ ],
50
+ };
51
+ });
52
+ // skilldex_uninstall
53
+ server.tool('skilldex_uninstall', 'Uninstall a skill from a scope', {
54
+ skillName: z.string().describe('Name of the skill to uninstall'),
55
+ scope: z.enum(['global', 'shared', 'project']).default('project'),
56
+ }, async ({ skillName, scope }) => {
57
+ await uninstallSkill(skillName, scope);
58
+ return {
59
+ content: [{ type: 'text', text: JSON.stringify({ removed: true, skillName, scope }) }],
60
+ };
61
+ });
62
+ // skilldex_list
63
+ server.tool('skilldex_list', 'List all installed skills across scopes', {
64
+ scope: z.enum(['global', 'shared', 'project']).optional(),
65
+ }, async ({ scope }) => {
66
+ const scopeConfigs = scope ? [await resolveScope(scope)] : await resolveAllScopes();
67
+ const results = [];
68
+ for (const sc of scopeConfigs) {
69
+ const manifest = await readManifest(sc);
70
+ results.push({ level: sc.level, skills: Object.values(manifest.skills) });
71
+ }
72
+ return {
73
+ content: [{ type: 'text', text: JSON.stringify(results) }],
74
+ };
75
+ });
76
+ // skilldex_suggest
77
+ server.tool('skilldex_suggest', 'Generate AI-powered skill suggestions for a project', {
78
+ projectPath: z.string().optional().describe('Path to project (defaults to cwd)'),
79
+ }, async ({ projectPath }) => {
80
+ const { gatherProjectContext, generateProposals } = await import('../core/suggest-agent.js');
81
+ const { findProjectRoot } = await import('../core/resolver.js');
82
+ const root = await findProjectRoot(projectPath ?? process.cwd());
83
+ const context = await gatherProjectContext(root);
84
+ const proposals = await generateProposals(context);
85
+ return {
86
+ content: [{ type: 'text', text: JSON.stringify({ proposals }) }],
87
+ };
88
+ });
89
+ // skilldex_search (stub)
90
+ server.tool('skilldex_search', 'Search the Skilldex registry for skills (coming soon)', {
91
+ query: z.string().describe('Search query'),
92
+ }, async ({ query }) => {
93
+ return {
94
+ content: [
95
+ {
96
+ type: 'text',
97
+ text: JSON.stringify({
98
+ results: [],
99
+ total: 0,
100
+ message: 'Registry search is not yet available in this version.',
101
+ }),
102
+ },
103
+ ],
104
+ };
105
+ });
106
+ const transport = new StdioServerTransport();
107
+ await server.connect(transport);
108
+ }
109
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { installFromGitUrl, parseGitUrl } from './sources/github.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,4 @@
1
+ // Registry facade — routes installs to the appropriate source
2
+ // Phase 5: will add search, publish, official registry
3
+ export { installFromGitUrl, parseGitUrl } from './sources/github.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,uDAAuD;AACvD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA"}