#!/usr/bin/env python3 """Create a new OpenCode skill with proper structure.""" import os import sys import argparse from pathlib import Path SKILL_TEMPLATE = """--- name: {name} description: {description} --- # {title} Brief description of what this skill does. ## Commands | Command | Args | Description | |---------|------|-------------| | `command1` | `` | Description | ## Options | Option | Default | Range | Description | |--------|---------|-------|-------------| | `--option` | 100 | 1-1000 | Description | ## Examples ```bash python3 scripts/{script_name}.py command "arg" --option 50 ``` ## Output Format - Success: `Result: filename [id]` - Error: `Error: message` (to stderr) ## Notes - Required environment variables: API_KEY - Additional constraints or notes """ SCRIPT_TEMPLATE = """#!/usr/bin/env python3 import os import sys import argparse from pathlib import Path def load_env(): env_path = Path(__file__).parent / ".env" if env_path.exists(): for line in env_path.read_text().splitlines(): line = line.strip() if line and not line.startswith("#") and "=" in line: k, v = line.split("=", 1) os.environ.setdefault(k.strip(), v.strip().strip("\"'")) load_env() API_KEY = os.environ.get("API_KEY") API_URL = "https://api.example.com/endpoint" def main_action(arg1, option1=100): if not API_KEY: print("Error: API_KEY not set in environment", file=sys.stderr) sys.exit(1) # TODO: Implement the main functionality print(f"Result: output [1]") def main(): parser = argparse.ArgumentParser(description="{title} skill") parser.add_argument("arg1", help="First argument") parser.add_argument("--option1", type=int, default=100, help="Option description") args = parser.parse_args() main_action(args.arg1, args.option1) if __name__ == "__main__": main() """ ENV_EXAMPLE_TEMPLATE = """# API credentials # Get your token from https://service.com/account # # WARNING: Never commit actual credentials! API_KEY=your_api_key_here """ REQUIREMENTS_TEMPLATE = """requests>=2.28.0 """ def validate_name(name): """Validate skill name follows OpenCode rules.""" import re if not name: print("Error: Name cannot be empty", file=sys.stderr) return False if len(name) > 64: print("Error: Name must be 64 characters or less", file=sys.stderr) return False pattern = r"^[a-z0-9]+(-[a-z0-9]+)*$" if not re.match(pattern, name): print( "Error: Name must be lowercase alphanumeric with single hyphens", file=sys.stderr, ) print(" - No leading/trailing hyphens", file=sys.stderr) print(" - No consecutive hyphens", file=sys.stderr) return False return True def create_skill(name, description, output_dir): """Create a new skill directory structure.""" if not validate_name(name): sys.exit(1) title = name.replace("-", " ").title() script_name = name.replace("-", "_") skill_dir = Path(output_dir) / name scripts_dir = skill_dir / "scripts" if skill_dir.exists(): print(f"Error: Skill '{name}' already exists at {skill_dir}", file=sys.stderr) sys.exit(1) # Create directories scripts_dir.mkdir(parents=True) # Create SKILL.md skill_md = skill_dir / "SKILL.md" skill_md.write_text( SKILL_TEMPLATE.format( name=name, description=description, title=title, script_name=script_name ) ) # Create script script_file = scripts_dir / f"{script_name}.py" script_file.write_text(SCRIPT_TEMPLATE.format(title=title)) script_file.chmod(0o755) # Create .env.example env_example = scripts_dir / ".env.example" env_example.write_text(ENV_EXAMPLE_TEMPLATE) # Create requirements.txt requirements = scripts_dir / "requirements.txt" requirements.write_text(REQUIREMENTS_TEMPLATE) print(f"Created skill: {name}") print(f" {skill_dir}/") print(f" {skill_dir}/SKILL.md") print(f" {scripts_dir}/{script_name}.py") print(f" {scripts_dir}/.env.example") print(f" {scripts_dir}/requirements.txt") print() print("Next steps:") print(f" 1. Edit {skill_dir}/SKILL.md to define commands") print(f" 2. Implement {scripts_dir}/{script_name}.py") print(f" 3. Update {scripts_dir}/.env.example with required env vars") print(f" 4. Run: ./scripts/install-skills.sh") def main(): parser = argparse.ArgumentParser(description="Create a new OpenCode skill") parser.add_argument("name", help="Skill name (lowercase, hyphens only)") parser.add_argument("description", help="Brief description of the skill") parser.add_argument( "--output", "-o", default="skills", help="Output directory (default: skills)" ) args = parser.parse_args() create_skill(args.name, args.description, args.output) if __name__ == "__main__": main()