claude-skills-cli 0.0.20 → 0.0.22
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/add-hook.cmd-JWw5UqA3.js +193 -0
- package/dist/add-hook.cmd-JWw5UqA3.js.map +1 -0
- package/dist/dependency-validator-CQJ1hCoU.js +382 -0
- package/dist/dependency-validator-CQJ1hCoU.js.map +1 -0
- package/dist/doctor.cmd-DJpHLDCV.js +142 -0
- package/dist/doctor.cmd-DJpHLDCV.js.map +1 -0
- package/dist/fs-CuGv3Ob2.js +23 -0
- package/dist/fs-CuGv3Ob2.js.map +1 -0
- package/dist/index.js +24 -22
- package/dist/index.js.map +1 -1
- package/dist/init.cmd-BdqImX8b.js +108 -0
- package/dist/init.cmd-BdqImX8b.js.map +1 -0
- package/dist/install.cmd-BaP8k9d2.js +79 -0
- package/dist/install.cmd-BaP8k9d2.js.map +1 -0
- package/dist/output-DiffPD2u.js +104 -0
- package/dist/output-DiffPD2u.js.map +1 -0
- package/dist/package.cmd-BYhkheya.js +107 -0
- package/dist/package.cmd-BYhkheya.js.map +1 -0
- package/dist/stats.cmd-Dd46qjoV.js +154 -0
- package/dist/stats.cmd-Dd46qjoV.js.map +1 -0
- package/dist/{core/templates.js → templates-fyteNbD0.js} +20 -13
- package/dist/templates-fyteNbD0.js.map +1 -0
- package/dist/validate.cmd-BxF4HNsu.js +96 -0
- package/dist/validate.cmd-BxF4HNsu.js.map +1 -0
- package/dist/validator-Dp5x-OjP.js +729 -0
- package/dist/validator-Dp5x-OjP.js.map +1 -0
- package/package.json +34 -35
- package/dist/commands/add-hook.cmd.js +0 -35
- package/dist/commands/add-hook.cmd.js.map +0 -1
- package/dist/commands/add-hook.js +0 -216
- package/dist/commands/add-hook.js.map +0 -1
- package/dist/commands/doctor.cmd.js +0 -19
- package/dist/commands/doctor.cmd.js.map +0 -1
- package/dist/commands/doctor.js +0 -128
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/init.cmd.js +0 -37
- package/dist/commands/init.cmd.js.map +0 -1
- package/dist/commands/init.js +0 -86
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/install.cmd.js +0 -23
- package/dist/commands/install.cmd.js.map +0 -1
- package/dist/commands/install.js +0 -64
- package/dist/commands/install.js.map +0 -1
- package/dist/commands/package.cmd.js +0 -28
- package/dist/commands/package.cmd.js.map +0 -1
- package/dist/commands/package.js +0 -134
- package/dist/commands/package.js.map +0 -1
- package/dist/commands/stats.cmd.js +0 -19
- package/dist/commands/stats.cmd.js.map +0 -1
- package/dist/commands/stats.js +0 -154
- package/dist/commands/stats.js.map +0 -1
- package/dist/commands/validate.cmd.js +0 -39
- package/dist/commands/validate.cmd.js.map +0 -1
- package/dist/commands/validate.js +0 -77
- package/dist/commands/validate.js.map +0 -1
- package/dist/core/templates.js.map +0 -1
- package/dist/core/validator.js +0 -252
- package/dist/core/validator.js.map +0 -1
- package/dist/help.js +0 -305
- package/dist/help.js.map +0 -1
- package/dist/skills/.gitkeep +0 -0
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils/fs.js +0 -25
- package/dist/utils/fs.js.map +0 -1
- package/dist/utils/output.js +0 -102
- package/dist/utils/output.js.map +0 -1
- package/dist/validators/alignment-validator.js +0 -54
- package/dist/validators/alignment-validator.js.map +0 -1
- package/dist/validators/content-validator.js +0 -156
- package/dist/validators/content-validator.js.map +0 -1
- package/dist/validators/description-validator.js +0 -150
- package/dist/validators/description-validator.js.map +0 -1
- package/dist/validators/file-structure-validator.js +0 -125
- package/dist/validators/file-structure-validator.js.map +0 -1
- package/dist/validators/frontmatter-validator.js +0 -190
- package/dist/validators/frontmatter-validator.js.map +0 -1
- package/dist/validators/references-validator.js +0 -155
- package/dist/validators/references-validator.js.map +0 -1
- package/dist/validators/text-analysis.js +0 -71
- package/dist/validators/text-analysis.js.map +0 -1
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Content validation (Level 2 progressive disclosure)
|
|
3
|
-
*/
|
|
4
|
-
import { count_words, estimate_tokens, strip_html_comments, } from './text-analysis.js';
|
|
5
|
-
// Progressive disclosure limits - three tiers
|
|
6
|
-
const LIMITS = {
|
|
7
|
-
strict: {
|
|
8
|
-
lines: { excellent: 30, good: 40, max: 50 },
|
|
9
|
-
words: { excellent: 300, good: 500, max: 1000 },
|
|
10
|
-
},
|
|
11
|
-
lenient: {
|
|
12
|
-
lines: { excellent: 50, good: 100, max: 150 },
|
|
13
|
-
words: { excellent: 500, good: 1000, max: 2000 },
|
|
14
|
-
},
|
|
15
|
-
loose: {
|
|
16
|
-
lines: { excellent: 100, good: 200, max: 500 },
|
|
17
|
-
words: { excellent: 1000, good: 2000, max: 5000 },
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Analyze content structure and patterns
|
|
22
|
-
*/
|
|
23
|
-
export function analyze_content_structure(body) {
|
|
24
|
-
// Count code blocks
|
|
25
|
-
const code_block_matches = body.match(/```[\s\S]*?```/g);
|
|
26
|
-
const code_blocks = code_block_matches
|
|
27
|
-
? code_block_matches.length
|
|
28
|
-
: 0;
|
|
29
|
-
// Count markdown sections (headings)
|
|
30
|
-
const heading_matches = body.match(/^#{1,6}\s/gm);
|
|
31
|
-
const sections = heading_matches ? heading_matches.length : 0;
|
|
32
|
-
// Count long paragraphs (>100 words)
|
|
33
|
-
const paragraphs = body.split(/\n\n+/);
|
|
34
|
-
const long_paragraphs = paragraphs.filter((p) => {
|
|
35
|
-
const words = count_words(p);
|
|
36
|
-
return words > 100;
|
|
37
|
-
}).length;
|
|
38
|
-
return { code_blocks, sections, long_paragraphs };
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Validate progressive disclosure (word count, token budget, and line count)
|
|
42
|
-
*/
|
|
43
|
-
export function validate_content(body, options = {}) {
|
|
44
|
-
const { mode = 'strict' } = options;
|
|
45
|
-
const limits = LIMITS[mode];
|
|
46
|
-
const word_count = count_words(body);
|
|
47
|
-
const estimated_tokens = estimate_tokens(word_count);
|
|
48
|
-
// Strip HTML comments before counting lines (progressive disclosure guidance shouldn't inflate count)
|
|
49
|
-
const body_without_comments = strip_html_comments(body);
|
|
50
|
-
const line_count = body_without_comments.trim().split('\n').length;
|
|
51
|
-
// Analyze content structure
|
|
52
|
-
const structure = analyze_content_structure(body);
|
|
53
|
-
const validation = {
|
|
54
|
-
stats: {
|
|
55
|
-
word_count,
|
|
56
|
-
estimated_tokens,
|
|
57
|
-
line_count,
|
|
58
|
-
...structure,
|
|
59
|
-
},
|
|
60
|
-
warnings: [],
|
|
61
|
-
errors: [],
|
|
62
|
-
};
|
|
63
|
-
// Word count validation
|
|
64
|
-
if (word_count > limits.words.max) {
|
|
65
|
-
validation.errors.push({
|
|
66
|
-
type: 'word_count',
|
|
67
|
-
message: `SKILL.md body has ${word_count} words (MAX: ${limits.words.max})\n` +
|
|
68
|
-
` → Move detailed content to references/ directory for Level 3 loading\n` +
|
|
69
|
-
` → This is a hard limit - skills must be concise`,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
else if (word_count > limits.words.good) {
|
|
73
|
-
validation.warnings.push({
|
|
74
|
-
type: 'word_count',
|
|
75
|
-
message: `SKILL.md body has ${word_count} words (recommended: <${limits.words.good}, max: ${limits.words.max})\n` +
|
|
76
|
-
` → Consider moving examples/docs to references/ for better token efficiency`,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
// Line count validation (Level 2 progressive disclosure)
|
|
80
|
-
if (line_count > limits.lines.max) {
|
|
81
|
-
validation.errors.push({
|
|
82
|
-
type: 'line_count',
|
|
83
|
-
message: `SKILL.md body is ${line_count} lines (MAX: ${limits.lines.max})\n` +
|
|
84
|
-
` → Move detailed content to references/ directory\n` +
|
|
85
|
-
` → This is a hard limit - skills must be concise`,
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
else if (line_count > limits.lines.good) {
|
|
89
|
-
validation.warnings.push({
|
|
90
|
-
type: 'line_count',
|
|
91
|
-
message: `SKILL.md body is ${line_count} lines (recommended: <${limits.lines.good}, max: ${limits.lines.max})\n` +
|
|
92
|
-
` → Consider moving examples to references/ for Level 3 loading`,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
// Content analysis warnings
|
|
96
|
-
// Code blocks: Recommend 1-2, warn at >3
|
|
97
|
-
if (structure.code_blocks > 3) {
|
|
98
|
-
validation.warnings.push({
|
|
99
|
-
type: 'code_blocks',
|
|
100
|
-
message: `SKILL.md contains ${structure.code_blocks} code examples (recommended: 1-2)\n` +
|
|
101
|
-
` → Move additional examples to references/examples.md for Level 3 loading`,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
// Long paragraphs
|
|
105
|
-
if (structure.long_paragraphs > 3) {
|
|
106
|
-
validation.warnings.push({
|
|
107
|
-
type: 'long_paragraphs',
|
|
108
|
-
message: `SKILL.md contains ${structure.long_paragraphs} lengthy paragraphs (>100 words)\n` +
|
|
109
|
-
` → Consider moving detailed explanations to references/`,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
// Sections: Recommend 3-5, warn at >8
|
|
113
|
-
if (structure.sections > 8) {
|
|
114
|
-
validation.warnings.push({
|
|
115
|
-
type: 'sections',
|
|
116
|
-
message: `SKILL.md contains ${structure.sections} sections (recommended: 3-5)\n` +
|
|
117
|
-
` → Consider splitting into focused reference files`,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
// Check for "Quick Start" section
|
|
121
|
-
if (!body.includes('## Quick Start') &&
|
|
122
|
-
!body.includes('## Quick start')) {
|
|
123
|
-
validation.warnings.push({
|
|
124
|
-
type: 'missing_quick_start',
|
|
125
|
-
message: `Missing "## Quick Start" section\n` +
|
|
126
|
-
` → Add one minimal working example to help Claude get started quickly`,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
// Check for references/ links when body is long (warn when exceeding good threshold)
|
|
130
|
-
const has_references = body.includes('references/');
|
|
131
|
-
if (!has_references && line_count > limits.lines.good) {
|
|
132
|
-
validation.warnings.push({
|
|
133
|
-
type: 'no_references',
|
|
134
|
-
message: `No references/ links found but SKILL.md is ${line_count} lines\n` +
|
|
135
|
-
` → Consider splitting detailed content into reference files`,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
// Check body content
|
|
139
|
-
if (body.trim().length < 100) {
|
|
140
|
-
validation.warnings.push({
|
|
141
|
-
type: 'short_body',
|
|
142
|
-
message: 'SKILL.md body is very short',
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
// Check for TODO placeholders
|
|
146
|
-
if (body.includes('TODO') ||
|
|
147
|
-
body.includes('[Add your') ||
|
|
148
|
-
body.includes('[Provide')) {
|
|
149
|
-
validation.warnings.push({
|
|
150
|
-
type: 'todo_placeholders',
|
|
151
|
-
message: 'SKILL.md contains TODO placeholders',
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
return validation;
|
|
155
|
-
}
|
|
156
|
-
//# sourceMappingURL=content-validator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"content-validator.js","sourceRoot":"","sources":["../../src/validators/content-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Description validation (Level 1 progressive disclosure)
|
|
3
|
-
*/
|
|
4
|
-
import { estimate_string_tokens } from './text-analysis.js';
|
|
5
|
-
/**
|
|
6
|
-
* Validate description length and quality
|
|
7
|
-
*/
|
|
8
|
-
export function validate_description_content(description) {
|
|
9
|
-
const desc_length = description.length;
|
|
10
|
-
const desc_tokens = estimate_string_tokens(description);
|
|
11
|
-
const validation = {
|
|
12
|
-
stats: {
|
|
13
|
-
description_length: desc_length,
|
|
14
|
-
description_tokens: desc_tokens,
|
|
15
|
-
},
|
|
16
|
-
warnings: [],
|
|
17
|
-
errors: [],
|
|
18
|
-
};
|
|
19
|
-
// Enforced limit: 300 chars (prevents Claude from bloating descriptions)
|
|
20
|
-
// Anthropic allows 1024, but that leads to verbose, inefficient descriptions
|
|
21
|
-
if (desc_length > 300) {
|
|
22
|
-
validation.errors.push({
|
|
23
|
-
type: 'length',
|
|
24
|
-
message: `Description is ${desc_length} characters (MAX: 300 for efficiency)\n` +
|
|
25
|
-
` → Keep descriptions concise - quality over quantity`,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
// Check for trigger keywords
|
|
29
|
-
const lower_desc = description.toLowerCase();
|
|
30
|
-
const has_trigger = lower_desc.includes('use when') ||
|
|
31
|
-
lower_desc.includes('use for') ||
|
|
32
|
-
lower_desc.includes('use to');
|
|
33
|
-
if (!has_trigger) {
|
|
34
|
-
validation.warnings.push({
|
|
35
|
-
type: 'trigger',
|
|
36
|
-
message: `Description missing trigger keywords ('Use when...', 'Use for...', 'Use to...')\n` +
|
|
37
|
-
` → Help Claude know when to activate this skill`,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
// Check for list bloat (multiple commas indicating detailed lists)
|
|
41
|
-
// Only warn if BOTH long description AND many commas (allows concise technical lists)
|
|
42
|
-
const comma_count = (description.match(/,/g) || []).length;
|
|
43
|
-
if (desc_length > 150 && comma_count >= 5) {
|
|
44
|
-
validation.warnings.push({
|
|
45
|
-
type: 'list_bloat',
|
|
46
|
-
message: `Description contains long lists (${comma_count} commas, ${desc_length} chars)\n` +
|
|
47
|
-
` → Move detailed lists to Level 2 (SKILL.md body) or Level 3 (references/)`,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
// Short description check
|
|
51
|
-
if (desc_length < 50) {
|
|
52
|
-
validation.warnings.push({
|
|
53
|
-
type: 'short',
|
|
54
|
-
message: `Description is very short (${desc_length} chars, minimum recommended: 50)\n` +
|
|
55
|
-
` → Must answer both "what does it do" AND "when to use it"`,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
return validation;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Analyze trigger phrase in description
|
|
62
|
-
*/
|
|
63
|
-
export function analyze_trigger_phrase(description) {
|
|
64
|
-
const lower = description.toLowerCase();
|
|
65
|
-
const has_trigger = lower.includes('use when') ||
|
|
66
|
-
lower.includes('use for') ||
|
|
67
|
-
lower.includes('use to');
|
|
68
|
-
let trigger_phrase = null;
|
|
69
|
-
let trigger_type = 'missing';
|
|
70
|
-
if (has_trigger) {
|
|
71
|
-
const match = description.match(/(use when|use for|use to)[^.!?]*/i);
|
|
72
|
-
if (match) {
|
|
73
|
-
trigger_phrase = match[0].trim();
|
|
74
|
-
trigger_type =
|
|
75
|
-
trigger_phrase.length > 50 ? 'specific' : 'generic';
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return {
|
|
79
|
-
has_explicit_trigger: has_trigger,
|
|
80
|
-
trigger_phrase,
|
|
81
|
-
trigger_type,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Analyze user phrasing style
|
|
86
|
-
*/
|
|
87
|
-
export function analyze_user_phrasing(description) {
|
|
88
|
-
const issues = [];
|
|
89
|
-
const warnings = [];
|
|
90
|
-
// Check for first person
|
|
91
|
-
const is_third_person = !/\b(I can|I will|I help|my|me)\b/i.test(description);
|
|
92
|
-
const first_person_patterns = /\b(I can|I will|I help|my|me)\b/i;
|
|
93
|
-
if (first_person_patterns.test(description)) {
|
|
94
|
-
const match = description.match(first_person_patterns);
|
|
95
|
-
if (match) {
|
|
96
|
-
warnings.push({
|
|
97
|
-
type: 'first_person',
|
|
98
|
-
message: `Description uses first person: "${match[0]}"\n` +
|
|
99
|
-
` → Anthropic requires third-person voice (e.g., "Generates..." not "I can generate...")`,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
// Check for second person
|
|
104
|
-
const second_person_patterns = /\b(You can|You should|You could|You'll|You will|You need|your)\b/i;
|
|
105
|
-
if (second_person_patterns.test(description)) {
|
|
106
|
-
const match = description.match(second_person_patterns);
|
|
107
|
-
if (match) {
|
|
108
|
-
warnings.push({
|
|
109
|
-
type: 'second_person',
|
|
110
|
-
message: `Description uses second person: "${match[0]}"\n` +
|
|
111
|
-
` → Anthropic requires third-person voice (e.g., "Processes..." not "You can process...")`,
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
// Check for vague terms
|
|
116
|
-
const vague_patterns = /\b(helper|utility|tool|various|several|some)\b/i;
|
|
117
|
-
if (vague_patterns.test(description)) {
|
|
118
|
-
const match = description.match(vague_patterns);
|
|
119
|
-
if (match) {
|
|
120
|
-
warnings.push({
|
|
121
|
-
type: 'vague',
|
|
122
|
-
message: `Description contains vague term: "${match[0]}"\n` +
|
|
123
|
-
` → Be specific about what the skill does`,
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Check for gerund form (verbs ending in -ing)
|
|
128
|
-
const uses_gerund = /\b\w+ing\b/i.test(description);
|
|
129
|
-
// Check for action-oriented (starts with action verbs)
|
|
130
|
-
const action_verbs = /^(create|build|design|analyze|test|validate|generate|process|manage|execute|handle|provide)/i;
|
|
131
|
-
const is_action_oriented = action_verbs.test(description.trim());
|
|
132
|
-
// Suggest action-oriented language if neither gerund nor action verb
|
|
133
|
-
if (!uses_gerund && !is_action_oriented) {
|
|
134
|
-
warnings.push({
|
|
135
|
-
type: 'passive',
|
|
136
|
-
message: `Description lacks action-oriented language\n` +
|
|
137
|
-
` → Start with a verb or gerund (e.g., "Generates...", "Managing...", "Extract...")`,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
const analysis = {
|
|
141
|
-
style_checks: {
|
|
142
|
-
is_third_person,
|
|
143
|
-
uses_gerund_form: uses_gerund,
|
|
144
|
-
is_action_oriented,
|
|
145
|
-
},
|
|
146
|
-
issues,
|
|
147
|
-
};
|
|
148
|
-
return { analysis, warnings };
|
|
149
|
-
}
|
|
150
|
-
//# sourceMappingURL=description-validator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"description-validator.js","sourceRoot":"","sources":["../../src/validators/description-validator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AA+B5D;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAC3C,WAAmB;IAEnB,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC;IACvC,MAAM,WAAW,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;IAExD,MAAM,UAAU,GAA0B;QACzC,KAAK,EAAE;YACN,kBAAkB,EAAE,WAAW;YAC/B,kBAAkB,EAAE,WAAW;SAC/B;QACD,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE;KACV,CAAC;IAEF,yEAAyE;IACzE,6EAA6E;IAC7E,IAAI,WAAW,GAAG,GAAG,EAAE,CAAC;QACvB,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;YACtB,IAAI,EAAE,QAAQ;YACd,OAAO,EACN,kBAAkB,WAAW,yCAAyC;gBACtE,uDAAuD;SACxD,CAAC,CAAC;IACJ,CAAC;IAED,6BAA6B;IAC7B,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,WAAW,GAChB,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC/B,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC9B,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE/B,IAAI,CAAC,WAAW,EAAE,CAAC;QAClB,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,SAAS;YACf,OAAO,EACN,mFAAmF;gBACnF,kDAAkD;SACnD,CAAC,CAAC;IACJ,CAAC;IAED,mEAAmE;IACnE,sFAAsF;IACtF,MAAM,WAAW,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IAC3D,IAAI,WAAW,GAAG,GAAG,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;QAC3C,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,YAAY;YAClB,OAAO,EACN,oCAAoC,WAAW,YAAY,WAAW,WAAW;gBACjF,6EAA6E;SAC9E,CAAC,CAAC;IACJ,CAAC;IAED,0BAA0B;IAC1B,IAAI,WAAW,GAAG,EAAE,EAAE,CAAC;QACtB,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,OAAO;YACb,OAAO,EACN,8BAA8B,WAAW,oCAAoC;gBAC7E,6DAA6D;SAC9D,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CACrC,WAAmB;IAEnB,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,WAAW,GAChB,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC1B,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE1B,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,IAAI,YAAY,GAAuC,SAAS,CAAC;IAEjE,IAAI,WAAW,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAC9B,mCAAmC,CACnC,CAAC;QACF,IAAI,KAAK,EAAE,CAAC;YACX,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACjC,YAAY;gBACX,cAAc,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QACtD,CAAC;IACF,CAAC;IAED,OAAO;QACN,oBAAoB,EAAE,WAAW;QACjC,cAAc;QACd,YAAY;KACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IAIxD,MAAM,MAAM,GAIP,EAAE,CAAC;IACR,MAAM,QAAQ,GAAyB,EAAE,CAAC;IAE1C,yBAAyB;IACzB,MAAM,eAAe,GAAG,CAAC,kCAAkC,CAAC,IAAI,CAC/D,WAAW,CACX,CAAC;IACF,MAAM,qBAAqB,GAAG,kCAAkC,CAAC;IACjE,IAAI,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACvD,IAAI,KAAK,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,cAAc;gBACpB,OAAO,EACN,mCAAmC,KAAK,CAAC,CAAC,CAAC,KAAK;oBAChD,0FAA0F;aAC3F,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,0BAA0B;IAC1B,MAAM,sBAAsB,GAC3B,mEAAmE,CAAC;IACrE,IAAI,sBAAsB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACxD,IAAI,KAAK,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,eAAe;gBACrB,OAAO,EACN,oCAAoC,KAAK,CAAC,CAAC,CAAC,KAAK;oBACjD,2FAA2F;aAC5F,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,wBAAwB;IACxB,MAAM,cAAc,GACnB,iDAAiD,CAAC;IACnD,IAAI,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAChD,IAAI,KAAK,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,OAAO;gBACb,OAAO,EACN,qCAAqC,KAAK,CAAC,CAAC,CAAC,KAAK;oBAClD,2CAA2C;aAC5C,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,+CAA+C;IAC/C,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAEpD,uDAAuD;IACvD,MAAM,YAAY,GACjB,8FAA8F,CAAC;IAChG,MAAM,kBAAkB,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IAEjE,qEAAqE;IACrE,IAAI,CAAC,WAAW,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC;YACb,IAAI,EAAE,SAAS;YACf,OAAO,EACN,8CAA8C;gBAC9C,qFAAqF;SACtF,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAyB;QACtC,YAAY,EAAE;YACb,eAAe;YACf,gBAAgB,EAAE,WAAW;YAC7B,kBAAkB;SAClB;QACD,MAAM;KACN,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File structure validation - paths, scripts, assets
|
|
3
|
-
*/
|
|
4
|
-
import { existsSync, readdirSync, readFileSync, statSync, } from 'node:fs';
|
|
5
|
-
import { join } from 'node:path';
|
|
6
|
-
/**
|
|
7
|
-
* Validate that skill directory exists and is valid
|
|
8
|
-
*/
|
|
9
|
-
export function validate_directory(skill_path) {
|
|
10
|
-
const errors = [];
|
|
11
|
-
if (!existsSync(skill_path)) {
|
|
12
|
-
errors.push({
|
|
13
|
-
type: 'not_found',
|
|
14
|
-
message: `Skill directory does not exist: ${skill_path}`,
|
|
15
|
-
});
|
|
16
|
-
return { valid: false, errors };
|
|
17
|
-
}
|
|
18
|
-
const stats = statSync(skill_path);
|
|
19
|
-
if (!stats.isDirectory()) {
|
|
20
|
-
errors.push({
|
|
21
|
-
type: 'not_directory',
|
|
22
|
-
message: `Path is not a directory: ${skill_path}`,
|
|
23
|
-
});
|
|
24
|
-
return { valid: false, errors };
|
|
25
|
-
}
|
|
26
|
-
return { valid: true, errors: [] };
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Validate path formats (no Windows backslashes)
|
|
30
|
-
*/
|
|
31
|
-
export function validate_path_formats(content, file_name = 'SKILL.md') {
|
|
32
|
-
const invalid_paths = [];
|
|
33
|
-
const errors = [];
|
|
34
|
-
const lines = content.split('\n');
|
|
35
|
-
lines.forEach((line, index) => {
|
|
36
|
-
// Skip code blocks (they might legitimately show Windows paths as examples)
|
|
37
|
-
if (line.trim().startsWith('```'))
|
|
38
|
-
return;
|
|
39
|
-
// Detect backslashes in file paths
|
|
40
|
-
// Match patterns like: scripts\file.py, references\doc.md, etc.
|
|
41
|
-
const backslash_pattern = /(?:scripts|references|assets|examples)\\[\w\\.-]+/g;
|
|
42
|
-
const matches = line.match(backslash_pattern);
|
|
43
|
-
if (matches) {
|
|
44
|
-
matches.forEach((match) => {
|
|
45
|
-
const fixed = match.replace(/\\/g, '/');
|
|
46
|
-
// Store in validation
|
|
47
|
-
invalid_paths.push({
|
|
48
|
-
line_number: index + 1,
|
|
49
|
-
path: match,
|
|
50
|
-
error: 'Windows-style backslash detected',
|
|
51
|
-
suggested_fix: fixed,
|
|
52
|
-
});
|
|
53
|
-
errors.push({
|
|
54
|
-
type: 'windows_path',
|
|
55
|
-
message: `Windows-style path in ${file_name}:${index + 1}\n` +
|
|
56
|
-
` → Found: ${match}\n` +
|
|
57
|
-
` → Use: ${fixed}`,
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
return {
|
|
63
|
-
validation: { invalid_paths },
|
|
64
|
-
errors,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Validate scripts directory
|
|
69
|
-
*/
|
|
70
|
-
export function validate_scripts(skill_path) {
|
|
71
|
-
const scripts_dir = join(skill_path, 'scripts');
|
|
72
|
-
const warnings = [];
|
|
73
|
-
if (existsSync(scripts_dir)) {
|
|
74
|
-
const files = readdirSync(scripts_dir);
|
|
75
|
-
const script_files = files.filter((f) => f.endsWith('.js') ||
|
|
76
|
-
f.endsWith('.ts') ||
|
|
77
|
-
f.endsWith('.mjs') ||
|
|
78
|
-
f.endsWith('.sh'));
|
|
79
|
-
if (script_files.length === 0) {
|
|
80
|
-
warnings.push({
|
|
81
|
-
type: 'empty_directory',
|
|
82
|
-
message: 'scripts/ directory exists but is empty',
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
for (const script_file of script_files) {
|
|
86
|
-
const script_path = join(scripts_dir, script_file);
|
|
87
|
-
const stats = statSync(script_path);
|
|
88
|
-
// Check if executable (0o111 = --x--x--x)
|
|
89
|
-
if ((stats.mode & 0o111) === 0) {
|
|
90
|
-
warnings.push({
|
|
91
|
-
type: 'not_executable',
|
|
92
|
-
message: `Script is not executable: ${script_file}`,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
// Check for shebang
|
|
96
|
-
const content = readFileSync(script_path, 'utf-8');
|
|
97
|
-
const first_line = content.split('\n')[0];
|
|
98
|
-
if (!first_line.startsWith('#!')) {
|
|
99
|
-
warnings.push({
|
|
100
|
-
type: 'missing_shebang',
|
|
101
|
-
message: `Script missing shebang: ${script_file}`,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return { warnings };
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Validate assets directory
|
|
110
|
-
*/
|
|
111
|
-
export function validate_assets(skill_path) {
|
|
112
|
-
const assets_dir = join(skill_path, 'assets');
|
|
113
|
-
const warnings = [];
|
|
114
|
-
if (existsSync(assets_dir)) {
|
|
115
|
-
const files = readdirSync(assets_dir);
|
|
116
|
-
if (files.length === 0) {
|
|
117
|
-
warnings.push({
|
|
118
|
-
type: 'empty_directory',
|
|
119
|
-
message: 'assets/ directory exists but is empty',
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return { warnings };
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=file-structure-validator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-structure-validator.js","sourceRoot":"","sources":["../../src/validators/file-structure-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* YAML frontmatter validation for SKILL.md
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Check if content has valid YAML frontmatter
|
|
6
|
-
*/
|
|
7
|
-
export function has_yaml_frontmatter(content) {
|
|
8
|
-
return content.startsWith('---\n') || content.startsWith('---\r\n');
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Check if description field spans multiple lines in raw YAML
|
|
12
|
-
*/
|
|
13
|
-
export function is_description_multiline(frontmatter) {
|
|
14
|
-
// Find the description line
|
|
15
|
-
const desc_line_match = frontmatter.match(/^description:\s*(.*)$/m);
|
|
16
|
-
if (!desc_line_match) {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
const value_on_same_line = desc_line_match[1].trim();
|
|
20
|
-
// If there's no value on the same line as "description:", it's multi-line
|
|
21
|
-
if (!value_on_same_line) {
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
// Check if there are continuation lines (indented lines after description:)
|
|
25
|
-
// that are not other YAML fields
|
|
26
|
-
const lines = frontmatter.split('\n');
|
|
27
|
-
let found_desc = false;
|
|
28
|
-
for (let i = 0; i < lines.length; i++) {
|
|
29
|
-
const line = lines[i];
|
|
30
|
-
if (line.match(/^description:/)) {
|
|
31
|
-
found_desc = true;
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
if (found_desc) {
|
|
35
|
-
// If next line starts with spaces/tabs and is not a comment and is not another field
|
|
36
|
-
if (line.match(/^\s+\S/) &&
|
|
37
|
-
!line.trim().startsWith('#') &&
|
|
38
|
-
!line.match(/^[a-z_-]+:/)) {
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
// Stop checking after we hit another field or end
|
|
42
|
-
if (line.match(/^[a-z_-]+:/)) {
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Extract frontmatter and body from SKILL.md content
|
|
51
|
-
*/
|
|
52
|
-
export function extract_frontmatter(content) {
|
|
53
|
-
if (!has_yaml_frontmatter(content)) {
|
|
54
|
-
return {
|
|
55
|
-
name: null,
|
|
56
|
-
description: null,
|
|
57
|
-
body: content,
|
|
58
|
-
description_is_multiline: false,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
const parts = content.split('---\n');
|
|
62
|
-
if (parts.length < 3) {
|
|
63
|
-
return {
|
|
64
|
-
name: null,
|
|
65
|
-
description: null,
|
|
66
|
-
body: content,
|
|
67
|
-
description_is_multiline: false,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
const frontmatter = parts[1];
|
|
71
|
-
const body = parts.slice(2).join('---\n');
|
|
72
|
-
// Extract name
|
|
73
|
-
const name_match = frontmatter.match(/name:\s*(.+)/);
|
|
74
|
-
const name = name_match ? name_match[1].trim() : null;
|
|
75
|
-
// Extract description
|
|
76
|
-
const desc_match = frontmatter.match(/description:\s*(.+?)(?=\n[a-z]+:|$)/s);
|
|
77
|
-
const description = desc_match ? desc_match[1].trim() : null;
|
|
78
|
-
// Check if description spans multiple lines in the raw YAML
|
|
79
|
-
const description_is_multiline = is_description_multiline(frontmatter);
|
|
80
|
-
return { name, description, body, description_is_multiline };
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Validate YAML frontmatter structure
|
|
84
|
-
*/
|
|
85
|
-
export function validate_frontmatter_structure(content) {
|
|
86
|
-
const validation = {
|
|
87
|
-
valid: true,
|
|
88
|
-
has_frontmatter: false,
|
|
89
|
-
parse_error: null,
|
|
90
|
-
missing_fields: [],
|
|
91
|
-
};
|
|
92
|
-
if (!has_yaml_frontmatter(content)) {
|
|
93
|
-
validation.valid = false;
|
|
94
|
-
validation.parse_error = 'Missing YAML frontmatter';
|
|
95
|
-
return validation;
|
|
96
|
-
}
|
|
97
|
-
validation.has_frontmatter = true;
|
|
98
|
-
const parts = content.split('---\n');
|
|
99
|
-
if (parts.length < 3) {
|
|
100
|
-
validation.valid = false;
|
|
101
|
-
validation.parse_error = 'Malformed YAML frontmatter';
|
|
102
|
-
return validation;
|
|
103
|
-
}
|
|
104
|
-
const frontmatter = parts[1];
|
|
105
|
-
// Check required fields
|
|
106
|
-
if (!frontmatter.includes('name:')) {
|
|
107
|
-
validation.missing_fields.push('name');
|
|
108
|
-
validation.valid = false;
|
|
109
|
-
}
|
|
110
|
-
if (!frontmatter.includes('description:')) {
|
|
111
|
-
validation.missing_fields.push('description');
|
|
112
|
-
validation.valid = false;
|
|
113
|
-
}
|
|
114
|
-
return validation;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Validate skill name format
|
|
118
|
-
*/
|
|
119
|
-
export function validate_name_format(name, directory_name) {
|
|
120
|
-
const validation = {
|
|
121
|
-
name,
|
|
122
|
-
format_valid: true,
|
|
123
|
-
directory_name,
|
|
124
|
-
matches_directory: true,
|
|
125
|
-
errors: [],
|
|
126
|
-
};
|
|
127
|
-
// Validate kebab-case format
|
|
128
|
-
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
129
|
-
validation.format_valid = false;
|
|
130
|
-
validation.errors.push(`Skill name must be lowercase kebab-case: '${name}'`);
|
|
131
|
-
}
|
|
132
|
-
// Reject leading/trailing hyphens
|
|
133
|
-
if (name.startsWith('-') || name.endsWith('-')) {
|
|
134
|
-
validation.format_valid = false;
|
|
135
|
-
validation.errors.push(`Skill name must not start or end with a hyphen: '${name}'`);
|
|
136
|
-
}
|
|
137
|
-
// Reject consecutive hyphens
|
|
138
|
-
if (name.includes('--')) {
|
|
139
|
-
validation.format_valid = false;
|
|
140
|
-
validation.errors.push(`Skill name must not contain consecutive hyphens: '${name}'`);
|
|
141
|
-
}
|
|
142
|
-
// Reject reserved prefixes
|
|
143
|
-
if (name.startsWith('claude') || name.startsWith('anthropic')) {
|
|
144
|
-
validation.format_valid = false;
|
|
145
|
-
validation.errors.push(`Skill name must not use reserved prefix 'claude' or 'anthropic': '${name}'`);
|
|
146
|
-
}
|
|
147
|
-
// Reject XML angle brackets in name (security)
|
|
148
|
-
if (name.includes('<') || name.includes('>')) {
|
|
149
|
-
validation.format_valid = false;
|
|
150
|
-
validation.errors.push(`Skill name must not contain XML angle brackets: '${name}'`);
|
|
151
|
-
}
|
|
152
|
-
// Check name matches directory
|
|
153
|
-
if (name !== directory_name) {
|
|
154
|
-
validation.matches_directory = false;
|
|
155
|
-
validation.errors.push(`Skill name '${name}' must match directory name '${directory_name}'`);
|
|
156
|
-
}
|
|
157
|
-
return validation;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Validate hard limits for name and description
|
|
161
|
-
*/
|
|
162
|
-
export function validate_hard_limits(name, description) {
|
|
163
|
-
const limits = {
|
|
164
|
-
name: { length: 0, limit: 64, valid: true, error: null },
|
|
165
|
-
description: { length: 0, limit: 1024, valid: true, error: null },
|
|
166
|
-
};
|
|
167
|
-
// Validate name length
|
|
168
|
-
if (name) {
|
|
169
|
-
limits.name.length = name.length;
|
|
170
|
-
if (name.length > 64) {
|
|
171
|
-
limits.name.valid = false;
|
|
172
|
-
limits.name.error = `Skill name too long (max 64 chars): ${name.length}`;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
// Validate description length (Anthropic hard limit)
|
|
176
|
-
if (description) {
|
|
177
|
-
limits.description.length = description.length;
|
|
178
|
-
if (description.length > 1024) {
|
|
179
|
-
limits.description.valid = false;
|
|
180
|
-
limits.description.error = `Description too long (max 1024 chars per Anthropic): ${description.length}`;
|
|
181
|
-
}
|
|
182
|
-
// Reject XML angle brackets in description (security)
|
|
183
|
-
if (description.includes('<') || description.includes('>')) {
|
|
184
|
-
limits.description.valid = false;
|
|
185
|
-
limits.description.error = `Description must not contain XML angle brackets`;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return limits;
|
|
189
|
-
}
|
|
190
|
-
//# sourceMappingURL=frontmatter-validator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter-validator.js","sourceRoot":"","sources":["../../src/validators/frontmatter-validator.ts"],"names":[],"mappings":"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"}
|