From e29329a49f9223f8d613a3205e8bb9d029f25555 Mon Sep 17 00:00:00 2001 From: Zhongwei Li Date: Sat, 29 Nov 2025 17:57:11 +0800 Subject: [PATCH] Initial commit --- .claude-plugin/plugin.json | 12 + README.md | 3 + commands/specweave-tooling-skill-create.md | 691 +++++++++++++++ commands/specweave-tooling-skill-package.md | 751 ++++++++++++++++ commands/specweave-tooling-skill-validate.md | 858 +++++++++++++++++++ plugin.lock.json | 53 ++ 6 files changed, 2368 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 README.md create mode 100644 commands/specweave-tooling-skill-create.md create mode 100644 commands/specweave-tooling-skill-package.md create mode 100644 commands/specweave-tooling-skill-validate.md create mode 100644 plugin.lock.json diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..8adc9f7 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "specweave-tooling", + "description": "Plugin development toolkit for SpecWeave. Provides skill creation, validation, packaging, and plugin scaffolding tools. Expert guidance for YAML frontmatter, skill routing, activation patterns, and best practices. Essential for SpecWeave plugin developers.", + "version": "0.24.0", + "author": { + "name": "SpecWeave Team", + "url": "https://spec-weave.com" + }, + "commands": [ + "./commands" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..33aad51 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# specweave-tooling + +Plugin development toolkit for SpecWeave. Provides skill creation, validation, packaging, and plugin scaffolding tools. Expert guidance for YAML frontmatter, skill routing, activation patterns, and best practices. Essential for SpecWeave plugin developers. diff --git a/commands/specweave-tooling-skill-create.md b/commands/specweave-tooling-skill-create.md new file mode 100644 index 0000000..4215453 --- /dev/null +++ b/commands/specweave-tooling-skill-create.md @@ -0,0 +1,691 @@ +--- +name: specweave-tooling:skill-create +description: Create new Claude Code skill with proper YAML frontmatter, directory structure, and activation triggers. Interactive wizard for skill creation with validation and best practices. +--- + +# Create New Skill + +**Interactive Wizard**: From concept to production-ready skill with proper structure and validation. + +You are helping the user create a new Claude Code skill following best practices and the required structure. + +## Critical Structure Rules (Get This Right First!) + +### 1. Directory Structure + +**MANDATORY format**: +``` +~/.claude/skills/ ← Personal skills +└── your-skill-name/ ← MUST be in subdirectory! + └── SKILL.md ← Must be named exactly SKILL.md + +.claude/skills/ ← Project skills (in project root) +└── your-skill-name/ ← MUST be in subdirectory! + └── SKILL.md ← Must be named exactly SKILL.md +``` + +**Common mistake**: Putting `SKILL.md` directly in `~/.claude/skills/` ❌ + +### 2. SKILL.md Format (Mandatory YAML Frontmatter) + +```yaml +--- +name: your-skill-name +description: What it does AND when to use it. Include trigger keywords users might say. +--- + +# Your Skill Title + +Rest of your markdown content here... +``` + +**Critical rules**: +- Opening `---` MUST be on line 1 +- `name` field: lowercase, hyphens only, max 64 chars +- `description` field: max 1024 chars, MUST include activation triggers +- Closing `---` before any markdown content +- No YAML frontmatter = skill won't work! + +## Steps + +### Step 1: Gather Skill Information + +Ask the user for the following information (use AskUserQuestion if appropriate): + +1. **Skill Name**: + - Lowercase, hyphens only + - Max 64 characters + - Example: `python-data-science`, `kubernetes-expert`, `react-hooks` + +2. **Skill Purpose**: + - What expertise does this skill provide? + - What questions should it answer? + - Example: "Python data science best practices" + +3. **Activation Triggers**: + - Keywords users might say + - Commands or patterns to detect + - Example: "pandas, numpy, matplotlib, jupyter notebooks, Python data analysis" + +4. **Skill Location**: + - Personal skill: `~/.claude/skills/` + - Project skill: `.claude/skills/` (in project root) + +5. **Optional Tool Restrictions**: + - Should this skill be read-only? + - Allowed tools: Read, Grep, Glob, WebSearch, etc. + - Leave empty for no restrictions + +### Step 2: Validate Skill Name + +**Validation rules**: +```bash +# Check format (lowercase, hyphens only) +if [[ ! "$skill_name" =~ ^[a-z0-9-]+$ ]]; then + echo "❌ Invalid name: must be lowercase with hyphens only" + exit 1 +fi + +# Check length (max 64 chars) +if [ ${#skill_name} -gt 64 ]; then + echo "❌ Invalid name: must be 64 characters or less" + exit 1 +fi + +# Check no consecutive hyphens +if [[ "$skill_name" =~ -- ]]; then + echo "❌ Invalid name: no consecutive hyphens allowed" + exit 1 +fi + +# Check doesn't start/end with hyphen +if [[ "$skill_name" =~ ^- ]] || [[ "$skill_name" =~ -$ ]]; then + echo "❌ Invalid name: cannot start or end with hyphen" + exit 1 +fi +``` + +### Step 3: Generate Skill Description + +**Requirements**: +- Max 1024 characters +- Must include activation triggers +- Must explain when to use the skill +- Include keyword variations (e.g., "k8s, kubernetes, kubectl") + +**Template**: +``` +[What the skill does]. [When to use it]. Activates for: [keyword1], [keyword2], [keyword3], [phrase1], [phrase2]. +``` + +**Examples**: + +```yaml +# Command-based skill +description: Kubernetes expert. Explains kubectl commands, pod management, deployments. Activates for: kubectl, k8s, kubernetes, pods, deployments, services, namespaces. + +# Framework skill +description: React expert for hooks, components, state management. Activates for: React, useState, useEffect, components, JSX, props, virtual DOM, React hooks. + +# Project-specific skill +description: MyCompany API documentation. Explains endpoints, authentication, rate limits. Activates for: MyCompany API, /api/v1, authentication token, rate limit, API key. +``` + +### Step 4: Create Skill Content Structure + +**Recommended sections**: + +```markdown +--- +name: your-skill-name +description: [Generated description with triggers] +--- + +# [Skill Title] + +## What I Know + +[Bullet list of expertise areas] +- Topic 1 +- Topic 2 +- Topic 3 + +## When to Use This Skill + +Ask me about: +- "How do I [use case 1]..." +- "What's the best way to [use case 2]..." +- "[Topic] tips and best practices" + +## Key Concepts + +### [Concept 1] + +[Explanation] + +### [Concept 2] + +[Explanation] + +## Examples + +### [Example 1: Common Task] + +```[language] +[code example] +``` + +**Explanation**: [Why this works] + +### [Example 2: Advanced Usage] + +```[language] +[code example] +``` + +**Explanation**: [When to use this pattern] + +## Best Practices + +1. ✅ **[Practice 1]**: [Explanation] +2. ✅ **[Practice 2]**: [Explanation] +3. ⚠️ **[Anti-pattern to avoid]**: [Why to avoid] + +## Common Patterns + +### [Pattern 1] +[Implementation details] + +### [Pattern 2] +[Implementation details] + +## Resources + +- [Documentation link] +- [Tutorial link] +- [Reference link] +``` + +### Step 5: Handle Optional Tool Restrictions + +**If user wants read-only skill**: + +```yaml +--- +name: documentation-helper +description: Documentation expert for project docs +allowed-tools: Read, Grep, Glob, WebSearch +--- +``` + +**Available tools**: +- `Read` - Read files +- `Write` - Create/overwrite files +- `Edit` - Edit existing files +- `Grep` - Search file contents +- `Glob` - Find files by pattern +- `Bash` - Execute bash commands +- `WebSearch` - Search the web +- `WebFetch` - Fetch web content +- `TodoWrite` - Manage todos +- `AskUserQuestion` - Ask user questions + +**Tool restriction patterns**: + +```yaml +# Read-only (no modifications) +allowed-tools: Read, Grep, Glob, WebSearch + +# Documentation expert (can create docs) +allowed-tools: Read, Grep, Glob, Write, Edit + +# Analysis expert (no file modifications) +allowed-tools: Read, Grep, Glob, Bash + +# Full access (no restrictions) +# (omit allowed-tools field) +``` + +### Step 6: Create Skill Directory and File + +**Implementation**: + +```bash +# Determine full path +if [ "$location" = "personal" ]; then + skill_dir="$HOME/.claude/skills/$skill_name" +else + skill_dir="$PWD/.claude/skills/$skill_name" +fi + +# Create directory +mkdir -p "$skill_dir" + +# Create SKILL.md +cat > "$skill_dir/SKILL.md" <<'EOF' +--- +name: $skill_name +description: $description +$allowed_tools_line +--- + +# $skill_title + +$skill_content +EOF + +echo "✅ Skill created at: $skill_dir/SKILL.md" +``` + +### Step 7: Validate Skill Structure + +**Validation checklist**: + +```bash +# 1. Check SKILL.md exists +if [ ! -f "$skill_dir/SKILL.md" ]; then + echo "❌ SKILL.md not found" + exit 1 +fi + +# 2. Check YAML frontmatter +if ! head -1 "$skill_dir/SKILL.md" | grep -q '^---$'; then + echo "❌ SKILL.md must start with '---'" + exit 1 +fi + +# 3. Check required fields +if ! grep -q '^name:' "$skill_dir/SKILL.md"; then + echo "❌ Missing 'name' field in YAML frontmatter" + exit 1 +fi + +if ! grep -q '^description:' "$skill_dir/SKILL.md"; then + echo "❌ Missing 'description' field in YAML frontmatter" + exit 1 +fi + +# 4. Check closing --- +if ! sed -n '2,10p' "$skill_dir/SKILL.md" | grep -q '^---$'; then + echo "❌ Missing closing '---' in YAML frontmatter" + exit 1 +fi + +# 5. Check description length +desc_length=$(grep '^description:' "$skill_dir/SKILL.md" | sed 's/^description: *//' | wc -c) +if [ "$desc_length" -gt 1024 ]; then + echo "⚠️ Warning: Description is ${desc_length} characters (max 1024)" +fi + +echo "✅ Skill structure validated successfully" +``` + +### Step 8: Provide Next Steps + +**User instructions**: + +``` +✅ Skill created successfully! + +📁 Location: $skill_dir/SKILL.md + +📝 Next steps: + +1. Review the skill content and customize as needed +2. Test the skill by asking a trigger question +3. Restart Claude Code to load the skill +4. Verify activation with a test question + +🔄 To restart Claude Code: + - Close and reopen the application + - OR use /restart command (if available) + +🧪 Test your skill: + Ask: "[example trigger question based on description]" + +📚 Documentation: + - Skill format: ~/CLAUDE.md (your quick reference) + - Activation patterns: Description keywords determine when skill loads + - Tool restrictions: Optional 'allowed-tools' field limits capabilities + +⚠️ Common issues: + - Skill doesn't activate → Check description has clear triggers + - YAML errors → Verify frontmatter format (opening/closing ---) + - File not found → Ensure SKILL.md is in subdirectory +``` + +## Examples + +### Example 1: Python Data Science Skill + +**Input**: +- Name: `python-data-science` +- Purpose: "Python best practices for data science projects" +- Triggers: "pandas, numpy, matplotlib, jupyter notebooks, Python data analysis" +- Location: Personal +- Tool restrictions: None + +**Output** (`~/.claude/skills/python-data-science/SKILL.md`): + +```yaml +--- +name: python-data-science +description: Python best practices for data science projects. Explains pandas DataFrame operations, NumPy arrays, matplotlib visualizations, and Jupyter notebook workflows. Activates for: pandas, numpy, matplotlib, jupyter notebooks, Python data analysis, data science, scientific computing. +--- + +# Python Data Science Skill + +## What I Know + +- Pandas DataFrame operations and transformations +- NumPy array manipulation and vectorization +- Matplotlib and Seaborn visualizations +- Jupyter notebook best practices +- Data cleaning and preprocessing +- Statistical analysis and modeling + +## When to Use This Skill + +Ask me about: +- "How do I use pandas to..." +- "What's the best way to visualize..." +- "Python data analysis tips" +- "NumPy array operations" +- "Jupyter notebook shortcuts" + +## Key Concepts + +### Pandas DataFrames + +DataFrames are the core data structure for tabular data in Python: +- Rows and columns with labels +- Rich indexing and selection capabilities +- Built-in aggregation and transformation methods + +### NumPy Arrays + +Efficient numerical computing with multi-dimensional arrays: +- Vectorized operations (avoid loops!) +- Broadcasting for element-wise operations +- Linear algebra and statistical functions + +## Examples + +### Example 1: Loading and Exploring Data + +```python +import pandas as pd + +# Load CSV file +df = pd.read_csv('data.csv') + +# Quick exploration +print(df.head()) # First 5 rows +print(df.info()) # Column types and nulls +print(df.describe()) # Statistical summary +``` + +**Explanation**: Always start with exploration to understand your data structure, types, and missing values. + +### Example 2: Data Cleaning + +```python +# Handle missing values +df_clean = df.dropna() # Drop rows with any nulls +df_filled = df.fillna(0) # Fill nulls with 0 +df_ffill = df.fillna(method='ffill') # Forward fill + +# Remove duplicates +df_unique = df.drop_duplicates() +``` + +**Explanation**: Choose the right strategy based on your data and analysis goals. + +## Best Practices + +1. ✅ **Use vectorized operations**: Avoid Python loops, use pandas/numpy methods +2. ✅ **Chain operations**: `df.groupby('col').agg('mean').sort_values()` +3. ✅ **Copy data explicitly**: Use `.copy()` to avoid SettingWithCopyWarning +4. ⚠️ **Avoid iterrows()**: Extremely slow, use `.apply()` or vectorization instead + +## Common Patterns + +### Groupby-Aggregation +```python +df.groupby('category').agg({ + 'sales': 'sum', + 'quantity': 'mean', + 'price': ['min', 'max'] +}) +``` + +### Time Series Resampling +```python +df.set_index('date').resample('M').mean() +``` + +## Resources + +- [Pandas Documentation](https://pandas.pydata.org/docs/) +- [NumPy User Guide](https://numpy.org/doc/stable/user/) +- [Matplotlib Gallery](https://matplotlib.org/stable/gallery/index.html) +``` + +### Example 2: Read-Only Documentation Skill + +**Input**: +- Name: `project-docs-helper` +- Purpose: "Project documentation expert" +- Triggers: "documentation, docs, readme, API reference" +- Location: Project (`.claude/skills/`) +- Tool restrictions: Read, Grep, Glob, WebSearch + +**Output** (`.claude/skills/project-docs-helper/SKILL.md`): + +```yaml +--- +name: project-docs-helper +description: Project documentation expert. Helps find and explain documentation, API references, and README files. Read-only access for safe documentation browsing. Activates for: documentation, docs, readme, API reference, how to use, user guide. +allowed-tools: Read, Grep, Glob, WebSearch +--- + +# Project Documentation Helper + +## What I Know + +- Location of all project documentation +- API reference structure +- README and getting started guides +- Architecture documentation +- Contributing guidelines + +## When to Use This Skill + +Ask me about: +- "Where is the documentation for..." +- "How do I use [feature]..." +- "What APIs are available..." +- "Getting started with this project" + +## Documentation Structure + +This project follows standard documentation patterns: +- `/docs/` - Main documentation folder +- `README.md` - Getting started guide +- `API.md` - API reference +- `CONTRIBUTING.md` - Contribution guidelines +- `ARCHITECTURE.md` - System design + +## How to Find Information + +### Search by Topic +I can search through all documentation files to find information about specific topics. + +### Navigate by Structure +I understand the documentation hierarchy and can guide you to the right files. + +### Explain Concepts +I can read and explain complex documentation sections in simpler terms. + +## Best Practices + +1. ✅ **Check README first**: Start with README.md for project overview +2. ✅ **Use search**: Ask me to search docs instead of browsing manually +3. ✅ **Verify versions**: Documentation may be version-specific +4. ⚠️ **Read-only**: This skill cannot modify documentation +``` + +## Validation and Testing + +### Post-Creation Validation + +**Run these checks after creation**: + +```bash +# 1. File exists in correct location +ls "$skill_dir/SKILL.md" + +# 2. YAML frontmatter is valid +head -10 "$skill_dir/SKILL.md" + +# Should see: +# --- +# name: your-skill-name +# description: ... +# --- + +# 3. No syntax errors +node -e " +const fs = require('fs'); +const yaml = require('js-yaml'); +const content = fs.readFileSync('$skill_dir/SKILL.md', 'utf-8'); +const match = content.match(/^---\\n([\\s\\S]*?)\\n---/); +if (!match) { + console.error('❌ No YAML frontmatter found'); + process.exit(1); +} +try { + const data = yaml.load(match[1]); + console.log('✅ Valid YAML:', JSON.stringify(data, null, 2)); +} catch (e) { + console.error('❌ YAML parsing error:', e.message); + process.exit(1); +} +" +``` + +### Testing Activation + +**Steps**: +1. Create skill +2. Restart Claude Code +3. Ask a question with trigger keywords +4. Verify skill activates (should see skill content in context) + +**Test questions based on examples**: +- Python Data Science: "How do I use pandas to read a CSV file?" +- Documentation Helper: "Where is the API documentation?" +- Kubernetes Expert: "How do I list all pods in a namespace?" + +## Troubleshooting + +### Skill Doesn't Activate + +**Possible causes**: + +1. **Claude Code not restarted**: Skills only load on startup + - **Fix**: Restart Claude Code + +2. **Missing trigger keywords**: Description doesn't match user's question + - **Fix**: Add more keyword variations to description + +3. **YAML syntax errors**: Frontmatter is invalid + - **Fix**: Validate YAML format (use checker above) + +4. **Wrong file location**: SKILL.md not in subdirectory + - **Fix**: Move to `skills/skill-name/SKILL.md` + +5. **Name mismatch**: YAML name doesn't match directory name + - **Fix**: Ensure consistency (can be different, but confusing) + +### YAML Parsing Errors + +**Common mistakes**: + +```yaml +# ❌ WRONG: Missing closing --- +--- +name: my-skill +description: My skill description + +# ✅ CORRECT: Closing --- present +--- +name: my-skill +description: My skill description +--- + +# ❌ WRONG: Invalid characters in name +--- +name: My Skill Name +--- + +# ✅ CORRECT: Lowercase with hyphens +--- +name: my-skill-name +--- + +# ❌ WRONG: Description too long (>1024 chars) +--- +name: skill +description: [2000 character description] +--- + +# ✅ CORRECT: Concise description (<1024 chars) +--- +name: skill +description: Focused description with key triggers +--- +``` + +## Best Practices + +### Naming Conventions + +1. **Be specific**: `react-hooks` not `react` +2. **Use domain language**: `kubernetes-expert` not `k8s-helper` +3. **Avoid redundancy**: `python-data-science` not `python-data-science-skill` +4. **Max 3 words**: Keep names concise + +### Description Writing + +1. **Front-load purpose**: Start with what the skill does +2. **List all variations**: Include abbreviations (k8s, kubernetes) +3. **Use action words**: "Explains", "Helps with", "Provides guidance" +4. **Include examples**: "React hooks (useState, useEffect, useContext)" + +### Content Structure + +1. **Start simple**: Basic examples before advanced patterns +2. **Use headings**: Clear section organization +3. **Include code**: Concrete examples over abstract explanations +4. **Anti-patterns**: Show what NOT to do (⚠️ warnings) + +### Tool Restrictions + +1. **Read-only by default**: Start restrictive, expand if needed +2. **Justify access**: Only grant Write/Edit if skill creates files +3. **Document reasons**: Explain why tools are needed + +## Summary + +**Key steps**: +1. ✅ Validate skill name (lowercase, hyphens, max 64 chars) +2. ✅ Create description with triggers (max 1024 chars) +3. ✅ Choose skill location (personal vs project) +4. ✅ Add tool restrictions if read-only +5. ✅ Generate SKILL.md with YAML frontmatter +6. ✅ Validate structure (frontmatter, fields, format) +7. ✅ Restart Claude Code +8. ✅ Test with trigger question + +**Remember**: Restart Claude Code after creating or modifying skills! diff --git a/commands/specweave-tooling-skill-package.md b/commands/specweave-tooling-skill-package.md new file mode 100644 index 0000000..bfec9a1 --- /dev/null +++ b/commands/specweave-tooling-skill-package.md @@ -0,0 +1,751 @@ +--- +name: specweave-tooling:skill-package +description: Package Claude Code skill for distribution via npm, GitHub, or direct sharing. Creates distributable archives with installation instructions and validation. +--- + +# Package Skill for Distribution + +**Distribution-Ready Packaging**: Create shareable skill packages with installation scripts and documentation. + +You are helping the user package a Claude Code skill for distribution to others. + +## Distribution Methods + +### 1. NPM Package +- Professional distribution +- Versioning and updates +- `npm install` workflow +- Best for public skills + +### 2. GitHub Repository +- Source control integration +- Easy cloning and updates +- Issue tracking +- Best for collaborative skills + +### 3. Direct Archive (.tar.gz) +- Self-contained package +- No dependencies +- Manual installation +- Best for private/internal sharing + +### 4. Plugin Bundle +- Multiple skills in one package +- Shared dependencies +- Professional presentation +- Best for skill collections + +## Steps + +### Step 1: Validate Skill + +**Before packaging, ensure skill is valid**: + +```bash +validate_before_package() { + local skill_path="$1" + + echo "Validating skill before packaging..." + + # Run validation (from skill-validate command) + if ! validate_skill "$skill_path"; then + echo "❌ Skill validation failed" + echo " Fix errors before packaging" + return 1 + fi + + echo "✅ Skill validation passed" + return 0 +} +``` + +### Step 2: Gather Package Metadata + +**Collect information for package**: + +1. **Package Name**: npm-compatible name (e.g., `claude-skill-python-data-science`) +2. **Version**: Semantic versioning (e.g., `1.0.0`) +3. **Description**: Brief summary for package managers +4. **Author**: Name and email +5. **License**: MIT, Apache-2.0, etc. +6. **Repository**: GitHub URL (optional) +7. **Keywords**: For discoverability + +**Example**: +```json +{ + "name": "claude-skill-python-data-science", + "version": "1.0.0", + "description": "Python data science expert skill for Claude Code", + "author": "Your Name ", + "license": "MIT", + "repository": "https://github.com/username/claude-skill-python-data-science", + "keywords": ["claude", "skill", "python", "data-science", "pandas", "numpy"] +} +``` + +### Step 3: Create Package Structure + +**Standard package structure**: + +``` +package-name/ +├── README.md # Installation and usage +├── LICENSE # License file +├── package.json # NPM metadata (if NPM) +├── install.sh # Installation script +├── uninstall.sh # Uninstall script +├── skill/ # Skill files +│ └── SKILL.md # The actual skill +└── examples/ # Usage examples (optional) + └── example-conversation.md +``` + +**Create structure**: + +```bash +create_package_structure() { + local skill_path="$1" + local package_name="$2" + local package_dir="$3" + + # Create directories + mkdir -p "$package_dir/skill" + mkdir -p "$package_dir/examples" + + # Copy skill + cp "$skill_path" "$package_dir/skill/SKILL.md" + + echo "✅ Package structure created" +} +``` + +### Step 4: Generate README.md + +**Comprehensive README template**: + +```markdown +# [Skill Name] + +[Brief description of what the skill does] + +## Installation + +### Personal Skills (Recommended) + +```bash +# Clone or download this repository +git clone [repository-url] + +# Run installation script +cd [package-name] +bash install.sh +``` + +Or manually: + +```bash +# Copy skill to personal skills directory +mkdir -p ~/.claude/skills/[skill-name] +cp skill/SKILL.md ~/.claude/skills/[skill-name]/SKILL.md +``` + +### Project Skills + +```bash +# Copy skill to project skills directory +mkdir -p .claude/skills/[skill-name] +cp skill/SKILL.md .claude/skills/[skill-name]/SKILL.md +``` + +### NPM (if published) + +```bash +npm install -g [package-name] +``` + +## Activation + +This skill activates automatically when you mention: +- [Trigger keyword 1] +- [Trigger keyword 2] +- [Trigger phrase 1] + +## Examples + +### Example 1: [Use Case] + +**You ask:** +> [Example question] + +**Skill provides:** +[Description of response] + +### Example 2: [Use Case] + +**You ask:** +> [Example question] + +**Skill provides:** +[Description of response] + +## Features + +- ✅ [Feature 1] +- ✅ [Feature 2] +- ✅ [Feature 3] + +## What This Skill Knows + +[Bullet list of expertise areas] + +## Uninstallation + +```bash +bash uninstall.sh +``` + +Or manually: + +```bash +rm -rf ~/.claude/skills/[skill-name] +``` + +## License + +[License name] - See LICENSE file for details + +## Author + +[Author name and contact] + +## Contributing + +[Contribution guidelines if applicable] + +## Version History + +### 1.0.0 (YYYY-MM-DD) +- Initial release +- [Feature 1] +- [Feature 2] +``` + +**Generate README**: + +```bash +generate_readme() { + local package_dir="$1" + local skill_name="$2" + local description="$3" + local author="$4" + local license="$5" + + cat > "$package_dir/README.md" < "$package_dir/install.sh" <<'INSTALL_SCRIPT' +#!/bin/bash +set -e + +# [Installation script content from above] +INSTALL_SCRIPT + + # Make executable + chmod +x "$package_dir/install.sh" + + echo "✅ install.sh generated" +} +``` + +### Step 6: Create Uninstallation Script + +**Uninstallation script** (`uninstall.sh`): + +```bash +#!/bin/bash +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Skill configuration +SKILL_NAME="[skill-name]" +SKILL_DISPLAY_NAME="[Skill Display Name]" + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "UNINSTALLING: $SKILL_DISPLAY_NAME" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +# Check if skill is installed +if [ ! -d "$HOME/.claude/skills/$SKILL_NAME" ]; then + echo -e "${YELLOW}⚠️ Skill not found at: ~/.claude/skills/$SKILL_NAME${NC}" + echo "" + echo "Nothing to uninstall." + exit 0 +fi + +# Confirm uninstallation +echo "This will remove: ~/.claude/skills/$SKILL_NAME/" +echo "" +read -p "Continue with uninstallation? (y/N) " -n 1 -r +echo "" +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Uninstallation cancelled." + exit 0 +fi + +# Remove skill +rm -rf "$HOME/.claude/skills/$SKILL_NAME" + +# Verify removal +if [ ! -d "$HOME/.claude/skills/$SKILL_NAME" ]; then + echo -e "${GREEN}✅ Uninstallation successful!${NC}" + echo "" + echo "Skill removed from: ~/.claude/skills/$SKILL_NAME/" + echo "" + echo "🔄 Restart Claude Code to complete uninstallation" +else + echo -e "${RED}❌ Uninstallation failed${NC}" + exit 1 +fi +``` + +### Step 7: Add License File + +**Common licenses**: + +**MIT License** (most permissive): +``` +MIT License + +Copyright (c) [year] [author] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + +### Step 8: Create package.json (NPM Only) + +**NPM package.json**: + +```json +{ + "name": "claude-skill-[skill-name]", + "version": "1.0.0", + "description": "[Skill description]", + "main": "index.js", + "scripts": { + "postinstall": "bash install.sh", + "preuninstall": "bash uninstall.sh" + }, + "keywords": [ + "claude", + "claude-code", + "skill", + "[domain]" + ], + "author": "[Author Name] <[email]>", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/[username]/[repo].git" + }, + "bugs": { + "url": "https://github.com/[username]/[repo]/issues" + }, + "homepage": "https://github.com/[username]/[repo]#readme", + "files": [ + "skill/", + "install.sh", + "uninstall.sh", + "README.md", + "LICENSE" + ], + "engines": { + "node": ">=14.0.0" + } +} +``` + +### Step 9: Create Archive + +**For direct distribution**: + +```bash +create_archive() { + local package_dir="$1" + local package_name="$2" + local version="$3" + + # Archive filename + archive_name="${package_name}-${version}.tar.gz" + + # Create archive + tar -czf "$archive_name" -C "$(dirname "$package_dir")" "$(basename "$package_dir")" + + # Verify archive + if [ -f "$archive_name" ]; then + echo "✅ Archive created: $archive_name" + echo "" + echo "Archive contents:" + tar -tzf "$archive_name" | head -20 + echo "" + echo "Distribution ready!" + else + echo "❌ Failed to create archive" + return 1 + fi +} +``` + +### Step 10: Generate Distribution Instructions + +**Include installation guide**: + +```markdown +# Distribution Instructions + +## For NPM + +1. Publish to npm: + ```bash + npm publish + ``` + +2. Users install with: + ```bash + npm install -g [package-name] + ``` + +## For GitHub + +1. Push to GitHub: + ```bash + git init + git add . + git commit -m "Initial commit" + git remote add origin [repository-url] + git push -u origin main + ``` + +2. Create release: + - Go to GitHub → Releases → New Release + - Tag: v1.0.0 + - Upload .tar.gz archive + - Add release notes + +3. Users install with: + ```bash + git clone [repository-url] + cd [package-name] + bash install.sh + ``` + +## For Direct Sharing + +1. Share the .tar.gz archive + +2. Users install with: + ```bash + tar -xzf [package-name]-1.0.0.tar.gz + cd [package-name] + bash install.sh + ``` + +## Verification + +After installation, users should: +1. Restart Claude Code +2. Test skill activation +3. Report issues +``` + +## Packaging Examples + +### Example 1: NPM Package + +**Input**: +- Skill: `python-data-science` +- Distribution: NPM +- Version: 1.0.0 +- License: MIT + +**Output structure**: +``` +claude-skill-python-data-science/ +├── README.md +├── LICENSE +├── package.json +├── install.sh +├── uninstall.sh +├── skill/ +│ └── SKILL.md +└── examples/ + └── example-conversation.md +``` + +**package.json**: +```json +{ + "name": "claude-skill-python-data-science", + "version": "1.0.0", + "description": "Python data science expert skill for Claude Code", + "author": "Your Name ", + "license": "MIT", + "keywords": ["claude", "skill", "python", "data-science"] +} +``` + +**Publishing**: +```bash +npm publish +``` + +### Example 2: GitHub Repository + +**Input**: +- Skill: `kubernetes-expert` +- Distribution: GitHub +- Repository: `github.com/username/claude-skill-k8s` + +**Setup**: +```bash +# Initialize repo +git init +git add . +git commit -m "Initial commit: Kubernetes expert skill" + +# Push to GitHub +git remote add origin https://github.com/username/claude-skill-k8s.git +git push -u origin main + +# Create release +gh release create v1.0.0 --title "v1.0.0" --notes "Initial release" +``` + +**Users install**: +```bash +git clone https://github.com/username/claude-skill-k8s.git +cd claude-skill-k8s +bash install.sh +``` + +### Example 3: Direct Archive + +**Input**: +- Skill: `project-docs-helper` +- Distribution: Internal sharing +- Archive: `project-docs-helper-1.0.0.tar.gz` + +**Create archive**: +```bash +# Package structure already created +tar -czf project-docs-helper-1.0.0.tar.gz project-docs-helper/ + +# Share archive via email, shared drive, etc. +``` + +**Users install**: +```bash +tar -xzf project-docs-helper-1.0.0.tar.gz +cd project-docs-helper +bash install.sh +``` + +## Quality Checklist + +**Before distributing, verify**: + +- [ ] ✅ Skill validated successfully +- [ ] ✅ README.md includes installation instructions +- [ ] ✅ LICENSE file present +- [ ] ✅ install.sh script works correctly +- [ ] ✅ uninstall.sh script works correctly +- [ ] ✅ Examples included +- [ ] ✅ Version number set +- [ ] ✅ Author information complete +- [ ] ✅ Repository URL (if applicable) +- [ ] ✅ Keywords for discoverability +- [ ] ✅ Archive created (if direct distribution) +- [ ] ✅ Tested installation on clean system + +## Publishing to NPM + +**Step-by-step**: + +```bash +# 1. Login to npm +npm login + +# 2. Validate package.json +npm pack --dry-run + +# 3. Publish +npm publish + +# 4. Verify +npm view [package-name] +``` + +**Scope packages (recommended)**: +```json +{ + "name": "@your-username/claude-skill-python-data-science", + ... +} +``` + +## Summary + +**Package includes**: +1. ✅ Skill file (SKILL.md) +2. ✅ README with installation instructions +3. ✅ LICENSE file +4. ✅ install.sh script +5. ✅ uninstall.sh script +6. ✅ package.json (NPM only) +7. ✅ Examples (optional) +8. ✅ Archive file (direct distribution) + +**Distribution methods**: +1. ✅ NPM (`npm install -g`) +2. ✅ GitHub (clone + install.sh) +3. ✅ Direct archive (.tar.gz) + +**Remember**: Test installation on clean system before distributing! diff --git a/commands/specweave-tooling-skill-validate.md b/commands/specweave-tooling-skill-validate.md new file mode 100644 index 0000000..3921938 --- /dev/null +++ b/commands/specweave-tooling-skill-validate.md @@ -0,0 +1,858 @@ +--- +name: specweave-tooling:skill-validate +description: Validate Claude Code skill structure, YAML frontmatter, and activation triggers. Comprehensive validation with detailed error reporting and auto-fix suggestions. +--- + +# Validate Skill Structure + +**Comprehensive Validation**: Detect and fix skill structure issues, YAML errors, and activation problems. + +You are helping the user validate an existing Claude Code skill to ensure it follows best practices and will activate correctly. + +## What Gets Validated + +### 1. Directory Structure +- ✅ SKILL.md exists in subdirectory (not root) +- ✅ File named exactly `SKILL.md` (case-sensitive) +- ✅ Only one SKILL.md per directory + +### 2. YAML Frontmatter +- ✅ Starts with `---` on line 1 +- ✅ Contains required fields (`name`, `description`) +- ✅ Has closing `---` before content +- ✅ Valid YAML syntax +- ✅ Field value constraints (length, format) + +### 3. Content Quality +- ✅ Description includes trigger keywords +- ✅ Content has clear structure +- ✅ Examples are present +- ✅ Best practices documented + +### 4. Activation Patterns +- ✅ Description has sufficient triggers +- ✅ Keyword variations included +- ✅ Domain-specific terms present + +## Steps + +### Step 1: Locate Skill + +**Ask user for skill path or name**: + +```bash +# Option 1: Full path +skill_path="/path/to/skill/SKILL.md" + +# Option 2: Skill name (search common locations) +skill_name="python-data-science" + +# Search order: +# 1. ~/.claude/skills/$skill_name/SKILL.md +# 2. .claude/skills/$skill_name/SKILL.md (project skills) +``` + +**Auto-detection**: + +```bash +# Find skill by name +find_skill() { + local skill_name="$1" + + # Check personal skills + if [ -f "$HOME/.claude/skills/$skill_name/SKILL.md" ]; then + echo "$HOME/.claude/skills/$skill_name/SKILL.md" + return 0 + fi + + # Check project skills + if [ -f ".claude/skills/$skill_name/SKILL.md" ]; then + echo ".claude/skills/$skill_name/SKILL.md" + return 0 + fi + + echo "❌ Skill not found: $skill_name" >&2 + return 1 +} +``` + +### Step 2: Validate Directory Structure + +**Checks**: + +```bash +validate_directory_structure() { + local skill_path="$1" + local errors=0 + + # 1. Check file exists + if [ ! -f "$skill_path" ]; then + echo "❌ ERROR: File not found: $skill_path" + ((errors++)) + return $errors + fi + + # 2. Check file is named SKILL.md (case-sensitive) + filename=$(basename "$skill_path") + if [ "$filename" != "SKILL.md" ]; then + echo "❌ ERROR: File must be named 'SKILL.md' (case-sensitive)" + echo " Found: $filename" + echo " Fix: mv '$skill_path' '$(dirname "$skill_path")/SKILL.md'" + ((errors++)) + fi + + # 3. Check file is in subdirectory (not root of skills/) + skill_dir=$(dirname "$skill_path") + parent_dir=$(dirname "$skill_dir") + parent_name=$(basename "$parent_dir") + + if [[ "$parent_name" != "skills" ]]; then + echo "⚠️ WARNING: Expected parent directory 'skills/'" + echo " Found: $parent_name" + fi + + # 4. Check directory name format (lowercase, hyphens) + dir_name=$(basename "$skill_dir") + if [[ ! "$dir_name" =~ ^[a-z0-9-]+$ ]]; then + echo "⚠️ WARNING: Directory name should be lowercase with hyphens" + echo " Found: $dir_name" + echo " Suggested: $(echo "$dir_name" | tr '[:upper:]' '[:lower:]' | tr '_' '-')" + fi + + # 5. Check for multiple SKILL.md files (only one allowed) + skill_count=$(find "$skill_dir" -name "SKILL.md" | wc -l) + if [ "$skill_count" -gt 1 ]; then + echo "❌ ERROR: Multiple SKILL.md files found in directory" + echo " Only one SKILL.md allowed per directory" + ((errors++)) + fi + + if [ $errors -eq 0 ]; then + echo "✅ Directory structure: PASSED" + else + echo "❌ Directory structure: FAILED ($errors errors)" + fi + + return $errors +} +``` + +### Step 3: Validate YAML Frontmatter + +**Checks**: + +```bash +validate_yaml_frontmatter() { + local skill_path="$1" + local errors=0 + + # 1. Check starts with --- + first_line=$(head -1 "$skill_path") + if [ "$first_line" != "---" ]; then + echo "❌ ERROR: File must start with '---' (YAML frontmatter)" + echo " Found: $first_line" + echo " Fix: Add '---' as first line" + ((errors++)) + return $errors + fi + + # 2. Extract YAML frontmatter + yaml_content=$(sed -n '2,/^---$/p' "$skill_path" | sed '$d') + + if [ -z "$yaml_content" ]; then + echo "❌ ERROR: Empty YAML frontmatter" + echo " Fix: Add 'name:' and 'description:' fields" + ((errors++)) + return $errors + fi + + # 3. Check closing --- + closing_line=$(sed -n '2,20p' "$skill_path" | grep -n '^---$' | head -1 | cut -d: -f1) + if [ -z "$closing_line" ]; then + echo "❌ ERROR: Missing closing '---' in YAML frontmatter" + echo " Fix: Add '---' after YAML fields" + ((errors++)) + fi + + # 4. Validate YAML syntax (using Node.js) + yaml_check=$(node -e " + const fs = require('fs'); + const yaml = require('js-yaml'); + const content = fs.readFileSync('$skill_path', 'utf-8'); + const match = content.match(/^---\\n([\\s\\S]*?)\\n---/); + if (!match) { + console.log('ERROR: No YAML frontmatter found'); + process.exit(1); + } + try { + const data = yaml.load(match[1]); + console.log(JSON.stringify(data)); + process.exit(0); + } catch (e) { + console.log('ERROR: ' + e.message); + process.exit(1); + } + " 2>&1) + + if [[ "$yaml_check" =~ ^ERROR: ]]; then + echo "❌ ERROR: YAML syntax error" + echo " $yaml_check" + ((errors++)) + return $errors + fi + + if [ $errors -eq 0 ]; then + echo "✅ YAML frontmatter structure: PASSED" + else + echo "❌ YAML frontmatter structure: FAILED ($errors errors)" + fi + + return $errors +} +``` + +### Step 4: Validate Required Fields + +**Checks**: + +```bash +validate_required_fields() { + local skill_path="$1" + local errors=0 + + # Parse YAML frontmatter + yaml_data=$(node -e " + const fs = require('fs'); + const yaml = require('js-yaml'); + const content = fs.readFileSync('$skill_path', 'utf-8'); + const match = content.match(/^---\\n([\\s\\S]*?)\\n---/); + if (match) { + const data = yaml.load(match[1]); + console.log(JSON.stringify(data)); + } + ") + + # 1. Check 'name' field + name=$(echo "$yaml_data" | node -e " + const data = JSON.parse(require('fs').readFileSync(0, 'utf-8')); + console.log(data.name || ''); + ") + + if [ -z "$name" ]; then + echo "❌ ERROR: Missing required field 'name'" + echo " Fix: Add 'name: your-skill-name' to YAML frontmatter" + ((errors++)) + else + # Validate name format + if [[ ! "$name" =~ ^[a-z0-9-]+$ ]]; then + echo "❌ ERROR: Invalid 'name' format: $name" + echo " Must be lowercase with hyphens only" + echo " Fix: name: $(echo "$name" | tr '[:upper:]' '[:lower:]' | tr '_' '-')" + ((errors++)) + fi + + # Validate name length + if [ ${#name} -gt 64 ]; then + echo "❌ ERROR: 'name' too long: ${#name} characters (max 64)" + echo " Fix: Shorten name to 64 characters or less" + ((errors++)) + fi + + # Check no consecutive hyphens + if [[ "$name" =~ -- ]]; then + echo "⚠️ WARNING: 'name' has consecutive hyphens: $name" + fi + + # Check doesn't start/end with hyphen + if [[ "$name" =~ ^- ]] || [[ "$name" =~ -$ ]]; then + echo "❌ ERROR: 'name' cannot start or end with hyphen: $name" + ((errors++)) + fi + fi + + # 2. Check 'description' field + description=$(echo "$yaml_data" | node -e " + const data = JSON.parse(require('fs').readFileSync(0, 'utf-8')); + console.log(data.description || ''); + ") + + if [ -z "$description" ]; then + echo "❌ ERROR: Missing required field 'description'" + echo " Fix: Add 'description: [what skill does]' to YAML frontmatter" + ((errors++)) + else + # Validate description length + desc_length=${#description} + if [ $desc_length -gt 1024 ]; then + echo "❌ ERROR: 'description' too long: $desc_length characters (max 1024)" + echo " Fix: Shorten description to 1024 characters or less" + ((errors++)) + fi + + # Check description has trigger keywords + if [[ ! "$description" =~ [Aa]ctivates|[Tt]riggers|[Kk]eywords ]]; then + echo "⚠️ WARNING: 'description' should include activation triggers" + echo " Recommended: Add 'Activates for: keyword1, keyword2, ...'" + fi + fi + + # 3. Check optional 'allowed-tools' field + allowed_tools=$(echo "$yaml_data" | node -e " + const data = JSON.parse(require('fs').readFileSync(0, 'utf-8')); + console.log(data['allowed-tools'] || ''); + ") + + if [ -n "$allowed_tools" ]; then + # Validate tool names + valid_tools="Read Write Edit Grep Glob Bash WebSearch WebFetch TodoWrite AskUserQuestion" + + # Split and validate each tool + echo "$allowed_tools" | tr ',' '\n' | while read -r tool; do + tool=$(echo "$tool" | xargs) # trim whitespace + if [[ ! " $valid_tools " =~ " $tool " ]]; then + echo "⚠️ WARNING: Unknown tool in allowed-tools: $tool" + echo " Valid tools: $valid_tools" + fi + done + fi + + if [ $errors -eq 0 ]; then + echo "✅ Required fields: PASSED" + echo " name: $name" + echo " description: ${description:0:80}..." + [ -n "$allowed_tools" ] && echo " allowed-tools: $allowed_tools" + else + echo "❌ Required fields: FAILED ($errors errors)" + fi + + return $errors +} +``` + +### Step 5: Validate Content Quality + +**Checks**: + +```bash +validate_content_quality() { + local skill_path="$1" + local warnings=0 + + # Extract content (everything after closing ---) + content=$(sed -n '/^---$/,/^---$/p' "$skill_path" | sed '1,2d') + content_after=$(sed -n '/^---$/,/^---$/p' "$skill_path" | tail -n +3) + + # 1. Check content exists + if [ -z "$content_after" ]; then + echo "⚠️ WARNING: No content after YAML frontmatter" + echo " Add skill documentation, examples, and best practices" + ((warnings++)) + fi + + # 2. Check for main heading + if ! echo "$content_after" | grep -q '^# '; then + echo "⚠️ WARNING: No main heading (# Title) found" + echo " Add a descriptive title after YAML frontmatter" + ((warnings++)) + fi + + # 3. Check for sections + section_count=$(echo "$content_after" | grep -c '^## ') + if [ $section_count -eq 0 ]; then + echo "⚠️ WARNING: No sections (## Heading) found" + echo " Recommended sections: What I Know, When to Use, Examples, Best Practices" + ((warnings++)) + elif [ $section_count -lt 3 ]; then + echo "⚠️ WARNING: Only $section_count sections found" + echo " Consider adding more structure for clarity" + ((warnings++)) + fi + + # 4. Check for code examples + if ! echo "$content_after" | grep -q '```'; then + echo "⚠️ WARNING: No code examples found" + echo " Add concrete examples to illustrate concepts" + ((warnings++)) + fi + + # 5. Check for lists + list_count=$(echo "$content_after" | grep -c '^- \|^[0-9]\. ') + if [ $list_count -eq 0 ]; then + echo "⚠️ WARNING: No lists found" + echo " Use bullet points and numbered lists for clarity" + ((warnings++)) + fi + + # 6. Check content length + content_length=$(echo "$content_after" | wc -c) + if [ $content_length -lt 500 ]; then + echo "⚠️ WARNING: Content is very short ($content_length characters)" + echo " Consider adding more detail, examples, and best practices" + ((warnings++)) + fi + + # 7. Check for recommended sections + recommended_sections=( + "What I Know" + "When to Use" + "Examples" + "Best Practices" + "Common Patterns" + ) + + missing_sections=() + for section in "${recommended_sections[@]}"; do + if ! echo "$content_after" | grep -iq "## $section"; then + missing_sections+=("$section") + fi + done + + if [ ${#missing_sections[@]} -gt 0 ]; then + echo "⚠️ WARNING: Missing recommended sections:" + for section in "${missing_sections[@]}"; do + echo " - ## $section" + done + ((warnings++)) + fi + + if [ $warnings -eq 0 ]; then + echo "✅ Content quality: PASSED" + echo " Sections: $section_count" + echo " Content length: $content_length characters" + else + echo "⚠️ Content quality: $warnings warnings" + fi + + return 0 # Warnings don't cause failure +} +``` + +### Step 6: Validate Activation Patterns + +**Checks**: + +```bash +validate_activation_patterns() { + local skill_path="$1" + local warnings=0 + + # Parse description + description=$(node -e " + const fs = require('fs'); + const yaml = require('js-yaml'); + const content = fs.readFileSync('$skill_path', 'utf-8'); + const match = content.match(/^---\\n([\\s\\S]*?)\\n---/); + if (match) { + const data = yaml.load(match[1]); + console.log(data.description || ''); + } + ") + + if [ -z "$description" ]; then + echo "⚠️ WARNING: No description to validate" + return 1 + fi + + # 1. Check for trigger section + if [[ ! "$description" =~ [Aa]ctivates\ for:|[Tt]riggers:|[Kk]eywords: ]]; then + echo "⚠️ WARNING: No explicit activation triggers in description" + echo " Recommended: Add 'Activates for: keyword1, keyword2, ...'" + ((warnings++)) + fi + + # 2. Count keywords (approximate) + keyword_count=$(echo "$description" | tr ',' '\n' | grep -v '^[[:space:]]*$' | wc -l) + if [ $keyword_count -lt 5 ]; then + echo "⚠️ WARNING: Only $keyword_count potential triggers found" + echo " Recommended: Include 5-10 keywords for better activation" + ((warnings++)) + fi + + # 3. Check for keyword variations + # Common patterns: abbreviations, full names, plurals + if [[ "$description" =~ k8s ]] && [[ ! "$description" =~ kubernetes ]]; then + echo "⚠️ WARNING: Include both abbreviation and full name" + echo " Found: k8s" + echo " Missing: kubernetes" + ((warnings++)) + fi + + # 4. Check description clarity + if [ ${#description} -lt 50 ]; then + echo "⚠️ WARNING: Description is very short (${#description} chars)" + echo " Add more context about what skill does and when to use it" + ((warnings++)) + fi + + # 5. Check for action words + action_words="explains|helps|provides|guides|assists|demonstrates|shows" + if [[ ! "$description" =~ $action_words ]]; then + echo "⚠️ WARNING: Description lacks action words" + echo " Recommended: Use verbs like 'Explains', 'Helps with', 'Provides'" + ((warnings++)) + fi + + if [ $warnings -eq 0 ]; then + echo "✅ Activation patterns: PASSED" + echo " Trigger count: ~$keyword_count" + else + echo "⚠️ Activation patterns: $warnings warnings" + fi + + return 0 # Warnings don't cause failure +} +``` + +### Step 7: Generate Validation Report + +**Report format**: + +```bash +generate_validation_report() { + local skill_path="$1" + local total_errors=0 + local total_warnings=0 + + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "SKILL VALIDATION REPORT" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + echo "📁 File: $skill_path" + echo "📅 Validated: $(date '+%Y-%m-%d %H:%M:%S')" + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "VALIDATION RESULTS" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + + # Run all validations + echo "1️⃣ Directory Structure" + validate_directory_structure "$skill_path" + total_errors=$((total_errors + $?)) + echo "" + + echo "2️⃣ YAML Frontmatter" + validate_yaml_frontmatter "$skill_path" + total_errors=$((total_errors + $?)) + echo "" + + echo "3️⃣ Required Fields" + validate_required_fields "$skill_path" + total_errors=$((total_errors + $?)) + echo "" + + echo "4️⃣ Content Quality" + validate_content_quality "$skill_path" + # Warnings only, don't count as errors + echo "" + + echo "5️⃣ Activation Patterns" + validate_activation_patterns "$skill_path" + # Warnings only, don't count as errors + echo "" + + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "SUMMARY" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + + if [ $total_errors -eq 0 ]; then + echo "✅ VALIDATION PASSED!" + echo "" + echo "Your skill is properly structured and ready to use." + echo "" + echo "Next steps:" + echo " 1. Restart Claude Code to load the skill" + echo " 2. Test with a trigger question" + echo " 3. Verify skill activates correctly" + else + echo "❌ VALIDATION FAILED!" + echo "" + echo "Total errors: $total_errors" + echo "" + echo "Please fix the errors above and re-run validation." + fi + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + return $total_errors +} +``` + +### Step 8: Provide Auto-Fix Suggestions + +**For common issues**: + +```bash +provide_autofix_suggestions() { + local skill_path="$1" + local errors="$2" + + if [ "$errors" -eq 0 ]; then + return 0 + fi + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "AUTO-FIX SUGGESTIONS" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + + # Missing YAML frontmatter + if ! head -1 "$skill_path" | grep -q '^---$'; then + echo "🔧 FIX: Add YAML frontmatter" + echo "" + echo "Run this command:" + echo "" + echo "cat > '$skill_path' <<'EOF'" + echo "---" + echo "name: $(basename $(dirname "$skill_path"))" + echo "description: [Add description with activation triggers]" + echo "---" + echo "" + echo "$(cat "$skill_path")" + echo "EOF" + echo "" + fi + + # Invalid name format + name=$(grep '^name:' "$skill_path" | sed 's/^name: *//') + if [ -n "$name" ] && [[ ! "$name" =~ ^[a-z0-9-]+$ ]]; then + fixed_name=$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr '_' '-') + echo "🔧 FIX: Update name format" + echo "" + echo "Run this command:" + echo "" + echo "sed -i '' 's/^name: .*/name: $fixed_name/' '$skill_path'" + echo "" + fi + + # Missing description triggers + description=$(grep '^description:' "$skill_path" | sed 's/^description: *//') + if [ -n "$description" ] && [[ ! "$description" =~ [Aa]ctivates ]]; then + echo "🔧 FIX: Add activation triggers to description" + echo "" + echo "Edit the description to include:" + echo "" + echo "description: $description Activates for: [keyword1], [keyword2], [keyword3]." + echo "" + fi + + # File in wrong location + if [ "$(basename "$skill_path")" != "SKILL.md" ]; then + echo "🔧 FIX: Rename file to SKILL.md" + echo "" + echo "Run this command:" + echo "" + echo "mv '$skill_path' '$(dirname "$skill_path")/SKILL.md'" + echo "" + fi + + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +} +``` + +## Validation Examples + +### Example 1: Valid Skill + +**Input**: `~/.claude/skills/python-data-science/SKILL.md` + +**Output**: +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +SKILL VALIDATION REPORT +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +📁 File: ~/.claude/skills/python-data-science/SKILL.md +📅 Validated: 2025-01-15 14:30:00 + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +VALIDATION RESULTS +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +1️⃣ Directory Structure +✅ Directory structure: PASSED + +2️⃣ YAML Frontmatter +✅ YAML frontmatter structure: PASSED + +3️⃣ Required Fields +✅ Required fields: PASSED + name: python-data-science + description: Python best practices for data science projects. Explains pandas DataFrame... + +4️⃣ Content Quality +✅ Content quality: PASSED + Sections: 6 + Content length: 3245 characters + +5️⃣ Activation Patterns +✅ Activation patterns: PASSED + Trigger count: ~12 + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +SUMMARY +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +✅ VALIDATION PASSED! + +Your skill is properly structured and ready to use. + +Next steps: + 1. Restart Claude Code to load the skill + 2. Test with a trigger question + 3. Verify skill activates correctly + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +### Example 2: Invalid Skill (Multiple Errors) + +**Input**: `~/.claude/skills/MySkill/skill.md` + +**Output**: +``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +SKILL VALIDATION REPORT +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +📁 File: ~/.claude/skills/MySkill/skill.md +📅 Validated: 2025-01-15 14:30:00 + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +VALIDATION RESULTS +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +1️⃣ Directory Structure +❌ ERROR: File must be named 'SKILL.md' (case-sensitive) + Found: skill.md + Fix: mv '~/.claude/skills/MySkill/skill.md' '~/.claude/skills/MySkill/SKILL.md' +⚠️ WARNING: Directory name should be lowercase with hyphens + Found: MySkill + Suggested: myskill +❌ Directory structure: FAILED (1 errors) + +2️⃣ YAML Frontmatter +❌ ERROR: File must start with '---' (YAML frontmatter) + Found: # My Skill + Fix: Add '---' as first line +❌ YAML frontmatter structure: FAILED (1 errors) + +3️⃣ Required Fields +❌ ERROR: Missing required field 'name' + Fix: Add 'name: your-skill-name' to YAML frontmatter +❌ ERROR: Missing required field 'description' + Fix: Add 'description: [what skill does]' to YAML frontmatter +❌ Required fields: FAILED (2 errors) + +4️⃣ Content Quality +⚠️ WARNING: No content after YAML frontmatter + Add skill documentation, examples, and best practices + +5️⃣ Activation Patterns +⚠️ WARNING: No description to validate + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +SUMMARY +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +❌ VALIDATION FAILED! + +Total errors: 4 + +Please fix the errors above and re-run validation. + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +AUTO-FIX SUGGESTIONS +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +🔧 FIX: Add YAML frontmatter + +Run this command: + +cat > '~/.claude/skills/MySkill/skill.md' <<'EOF' +--- +name: myskill +description: [Add description with activation triggers] +--- + +# My Skill +EOF + +🔧 FIX: Rename file to SKILL.md + +Run this command: + +mv '~/.claude/skills/MySkill/skill.md' '~/.claude/skills/MySkill/SKILL.md' + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + +## Batch Validation + +**Validate all skills in a directory**: + +```bash +validate_all_skills() { + local skills_dir="$1" + local total_skills=0 + local passed_skills=0 + local failed_skills=0 + + echo "Scanning for skills in: $skills_dir" + echo "" + + # Find all SKILL.md files + while IFS= read -r skill_file; do + ((total_skills++)) + + echo "Validating: $skill_file" + + if generate_validation_report "$skill_file"; then + ((passed_skills++)) + else + ((failed_skills++)) + fi + + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + done < <(find "$skills_dir" -name "SKILL.md" -type f) + + echo "BATCH VALIDATION SUMMARY" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + echo "Total skills: $total_skills" + echo "✅ Passed: $passed_skills" + echo "❌ Failed: $failed_skills" + echo "" + + if [ $failed_skills -eq 0 ]; then + echo "✅ All skills validated successfully!" + else + echo "⚠️ $failed_skills skill(s) need attention" + fi +} +``` + +## Summary + +**Validation covers**: +1. ✅ Directory structure (subdirectory, filename) +2. ✅ YAML frontmatter (format, syntax) +3. ✅ Required fields (name, description) +4. ✅ Field constraints (length, format) +5. ✅ Content quality (structure, examples) +6. ✅ Activation patterns (triggers, keywords) + +**Report includes**: +- ✅ Pass/fail status for each check +- ✅ Error messages with line numbers +- ✅ Auto-fix suggestions for common issues +- ✅ Overall summary and next steps + +**Remember**: Fix all errors before using the skill. Restart Claude Code after fixes! diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..6af001d --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,53 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:anton-abyzov/specweave:plugins/specweave-tooling", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "2efb2ac5031eb62fbf869a47e96e71561fa4c102", + "treeHash": "364ad4576a27f915b0d06f519aaeab40df9f8aae1c8b34d1b2da70506ab4a853", + "generatedAt": "2025-11-28T10:13:54.157715Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "specweave-tooling", + "description": "Plugin development toolkit for SpecWeave. Provides skill creation, validation, packaging, and plugin scaffolding tools. Expert guidance for YAML frontmatter, skill routing, activation patterns, and best practices. Essential for SpecWeave plugin developers.", + "version": "0.24.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "1641e6216ef63123b980c8b21786b4c885573236c62afad6ddc86191bf02e042" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "8870ef264a77ecdf30946c417d5c78341d88d4882c4c1d7ae3bc8f79fc4c09b2" + }, + { + "path": "commands/specweave-tooling-skill-validate.md", + "sha256": "d64f2266f3f121a4554d8d6b47434569fb7b06bcba2acedc3e14ef9ffc03b66d" + }, + { + "path": "commands/specweave-tooling-skill-package.md", + "sha256": "b46031479f66507b0f541cf9d3804f896970a37dbf742a27073ef8f1a88aaa03" + }, + { + "path": "commands/specweave-tooling-skill-create.md", + "sha256": "d474189f0c6c0de05a6bda0bf963d58a61172bb5dc3264b1d0d47c55cf5f0b22" + } + ], + "dirSha256": "364ad4576a27f915b0d06f519aaeab40df9f8aae1c8b34d1b2da70506ab4a853" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file