Recreate source from .skill zip file

This commit is contained in:
Your Name
2026-05-21 10:29:13 +00:00
parent 38722fdcb8
commit c59c59b8ba
11 changed files with 2521 additions and 0 deletions
+271
View File
@@ -0,0 +1,271 @@
#!/usr/bin/env python3
"""
Workflow Analysis Script for Meta Skill Generator
Analyzes user requirements and suggests which operations should be:
- Go scripts (deterministic, performance-critical)
- Python scripts (library-heavy, data science)
- Agent workflows (requires reasoning, context-dependent)
Usage:
analyze_workflow.py [--examples file1.txt file2.txt ...] [--interactive]
"""
import argparse
import sys
from pathlib import Path
from typing import List, Dict, Tuple
# Keywords that indicate deterministic operations
DETERMINISTIC_KEYWORDS = {
'convert', 'transform', 'parse', 'extract', 'validate',
'format', 'encode', 'decode', 'compress', 'decompress',
'resize', 'crop', 'rotate', 'merge', 'split',
'sort', 'filter', 'calculate', 'compute'
}
# Keywords that indicate dynamic/reasoning operations
DYNAMIC_KEYWORDS = {
'analyze', 'understand', 'interpret', 'decide', 'choose',
'suggest', 'recommend', 'summarize', 'explain', 'describe',
'evaluate', 'assess', 'determine', 'identify', 'classify'
}
# Keywords that suggest Go (performance-critical)
GO_INDICATORS = {
'large file', 'batch', 'thousands', 'millions', 'concurrent',
'parallel', 'performance', 'fast', 'binary', 'low-level',
'file system', 'network', 'stream'
}
# Keywords that suggest Python (library-heavy)
PYTHON_INDICATORS = {
'pandas', 'numpy', 'scikit', 'machine learning', 'data science',
'plot', 'graph', 'visualization', 'api client', 'requests',
'beautiful soup', 'selenium', 'opencv'
}
class OperationAnalyzer:
def __init__(self):
self.operations = []
def analyze_text(self, text: str) -> List[Dict]:
"""Analyze text and identify operations."""
text_lower = text.lower()
sentences = text.replace('?', '.').replace('!', '.').split('.')
operations = []
for sentence in sentences:
sentence = sentence.strip()
if not sentence:
continue
op = self._analyze_sentence(sentence)
if op:
operations.append(op)
return operations
def _analyze_sentence(self, sentence: str) -> Dict:
"""Analyze a single sentence for operation type."""
sentence_lower = sentence.lower()
# Check for deterministic vs dynamic
det_score = sum(1 for kw in DETERMINISTIC_KEYWORDS if kw in sentence_lower)
dyn_score = sum(1 for kw in DYNAMIC_KEYWORDS if kw in sentence_lower)
# Check for Go vs Python indicators
go_score = sum(1 for kw in GO_INDICATORS if kw in sentence_lower)
py_score = sum(1 for kw in PYTHON_INDICATORS if kw in sentence_lower)
if det_score == 0 and dyn_score == 0:
return None
# Determine operation type
if det_score > dyn_score:
if go_score > py_score:
op_type = 'go_script'
reason = 'Deterministic operation with performance/binary characteristics'
elif py_score > 0:
op_type = 'python_script'
reason = 'Deterministic operation requiring specialized libraries'
else:
op_type = 'go_script'
reason = 'Deterministic operation suitable for compiled binary'
else:
op_type = 'agent_workflow'
reason = 'Requires reasoning, context analysis, or decision-making'
return {
'description': sentence,
'type': op_type,
'reason': reason,
'det_score': det_score,
'dyn_score': dyn_score,
'go_score': go_score,
'py_score': py_score
}
def generate_recommendations(self, operations: List[Dict]) -> str:
"""Generate recommendations report."""
go_ops = [op for op in operations if op['type'] == 'go_script']
py_ops = [op for op in operations if op['type'] == 'python_script']
agent_ops = [op for op in operations if op['type'] == 'agent_workflow']
report = []
report.append("=" * 70)
report.append("WORKFLOW ANALYSIS REPORT")
report.append("=" * 70)
report.append("")
report.append(f"Total operations identified: {len(operations)}")
report.append(f" - Go scripts recommended: {len(go_ops)}")
report.append(f" - Python scripts recommended: {len(py_ops)}")
report.append(f" - Agent workflows recommended: {len(agent_ops)}")
report.append("")
if go_ops:
report.append("-" * 70)
report.append("GO SCRIPTS (Deterministic, Performance-Critical)")
report.append("-" * 70)
for i, op in enumerate(go_ops, 1):
report.append(f"\n{i}. {op['description']}")
report.append(f" Reason: {op['reason']}")
report.append(f" Suggested name: {self._suggest_script_name(op['description'])}")
report.append("")
if py_ops:
report.append("-" * 70)
report.append("PYTHON SCRIPTS (Library-Heavy Operations)")
report.append("-" * 70)
for i, op in enumerate(py_ops, 1):
report.append(f"\n{i}. {op['description']}")
report.append(f" Reason: {op['reason']}")
report.append(f" Suggested name: {self._suggest_script_name(op['description'])}")
report.append("")
if agent_ops:
report.append("-" * 70)
report.append("AGENT WORKFLOWS (Reasoning Required)")
report.append("-" * 70)
for i, op in enumerate(agent_ops, 1):
report.append(f"\n{i}. {op['description']}")
report.append(f" Reason: {op['reason']}")
report.append(f" Implementation: Keep as natural language workflow in SKILL.md")
report.append("")
report.append("=" * 70)
report.append("RECOMMENDATIONS")
report.append("=" * 70)
report.append("")
if go_ops:
report.append("For Go scripts:")
report.append(" 1. Use generate_go_script.py to create each script")
report.append(" 2. Focus on performance and error handling")
report.append(" 3. Support parallel processing where applicable")
report.append("")
if py_ops:
report.append("For Python scripts:")
report.append(" 1. Create scripts in scripts/ directory")
report.append(" 2. Add requirements.txt for dependencies")
report.append(" 3. Consider virtual environments")
report.append("")
if agent_ops:
report.append("For agent workflows:")
report.append(" 1. Document in SKILL.md with clear decision points")
report.append(" 2. Provide examples for different scenarios")
report.append(" 3. Use references/ for detailed guidance")
report.append("")
return '\n'.join(report)
def _suggest_script_name(self, description: str) -> str:
"""Suggest a script name from description."""
# Extract key verbs and nouns
words = description.lower().split()
important_words = []
for word in words:
cleaned = ''.join(c for c in word if c.isalnum())
if cleaned in DETERMINISTIC_KEYWORDS or len(cleaned) > 3:
important_words.append(cleaned)
if len(important_words) >= 3:
break
return '-'.join(important_words[:3]) if important_words else 'operation'
def interactive_mode():
"""Run in interactive mode to gather requirements."""
print("=" * 70)
print("WORKFLOW ANALYSIS - INTERACTIVE MODE")
print("=" * 70)
print("\nDescribe the operations your skill should perform.")
print("Enter each operation on a separate line.")
print("Press Ctrl+D (Unix) or Ctrl+Z (Windows) when done.\n")
lines = []
try:
while True:
line = input("> ")
if line.strip():
lines.append(line)
except EOFError:
pass
return '\n'.join(lines)
def main():
parser = argparse.ArgumentParser(
description='Analyze workflows to identify deterministic vs dynamic operations',
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument('--examples', nargs='+', help='Files containing example requests')
parser.add_argument('--interactive', action='store_true', help='Run in interactive mode')
parser.add_argument('--output', help='Output file for report (default: stdout)')
args = parser.parse_args()
analyzer = OperationAnalyzer()
# Gather input
text = ""
if args.interactive:
text = interactive_mode()
elif args.examples:
for example_file in args.examples:
path = Path(example_file)
if path.exists():
text += path.read_text() + '\n'
else:
print(f"Warning: File not found: {example_file}", file=sys.stderr)
else:
print("Error: Provide --examples or use --interactive mode", file=sys.stderr)
sys.exit(1)
if not text.strip():
print("Error: No input provided", file=sys.stderr)
sys.exit(1)
# Analyze
operations = analyzer.analyze_text(text)
if not operations:
print("No operations detected in input", file=sys.stderr)
sys.exit(1)
# Generate report
report = analyzer.generate_recommendations(operations)
# Output
if args.output:
Path(args.output).write_text(report)
print(f"✅ Report written to: {args.output}")
else:
print(report)
if __name__ == '__main__':
main()
+438
View File
@@ -0,0 +1,438 @@
#!/usr/bin/env python3
"""
Go Script Generator for Claude Code Skills
Analyzes operation requirements and generates efficient Go scripts for
deterministic operations that don't require agent interaction.
Usage:
generate_go_script.py --name <script-name> --description <desc> \
--input <input-desc> --output <output-desc> \
--logic <logic-desc> --skill-path <path>
Example:
generate_go_script.py \
--name pdf-to-images \
--description "Convert PDF pages to PNG images" \
--input "PDF file path" \
--output "Directory of PNG files" \
--logic "Extract each page as separate image at 300 DPI" \
--skill-path ./my-skill
"""
import argparse
import sys
from pathlib import Path
from textwrap import dedent
# Go script template with best practices
GO_SCRIPT_TEMPLATE = '''package main
import (
"flag"
"fmt"
"log"
"os"
{extra_imports}
)
// {description}
// Generated by meta-skill-generator for Claude Code skills
var (
verbose = flag.Bool("verbose", false, "Enable verbose logging")
help = flag.Bool("help", false, "Show this help message")
)
func main() {{
flag.Usage = usage
flag.Parse()
if *help {{
usage()
os.Exit(0)
}}
if *verbose {{
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
}} else {{
log.SetFlags(0)
}}
// Validate command line arguments
if err := validateArgs(); err != nil {{
fmt.Fprintf(os.Stderr, "Error: %v\\n", err)
usage()
os.Exit(2)
}}
// Execute main logic
if err := run(); err != nil {{
fmt.Fprintf(os.Stderr, "Error: %v\\n", err)
os.Exit(1)
}}
}}
func usage() {{
fmt.Fprintf(os.Stderr, "Usage: %s [options] {usage_args}\\n", os.Args[0])
fmt.Fprintf(os.Stderr, "\\n{description}\\n\\n")
fmt.Fprintf(os.Stderr, "Input: {input_desc}\\n")
fmt.Fprintf(os.Stderr, "Output: {output_desc}\\n\\n")
fmt.Fprintf(os.Stderr, "Options:\\n")
flag.PrintDefaults()
}}
func validateArgs() error {{
{validation_logic}
return nil
}}
func run() error {{
if *verbose {{
log.Println("Starting {name}...")
}}
{run_logic}
if *verbose {{
log.Println("Completed successfully")
}}
return nil
}}
{helper_functions}
'''
def infer_imports(logic_desc):
"""Infer required Go imports from operation description."""
imports = []
logic_lower = logic_desc.lower()
if any(word in logic_lower for word in ['file', 'directory', 'path', 'copy', 'move']):
imports.append('"io"')
imports.append('"path/filepath"')
if any(word in logic_lower for word in ['json', 'parse']):
imports.append('"encoding/json"')
if any(word in logic_lower for word in ['csv', 'comma']):
imports.append('"encoding/csv"')
if any(word in logic_lower for word in ['http', 'api', 'request']):
imports.append('"net/http"')
if any(word in logic_lower for word in ['string', 'text', 'replace']):
imports.append('"strings"')
if any(word in logic_lower for word in ['regex', 'pattern', 'match']):
imports.append('"regexp"')
if any(word in logic_lower for word in ['time', 'date', 'duration']):
imports.append('"time"')
if any(word in logic_lower for word in ['concurrent', 'parallel', 'goroutine']):
imports.append('"sync"')
if any(word in logic_lower for word in ['buffer', 'bytes']):
imports.append('"bytes"')
return imports
def generate_validation_logic(input_desc):
"""Generate input validation logic."""
validations = []
if 'file' in input_desc.lower():
validations.append(dedent('''
if flag.NArg() < 1 {
return fmt.Errorf("input file required")
}
inputFile := flag.Arg(0)
if _, err := os.Stat(inputFile); os.IsNotExist(err) {
return fmt.Errorf("input file does not exist: %s", inputFile)
}
''').strip())
if 'directory' in input_desc.lower():
validations.append(dedent('''
if flag.NArg() < 1 {
return fmt.Errorf("input directory required")
}
inputDir := flag.Arg(0)
if info, err := os.Stat(inputDir); os.IsNotExist(err) || !info.IsDir() {
return fmt.Errorf("input directory does not exist: %s", inputDir)
}
''').strip())
return '\n\t'.join(validations) if validations else '// No validation needed'
def generate_run_logic(logic_desc, input_desc, output_desc):
"""Generate main execution logic with placeholder."""
logic_lower = logic_desc.lower()
# Start with input handling
logic = []
if 'file' in input_desc.lower():
logic.append('inputFile := flag.Arg(0)')
logic.append('')
if 'directory' in input_desc.lower():
logic.append('inputDir := flag.Arg(0)')
logic.append('')
# Add operation-specific logic template
logic.append('// TODO: Implement the following logic:')
logic.append(f'// {logic_desc}')
logic.append('')
if any(word in logic_lower for word in ['convert', 'transform', 'process']):
logic.append(dedent('''
// 1. Read input
// 2. Process/transform data
// 3. Write output
''').strip())
if 'parallel' in logic_lower or 'concurrent' in logic_lower:
logic.append(dedent('''
// Consider using goroutines for parallel processing:
// var wg sync.WaitGroup
// for _, item := range items {
// wg.Add(1)
// go func(item Item) {
// defer wg.Done()
// // Process item
// }(item)
// }
// wg.Wait()
''').strip())
# Add output handling
if 'stdout' in output_desc.lower():
logic.append('')
logic.append('// Write results to stdout')
logic.append('fmt.Println(result)')
elif 'file' in output_desc.lower():
logic.append('')
logic.append('outputFile := "output.txt" // TODO: Make configurable')
logic.append('if err := os.WriteFile(outputFile, []byte(result), 0644); err != nil {')
logic.append(' return fmt.Errorf("failed to write output: %w", err)')
logic.append('}')
logic.append('')
logic.append('return nil')
return '\n\t'.join(logic)
def generate_helper_functions(logic_desc):
"""Generate helper function templates."""
helpers = []
logic_lower = logic_desc.lower()
if 'progress' in logic_lower or 'batch' in logic_lower:
helpers.append(dedent('''
func showProgress(current, total int) {
if total > 0 {
percent := float64(current) / float64(total) * 100
fmt.Fprintf(os.Stderr, "\\rProgress: %.1f%% (%d/%d)", percent, current, total)
if current == total {
fmt.Fprintln(os.Stderr)
}
}
}
''').strip())
if 'validate' in logic_lower or 'check' in logic_lower:
helpers.append(dedent('''
func validateInput(data interface{}) error {
// TODO: Implement validation logic
return nil
}
''').strip())
return '\n\n'.join(helpers) if helpers else '// No helper functions needed'
def determine_usage_args(input_desc):
"""Determine usage string from input description."""
if 'file' in input_desc.lower():
return '<input-file>'
elif 'directory' in input_desc.lower():
return '<input-dir>'
else:
return '<input>'
def generate_go_script(name, description, input_desc, output_desc, logic_desc, skill_path):
"""Generate a complete Go script."""
# Infer what imports we need
extra_imports = '\n\t'.join(infer_imports(logic_desc))
# Generate different sections
validation_logic = generate_validation_logic(input_desc)
run_logic = generate_run_logic(logic_desc, input_desc, output_desc)
helper_functions = generate_helper_functions(logic_desc)
usage_args = determine_usage_args(input_desc)
# Fill in template
script_content = GO_SCRIPT_TEMPLATE.format(
description=description,
name=name,
input_desc=input_desc,
output_desc=output_desc,
usage_args=usage_args,
extra_imports=extra_imports,
validation_logic=validation_logic,
run_logic=run_logic,
helper_functions=helper_functions
)
return script_content
def create_build_script(skill_path, script_name):
"""Create a build script to compile the Go binary."""
build_script = f'''#!/bin/bash
# Build script for {script_name}
set -e
SCRIPT_DIR="$(cd "$(dirname "${{BASH_SOURCE[0]}}")" && pwd)"
BIN_DIR="$SCRIPT_DIR/bin"
mkdir -p "$BIN_DIR"
echo "Building {script_name}..."
cd "$SCRIPT_DIR"
go build -o "$BIN_DIR/{script_name}" {script_name}.go
echo "✅ Built: $BIN_DIR/{script_name}"
echo "Run with: $BIN_DIR/{script_name} --help"
'''
build_path = skill_path / 'scripts' / f'build_{script_name}.sh'
build_path.write_text(build_script)
build_path.chmod(0o755)
return build_path
def update_skill_md(skill_path, script_name, description, input_desc, output_desc):
"""Add usage information to SKILL.md."""
skill_md = skill_path / 'SKILL.md'
if not skill_md.exists():
print(f"⚠️ Warning: SKILL.md not found at {skill_md}")
return
content = skill_md.read_text()
# Add script documentation if not already present
script_section = f'''
### {script_name}
{description}
**Input:** {input_desc}
**Output:** {output_desc}
**Usage:**
```bash
scripts/bin/{script_name} [options] <input>
scripts/bin/{script_name} --help # For detailed options
```
**Example:**
```bash
scripts/bin/{script_name} input.txt
```
'''
if script_name not in content:
# Try to add after "## Resources" or at the end
if '## Resources' in content:
content = content.replace('## Resources', script_section + '\n## Resources')
else:
content += '\n' + script_section
skill_md.write_text(content)
print(f"✅ Updated SKILL.md with {script_name} documentation")
else:
print(f"{script_name} already documented in SKILL.md")
def main():
parser = argparse.ArgumentParser(
description='Generate Go scripts for Claude Code skills',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=dedent('''
Examples:
generate_go_script.py \\
--name pdf-extract-text \\
--description "Extract text from PDF files" \\
--input "PDF file path" \\
--output "Text content to stdout" \\
--logic "Parse PDF and extract all text content" \\
--skill-path ./my-pdf-skill
generate_go_script.py \\
--name csv-to-json \\
--description "Convert CSV files to JSON" \\
--input "CSV file path" \\
--output "JSON file" \\
--logic "Parse CSV rows and convert to JSON array" \\
--skill-path ./data-tools
''')
)
parser.add_argument('--name', required=True, help='Name of the script (e.g., pdf-to-images)')
parser.add_argument('--description', required=True, help='What the script does')
parser.add_argument('--input', required=True, help='Description of input')
parser.add_argument('--output', required=True, help='Description of output')
parser.add_argument('--logic', required=True, help='Description of the transformation logic')
parser.add_argument('--skill-path', required=True, help='Path to the skill directory')
parser.add_argument('--no-build', action='store_true', help='Skip creating build script')
parser.add_argument('--no-update-md', action='store_true', help='Skip updating SKILL.md')
args = parser.parse_args()
# Validate skill path
skill_path = Path(args.skill_path).resolve()
if not skill_path.exists():
print(f"❌ Error: Skill path does not exist: {skill_path}")
sys.exit(1)
# Create scripts directory if needed
scripts_dir = skill_path / 'scripts'
scripts_dir.mkdir(exist_ok=True)
# Generate Go script
print(f"🚀 Generating Go script: {args.name}")
script_content = generate_go_script(
args.name,
args.description,
args.input,
args.output,
args.logic,
skill_path
)
# Write Go file
go_file = scripts_dir / f'{args.name}.go'
go_file.write_text(script_content)
print(f"✅ Created: {go_file}")
# Create build script
if not args.no_build:
build_script = create_build_script(skill_path, args.name)
print(f"✅ Created build script: {build_script}")
print(f" Run: ./scripts/build_{args.name}.sh")
# Update SKILL.md
if not args.no_update_md:
update_skill_md(skill_path, args.name, args.description, args.input, args.output)
print(f"\n✅ Go script '{args.name}' generated successfully")
print("\nNext steps:")
print(f"1. Review and customize: {go_file}")
print(f"2. Build the binary: ./scripts/build_{args.name}.sh")
print(f"3. Test: ./scripts/bin/{args.name} --help")
if __name__ == '__main__':
main()
@@ -0,0 +1,280 @@
#!/usr/bin/env python3
"""
End-to-End Skill Creator with Workflow Analysis
Guides through the complete process of creating a Claude Code skill with
intelligent Go script generation.
Usage:
init_skill_with_analysis.py <skill-name> --path <output-dir>
"""
import argparse
import subprocess
import sys
from pathlib import Path
def run_command(cmd, cwd=None):
"""Run a command and return success status."""
try:
result = subprocess.run(
cmd,
cwd=cwd,
capture_output=True,
text=True,
check=True
)
return True, result.stdout
except subprocess.CalledProcessError as e:
return False, e.stderr
def gather_examples():
"""Gather example use cases from user."""
print("\n" + "="*70)
print("STEP 1: GATHER EXAMPLE USE CASES")
print("="*70)
print("\nProvide 3-5 example requests that your skill should handle.")
print("Each example should be a concrete user request.")
print("Press Enter twice when done.\n")
examples = []
blank_count = 0
while blank_count < 2:
line = input(f"Example {len(examples)+1}: ").strip()
if not line:
blank_count += 1
else:
blank_count = 0
examples.append(line)
if not examples:
print("Error: No examples provided")
sys.exit(1)
return examples
def analyze_workflow(examples):
"""Analyze examples to identify operation types."""
print("\n" + "="*70)
print("STEP 2: ANALYZING WORKFLOW")
print("="*70)
# Create temporary file with examples
temp_file = Path("/tmp/skill_examples.txt")
temp_file.write_text('\n'.join(examples))
# Run analysis
script_path = Path(__file__).parent / "analyze_workflow.py"
cmd = [sys.executable, str(script_path), "--examples", str(temp_file)]
success, output = run_command(cmd)
if not success:
print(f"Warning: Workflow analysis failed: {output}")
return None
print(output)
return output
def confirm_plan():
"""Ask user to confirm the plan."""
print("\n" + "="*70)
print("Does this analysis look correct?")
response = input("Continue with skill creation? (y/n): ").lower()
return response == 'y'
def initialize_skill(skill_name, path):
"""Initialize skill directory structure."""
print("\n" + "="*70)
print("STEP 3: INITIALIZING SKILL")
print("="*70)
# Run init_skill.py
init_script = Path("/mnt/skills/examples/skill-creator/scripts/init_skill.py")
cmd = [sys.executable, str(init_script), skill_name, "--path", path]
success, output = run_command(cmd)
if not success:
print(f"Error: Failed to initialize skill: {output}")
sys.exit(1)
print(output)
return Path(path) / skill_name
def gather_script_specs(skill_path):
"""Gather specifications for Go scripts."""
print("\n" + "="*70)
print("STEP 4: SPECIFY GO SCRIPTS")
print("="*70)
print("\nBased on the analysis, let's define the Go scripts.")
print("Enter details for each deterministic operation.")
print()
scripts = []
while True:
print(f"\n--- Go Script {len(scripts)+1} ---")
print("Press Enter with empty name to finish")
name = input("Script name (e.g., pdf-to-images): ").strip()
if not name:
break
description = input("Description: ").strip()
if not description:
print("Description required")
continue
input_desc = input("Input (e.g., 'PDF file path'): ").strip()
if not input_desc:
print("Input description required")
continue
output_desc = input("Output (e.g., 'Directory of PNG files'): ").strip()
if not output_desc:
print("Output description required")
continue
logic = input("Logic (e.g., 'Extract each page at 300 DPI'): ").strip()
if not logic:
print("Logic description required")
continue
scripts.append({
'name': name,
'description': description,
'input': input_desc,
'output': output_desc,
'logic': logic
})
print(f"✅ Script '{name}' configured")
return scripts
def generate_go_scripts(skill_path, scripts):
"""Generate Go scripts using generate_go_script.py."""
if not scripts:
print("\nNo Go scripts to generate")
return
print("\n" + "="*70)
print("STEP 5: GENERATING GO SCRIPTS")
print("="*70)
generator = Path(__file__).parent / "generate_go_script.py"
for script in scripts:
print(f"\nGenerating {script['name']}...")
cmd = [
sys.executable, str(generator),
"--name", script['name'],
"--description", script['description'],
"--input", script['input'],
"--output", script['output'],
"--logic", script['logic'],
"--skill-path", str(skill_path)
]
success, output = run_command(cmd)
if not success:
print(f"⚠️ Warning: Failed to generate {script['name']}: {output}")
else:
print(f"✅ Generated {script['name']}")
def finalize_skill_md(skill_path, examples):
"""Add examples to SKILL.md."""
print("\n" + "="*70)
print("STEP 6: FINALIZING SKILL.MD")
print("="*70)
skill_md = skill_path / "SKILL.md"
content = skill_md.read_text()
# Add examples section
examples_section = "\n## Example Use Cases\n\n"
for i, example in enumerate(examples, 1):
examples_section += f"{i}. {example}\n"
# Insert before ## Resources section
if "## Resources" in content:
content = content.replace("## Resources", examples_section + "\n## Resources")
else:
content += examples_section
skill_md.write_text(content)
print(f"✅ Updated SKILL.md with {len(examples)} example use cases")
def print_next_steps(skill_path):
"""Print next steps for the user."""
print("\n" + "="*70)
print("✅ SKILL CREATED SUCCESSFULLY")
print("="*70)
print(f"\nSkill location: {skill_path}")
print("\nNext steps:")
print(f"1. Review and customize SKILL.md:")
print(f" - Complete the description in frontmatter")
print(f" - Add detailed workflow instructions")
print(f" - Remove TODO placeholders")
print()
print(f"2. Build Go scripts:")
print(f" cd {skill_path}")
for script_file in (skill_path / "scripts").glob("build_*.sh"):
print(f" ./{script_file.relative_to(skill_path)}")
print()
print(f"3. Test the scripts:")
for bin_file in (skill_path / "scripts" / "bin").glob("*"):
if bin_file.is_file():
print(f" ./scripts/bin/{bin_file.name} --help")
print()
print(f"4. Package the skill:")
print(f" python3 /mnt/skills/examples/skill-creator/scripts/package_skill.py {skill_path}")
print()
def main():
parser = argparse.ArgumentParser(
description='Create a Claude Code skill with workflow analysis and Go script generation',
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument('skill_name', help='Name of the skill (e.g., pdf-tools)')
parser.add_argument('--path', required=True, help='Directory where skill will be created')
parser.add_argument('--skip-analysis', action='store_true',
help='Skip workflow analysis (use for simple skills)')
parser.add_argument('--skip-go', action='store_true',
help='Skip Go script generation (create structure only)')
args = parser.parse_args()
print("="*70)
print("CLAUDE CODE SKILL CREATOR")
print("="*70)
print(f"\nCreating skill: {args.skill_name}")
print(f"Location: {args.path}")
# Step 1: Gather examples
examples = gather_examples()
# Step 2: Analyze workflow (optional)
if not args.skip_analysis:
analysis = analyze_workflow(examples)
if analysis and not confirm_plan():
print("\nAborted by user")
sys.exit(0)
# Step 3: Initialize skill
skill_path = initialize_skill(args.skill_name, args.path)
# Step 4-5: Generate Go scripts (optional)
if not args.skip_go:
scripts = gather_script_specs(skill_path)
generate_go_scripts(skill_path, scripts)
# Step 6: Finalize
finalize_skill_md(skill_path, examples)
# Done
print_next_steps(skill_path)
if __name__ == '__main__':
main()
+194
View File
@@ -0,0 +1,194 @@
#!/usr/bin/env python3
"""
Test runner for skill scripts
Validates that all scripts in a skill are properly structured and executable.
Usage:
test_skill_scripts.py <skill-path>
"""
import argparse
import subprocess
import sys
from pathlib import Path
def test_python_scripts(scripts_dir):
"""Test Python scripts for syntax and executability."""
results = []
for script in scripts_dir.glob("*.py"):
if script.name.startswith("test_") or script.name == "__init__.py":
continue
# Check if executable
is_executable = script.stat().st_mode & 0o111
# Check syntax
try:
subprocess.run(
[sys.executable, "-m", "py_compile", str(script)],
capture_output=True,
check=True
)
syntax_ok = True
except subprocess.CalledProcessError:
syntax_ok = False
results.append({
'name': script.name,
'type': 'python',
'executable': is_executable,
'syntax_ok': syntax_ok
})
return results
def test_go_scripts(scripts_dir):
"""Test Go scripts for compilation."""
results = []
for script in scripts_dir.glob("*.go"):
# Try to compile
try:
result = subprocess.run(
["go", "build", "-o", "/dev/null", str(script)],
capture_output=True,
check=True
)
compiles = True
error = None
except subprocess.CalledProcessError as e:
compiles = False
error = e.stderr.decode()
except FileNotFoundError:
compiles = None # Go not installed
error = "Go compiler not found"
results.append({
'name': script.name,
'type': 'go',
'compiles': compiles,
'error': error
})
return results
def test_bash_scripts(scripts_dir):
"""Test Bash scripts for syntax."""
results = []
for script in scripts_dir.glob("*.sh"):
# Check if executable
is_executable = script.stat().st_mode & 0o111
# Check syntax
try:
subprocess.run(
["bash", "-n", str(script)],
capture_output=True,
check=True
)
syntax_ok = True
except subprocess.CalledProcessError:
syntax_ok = False
results.append({
'name': script.name,
'type': 'bash',
'executable': is_executable,
'syntax_ok': syntax_ok
})
return results
def print_results(results):
"""Print test results."""
print("\n" + "="*70)
print("SCRIPT TEST RESULTS")
print("="*70 + "\n")
all_passed = True
for result in results:
name = result['name']
script_type = result['type']
print(f"{name} ({script_type})")
if script_type == 'python':
if result['syntax_ok']:
print(" ✅ Syntax: OK")
else:
print(" ❌ Syntax: FAILED")
all_passed = False
if result['executable']:
print(" ✅ Executable: Yes")
else:
print(" ⚠️ Executable: No (run: chmod +x)")
elif script_type == 'go':
if result['compiles'] is None:
print(" ⚠️ Go compiler not found (skipped)")
elif result['compiles']:
print(" ✅ Compiles: OK")
else:
print(" ❌ Compiles: FAILED")
if result['error']:
print(f" Error: {result['error'][:100]}")
all_passed = False
elif script_type == 'bash':
if result['syntax_ok']:
print(" ✅ Syntax: OK")
else:
print(" ❌ Syntax: FAILED")
all_passed = False
if result['executable']:
print(" ✅ Executable: Yes")
else:
print(" ⚠️ Executable: No (run: chmod +x)")
print()
return all_passed
def main():
parser = argparse.ArgumentParser(
description='Test all scripts in a skill directory'
)
parser.add_argument('skill_path', help='Path to skill directory')
args = parser.parse_args()
skill_path = Path(args.skill_path).resolve()
scripts_dir = skill_path / 'scripts'
if not scripts_dir.exists():
print(f"Error: scripts directory not found: {scripts_dir}")
sys.exit(1)
print(f"Testing scripts in: {scripts_dir}")
results = []
results.extend(test_python_scripts(scripts_dir))
results.extend(test_go_scripts(scripts_dir))
results.extend(test_bash_scripts(scripts_dir))
if not results:
print("No scripts found to test")
sys.exit(0)
all_passed = print_results(results)
if all_passed:
print("✅ All tests passed!")
sys.exit(0)
else:
print("❌ Some tests failed")
sys.exit(1)
if __name__ == '__main__':
main()