fix: Add YAML frontmatter to unified, GitHub, and PDF skill builders

**Problem:** (PR #170 verified)
Three skill builders were generating SKILL.md files without YAML
frontmatter, making skills invisible to Claude after upload:
- unified_skill_builder.py
- github_scraper.py
- pdf_scraper.py

Only doc_scraper.py had frontmatter implemented.

**Root Cause:**
Claude requires YAML frontmatter with 'name' and 'description' fields
to recognize and index skills. Without it, uploaded skills don't appear
in skill lists and can't be triggered.

**Fix:**
Added consistent frontmatter generation to all three builders:
- Normalizes skill name (lowercase, hyphens, max 64 chars)
- Truncates description to 1024 chars (Claude requirement)
- Generates YAML frontmatter with proper formatting

**Test Results:**
 All 390/390 tests passing (0 failures, 0 skipped)
 Consistent implementation across all builders
 Meets Claude's official skill specification

**Example Output:**
```yaml
---
name: my-skill-name
description: Skill description here
---

# My Skill Name
...
```

**Credits:**
Original fix by @AbdelrahmanHafez in PR #170
Rebased to current development by Claude Code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: AbdelrahmanHafez <AbdelrahmanHafez@users.noreply.github.com>
This commit is contained in:
yusyus
2025-11-06 23:56:31 +03:00
parent 4ddc4cf1f3
commit 459c6cfd5b
3 changed files with 36 additions and 2 deletions

View File

@@ -536,7 +536,18 @@ class GitHubToSkillConverter:
"""Generate main SKILL.md file."""
repo_info = self.data.get('repo_info', {})
skill_content = f"""# {repo_info.get('name', self.name)}
# Generate skill name (lowercase, hyphens only, max 64 chars)
skill_name = self.name.lower().replace('_', '-').replace(' ', '-')[:64]
# Truncate description to 1024 chars if needed
desc = self.description[:1024] if len(self.description) > 1024 else self.description
skill_content = f"""---
name: {skill_name}
description: {desc}
---
# {repo_info.get('name', self.name)}
{self.description}