specweave 0.23.18 → 0.24.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.
- package/.claude-plugin/marketplace.json +93 -49
- package/CLAUDE.md +137 -4
- package/dist/src/cli/helpers/ado-area-path-mapper.d.ts +89 -0
- package/dist/src/cli/helpers/ado-area-path-mapper.d.ts.map +1 -0
- package/dist/src/cli/helpers/ado-area-path-mapper.js +213 -0
- package/dist/src/cli/helpers/ado-area-path-mapper.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts +29 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js +109 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado.d.ts +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado.js +2 -0
- package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
- package/dist/src/cli/helpers/smart-filter.d.ts +83 -0
- package/dist/src/cli/helpers/smart-filter.d.ts.map +1 -0
- package/dist/src/cli/helpers/smart-filter.js +265 -0
- package/dist/src/cli/helpers/smart-filter.js.map +1 -0
- package/dist/src/core/qa/quality-gate-decider.d.ts +1 -1
- package/dist/src/core/qa/quality-gate-decider.js +2 -2
- package/dist/src/core/qa/quality-gate-decider.js.map +1 -1
- package/dist/src/core/qa/risk-calculator.d.ts +2 -2
- package/dist/src/core/qa/risk-calculator.js +2 -2
- package/dist/src/core/validators/ac-presence-validator.d.ts +56 -0
- package/dist/src/core/validators/ac-presence-validator.d.ts.map +1 -0
- package/dist/src/core/validators/ac-presence-validator.js +149 -0
- package/dist/src/core/validators/ac-presence-validator.js.map +1 -0
- package/dist/src/integrations/ado/area-path-mapper.d.ts +137 -0
- package/dist/src/integrations/ado/area-path-mapper.d.ts.map +1 -0
- package/dist/src/integrations/ado/area-path-mapper.js +267 -0
- package/dist/src/integrations/ado/area-path-mapper.js.map +1 -0
- package/dist/src/integrations/jira/filter-processor.d.ts +126 -0
- package/dist/src/integrations/jira/filter-processor.d.ts.map +1 -0
- package/dist/src/integrations/jira/filter-processor.js +207 -0
- package/dist/src/integrations/jira/filter-processor.js.map +1 -0
- package/dist/src/integrations/jira/jira-client.d.ts +13 -0
- package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-client.js +33 -0
- package/dist/src/integrations/jira/jira-client.js.map +1 -1
- package/dist/src/utils/ac-embedder.d.ts +63 -0
- package/dist/src/utils/ac-embedder.d.ts.map +1 -0
- package/dist/src/utils/ac-embedder.js +217 -0
- package/dist/src/utils/ac-embedder.js.map +1 -0
- package/dist/src/utils/env-manager.d.ts +86 -0
- package/dist/src/utils/env-manager.d.ts.map +1 -0
- package/dist/src/utils/env-manager.js +188 -0
- package/dist/src/utils/env-manager.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave/agents/AGENTS-INDEX.md +1 -1
- package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +9 -9
- package/plugins/specweave/commands/specweave-do.md +37 -0
- package/plugins/specweave/commands/specweave-done.md +159 -0
- package/plugins/specweave/commands/specweave-embed-acs.md +446 -0
- package/plugins/specweave/commands/specweave-next.md +148 -3
- package/plugins/specweave/commands/specweave-qa.md +2 -2
- package/plugins/specweave/hooks/pre-increment-start.sh +168 -0
- package/plugins/specweave/skills/SKILLS-INDEX.md +1 -1
- package/plugins/specweave-ado/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-ado/commands/specweave-ado-import-projects.md +331 -0
- package/plugins/specweave-alternatives/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave-alternatives/commands/alternatives-analyze.md +336 -0
- package/plugins/specweave-alternatives/skills/architecture-alternatives/SKILL.md +651 -0
- package/plugins/specweave-alternatives/skills/bmad-method/SKILL.md +420 -0
- package/plugins/specweave-alternatives/skills/spec-kit-expert/SKILL.md +487 -0
- package/plugins/specweave-backend/commands/api-scaffold.md +80 -0
- package/plugins/specweave-backend/commands/crud-generate.md +109 -0
- package/plugins/specweave-backend/commands/migration-generate.md +139 -0
- package/plugins/specweave-confluent/commands/connector-deploy.md +154 -0
- package/plugins/specweave-confluent/commands/ksqldb-query.md +179 -0
- package/plugins/specweave-confluent/commands/schema-register.md +123 -0
- package/plugins/specweave-core/.claude-plugin/plugin.json +21 -0
- package/plugins/specweave-core/commands/architecture-review.md +288 -0
- package/plugins/specweave-core/commands/code-review.md +213 -0
- package/plugins/specweave-core/commands/refactor-plan.md +249 -0
- package/plugins/specweave-core/skills/code-quality/SKILL.md +157 -0
- package/plugins/specweave-core/skills/design-patterns/SKILL.md +244 -0
- package/plugins/specweave-core/skills/software-architecture/SKILL.md +83 -0
- package/plugins/specweave-cost-optimizer/.claude-plugin/plugin.json +22 -0
- package/plugins/specweave-cost-optimizer/commands/cost-analyze.md +360 -0
- package/plugins/specweave-cost-optimizer/commands/cost-optimize.md +480 -0
- package/plugins/specweave-cost-optimizer/skills/aws-cost-expert/SKILL.md +416 -0
- package/plugins/specweave-cost-optimizer/skills/cloud-pricing/SKILL.md +325 -0
- package/plugins/specweave-cost-optimizer/skills/cost-optimization/SKILL.md +337 -0
- package/plugins/specweave-diagrams/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-diagrams/commands/diagrams-generate.md +168 -0
- package/plugins/specweave-docs/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave-docs/commands/docs-generate.md +441 -0
- package/plugins/specweave-docs/commands/docs-init.md +334 -0
- package/plugins/specweave-docs/skills/docusaurus/SKILL.md +581 -0
- package/plugins/specweave-docs/skills/spec-driven-brainstorming/SKILL.md +689 -0
- package/plugins/specweave-docs/skills/technical-writing/SKILL.md +1039 -0
- package/plugins/specweave-docs-preview/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-figma/.claude-plugin/plugin.json +23 -0
- package/plugins/specweave-figma/commands/figma-import.md +690 -0
- package/plugins/specweave-figma/commands/figma-to-react.md +834 -0
- package/plugins/specweave-figma/commands/figma-tokens.md +815 -0
- package/plugins/specweave-frontend/.claude-plugin/plugin.json +21 -0
- package/plugins/specweave-frontend/agents/frontend-architect/AGENT.md +387 -0
- package/plugins/specweave-frontend/agents/frontend-architect/README.md +385 -0
- package/plugins/specweave-frontend/agents/frontend-architect/examples.md +590 -0
- package/plugins/specweave-frontend/agents/frontend-architect/templates/component-template.tsx +152 -0
- package/plugins/specweave-frontend/agents/frontend-architect/templates/hook-template.ts +311 -0
- package/plugins/specweave-frontend/agents/frontend-architect/templates/page-template.tsx +228 -0
- package/plugins/specweave-frontend/commands/component-generate.md +510 -0
- package/plugins/specweave-frontend/commands/design-system-init.md +494 -0
- package/plugins/specweave-frontend/commands/frontend-scaffold.md +207 -0
- package/plugins/specweave-frontend/commands/nextjs-setup.md +396 -0
- package/plugins/specweave-frontend/skills/design-system-architect/SKILL.md +278 -0
- package/plugins/specweave-frontend/skills/frontend/SKILL.md +420 -0
- package/plugins/specweave-frontend/skills/nextjs/SKILL.md +546 -0
- package/plugins/specweave-github/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +194 -0
- package/plugins/specweave-infrastructure/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-jira/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-jira/commands/import-projects.js +183 -0
- package/plugins/specweave-jira/commands/import-projects.md +97 -0
- package/plugins/specweave-jira/commands/import-projects.ts +288 -0
- package/plugins/specweave-jira/commands/specweave-jira-import-projects.md +298 -0
- package/plugins/specweave-kafka/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-kubernetes/commands/cluster-setup.md +262 -0
- package/plugins/specweave-kubernetes/commands/deployment-generate.md +242 -0
- package/plugins/specweave-kubernetes/commands/helm-scaffold.md +333 -0
- package/plugins/specweave-ml/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-mobile/commands/app-scaffold.md +233 -0
- package/plugins/specweave-mobile/commands/build-config.md +256 -0
- package/plugins/specweave-mobile/commands/screen-generate.md +289 -0
- package/plugins/specweave-n8n/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-plugin-dev/.claude-plugin/plugin.json +13 -12
- package/plugins/specweave-plugin-dev/commands/plugin-create.md +333 -0
- package/plugins/specweave-plugin-dev/commands/plugin-publish.md +339 -0
- package/plugins/specweave-plugin-dev/commands/plugin-test.md +293 -0
- package/plugins/specweave-plugin-dev/skills/claude-sdk/SKILL.md +162 -0
- package/plugins/specweave-plugin-dev/skills/marketplace-publishing/SKILL.md +263 -0
- package/plugins/specweave-plugin-dev/skills/plugin-development/SKILL.md +316 -0
- package/plugins/specweave-release/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-release/commands/specweave-release-npm.md +110 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +168 -0
- package/plugins/specweave-testing/.claude-plugin/plugin.json +21 -0
- package/plugins/specweave-testing/agents/qa-engineer/AGENT.md +797 -0
- package/plugins/specweave-testing/agents/qa-engineer/README.md +443 -0
- package/plugins/specweave-testing/agents/qa-engineer/templates/playwright-e2e-test.ts +470 -0
- package/plugins/specweave-testing/agents/qa-engineer/templates/test-data-factory.ts +507 -0
- package/plugins/specweave-testing/agents/qa-engineer/templates/vitest-unit-test.ts +400 -0
- package/plugins/specweave-testing/agents/qa-engineer/test-strategies.md +726 -0
- package/plugins/specweave-testing/commands/e2e-setup.md +1081 -0
- package/plugins/specweave-testing/commands/test-coverage.md +979 -0
- package/plugins/specweave-testing/commands/test-generate.md +1156 -0
- package/plugins/specweave-testing/commands/test-init.md +409 -0
- package/plugins/specweave-testing/skills/e2e-playwright/SKILL.md +769 -0
- package/plugins/specweave-testing/skills/tdd-expert/SKILL.md +934 -0
- package/plugins/specweave-testing/skills/unit-testing-expert/SKILL.md +1011 -0
- package/plugins/specweave-tooling/.claude-plugin/plugin.json +22 -0
- package/plugins/specweave-tooling/commands/specweave-tooling-skill-create.md +691 -0
- package/plugins/specweave-tooling/commands/specweave-tooling-skill-package.md +751 -0
- package/plugins/specweave-tooling/commands/specweave-tooling-skill-validate.md +858 -0
- package/plugins/specweave-ui/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave-ui/commands/ui-automate.md +199 -0
- package/plugins/specweave-ui/commands/ui-inspect.md +70 -0
- package/plugins/specweave-ui/skills/browser-automation/SKILL.md +314 -0
- package/plugins/specweave-ui/skills/ui-testing/SKILL.md +716 -0
- package/plugins/specweave-ui/skills/visual-regression/SKILL.md +728 -0
- package/plugins/specweave/commands/check-hooks.md +0 -257
- package/plugins/specweave/commands/specweave-archive-increments.md +0 -82
- package/plugins/specweave-plugin-dev/skills/plugin-expert/SKILL.md +0 -1231
- /package/plugins/specweave/{agents/code-reviewer.md → skills/code-reviewer/SKILL.md} +0 -0
|
@@ -0,0 +1,858 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specweave-tooling:skill-validate
|
|
3
|
+
description: Validate Claude Code skill structure, YAML frontmatter, and activation triggers. Comprehensive validation with detailed error reporting and auto-fix suggestions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Validate Skill Structure
|
|
7
|
+
|
|
8
|
+
**Comprehensive Validation**: Detect and fix skill structure issues, YAML errors, and activation problems.
|
|
9
|
+
|
|
10
|
+
You are helping the user validate an existing Claude Code skill to ensure it follows best practices and will activate correctly.
|
|
11
|
+
|
|
12
|
+
## What Gets Validated
|
|
13
|
+
|
|
14
|
+
### 1. Directory Structure
|
|
15
|
+
- ✅ SKILL.md exists in subdirectory (not root)
|
|
16
|
+
- ✅ File named exactly `SKILL.md` (case-sensitive)
|
|
17
|
+
- ✅ Only one SKILL.md per directory
|
|
18
|
+
|
|
19
|
+
### 2. YAML Frontmatter
|
|
20
|
+
- ✅ Starts with `---` on line 1
|
|
21
|
+
- ✅ Contains required fields (`name`, `description`)
|
|
22
|
+
- ✅ Has closing `---` before content
|
|
23
|
+
- ✅ Valid YAML syntax
|
|
24
|
+
- ✅ Field value constraints (length, format)
|
|
25
|
+
|
|
26
|
+
### 3. Content Quality
|
|
27
|
+
- ✅ Description includes trigger keywords
|
|
28
|
+
- ✅ Content has clear structure
|
|
29
|
+
- ✅ Examples are present
|
|
30
|
+
- ✅ Best practices documented
|
|
31
|
+
|
|
32
|
+
### 4. Activation Patterns
|
|
33
|
+
- ✅ Description has sufficient triggers
|
|
34
|
+
- ✅ Keyword variations included
|
|
35
|
+
- ✅ Domain-specific terms present
|
|
36
|
+
|
|
37
|
+
## Steps
|
|
38
|
+
|
|
39
|
+
### Step 1: Locate Skill
|
|
40
|
+
|
|
41
|
+
**Ask user for skill path or name**:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Option 1: Full path
|
|
45
|
+
skill_path="/path/to/skill/SKILL.md"
|
|
46
|
+
|
|
47
|
+
# Option 2: Skill name (search common locations)
|
|
48
|
+
skill_name="python-data-science"
|
|
49
|
+
|
|
50
|
+
# Search order:
|
|
51
|
+
# 1. ~/.claude/skills/$skill_name/SKILL.md
|
|
52
|
+
# 2. .claude/skills/$skill_name/SKILL.md (project skills)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Auto-detection**:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Find skill by name
|
|
59
|
+
find_skill() {
|
|
60
|
+
local skill_name="$1"
|
|
61
|
+
|
|
62
|
+
# Check personal skills
|
|
63
|
+
if [ -f "$HOME/.claude/skills/$skill_name/SKILL.md" ]; then
|
|
64
|
+
echo "$HOME/.claude/skills/$skill_name/SKILL.md"
|
|
65
|
+
return 0
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Check project skills
|
|
69
|
+
if [ -f ".claude/skills/$skill_name/SKILL.md" ]; then
|
|
70
|
+
echo ".claude/skills/$skill_name/SKILL.md"
|
|
71
|
+
return 0
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
echo "❌ Skill not found: $skill_name" >&2
|
|
75
|
+
return 1
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Step 2: Validate Directory Structure
|
|
80
|
+
|
|
81
|
+
**Checks**:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
validate_directory_structure() {
|
|
85
|
+
local skill_path="$1"
|
|
86
|
+
local errors=0
|
|
87
|
+
|
|
88
|
+
# 1. Check file exists
|
|
89
|
+
if [ ! -f "$skill_path" ]; then
|
|
90
|
+
echo "❌ ERROR: File not found: $skill_path"
|
|
91
|
+
((errors++))
|
|
92
|
+
return $errors
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# 2. Check file is named SKILL.md (case-sensitive)
|
|
96
|
+
filename=$(basename "$skill_path")
|
|
97
|
+
if [ "$filename" != "SKILL.md" ]; then
|
|
98
|
+
echo "❌ ERROR: File must be named 'SKILL.md' (case-sensitive)"
|
|
99
|
+
echo " Found: $filename"
|
|
100
|
+
echo " Fix: mv '$skill_path' '$(dirname "$skill_path")/SKILL.md'"
|
|
101
|
+
((errors++))
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# 3. Check file is in subdirectory (not root of skills/)
|
|
105
|
+
skill_dir=$(dirname "$skill_path")
|
|
106
|
+
parent_dir=$(dirname "$skill_dir")
|
|
107
|
+
parent_name=$(basename "$parent_dir")
|
|
108
|
+
|
|
109
|
+
if [[ "$parent_name" != "skills" ]]; then
|
|
110
|
+
echo "⚠️ WARNING: Expected parent directory 'skills/'"
|
|
111
|
+
echo " Found: $parent_name"
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# 4. Check directory name format (lowercase, hyphens)
|
|
115
|
+
dir_name=$(basename "$skill_dir")
|
|
116
|
+
if [[ ! "$dir_name" =~ ^[a-z0-9-]+$ ]]; then
|
|
117
|
+
echo "⚠️ WARNING: Directory name should be lowercase with hyphens"
|
|
118
|
+
echo " Found: $dir_name"
|
|
119
|
+
echo " Suggested: $(echo "$dir_name" | tr '[:upper:]' '[:lower:]' | tr '_' '-')"
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# 5. Check for multiple SKILL.md files (only one allowed)
|
|
123
|
+
skill_count=$(find "$skill_dir" -name "SKILL.md" | wc -l)
|
|
124
|
+
if [ "$skill_count" -gt 1 ]; then
|
|
125
|
+
echo "❌ ERROR: Multiple SKILL.md files found in directory"
|
|
126
|
+
echo " Only one SKILL.md allowed per directory"
|
|
127
|
+
((errors++))
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
if [ $errors -eq 0 ]; then
|
|
131
|
+
echo "✅ Directory structure: PASSED"
|
|
132
|
+
else
|
|
133
|
+
echo "❌ Directory structure: FAILED ($errors errors)"
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
return $errors
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Step 3: Validate YAML Frontmatter
|
|
141
|
+
|
|
142
|
+
**Checks**:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
validate_yaml_frontmatter() {
|
|
146
|
+
local skill_path="$1"
|
|
147
|
+
local errors=0
|
|
148
|
+
|
|
149
|
+
# 1. Check starts with ---
|
|
150
|
+
first_line=$(head -1 "$skill_path")
|
|
151
|
+
if [ "$first_line" != "---" ]; then
|
|
152
|
+
echo "❌ ERROR: File must start with '---' (YAML frontmatter)"
|
|
153
|
+
echo " Found: $first_line"
|
|
154
|
+
echo " Fix: Add '---' as first line"
|
|
155
|
+
((errors++))
|
|
156
|
+
return $errors
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
# 2. Extract YAML frontmatter
|
|
160
|
+
yaml_content=$(sed -n '2,/^---$/p' "$skill_path" | sed '$d')
|
|
161
|
+
|
|
162
|
+
if [ -z "$yaml_content" ]; then
|
|
163
|
+
echo "❌ ERROR: Empty YAML frontmatter"
|
|
164
|
+
echo " Fix: Add 'name:' and 'description:' fields"
|
|
165
|
+
((errors++))
|
|
166
|
+
return $errors
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
# 3. Check closing ---
|
|
170
|
+
closing_line=$(sed -n '2,20p' "$skill_path" | grep -n '^---$' | head -1 | cut -d: -f1)
|
|
171
|
+
if [ -z "$closing_line" ]; then
|
|
172
|
+
echo "❌ ERROR: Missing closing '---' in YAML frontmatter"
|
|
173
|
+
echo " Fix: Add '---' after YAML fields"
|
|
174
|
+
((errors++))
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# 4. Validate YAML syntax (using Node.js)
|
|
178
|
+
yaml_check=$(node -e "
|
|
179
|
+
const fs = require('fs');
|
|
180
|
+
const yaml = require('js-yaml');
|
|
181
|
+
const content = fs.readFileSync('$skill_path', 'utf-8');
|
|
182
|
+
const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);
|
|
183
|
+
if (!match) {
|
|
184
|
+
console.log('ERROR: No YAML frontmatter found');
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
const data = yaml.load(match[1]);
|
|
189
|
+
console.log(JSON.stringify(data));
|
|
190
|
+
process.exit(0);
|
|
191
|
+
} catch (e) {
|
|
192
|
+
console.log('ERROR: ' + e.message);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
" 2>&1)
|
|
196
|
+
|
|
197
|
+
if [[ "$yaml_check" =~ ^ERROR: ]]; then
|
|
198
|
+
echo "❌ ERROR: YAML syntax error"
|
|
199
|
+
echo " $yaml_check"
|
|
200
|
+
((errors++))
|
|
201
|
+
return $errors
|
|
202
|
+
fi
|
|
203
|
+
|
|
204
|
+
if [ $errors -eq 0 ]; then
|
|
205
|
+
echo "✅ YAML frontmatter structure: PASSED"
|
|
206
|
+
else
|
|
207
|
+
echo "❌ YAML frontmatter structure: FAILED ($errors errors)"
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
return $errors
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Step 4: Validate Required Fields
|
|
215
|
+
|
|
216
|
+
**Checks**:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
validate_required_fields() {
|
|
220
|
+
local skill_path="$1"
|
|
221
|
+
local errors=0
|
|
222
|
+
|
|
223
|
+
# Parse YAML frontmatter
|
|
224
|
+
yaml_data=$(node -e "
|
|
225
|
+
const fs = require('fs');
|
|
226
|
+
const yaml = require('js-yaml');
|
|
227
|
+
const content = fs.readFileSync('$skill_path', 'utf-8');
|
|
228
|
+
const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);
|
|
229
|
+
if (match) {
|
|
230
|
+
const data = yaml.load(match[1]);
|
|
231
|
+
console.log(JSON.stringify(data));
|
|
232
|
+
}
|
|
233
|
+
")
|
|
234
|
+
|
|
235
|
+
# 1. Check 'name' field
|
|
236
|
+
name=$(echo "$yaml_data" | node -e "
|
|
237
|
+
const data = JSON.parse(require('fs').readFileSync(0, 'utf-8'));
|
|
238
|
+
console.log(data.name || '');
|
|
239
|
+
")
|
|
240
|
+
|
|
241
|
+
if [ -z "$name" ]; then
|
|
242
|
+
echo "❌ ERROR: Missing required field 'name'"
|
|
243
|
+
echo " Fix: Add 'name: your-skill-name' to YAML frontmatter"
|
|
244
|
+
((errors++))
|
|
245
|
+
else
|
|
246
|
+
# Validate name format
|
|
247
|
+
if [[ ! "$name" =~ ^[a-z0-9-]+$ ]]; then
|
|
248
|
+
echo "❌ ERROR: Invalid 'name' format: $name"
|
|
249
|
+
echo " Must be lowercase with hyphens only"
|
|
250
|
+
echo " Fix: name: $(echo "$name" | tr '[:upper:]' '[:lower:]' | tr '_' '-')"
|
|
251
|
+
((errors++))
|
|
252
|
+
fi
|
|
253
|
+
|
|
254
|
+
# Validate name length
|
|
255
|
+
if [ ${#name} -gt 64 ]; then
|
|
256
|
+
echo "❌ ERROR: 'name' too long: ${#name} characters (max 64)"
|
|
257
|
+
echo " Fix: Shorten name to 64 characters or less"
|
|
258
|
+
((errors++))
|
|
259
|
+
fi
|
|
260
|
+
|
|
261
|
+
# Check no consecutive hyphens
|
|
262
|
+
if [[ "$name" =~ -- ]]; then
|
|
263
|
+
echo "⚠️ WARNING: 'name' has consecutive hyphens: $name"
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
# Check doesn't start/end with hyphen
|
|
267
|
+
if [[ "$name" =~ ^- ]] || [[ "$name" =~ -$ ]]; then
|
|
268
|
+
echo "❌ ERROR: 'name' cannot start or end with hyphen: $name"
|
|
269
|
+
((errors++))
|
|
270
|
+
fi
|
|
271
|
+
fi
|
|
272
|
+
|
|
273
|
+
# 2. Check 'description' field
|
|
274
|
+
description=$(echo "$yaml_data" | node -e "
|
|
275
|
+
const data = JSON.parse(require('fs').readFileSync(0, 'utf-8'));
|
|
276
|
+
console.log(data.description || '');
|
|
277
|
+
")
|
|
278
|
+
|
|
279
|
+
if [ -z "$description" ]; then
|
|
280
|
+
echo "❌ ERROR: Missing required field 'description'"
|
|
281
|
+
echo " Fix: Add 'description: [what skill does]' to YAML frontmatter"
|
|
282
|
+
((errors++))
|
|
283
|
+
else
|
|
284
|
+
# Validate description length
|
|
285
|
+
desc_length=${#description}
|
|
286
|
+
if [ $desc_length -gt 1024 ]; then
|
|
287
|
+
echo "❌ ERROR: 'description' too long: $desc_length characters (max 1024)"
|
|
288
|
+
echo " Fix: Shorten description to 1024 characters or less"
|
|
289
|
+
((errors++))
|
|
290
|
+
fi
|
|
291
|
+
|
|
292
|
+
# Check description has trigger keywords
|
|
293
|
+
if [[ ! "$description" =~ [Aa]ctivates|[Tt]riggers|[Kk]eywords ]]; then
|
|
294
|
+
echo "⚠️ WARNING: 'description' should include activation triggers"
|
|
295
|
+
echo " Recommended: Add 'Activates for: keyword1, keyword2, ...'"
|
|
296
|
+
fi
|
|
297
|
+
fi
|
|
298
|
+
|
|
299
|
+
# 3. Check optional 'allowed-tools' field
|
|
300
|
+
allowed_tools=$(echo "$yaml_data" | node -e "
|
|
301
|
+
const data = JSON.parse(require('fs').readFileSync(0, 'utf-8'));
|
|
302
|
+
console.log(data['allowed-tools'] || '');
|
|
303
|
+
")
|
|
304
|
+
|
|
305
|
+
if [ -n "$allowed_tools" ]; then
|
|
306
|
+
# Validate tool names
|
|
307
|
+
valid_tools="Read Write Edit Grep Glob Bash WebSearch WebFetch TodoWrite AskUserQuestion"
|
|
308
|
+
|
|
309
|
+
# Split and validate each tool
|
|
310
|
+
echo "$allowed_tools" | tr ',' '\n' | while read -r tool; do
|
|
311
|
+
tool=$(echo "$tool" | xargs) # trim whitespace
|
|
312
|
+
if [[ ! " $valid_tools " =~ " $tool " ]]; then
|
|
313
|
+
echo "⚠️ WARNING: Unknown tool in allowed-tools: $tool"
|
|
314
|
+
echo " Valid tools: $valid_tools"
|
|
315
|
+
fi
|
|
316
|
+
done
|
|
317
|
+
fi
|
|
318
|
+
|
|
319
|
+
if [ $errors -eq 0 ]; then
|
|
320
|
+
echo "✅ Required fields: PASSED"
|
|
321
|
+
echo " name: $name"
|
|
322
|
+
echo " description: ${description:0:80}..."
|
|
323
|
+
[ -n "$allowed_tools" ] && echo " allowed-tools: $allowed_tools"
|
|
324
|
+
else
|
|
325
|
+
echo "❌ Required fields: FAILED ($errors errors)"
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
return $errors
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Step 5: Validate Content Quality
|
|
333
|
+
|
|
334
|
+
**Checks**:
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
validate_content_quality() {
|
|
338
|
+
local skill_path="$1"
|
|
339
|
+
local warnings=0
|
|
340
|
+
|
|
341
|
+
# Extract content (everything after closing ---)
|
|
342
|
+
content=$(sed -n '/^---$/,/^---$/p' "$skill_path" | sed '1,2d')
|
|
343
|
+
content_after=$(sed -n '/^---$/,/^---$/p' "$skill_path" | tail -n +3)
|
|
344
|
+
|
|
345
|
+
# 1. Check content exists
|
|
346
|
+
if [ -z "$content_after" ]; then
|
|
347
|
+
echo "⚠️ WARNING: No content after YAML frontmatter"
|
|
348
|
+
echo " Add skill documentation, examples, and best practices"
|
|
349
|
+
((warnings++))
|
|
350
|
+
fi
|
|
351
|
+
|
|
352
|
+
# 2. Check for main heading
|
|
353
|
+
if ! echo "$content_after" | grep -q '^# '; then
|
|
354
|
+
echo "⚠️ WARNING: No main heading (# Title) found"
|
|
355
|
+
echo " Add a descriptive title after YAML frontmatter"
|
|
356
|
+
((warnings++))
|
|
357
|
+
fi
|
|
358
|
+
|
|
359
|
+
# 3. Check for sections
|
|
360
|
+
section_count=$(echo "$content_after" | grep -c '^## ')
|
|
361
|
+
if [ $section_count -eq 0 ]; then
|
|
362
|
+
echo "⚠️ WARNING: No sections (## Heading) found"
|
|
363
|
+
echo " Recommended sections: What I Know, When to Use, Examples, Best Practices"
|
|
364
|
+
((warnings++))
|
|
365
|
+
elif [ $section_count -lt 3 ]; then
|
|
366
|
+
echo "⚠️ WARNING: Only $section_count sections found"
|
|
367
|
+
echo " Consider adding more structure for clarity"
|
|
368
|
+
((warnings++))
|
|
369
|
+
fi
|
|
370
|
+
|
|
371
|
+
# 4. Check for code examples
|
|
372
|
+
if ! echo "$content_after" | grep -q '```'; then
|
|
373
|
+
echo "⚠️ WARNING: No code examples found"
|
|
374
|
+
echo " Add concrete examples to illustrate concepts"
|
|
375
|
+
((warnings++))
|
|
376
|
+
fi
|
|
377
|
+
|
|
378
|
+
# 5. Check for lists
|
|
379
|
+
list_count=$(echo "$content_after" | grep -c '^- \|^[0-9]\. ')
|
|
380
|
+
if [ $list_count -eq 0 ]; then
|
|
381
|
+
echo "⚠️ WARNING: No lists found"
|
|
382
|
+
echo " Use bullet points and numbered lists for clarity"
|
|
383
|
+
((warnings++))
|
|
384
|
+
fi
|
|
385
|
+
|
|
386
|
+
# 6. Check content length
|
|
387
|
+
content_length=$(echo "$content_after" | wc -c)
|
|
388
|
+
if [ $content_length -lt 500 ]; then
|
|
389
|
+
echo "⚠️ WARNING: Content is very short ($content_length characters)"
|
|
390
|
+
echo " Consider adding more detail, examples, and best practices"
|
|
391
|
+
((warnings++))
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
# 7. Check for recommended sections
|
|
395
|
+
recommended_sections=(
|
|
396
|
+
"What I Know"
|
|
397
|
+
"When to Use"
|
|
398
|
+
"Examples"
|
|
399
|
+
"Best Practices"
|
|
400
|
+
"Common Patterns"
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
missing_sections=()
|
|
404
|
+
for section in "${recommended_sections[@]}"; do
|
|
405
|
+
if ! echo "$content_after" | grep -iq "## $section"; then
|
|
406
|
+
missing_sections+=("$section")
|
|
407
|
+
fi
|
|
408
|
+
done
|
|
409
|
+
|
|
410
|
+
if [ ${#missing_sections[@]} -gt 0 ]; then
|
|
411
|
+
echo "⚠️ WARNING: Missing recommended sections:"
|
|
412
|
+
for section in "${missing_sections[@]}"; do
|
|
413
|
+
echo " - ## $section"
|
|
414
|
+
done
|
|
415
|
+
((warnings++))
|
|
416
|
+
fi
|
|
417
|
+
|
|
418
|
+
if [ $warnings -eq 0 ]; then
|
|
419
|
+
echo "✅ Content quality: PASSED"
|
|
420
|
+
echo " Sections: $section_count"
|
|
421
|
+
echo " Content length: $content_length characters"
|
|
422
|
+
else
|
|
423
|
+
echo "⚠️ Content quality: $warnings warnings"
|
|
424
|
+
fi
|
|
425
|
+
|
|
426
|
+
return 0 # Warnings don't cause failure
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Step 6: Validate Activation Patterns
|
|
431
|
+
|
|
432
|
+
**Checks**:
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
validate_activation_patterns() {
|
|
436
|
+
local skill_path="$1"
|
|
437
|
+
local warnings=0
|
|
438
|
+
|
|
439
|
+
# Parse description
|
|
440
|
+
description=$(node -e "
|
|
441
|
+
const fs = require('fs');
|
|
442
|
+
const yaml = require('js-yaml');
|
|
443
|
+
const content = fs.readFileSync('$skill_path', 'utf-8');
|
|
444
|
+
const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);
|
|
445
|
+
if (match) {
|
|
446
|
+
const data = yaml.load(match[1]);
|
|
447
|
+
console.log(data.description || '');
|
|
448
|
+
}
|
|
449
|
+
")
|
|
450
|
+
|
|
451
|
+
if [ -z "$description" ]; then
|
|
452
|
+
echo "⚠️ WARNING: No description to validate"
|
|
453
|
+
return 1
|
|
454
|
+
fi
|
|
455
|
+
|
|
456
|
+
# 1. Check for trigger section
|
|
457
|
+
if [[ ! "$description" =~ [Aa]ctivates\ for:|[Tt]riggers:|[Kk]eywords: ]]; then
|
|
458
|
+
echo "⚠️ WARNING: No explicit activation triggers in description"
|
|
459
|
+
echo " Recommended: Add 'Activates for: keyword1, keyword2, ...'"
|
|
460
|
+
((warnings++))
|
|
461
|
+
fi
|
|
462
|
+
|
|
463
|
+
# 2. Count keywords (approximate)
|
|
464
|
+
keyword_count=$(echo "$description" | tr ',' '\n' | grep -v '^[[:space:]]*$' | wc -l)
|
|
465
|
+
if [ $keyword_count -lt 5 ]; then
|
|
466
|
+
echo "⚠️ WARNING: Only $keyword_count potential triggers found"
|
|
467
|
+
echo " Recommended: Include 5-10 keywords for better activation"
|
|
468
|
+
((warnings++))
|
|
469
|
+
fi
|
|
470
|
+
|
|
471
|
+
# 3. Check for keyword variations
|
|
472
|
+
# Common patterns: abbreviations, full names, plurals
|
|
473
|
+
if [[ "$description" =~ k8s ]] && [[ ! "$description" =~ kubernetes ]]; then
|
|
474
|
+
echo "⚠️ WARNING: Include both abbreviation and full name"
|
|
475
|
+
echo " Found: k8s"
|
|
476
|
+
echo " Missing: kubernetes"
|
|
477
|
+
((warnings++))
|
|
478
|
+
fi
|
|
479
|
+
|
|
480
|
+
# 4. Check description clarity
|
|
481
|
+
if [ ${#description} -lt 50 ]; then
|
|
482
|
+
echo "⚠️ WARNING: Description is very short (${#description} chars)"
|
|
483
|
+
echo " Add more context about what skill does and when to use it"
|
|
484
|
+
((warnings++))
|
|
485
|
+
fi
|
|
486
|
+
|
|
487
|
+
# 5. Check for action words
|
|
488
|
+
action_words="explains|helps|provides|guides|assists|demonstrates|shows"
|
|
489
|
+
if [[ ! "$description" =~ $action_words ]]; then
|
|
490
|
+
echo "⚠️ WARNING: Description lacks action words"
|
|
491
|
+
echo " Recommended: Use verbs like 'Explains', 'Helps with', 'Provides'"
|
|
492
|
+
((warnings++))
|
|
493
|
+
fi
|
|
494
|
+
|
|
495
|
+
if [ $warnings -eq 0 ]; then
|
|
496
|
+
echo "✅ Activation patterns: PASSED"
|
|
497
|
+
echo " Trigger count: ~$keyword_count"
|
|
498
|
+
else
|
|
499
|
+
echo "⚠️ Activation patterns: $warnings warnings"
|
|
500
|
+
fi
|
|
501
|
+
|
|
502
|
+
return 0 # Warnings don't cause failure
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Step 7: Generate Validation Report
|
|
507
|
+
|
|
508
|
+
**Report format**:
|
|
509
|
+
|
|
510
|
+
```bash
|
|
511
|
+
generate_validation_report() {
|
|
512
|
+
local skill_path="$1"
|
|
513
|
+
local total_errors=0
|
|
514
|
+
local total_warnings=0
|
|
515
|
+
|
|
516
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
517
|
+
echo "SKILL VALIDATION REPORT"
|
|
518
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
519
|
+
echo ""
|
|
520
|
+
echo "📁 File: $skill_path"
|
|
521
|
+
echo "📅 Validated: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
522
|
+
echo ""
|
|
523
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
524
|
+
echo "VALIDATION RESULTS"
|
|
525
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
526
|
+
echo ""
|
|
527
|
+
|
|
528
|
+
# Run all validations
|
|
529
|
+
echo "1️⃣ Directory Structure"
|
|
530
|
+
validate_directory_structure "$skill_path"
|
|
531
|
+
total_errors=$((total_errors + $?))
|
|
532
|
+
echo ""
|
|
533
|
+
|
|
534
|
+
echo "2️⃣ YAML Frontmatter"
|
|
535
|
+
validate_yaml_frontmatter "$skill_path"
|
|
536
|
+
total_errors=$((total_errors + $?))
|
|
537
|
+
echo ""
|
|
538
|
+
|
|
539
|
+
echo "3️⃣ Required Fields"
|
|
540
|
+
validate_required_fields "$skill_path"
|
|
541
|
+
total_errors=$((total_errors + $?))
|
|
542
|
+
echo ""
|
|
543
|
+
|
|
544
|
+
echo "4️⃣ Content Quality"
|
|
545
|
+
validate_content_quality "$skill_path"
|
|
546
|
+
# Warnings only, don't count as errors
|
|
547
|
+
echo ""
|
|
548
|
+
|
|
549
|
+
echo "5️⃣ Activation Patterns"
|
|
550
|
+
validate_activation_patterns "$skill_path"
|
|
551
|
+
# Warnings only, don't count as errors
|
|
552
|
+
echo ""
|
|
553
|
+
|
|
554
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
555
|
+
echo "SUMMARY"
|
|
556
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
557
|
+
echo ""
|
|
558
|
+
|
|
559
|
+
if [ $total_errors -eq 0 ]; then
|
|
560
|
+
echo "✅ VALIDATION PASSED!"
|
|
561
|
+
echo ""
|
|
562
|
+
echo "Your skill is properly structured and ready to use."
|
|
563
|
+
echo ""
|
|
564
|
+
echo "Next steps:"
|
|
565
|
+
echo " 1. Restart Claude Code to load the skill"
|
|
566
|
+
echo " 2. Test with a trigger question"
|
|
567
|
+
echo " 3. Verify skill activates correctly"
|
|
568
|
+
else
|
|
569
|
+
echo "❌ VALIDATION FAILED!"
|
|
570
|
+
echo ""
|
|
571
|
+
echo "Total errors: $total_errors"
|
|
572
|
+
echo ""
|
|
573
|
+
echo "Please fix the errors above and re-run validation."
|
|
574
|
+
fi
|
|
575
|
+
|
|
576
|
+
echo ""
|
|
577
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
578
|
+
|
|
579
|
+
return $total_errors
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Step 8: Provide Auto-Fix Suggestions
|
|
584
|
+
|
|
585
|
+
**For common issues**:
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
provide_autofix_suggestions() {
|
|
589
|
+
local skill_path="$1"
|
|
590
|
+
local errors="$2"
|
|
591
|
+
|
|
592
|
+
if [ "$errors" -eq 0 ]; then
|
|
593
|
+
return 0
|
|
594
|
+
fi
|
|
595
|
+
|
|
596
|
+
echo ""
|
|
597
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
598
|
+
echo "AUTO-FIX SUGGESTIONS"
|
|
599
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
600
|
+
echo ""
|
|
601
|
+
|
|
602
|
+
# Missing YAML frontmatter
|
|
603
|
+
if ! head -1 "$skill_path" | grep -q '^---$'; then
|
|
604
|
+
echo "🔧 FIX: Add YAML frontmatter"
|
|
605
|
+
echo ""
|
|
606
|
+
echo "Run this command:"
|
|
607
|
+
echo ""
|
|
608
|
+
echo "cat > '$skill_path' <<'EOF'"
|
|
609
|
+
echo "---"
|
|
610
|
+
echo "name: $(basename $(dirname "$skill_path"))"
|
|
611
|
+
echo "description: [Add description with activation triggers]"
|
|
612
|
+
echo "---"
|
|
613
|
+
echo ""
|
|
614
|
+
echo "$(cat "$skill_path")"
|
|
615
|
+
echo "EOF"
|
|
616
|
+
echo ""
|
|
617
|
+
fi
|
|
618
|
+
|
|
619
|
+
# Invalid name format
|
|
620
|
+
name=$(grep '^name:' "$skill_path" | sed 's/^name: *//')
|
|
621
|
+
if [ -n "$name" ] && [[ ! "$name" =~ ^[a-z0-9-]+$ ]]; then
|
|
622
|
+
fixed_name=$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr '_' '-')
|
|
623
|
+
echo "🔧 FIX: Update name format"
|
|
624
|
+
echo ""
|
|
625
|
+
echo "Run this command:"
|
|
626
|
+
echo ""
|
|
627
|
+
echo "sed -i '' 's/^name: .*/name: $fixed_name/' '$skill_path'"
|
|
628
|
+
echo ""
|
|
629
|
+
fi
|
|
630
|
+
|
|
631
|
+
# Missing description triggers
|
|
632
|
+
description=$(grep '^description:' "$skill_path" | sed 's/^description: *//')
|
|
633
|
+
if [ -n "$description" ] && [[ ! "$description" =~ [Aa]ctivates ]]; then
|
|
634
|
+
echo "🔧 FIX: Add activation triggers to description"
|
|
635
|
+
echo ""
|
|
636
|
+
echo "Edit the description to include:"
|
|
637
|
+
echo ""
|
|
638
|
+
echo "description: $description Activates for: [keyword1], [keyword2], [keyword3]."
|
|
639
|
+
echo ""
|
|
640
|
+
fi
|
|
641
|
+
|
|
642
|
+
# File in wrong location
|
|
643
|
+
if [ "$(basename "$skill_path")" != "SKILL.md" ]; then
|
|
644
|
+
echo "🔧 FIX: Rename file to SKILL.md"
|
|
645
|
+
echo ""
|
|
646
|
+
echo "Run this command:"
|
|
647
|
+
echo ""
|
|
648
|
+
echo "mv '$skill_path' '$(dirname "$skill_path")/SKILL.md'"
|
|
649
|
+
echo ""
|
|
650
|
+
fi
|
|
651
|
+
|
|
652
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
## Validation Examples
|
|
657
|
+
|
|
658
|
+
### Example 1: Valid Skill
|
|
659
|
+
|
|
660
|
+
**Input**: `~/.claude/skills/python-data-science/SKILL.md`
|
|
661
|
+
|
|
662
|
+
**Output**:
|
|
663
|
+
```
|
|
664
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
665
|
+
SKILL VALIDATION REPORT
|
|
666
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
667
|
+
|
|
668
|
+
📁 File: ~/.claude/skills/python-data-science/SKILL.md
|
|
669
|
+
📅 Validated: 2025-01-15 14:30:00
|
|
670
|
+
|
|
671
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
672
|
+
VALIDATION RESULTS
|
|
673
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
674
|
+
|
|
675
|
+
1️⃣ Directory Structure
|
|
676
|
+
✅ Directory structure: PASSED
|
|
677
|
+
|
|
678
|
+
2️⃣ YAML Frontmatter
|
|
679
|
+
✅ YAML frontmatter structure: PASSED
|
|
680
|
+
|
|
681
|
+
3️⃣ Required Fields
|
|
682
|
+
✅ Required fields: PASSED
|
|
683
|
+
name: python-data-science
|
|
684
|
+
description: Python best practices for data science projects. Explains pandas DataFrame...
|
|
685
|
+
|
|
686
|
+
4️⃣ Content Quality
|
|
687
|
+
✅ Content quality: PASSED
|
|
688
|
+
Sections: 6
|
|
689
|
+
Content length: 3245 characters
|
|
690
|
+
|
|
691
|
+
5️⃣ Activation Patterns
|
|
692
|
+
✅ Activation patterns: PASSED
|
|
693
|
+
Trigger count: ~12
|
|
694
|
+
|
|
695
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
696
|
+
SUMMARY
|
|
697
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
698
|
+
|
|
699
|
+
✅ VALIDATION PASSED!
|
|
700
|
+
|
|
701
|
+
Your skill is properly structured and ready to use.
|
|
702
|
+
|
|
703
|
+
Next steps:
|
|
704
|
+
1. Restart Claude Code to load the skill
|
|
705
|
+
2. Test with a trigger question
|
|
706
|
+
3. Verify skill activates correctly
|
|
707
|
+
|
|
708
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
### Example 2: Invalid Skill (Multiple Errors)
|
|
712
|
+
|
|
713
|
+
**Input**: `~/.claude/skills/MySkill/skill.md`
|
|
714
|
+
|
|
715
|
+
**Output**:
|
|
716
|
+
```
|
|
717
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
718
|
+
SKILL VALIDATION REPORT
|
|
719
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
720
|
+
|
|
721
|
+
📁 File: ~/.claude/skills/MySkill/skill.md
|
|
722
|
+
📅 Validated: 2025-01-15 14:30:00
|
|
723
|
+
|
|
724
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
725
|
+
VALIDATION RESULTS
|
|
726
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
727
|
+
|
|
728
|
+
1️⃣ Directory Structure
|
|
729
|
+
❌ ERROR: File must be named 'SKILL.md' (case-sensitive)
|
|
730
|
+
Found: skill.md
|
|
731
|
+
Fix: mv '~/.claude/skills/MySkill/skill.md' '~/.claude/skills/MySkill/SKILL.md'
|
|
732
|
+
⚠️ WARNING: Directory name should be lowercase with hyphens
|
|
733
|
+
Found: MySkill
|
|
734
|
+
Suggested: myskill
|
|
735
|
+
❌ Directory structure: FAILED (1 errors)
|
|
736
|
+
|
|
737
|
+
2️⃣ YAML Frontmatter
|
|
738
|
+
❌ ERROR: File must start with '---' (YAML frontmatter)
|
|
739
|
+
Found: # My Skill
|
|
740
|
+
Fix: Add '---' as first line
|
|
741
|
+
❌ YAML frontmatter structure: FAILED (1 errors)
|
|
742
|
+
|
|
743
|
+
3️⃣ Required Fields
|
|
744
|
+
❌ ERROR: Missing required field 'name'
|
|
745
|
+
Fix: Add 'name: your-skill-name' to YAML frontmatter
|
|
746
|
+
❌ ERROR: Missing required field 'description'
|
|
747
|
+
Fix: Add 'description: [what skill does]' to YAML frontmatter
|
|
748
|
+
❌ Required fields: FAILED (2 errors)
|
|
749
|
+
|
|
750
|
+
4️⃣ Content Quality
|
|
751
|
+
⚠️ WARNING: No content after YAML frontmatter
|
|
752
|
+
Add skill documentation, examples, and best practices
|
|
753
|
+
|
|
754
|
+
5️⃣ Activation Patterns
|
|
755
|
+
⚠️ WARNING: No description to validate
|
|
756
|
+
|
|
757
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
758
|
+
SUMMARY
|
|
759
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
760
|
+
|
|
761
|
+
❌ VALIDATION FAILED!
|
|
762
|
+
|
|
763
|
+
Total errors: 4
|
|
764
|
+
|
|
765
|
+
Please fix the errors above and re-run validation.
|
|
766
|
+
|
|
767
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
768
|
+
|
|
769
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
770
|
+
AUTO-FIX SUGGESTIONS
|
|
771
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
772
|
+
|
|
773
|
+
🔧 FIX: Add YAML frontmatter
|
|
774
|
+
|
|
775
|
+
Run this command:
|
|
776
|
+
|
|
777
|
+
cat > '~/.claude/skills/MySkill/skill.md' <<'EOF'
|
|
778
|
+
---
|
|
779
|
+
name: myskill
|
|
780
|
+
description: [Add description with activation triggers]
|
|
781
|
+
---
|
|
782
|
+
|
|
783
|
+
# My Skill
|
|
784
|
+
EOF
|
|
785
|
+
|
|
786
|
+
🔧 FIX: Rename file to SKILL.md
|
|
787
|
+
|
|
788
|
+
Run this command:
|
|
789
|
+
|
|
790
|
+
mv '~/.claude/skills/MySkill/skill.md' '~/.claude/skills/MySkill/SKILL.md'
|
|
791
|
+
|
|
792
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
## Batch Validation
|
|
796
|
+
|
|
797
|
+
**Validate all skills in a directory**:
|
|
798
|
+
|
|
799
|
+
```bash
|
|
800
|
+
validate_all_skills() {
|
|
801
|
+
local skills_dir="$1"
|
|
802
|
+
local total_skills=0
|
|
803
|
+
local passed_skills=0
|
|
804
|
+
local failed_skills=0
|
|
805
|
+
|
|
806
|
+
echo "Scanning for skills in: $skills_dir"
|
|
807
|
+
echo ""
|
|
808
|
+
|
|
809
|
+
# Find all SKILL.md files
|
|
810
|
+
while IFS= read -r skill_file; do
|
|
811
|
+
((total_skills++))
|
|
812
|
+
|
|
813
|
+
echo "Validating: $skill_file"
|
|
814
|
+
|
|
815
|
+
if generate_validation_report "$skill_file"; then
|
|
816
|
+
((passed_skills++))
|
|
817
|
+
else
|
|
818
|
+
((failed_skills++))
|
|
819
|
+
fi
|
|
820
|
+
|
|
821
|
+
echo ""
|
|
822
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
823
|
+
echo ""
|
|
824
|
+
done < <(find "$skills_dir" -name "SKILL.md" -type f)
|
|
825
|
+
|
|
826
|
+
echo "BATCH VALIDATION SUMMARY"
|
|
827
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
828
|
+
echo ""
|
|
829
|
+
echo "Total skills: $total_skills"
|
|
830
|
+
echo "✅ Passed: $passed_skills"
|
|
831
|
+
echo "❌ Failed: $failed_skills"
|
|
832
|
+
echo ""
|
|
833
|
+
|
|
834
|
+
if [ $failed_skills -eq 0 ]; then
|
|
835
|
+
echo "✅ All skills validated successfully!"
|
|
836
|
+
else
|
|
837
|
+
echo "⚠️ $failed_skills skill(s) need attention"
|
|
838
|
+
fi
|
|
839
|
+
}
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
## Summary
|
|
843
|
+
|
|
844
|
+
**Validation covers**:
|
|
845
|
+
1. ✅ Directory structure (subdirectory, filename)
|
|
846
|
+
2. ✅ YAML frontmatter (format, syntax)
|
|
847
|
+
3. ✅ Required fields (name, description)
|
|
848
|
+
4. ✅ Field constraints (length, format)
|
|
849
|
+
5. ✅ Content quality (structure, examples)
|
|
850
|
+
6. ✅ Activation patterns (triggers, keywords)
|
|
851
|
+
|
|
852
|
+
**Report includes**:
|
|
853
|
+
- ✅ Pass/fail status for each check
|
|
854
|
+
- ✅ Error messages with line numbers
|
|
855
|
+
- ✅ Auto-fix suggestions for common issues
|
|
856
|
+
- ✅ Overall summary and next steps
|
|
857
|
+
|
|
858
|
+
**Remember**: Fix all errors before using the skill. Restart Claude Code after fixes!
|