281 lines
8.6 KiB
Python
Executable File
281 lines
8.6 KiB
Python
Executable File
#!/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()
|