#!/usr/bin/env python3 """ Skill Packager - Creates a distributable zip file of a skill folder Usage: python utils/package_skill.py [output-directory] Example: python utils/package_skill.py skills/public/my-skill python utils/package_skill.py skills/public/my-skill ./dist """ import sys import zipfile from pathlib import Path from quick_validate import validate_skill def package_skill(skill_path, output_dir=None): """ Package a skill folder into a zip file. Args: skill_path: Path to the skill folder output_dir: Optional output directory for the zip file (defaults to current directory) Returns: Path to the created zip file, or None if error """ skill_path = Path(skill_path).resolve() # Validate skill folder exists if not skill_path.exists(): return None if not skill_path.is_dir(): return None # Validate SKILL.md exists skill_md = skill_path / 'SKILL.md' if not skill_md.exists(): return None # Run validation before packaging valid, message = validate_skill(skill_path) if not valid: return None # Determine output location skill_name = skill_path.name if output_dir: output_path = Path(output_dir).resolve() output_path.mkdir(parents=True, exist_ok=True) else: output_path = Path.cwd() zip_filename = output_path / f'{skill_name}.zip' # Create the zip file try: with zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: # Walk through the skill directory for file_path in skill_path.rglob('*'): if file_path.is_file(): # Calculate the relative path within the zip arcname = file_path.relative_to(skill_path.parent) zipf.write(file_path, arcname) return zip_filename except Exception: return None def main() -> None: if len(sys.argv) < 2: sys.exit(1) skill_path = sys.argv[1] output_dir = sys.argv[2] if len(sys.argv) > 2 else None if output_dir: pass result = package_skill(skill_path, output_dir) if result: sys.exit(0) else: sys.exit(1) if __name__ == '__main__': main()