feat(skill-creator): Add path reference validation
- Add find_path_references() to scan SKILL.md for bundled resource paths - Add validate_path_references() to verify referenced files exist - Smart filtering for example/documentation contexts - Update SKILL.md Step 6 with validation details - Bump version to 1.2.0 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,17 +5,17 @@
|
||||
"email": "daymadev89@gmail.com"
|
||||
},
|
||||
"metadata": {
|
||||
"description": "Professional Claude Code skills for GitHub operations, document conversion, diagram generation, statusline customization, Teams communication, repomix utilities, skill creation, CLI demo generation, LLM icon access, Cloudflare troubleshooting, UI design system extraction, professional presentation creation, YouTube video downloading, secure repomix packaging, ASR transcription correction, video comparison quality analysis, comprehensive QA testing infrastructure, and prompt optimization with EARS methodology",
|
||||
"version": "1.11.0",
|
||||
"description": "Professional Claude Code skills for GitHub operations, document conversion, diagram generation, statusline customization, Teams communication, repomix utilities, skill creation, CLI demo generation, LLM icon access, Cloudflare troubleshooting, UI design system extraction, professional presentation creation, YouTube video downloading, secure repomix packaging, ASR transcription correction, video comparison quality analysis, comprehensive QA testing infrastructure, prompt optimization with EARS methodology, session history recovery, and documentation cleanup",
|
||||
"version": "1.13.0",
|
||||
"homepage": "https://github.com/daymade/claude-code-skills"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "skill-creator",
|
||||
"description": "Essential meta-skill for creating effective Claude Code skills with initialization scripts, validation, packaging, and privacy best practices",
|
||||
"description": "Essential meta-skill for creating effective Claude Code skills with initialization scripts, validation, packaging, marketplace registration, and privacy best practices",
|
||||
"source": "./",
|
||||
"strict": false,
|
||||
"version": "1.0.0",
|
||||
"version": "1.2.0",
|
||||
"category": "developer-tools",
|
||||
"keywords": ["skill-creation", "claude-code", "development", "tooling", "workflow", "meta-skill", "essential"],
|
||||
"skills": ["./skill-creator"]
|
||||
@@ -189,6 +189,26 @@
|
||||
"category": "productivity",
|
||||
"keywords": ["prompt-engineering", "ears", "requirements", "specifications", "optimization", "domain-theory", "prompt-enhancement", "ai-prompting"],
|
||||
"skills": ["./prompt-optimizer"]
|
||||
},
|
||||
{
|
||||
"name": "claude-code-history-files-finder",
|
||||
"description": "Find and recover content from Claude Code session history files. Use when searching for deleted files, tracking changes across sessions, analyzing conversation history, or recovering code/documents from previous Claude interactions. Triggers include mentions of session history, recover deleted, find in history, previous conversation, or .claude/projects",
|
||||
"source": "./",
|
||||
"strict": false,
|
||||
"version": "1.0.0",
|
||||
"category": "developer-tools",
|
||||
"keywords": ["session-history", "recovery", "deleted-files", "conversation-history", "file-tracking", "claude-code", "history-analysis"],
|
||||
"skills": ["./claude-code-history-files-finder"]
|
||||
},
|
||||
{
|
||||
"name": "docs-cleaner",
|
||||
"description": "Consolidates redundant documentation while preserving all valuable content. Use when cleaning up documentation bloat, merging redundant docs, reducing documentation sprawl, or consolidating multiple files covering the same topic",
|
||||
"source": "./",
|
||||
"strict": false,
|
||||
"version": "1.0.0",
|
||||
"category": "productivity",
|
||||
"keywords": ["documentation", "cleanup", "consolidation", "redundancy", "merge", "docs"],
|
||||
"skills": ["./docs-cleaner"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -194,6 +194,8 @@ To begin implementation, start with the reusable resources identified above: `sc
|
||||
|
||||
Also, delete any example files and directories not needed for the skill. The initialization script creates example files in `scripts/`, `references/`, and `assets/` to demonstrate structure, but most skills won't need all of them.
|
||||
|
||||
**When updating an existing skill**: Scan all existing reference files to check if they need corresponding updates. New features often require updates to architecture, workflow, or other existing documentation to maintain consistency.
|
||||
|
||||
#### Reference File Naming
|
||||
|
||||
Filenames must be self-explanatory without reading contents.
|
||||
@@ -276,13 +278,41 @@ The packaging script will:
|
||||
- YAML frontmatter format and required fields
|
||||
- Skill naming conventions and directory structure
|
||||
- Description completeness and quality
|
||||
- File organization and resource references
|
||||
- **Path reference integrity** - all `scripts/`, `references/`, and `assets/` paths mentioned in SKILL.md must exist
|
||||
|
||||
2. **Package** the skill if validation passes, creating a zip file named after the skill (e.g., `my-skill.zip`) that includes all files and maintains the proper directory structure for distribution.
|
||||
|
||||
**Common validation failure:** If SKILL.md references `scripts/my_script.py` but the file doesn't exist, validation will fail with "Missing referenced files: scripts/my_script.py". Ensure all bundled resources exist before packaging.
|
||||
|
||||
If validation fails, the script will report the errors and exit without creating a package. Fix any validation errors and run the packaging command again.
|
||||
|
||||
### Step 7: Iterate
|
||||
### Step 7: Update Marketplace
|
||||
|
||||
After packaging, update the marketplace registry to include the new or updated skill.
|
||||
|
||||
**For new skills**, add an entry to `.claude-plugin/marketplace.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "skill-name",
|
||||
"description": "Copy from SKILL.md frontmatter description",
|
||||
"source": "./",
|
||||
"strict": false,
|
||||
"version": "1.0.0",
|
||||
"category": "developer-tools",
|
||||
"keywords": ["relevant", "keywords"],
|
||||
"skills": ["./skill-name"]
|
||||
}
|
||||
```
|
||||
|
||||
**For updated skills**, bump the version in `plugins[].version` following semver:
|
||||
- Patch (1.0.x): Bug fixes, typo corrections
|
||||
- Minor (1.x.0): New features, additional references
|
||||
- Major (x.0.0): Breaking changes, restructured workflows
|
||||
|
||||
**Also update** `metadata.version` and `metadata.description` if the overall plugin collection changed significantly.
|
||||
|
||||
### Step 8: Iterate
|
||||
|
||||
After testing the skill, users may request improvements. Often this happens right after using the skill, with fresh context of how the skill performed.
|
||||
|
||||
|
||||
@@ -8,33 +8,90 @@ import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def find_path_references(content: str) -> list[str]:
|
||||
"""
|
||||
Extract path references from SKILL.md content.
|
||||
Looks for patterns like scripts/xxx, references/xxx, assets/xxx
|
||||
|
||||
Filters out:
|
||||
- Placeholder paths (xxx, example, etc.)
|
||||
- Paths in example contexts (lines containing "Example:", "e.g.", etc.)
|
||||
- Generic documentation examples
|
||||
"""
|
||||
# Pattern to match bundled resource paths (scripts/, references/, assets/)
|
||||
pattern = r'(?:scripts|references|assets)/[\w./-]+'
|
||||
|
||||
# Find all matches with their line context
|
||||
unique_paths = set()
|
||||
for line in content.split('\n'):
|
||||
# Skip lines that are clearly examples or documentation
|
||||
line_lower = line.lower()
|
||||
if any(x in line_lower for x in [
|
||||
'example:', 'examples:', 'e.g.', 'for example',
|
||||
'- **example', '- example:', 'such as',
|
||||
'pattern:', 'usage:', '❌', '✅',
|
||||
'- **allowed', '- **best practice', 'would be helpful',
|
||||
'like `scripts/', 'like `references/', 'like `assets/',
|
||||
]):
|
||||
continue
|
||||
|
||||
# Find paths in this line
|
||||
matches = re.findall(pattern, line)
|
||||
for path in matches:
|
||||
# Skip obvious placeholders
|
||||
if any(x in path.lower() for x in ['example', 'xxx', '<', '>', 'my-', 'my_']):
|
||||
continue
|
||||
unique_paths.add(path)
|
||||
|
||||
return list(unique_paths)
|
||||
|
||||
|
||||
def validate_path_references(skill_path: Path, content: str) -> tuple[bool, list[str]]:
|
||||
"""
|
||||
Verify all path references in SKILL.md actually exist.
|
||||
|
||||
Returns:
|
||||
(all_exist, missing_paths)
|
||||
"""
|
||||
referenced_paths = find_path_references(content)
|
||||
missing = []
|
||||
|
||||
for ref_path in referenced_paths:
|
||||
full_path = skill_path / ref_path
|
||||
if not full_path.exists():
|
||||
missing.append(ref_path)
|
||||
|
||||
return len(missing) == 0, missing
|
||||
|
||||
|
||||
def validate_skill(skill_path):
|
||||
"""Basic validation of a skill"""
|
||||
skill_path = Path(skill_path)
|
||||
|
||||
|
||||
# Check SKILL.md exists
|
||||
skill_md = skill_path / 'SKILL.md'
|
||||
if not skill_md.exists():
|
||||
return False, "SKILL.md not found"
|
||||
|
||||
|
||||
# Read and validate frontmatter
|
||||
content = skill_md.read_text()
|
||||
if not content.startswith('---'):
|
||||
return False, "No YAML frontmatter found"
|
||||
|
||||
|
||||
# Extract frontmatter
|
||||
match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
|
||||
if not match:
|
||||
return False, "Invalid frontmatter format"
|
||||
|
||||
|
||||
frontmatter = match.group(1)
|
||||
|
||||
|
||||
# Check required fields
|
||||
if 'name:' not in frontmatter:
|
||||
return False, "Missing 'name' in frontmatter"
|
||||
if 'description:' not in frontmatter:
|
||||
return False, "Missing 'description' in frontmatter"
|
||||
|
||||
|
||||
# Extract name for validation
|
||||
name_match = re.search(r'name:\s*(.+)', frontmatter)
|
||||
if name_match:
|
||||
@@ -53,6 +110,11 @@ def validate_skill(skill_path):
|
||||
if '<' in description or '>' in description:
|
||||
return False, "Description cannot contain angle brackets (< or >)"
|
||||
|
||||
# Validate path references exist
|
||||
paths_valid, missing_paths = validate_path_references(skill_path, content)
|
||||
if not paths_valid:
|
||||
return False, f"Missing referenced files: {', '.join(missing_paths)}"
|
||||
|
||||
return True, "Skill is valid!"
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user