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.
- package/README.md +49 -9
- package/dist/commands/doctor.js +128 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.js +5 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.js +1 -1
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/stats.js +1 -1
- package/dist/commands/stats.js.map +1 -1
- package/dist/commands/validate.js +24 -3
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/watch.js +82 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/core/templates.js +18 -0
- package/dist/core/templates.js.map +1 -1
- package/dist/core/validator.js +174 -321
- package/dist/core/validator.js.map +1 -1
- package/dist/index.js +38 -12
- package/dist/index.js.map +1 -1
- package/dist/skills/skill-creator/SKILL.md +28 -112
- package/dist/skills/skill-creator/references/cli-reference.md +152 -38
- package/dist/skills/skill-creator/references/development-process.md +208 -0
- package/dist/skills/skill-creator/references/skill-examples.md +1 -1
- package/dist/validators/alignment-validator.js +54 -0
- package/dist/validators/alignment-validator.js.map +1 -0
- package/dist/validators/content-validator.js +144 -0
- package/dist/validators/content-validator.js.map +1 -0
- package/dist/validators/description-validator.js +136 -0
- package/dist/validators/description-validator.js.map +1 -0
- package/dist/validators/file-structure-validator.js +125 -0
- package/dist/validators/file-structure-validator.js.map +1 -0
- package/dist/validators/frontmatter-validator.js +165 -0
- package/dist/validators/frontmatter-validator.js.map +1 -0
- package/dist/validators/references-validator.js +125 -0
- package/dist/validators/references-validator.js.map +1 -0
- package/dist/validators/text-analysis.js +71 -0
- package/dist/validators/text-analysis.js.map +1 -0
- package/docs/prompt-that-started-it-all.md +19 -0
- package/package.json +3 -3
- package/docs/SKILL-DEVELOPMENT.md +0 -460
- package/docs/SKILL-EXAMPLES.md +0 -528
- 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":"AAAA;;GAEG;AAEH,OAAO,EACN,WAAW,EACX,eAAe,EACf,mBAAmB,GACnB,MAAM,oBAAoB,CAAC;AAoC5B,0DAA0D;AAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,+BAA+B;AACvD,MAAM,iBAAiB,GAAG,GAAG,CAAC,CAAC,oBAAoB;AAEnD;;GAEG;AACH,MAAM,UAAU,yBAAyB,CACxC,IAAY;IAKZ,oBAAoB;IACpB,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,kBAAkB;QACrC,CAAC,CAAC,kBAAkB,CAAC,MAAM;QAC3B,CAAC,CAAC,CAAC,CAAC;IAEL,qCAAqC;IACrC,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9D,qCAAqC;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC/C,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAC7B,OAAO,KAAK,GAAG,GAAG,CAAC;IACpB,CAAC,CAAC,CAAC,MAAM,CAAC;IAEV,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC5C,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,gBAAgB,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAErD,sGAAsG;IACtG,MAAM,qBAAqB,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,qBAAqB,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAEnE,4BAA4B;IAC5B,MAAM,SAAS,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC;IAElD,MAAM,UAAU,GAAsB;QACrC,KAAK,EAAE;YACN,UAAU;YACV,gBAAgB;YAChB,UAAU;YACV,GAAG,SAAS;SACZ;QACD,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE;KACV,CAAC;IAEF,oDAAoD;IACpD,IAAI,UAAU,GAAG,SAAS,EAAE,CAAC;QAC5B,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;YACtB,IAAI,EAAE,YAAY;YAClB,OAAO,EACN,qBAAqB,UAAU,gBAAgB,SAAS,KAAK;gBAC7D,0EAA0E;gBAC1E,mDAAmD;SACpD,CAAC,CAAC;IACJ,CAAC;IACD,iCAAiC;SAC5B,IAAI,UAAU,GAAG,iBAAiB,EAAE,CAAC;QACzC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,YAAY;YAClB,OAAO,EACN,qBAAqB,UAAU,yBAAyB,iBAAiB,UAAU,SAAS,KAAK;gBACjG,8EAA8E;SAC/E,CAAC,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,kCAAkC;IAClC,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;QACrB,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;YACtB,IAAI,EAAE,YAAY;YAClB,OAAO,EACN,oBAAoB,UAAU,uDAAuD;gBACrF,sDAAsD;gBACtD,mDAAmD;SACpD,CAAC,CAAC;IACJ,CAAC;SAAM,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;QAC5B,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,YAAY;YAClB,OAAO,EACN,oBAAoB,UAAU,sCAAsC;gBACpE,iEAAiE;SAClE,CAAC,CAAC;IACJ,CAAC;IAED,4BAA4B;IAC5B,yCAAyC;IACzC,IAAI,SAAS,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;QAC/B,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,aAAa;YACnB,OAAO,EACN,qBAAqB,SAAS,CAAC,WAAW,qCAAqC;gBAC/E,4EAA4E;SAC7E,CAAC,CAAC;IACJ,CAAC;IAED,kBAAkB;IAClB,IAAI,SAAS,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;QACnC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,iBAAiB;YACvB,OAAO,EACN,qBAAqB,SAAS,CAAC,eAAe,oCAAoC;gBAClF,0DAA0D;SAC3D,CAAC,CAAC;IACJ,CAAC;IAED,sCAAsC;IACtC,IAAI,SAAS,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC5B,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,UAAU;YAChB,OAAO,EACN,qBAAqB,SAAS,CAAC,QAAQ,gCAAgC;gBACvE,qDAAqD;SACtD,CAAC,CAAC;IACJ,CAAC;IAED,kCAAkC;IAClC,IACC,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAChC,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAC/B,CAAC;QACF,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EACN,oCAAoC;gBACpC,wEAAwE;SACzE,CAAC,CAAC;IACJ,CAAC;IAED,gDAAgD;IAChD,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IACpD,IAAI,CAAC,cAAc,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;QACxC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,eAAe;YACrB,OAAO,EACN,8CAA8C,UAAU,UAAU;gBAClE,8DAA8D;SAC/D,CAAC,CAAC;IACJ,CAAC;IAED,qBAAqB;IACrB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC9B,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,6BAA6B;SACtC,CAAC,CAAC;IACJ,CAAC;IAED,8BAA8B;IAC9B,IACC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC1B,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EACxB,CAAC;QACF,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxB,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,qCAAqC;SAC9C,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC;AACnB,CAAC"}
|
|
@@ -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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"}
|