claude-skills-cli 0.0.6 → 0.0.8

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 (42) hide show
  1. package/README.md +49 -9
  2. package/dist/commands/doctor.js +128 -0
  3. package/dist/commands/doctor.js.map +1 -0
  4. package/dist/commands/init.js +5 -3
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/commands/install.js +1 -1
  7. package/dist/commands/install.js.map +1 -1
  8. package/dist/commands/stats.js +1 -1
  9. package/dist/commands/stats.js.map +1 -1
  10. package/dist/commands/validate.js +24 -3
  11. package/dist/commands/validate.js.map +1 -1
  12. package/dist/commands/watch.js +82 -0
  13. package/dist/commands/watch.js.map +1 -0
  14. package/dist/core/templates.js +18 -0
  15. package/dist/core/templates.js.map +1 -1
  16. package/dist/core/validator.js +174 -321
  17. package/dist/core/validator.js.map +1 -1
  18. package/dist/index.js +38 -12
  19. package/dist/index.js.map +1 -1
  20. package/dist/skills/skill-creator/SKILL.md +28 -112
  21. package/dist/skills/skill-creator/references/cli-reference.md +152 -38
  22. package/dist/skills/skill-creator/references/development-process.md +208 -0
  23. package/dist/skills/skill-creator/references/skill-examples.md +1 -1
  24. package/dist/validators/alignment-validator.js +54 -0
  25. package/dist/validators/alignment-validator.js.map +1 -0
  26. package/dist/validators/content-validator.js +144 -0
  27. package/dist/validators/content-validator.js.map +1 -0
  28. package/dist/validators/description-validator.js +136 -0
  29. package/dist/validators/description-validator.js.map +1 -0
  30. package/dist/validators/file-structure-validator.js +125 -0
  31. package/dist/validators/file-structure-validator.js.map +1 -0
  32. package/dist/validators/frontmatter-validator.js +165 -0
  33. package/dist/validators/frontmatter-validator.js.map +1 -0
  34. package/dist/validators/references-validator.js +125 -0
  35. package/dist/validators/references-validator.js.map +1 -0
  36. package/dist/validators/text-analysis.js +71 -0
  37. package/dist/validators/text-analysis.js.map +1 -0
  38. package/docs/prompt-that-started-it-all.md +19 -0
  39. package/package.json +3 -3
  40. package/docs/SKILL-DEVELOPMENT.md +0 -460
  41. package/docs/SKILL-EXAMPLES.md +0 -528
  42. package/docs/SKILLS-ARCHITECTURE.md +0 -381
@@ -0,0 +1,208 @@
1
+ # Development Process
2
+
3
+ Step-by-step workflow for creating effective Claude Skills.
4
+
5
+ ## The Seven Steps
6
+
7
+ ### 1. Recognize
8
+
9
+ Notice when you're repeatedly providing the same context or domain
10
+ knowledge:
11
+
12
+ - Explaining the same database schema multiple times
13
+ - Providing API integration details in every conversation
14
+ - Sharing framework-specific conventions repeatedly
15
+ - Teaching the same domain concepts
16
+
17
+ **Signal**: "I've explained this 3+ times in different conversations"
18
+
19
+ ### 2. Gather
20
+
21
+ Collect 3-5 concrete examples of how you've used this knowledge:
22
+
23
+ - Save conversation snippets showing the repeated context
24
+ - Document the specific questions or tasks that triggered the need
25
+ - Note the exact information you provided each time
26
+ - Identify common patterns across usage
27
+
28
+ **Output**: A collection of real usage examples
29
+
30
+ ### 3. Plan
31
+
32
+ Decide information hierarchy:
33
+
34
+ **SKILL.md (Level 2)** - Core patterns only:
35
+
36
+ - What the skill does
37
+ - When to use it
38
+ - Essential structure/commands
39
+ - Links to references
40
+
41
+ **references/ (Level 3)** - Detailed docs:
42
+
43
+ - Complete API documentation
44
+ - Detailed examples and tutorials
45
+ - Background and theory
46
+ - Edge cases and troubleshooting
47
+
48
+ **scripts/ (Level 3)** - Deterministic operations:
49
+
50
+ - Validation logic
51
+ - Code generation
52
+ - File transformations
53
+ - Data processing
54
+
55
+ **assets/ (Level 3)** - Static resources:
56
+
57
+ - Templates
58
+ - Configuration files
59
+ - Images and diagrams
60
+
61
+ ### 4. Structure
62
+
63
+ Create the directory structure:
64
+
65
+ ```bash
66
+ mkdir -p .claude/skills/my-skill/{references,scripts,assets}
67
+ touch .claude/skills/my-skill/SKILL.md
68
+ ```
69
+
70
+ ### 5. Write
71
+
72
+ #### Write Description First
73
+
74
+ The description is critical for skill discovery. Format:
75
+
76
+ ```
77
+ [Domain/Context] [operations/capabilities]. Use when [trigger scenarios].
78
+ ```
79
+
80
+ Examples:
81
+
82
+ - ✅ "PostgreSQL schema and query patterns. Use when designing
83
+ databases, writing queries, or optimizing performance."
84
+ - ✅ "Next.js 14 App Router conventions. Use when building Next.js
85
+ apps, configuring routes, or implementing server components."
86
+ - ❌ "A skill for databases" (too vague)
87
+ - ❌ "This skill helps you work with PostgreSQL databases" (second
88
+ person)
89
+
90
+ Target: <200 chars for optimal Level 1 efficiency
91
+
92
+ #### Write SKILL.md Body
93
+
94
+ Structure:
95
+
96
+ 1. **Brief intro** (1-2 lines) - What this skill provides
97
+ 2. **When to use** (3-5 bullets) - Triggering scenarios
98
+ 3. **Core patterns** (3-5 sections) - Essential knowledge
99
+ 4. **Links to references** - Point to detailed docs
100
+
101
+ Guidelines:
102
+
103
+ - Use imperative voice ("Use X for Y", not "You should use X")
104
+ - Provide concrete examples, not abstract concepts
105
+ - Keep it scannable with clear headings
106
+ - Target ~50 lines, max ~150 lines
107
+ - Link liberally to references/
108
+
109
+ #### Write References
110
+
111
+ No size limits - be as detailed as needed:
112
+
113
+ - Use descriptive filenames (api-endpoints.md, not reference.md)
114
+ - Structure with clear headings
115
+ - Include code examples
116
+ - Cover edge cases
117
+ - Provide context and rationale
118
+
119
+ ### 6. Enhance
120
+
121
+ Add progressive enhancements:
122
+
123
+ **Scripts** - When operations are:
124
+
125
+ - Deterministic (same input = same output)
126
+ - Complex (would require Claude to generate code)
127
+ - Reusable (used frequently)
128
+
129
+ Examples: validators, code generators, formatters
130
+
131
+ **Assets** - When you need:
132
+
133
+ - Templates (boilerplate code, config files)
134
+ - Static files (images, data files)
135
+ - Resources that shouldn't be loaded into context
136
+
137
+ ### 7. Iterate
138
+
139
+ Test and refine:
140
+
141
+ **Testing**:
142
+
143
+ - Start a new conversation
144
+ - Trigger the skill naturally (don't force it)
145
+ - Observe if Claude loads it appropriately
146
+ - Check if the content is helpful and sufficient
147
+
148
+ **Refining**:
149
+
150
+ - If skill loads too often → Make description more specific
151
+ - If skill never loads → Add trigger keywords to description
152
+ - If Claude asks for info that's in references → Add links in SKILL.md
153
+ - If SKILL.md feels bloated → Move content to references
154
+ - If you're repeating the same complex operation → Create a script
155
+
156
+ **Iteration Cycle**:
157
+
158
+ 1. Use skill in real conversations
159
+ 2. Note friction points and gaps
160
+ 3. Refactor structure and content
161
+ 4. Test again
162
+
163
+ ## Common Pitfalls
164
+
165
+ **Starting Too Big**
166
+
167
+ - ❌ Writing 500 lines before testing
168
+ - ✅ Start with 30-line SKILL.md, iterate
169
+
170
+ **Generic Descriptions**
171
+
172
+ - ❌ "Helps with coding tasks"
173
+ - ✅ "React hooks patterns and performance optimization. Use when
174
+ building React components or debugging re-renders."
175
+
176
+ **Bloated SKILL.md**
177
+
178
+ - ❌ Including complete API docs in SKILL.md
179
+ - ✅ Core patterns in SKILL.md, full docs in references/
180
+
181
+ **Missing Triggers**
182
+
183
+ - ❌ Description with no "Use when..." clause
184
+ - ✅ Clear triggering scenarios in description
185
+
186
+ **Second Person Voice**
187
+
188
+ - ❌ "You should use this pattern when you need..."
189
+ - ✅ "Use this pattern when..."
190
+
191
+ ## Success Criteria
192
+
193
+ A well-designed skill:
194
+
195
+ - ✅ Loads automatically when relevant (no manual triggering)
196
+ - ✅ Provides exactly the context needed (not too much, not too
197
+ little)
198
+ - ✅ Improves with each conversation (you notice missing pieces)
199
+ - ✅ Saves you time (no more re-explaining the same concepts)
200
+
201
+ ## Tips
202
+
203
+ - **Start minimal**: Better to add than to remove
204
+ - **Test early**: Don't perfect in isolation
205
+ - **Use real examples**: Concrete beats abstract
206
+ - **Trust progressive disclosure**: Claude will ask for references
207
+ when needed
208
+ - **Iterate based on usage**: Let real conversations drive refinement
@@ -396,7 +396,7 @@ Before considering a skill "done":
396
396
  - [ ] Detailed docs in references/
397
397
  - [ ] Scripts for repeated code
398
398
  - [ ] Assets for templates
399
- - [ ] Validated with `npx claude-skills validate`
399
+ - [ ] Validated with `npx claude-skills-cli validate`
400
400
  - [ ] Tested in real conversations
401
401
  - [ ] No TODO placeholders
402
402
  - [ ] Imperative voice throughout
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Alignment validation - checks description and content alignment
3
+ */
4
+ import { extract_keywords } from './text-analysis.js';
5
+ /**
6
+ * Analyze description and content alignment
7
+ */
8
+ export function analyze_alignment(description, body) {
9
+ const desc_keywords = extract_keywords(description);
10
+ const content_keywords = extract_keywords(body);
11
+ const overlap = desc_keywords.filter((k) => content_keywords.includes(k));
12
+ const desc_only = desc_keywords.filter((k) => !content_keywords.includes(k));
13
+ const content_only = content_keywords
14
+ .filter((k) => !desc_keywords.includes(k))
15
+ .slice(0, 20);
16
+ const overlap_ratio = desc_keywords.length > 0
17
+ ? overlap.length / desc_keywords.length
18
+ : 0;
19
+ let severity = 'good';
20
+ let explanation = 'Description aligns well with content';
21
+ if (overlap_ratio < 0.2 && desc_keywords.length > 5) {
22
+ severity = 'critical';
23
+ explanation = `Very low keyword overlap (${Math.round(overlap_ratio * 100)}%). Description may not match skill content.`;
24
+ }
25
+ else if (overlap_ratio < 0.3 && desc_keywords.length > 5) {
26
+ severity = 'moderate';
27
+ explanation = `Low keyword overlap (${Math.round(overlap_ratio * 100)}%). Description may not accurately reflect skill content.`;
28
+ }
29
+ const keywords = {
30
+ description_keywords: desc_keywords,
31
+ content_keywords: content_keywords.slice(0, 30),
32
+ overlap,
33
+ description_only: desc_only,
34
+ content_only,
35
+ };
36
+ const alignment = {
37
+ severity,
38
+ description_focus: desc_keywords.slice(0, 10),
39
+ content_focus: content_keywords.slice(0, 10),
40
+ matches: overlap,
41
+ mismatches: desc_only,
42
+ explanation,
43
+ };
44
+ const warnings = [];
45
+ if (overlap_ratio < 0.3 && desc_keywords.length > 5) {
46
+ warnings.push({
47
+ type: 'low_overlap',
48
+ message: `Low keyword overlap between description and content (${Math.round(overlap_ratio * 100)}%)\n` +
49
+ ` → Description may not accurately reflect skill content`,
50
+ });
51
+ }
52
+ return { keywords, alignment, warnings };
53
+ }
54
+ //# sourceMappingURL=alignment-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alignment-validator.js","sourceRoot":"","sources":["../../src/validators/alignment-validator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AActD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAChC,WAAmB,EACnB,IAAY;IAEZ,MAAM,aAAa,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAEhD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1C,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC5B,CAAC;IACF,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CACpC,CAAC;IACF,MAAM,YAAY,GAAG,gBAAgB;SACnC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SACzC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEf,MAAM,aAAa,GAClB,aAAa,CAAC,MAAM,GAAG,CAAC;QACvB,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM;QACvC,CAAC,CAAC,CAAC,CAAC;IAEN,IAAI,QAAQ,GAAqC,MAAM,CAAC;IACxD,IAAI,WAAW,GAAG,sCAAsC,CAAC;IAEzD,IAAI,aAAa,GAAG,GAAG,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrD,QAAQ,GAAG,UAAU,CAAC;QACtB,WAAW,GAAG,6BAA6B,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,8CAA8C,CAAC;IAC1H,CAAC;SAAM,IAAI,aAAa,GAAG,GAAG,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,QAAQ,GAAG,UAAU,CAAC;QACtB,WAAW,GAAG,wBAAwB,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,2DAA2D,CAAC;IAClI,CAAC;IAED,MAAM,QAAQ,GAAoB;QACjC,oBAAoB,EAAE,aAAa;QACnC,gBAAgB,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC/C,OAAO;QACP,gBAAgB,EAAE,SAAS;QAC3B,YAAY;KACZ,CAAC;IAEF,MAAM,SAAS,GAAsB;QACpC,QAAQ;QACR,iBAAiB,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7C,aAAa,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC5C,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,SAAS;QACrB,WAAW;KACX,CAAC;IAEF,MAAM,QAAQ,GAAuB,EAAE,CAAC;IAExC,IAAI,aAAa,GAAG,GAAG,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrD,QAAQ,CAAC,IAAI,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EACN,wDAAwD,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,MAAM;gBAC7F,0DAA0D;SAC3D,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,144 @@
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 (enforced as hard limits)
6
+ const MAX_WORDS = 1000; // Hard limit (was recommended)
7
+ const RECOMMENDED_WORDS = 500; // Warning threshold
8
+ /**
9
+ * Analyze content structure and patterns
10
+ */
11
+ export function analyze_content_structure(body) {
12
+ // Count code blocks
13
+ const code_block_matches = body.match(/```[\s\S]*?```/g);
14
+ const code_blocks = code_block_matches
15
+ ? code_block_matches.length
16
+ : 0;
17
+ // Count markdown sections (headings)
18
+ const heading_matches = body.match(/^#{1,6}\s/gm);
19
+ const sections = heading_matches ? heading_matches.length : 0;
20
+ // Count long paragraphs (>100 words)
21
+ const paragraphs = body.split(/\n\n+/);
22
+ const long_paragraphs = paragraphs.filter((p) => {
23
+ const words = count_words(p);
24
+ return words > 100;
25
+ }).length;
26
+ return { code_blocks, sections, long_paragraphs };
27
+ }
28
+ /**
29
+ * Validate progressive disclosure (word count, token budget, and line count)
30
+ */
31
+ export function validate_content(body) {
32
+ const word_count = count_words(body);
33
+ const estimated_tokens = estimate_tokens(word_count);
34
+ // Strip HTML comments before counting lines (progressive disclosure guidance shouldn't inflate count)
35
+ const body_without_comments = strip_html_comments(body);
36
+ const line_count = body_without_comments.trim().split('\n').length;
37
+ // Analyze content structure
38
+ const structure = analyze_content_structure(body);
39
+ const validation = {
40
+ stats: {
41
+ word_count,
42
+ estimated_tokens,
43
+ line_count,
44
+ ...structure,
45
+ },
46
+ warnings: [],
47
+ errors: [],
48
+ };
49
+ // Hard limit check (error) - enforced at 1000 words
50
+ if (word_count > MAX_WORDS) {
51
+ validation.errors.push({
52
+ type: 'word_count',
53
+ message: `SKILL.md body has ${word_count} words (MAX: ${MAX_WORDS})\n` +
54
+ ` → Move detailed content to references/ directory for Level 3 loading\n` +
55
+ ` → This is a hard limit - skills must be concise`,
56
+ });
57
+ }
58
+ // Warning threshold at 500 words
59
+ else if (word_count > RECOMMENDED_WORDS) {
60
+ validation.warnings.push({
61
+ type: 'word_count',
62
+ message: `SKILL.md body has ${word_count} words (recommended: <${RECOMMENDED_WORDS}, max: ${MAX_WORDS})\n` +
63
+ ` → Consider moving examples/docs to references/ for better token efficiency`,
64
+ });
65
+ }
66
+ // Line count validation (Level 2 progressive disclosure)
67
+ // Hard limit: 50 lines (enforced)
68
+ if (line_count > 50) {
69
+ validation.errors.push({
70
+ type: 'line_count',
71
+ message: `SKILL.md body is ${line_count} lines (MAX: 50 for Level 2 progressive disclosure)\n` +
72
+ ` → Move detailed content to references/ directory\n` +
73
+ ` → This is a hard limit - skills must be concise`,
74
+ });
75
+ }
76
+ else if (line_count > 40) {
77
+ validation.warnings.push({
78
+ type: 'line_count',
79
+ message: `SKILL.md body is ${line_count} lines (recommended: ~40, max: 50)\n` +
80
+ ` → Consider moving examples to references/ for Level 3 loading`,
81
+ });
82
+ }
83
+ // Content analysis warnings
84
+ // Code blocks: Recommend 1-2, warn at >3
85
+ if (structure.code_blocks > 3) {
86
+ validation.warnings.push({
87
+ type: 'code_blocks',
88
+ message: `SKILL.md contains ${structure.code_blocks} code examples (recommended: 1-2)\n` +
89
+ ` → Move additional examples to references/examples.md for Level 3 loading`,
90
+ });
91
+ }
92
+ // Long paragraphs
93
+ if (structure.long_paragraphs > 3) {
94
+ validation.warnings.push({
95
+ type: 'long_paragraphs',
96
+ message: `SKILL.md contains ${structure.long_paragraphs} lengthy paragraphs (>100 words)\n` +
97
+ ` → Consider moving detailed explanations to references/`,
98
+ });
99
+ }
100
+ // Sections: Recommend 3-5, warn at >8
101
+ if (structure.sections > 8) {
102
+ validation.warnings.push({
103
+ type: 'sections',
104
+ message: `SKILL.md contains ${structure.sections} sections (recommended: 3-5)\n` +
105
+ ` → Consider splitting into focused reference files`,
106
+ });
107
+ }
108
+ // Check for "Quick Start" section
109
+ if (!body.includes('## Quick Start') &&
110
+ !body.includes('## Quick start')) {
111
+ validation.warnings.push({
112
+ type: 'missing_quick_start',
113
+ message: `Missing "## Quick Start" section\n` +
114
+ ` → Add one minimal working example to help Claude get started quickly`,
115
+ });
116
+ }
117
+ // Check for references/ links when body is long
118
+ const has_references = body.includes('references/');
119
+ if (!has_references && line_count > 60) {
120
+ validation.warnings.push({
121
+ type: 'no_references',
122
+ message: `No references/ links found but SKILL.md is ${line_count} lines\n` +
123
+ ` → Consider splitting detailed content into reference files`,
124
+ });
125
+ }
126
+ // Check body content
127
+ if (body.trim().length < 100) {
128
+ validation.warnings.push({
129
+ type: 'short_body',
130
+ message: 'SKILL.md body is very short',
131
+ });
132
+ }
133
+ // Check for TODO placeholders
134
+ if (body.includes('TODO') ||
135
+ body.includes('[Add your') ||
136
+ body.includes('[Provide')) {
137
+ validation.warnings.push({
138
+ type: 'todo_placeholders',
139
+ message: 'SKILL.md contains TODO placeholders',
140
+ });
141
+ }
142
+ return validation;
143
+ }
144
+ //# sourceMappingURL=content-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-validator.js","sourceRoot":"","sources":["../../src/validators/content-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
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
+ else if (desc_length > 200) {
29
+ validation.warnings.push({
30
+ type: 'length',
31
+ message: `Description is ${desc_length} characters (recommended: <200)\n` +
32
+ ` → Estimated ~${desc_tokens} tokens - consider shortening`,
33
+ });
34
+ }
35
+ // Check for trigger keywords
36
+ const lower_desc = description.toLowerCase();
37
+ const has_trigger = lower_desc.includes('use when') ||
38
+ lower_desc.includes('use for') ||
39
+ lower_desc.includes('use to');
40
+ if (!has_trigger) {
41
+ validation.warnings.push({
42
+ type: 'trigger',
43
+ message: `Description missing trigger keywords ('Use when...', 'Use for...', 'Use to...')\n` +
44
+ ` → Help Claude know when to activate this skill`,
45
+ });
46
+ }
47
+ // Check for list bloat (multiple commas indicating detailed lists)
48
+ // Only warn if BOTH long description AND many commas (allows concise technical lists)
49
+ const comma_count = (description.match(/,/g) || []).length;
50
+ if (desc_length > 150 && comma_count >= 5) {
51
+ validation.warnings.push({
52
+ type: 'list_bloat',
53
+ message: `Description contains long lists (${comma_count} commas, ${desc_length} chars)\n` +
54
+ ` → Move detailed lists to Level 2 (SKILL.md body) or Level 3 (references/)`,
55
+ });
56
+ }
57
+ // Short description check
58
+ if (desc_length < 20) {
59
+ validation.warnings.push({
60
+ type: 'short',
61
+ message: 'Description is very short (consider adding more detail)',
62
+ });
63
+ }
64
+ return validation;
65
+ }
66
+ /**
67
+ * Analyze trigger phrase in description
68
+ */
69
+ export function analyze_trigger_phrase(description) {
70
+ const lower = description.toLowerCase();
71
+ const has_trigger = lower.includes('use when') ||
72
+ lower.includes('use for') ||
73
+ lower.includes('use to');
74
+ let trigger_phrase = null;
75
+ let trigger_type = 'missing';
76
+ if (has_trigger) {
77
+ const match = description.match(/(use when|use for|use to)[^.!?]*/i);
78
+ if (match) {
79
+ trigger_phrase = match[0].trim();
80
+ trigger_type =
81
+ trigger_phrase.length > 50 ? 'specific' : 'generic';
82
+ }
83
+ }
84
+ return {
85
+ has_explicit_trigger: has_trigger,
86
+ trigger_phrase,
87
+ trigger_type,
88
+ };
89
+ }
90
+ /**
91
+ * Analyze user phrasing style
92
+ */
93
+ export function analyze_user_phrasing(description) {
94
+ const issues = [];
95
+ const warnings = [];
96
+ // Check for first person
97
+ const is_third_person = !/\b(I can|I will|I help|my|me)\b/i.test(description);
98
+ const first_person_patterns = /\b(I can|I will|I help|my|me)\b/i;
99
+ if (first_person_patterns.test(description)) {
100
+ const match = description.match(first_person_patterns);
101
+ if (match) {
102
+ warnings.push({
103
+ type: 'first_person',
104
+ message: `Description uses first person: "${match[0]}"\n` +
105
+ ` → Prefer third person for clarity (not required but recommended)`,
106
+ });
107
+ }
108
+ }
109
+ // Check for vague terms
110
+ const vague_patterns = /\b(helper|utility|tool|various|several|some)\b/i;
111
+ if (vague_patterns.test(description)) {
112
+ const match = description.match(vague_patterns);
113
+ if (match) {
114
+ warnings.push({
115
+ type: 'vague',
116
+ message: `Description contains vague term: "${match[0]}"\n` +
117
+ ` → Be specific about what the skill does`,
118
+ });
119
+ }
120
+ }
121
+ // Check for gerund form (verbs ending in -ing)
122
+ const uses_gerund = /\b\w+ing\b/i.test(description);
123
+ // Check for action-oriented (starts with action verbs)
124
+ const action_verbs = /^(create|build|design|analyze|test|validate|generate|process|manage|execute|handle|provide)/i;
125
+ const is_action_oriented = action_verbs.test(description.trim());
126
+ const analysis = {
127
+ style_checks: {
128
+ is_third_person,
129
+ uses_gerund_form: uses_gerund,
130
+ is_action_oriented,
131
+ },
132
+ issues,
133
+ };
134
+ return { analysis, warnings };
135
+ }
136
+ //# sourceMappingURL=description-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"description-validator.js","sourceRoot":"","sources":["../../src/validators/description-validator.ts"],"names":[],"mappings":"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"}