#!/bin/bash # # init-skill.sh - Scaffold a new skill with proper structure # # Usage: ./init-skill.sh [options] # # Options: # --local Create in current project (.opencode/skills/) instead of global # --with-scripts Include scripts/ directory # --with-refs Include references/ directory # --with-assets Include assets/ directory # --with-tests Include evals/ directory for test cases # --full Include all optional directories # set -euo pipefail # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Get script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SKILL_BUILDER_DIR="$(dirname "$SCRIPT_DIR")" # Parse arguments SKILL_NAME="" LOCAL=false WITH_SCRIPTS=false WITH_REFS=false WITH_ASSETS=false WITH_TESTS=false usage() { echo "Usage: $0 [options]" echo "" echo "Options:" echo " --local Create in current project (.opencode/skills/)" echo " --with-scripts Include scripts/ directory" echo " --with-refs Include references/ directory" echo " --with-assets Include assets/ directory" echo " --with-tests Include evals/ directory for test cases" echo " --full Include all optional directories" echo "" echo "Examples:" echo " $0 my-skill" echo " $0 my-skill --full" echo " $0 my-skill --local --with-scripts" exit 1 } # Validate skill name validate_name() { local name="$1" if [[ -z "$name" ]]; then echo -e "${RED}Error: Skill name is required${NC}" usage fi if [[ ! "$name" =~ ^[a-z0-9-]+$ ]]; then echo -e "${RED}Error: Skill name must be lowercase alphanumeric with hyphens only${NC}" echo " Valid: my-skill, docker-helper, test-runner" echo " Invalid: My Skill, docker_helper, testRunner" exit 1 fi if [[ ${#name} -lt 1 ]]; then echo -e "${RED}Error: Skill name cannot be empty${NC}" exit 1 fi if [[ ${#name} -gt 64 ]]; then echo -e "${RED}Error: Skill name must be under 64 characters${NC}" exit 1 fi } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in --local) LOCAL=true shift ;; --with-scripts) WITH_SCRIPTS=true shift ;; --with-refs) WITH_REFS=true shift ;; --with-assets) WITH_ASSETS=true shift ;; --with-tests) WITH_TESTS=true shift ;; --full) WITH_SCRIPTS=true WITH_REFS=true WITH_ASSETS=true WITH_TESTS=true shift ;; -h|--help) usage ;; -*) echo -e "${RED}Error: Unknown option $1${NC}" usage ;; *) if [[ -z "$SKILL_NAME" ]]; then SKILL_NAME="$1" else echo -e "${RED}Error: Multiple skill names provided${NC}" usage fi shift ;; esac done # Validate skill name validate_name "$SKILL_NAME" # Determine target directory if [[ "$LOCAL" == true ]]; then # Check if we're in a git repository if ! git rev-parse --git-dir > /dev/null 2>&1; then echo -e "${RED}Error: --local requires being in a git repository${NC}" exit 1 fi TARGET_DIR=".opencode/skills/$SKILL_NAME" # Check for AGENTS.md in project if [[ -f "AGENTS.md" ]]; then echo -e "${GREEN}✓ Found AGENTS.md in project root${NC}" else echo -e "${YELLOW}⚠ No AGENTS.md found in project root${NC}" echo " Consider creating one for project-specific rules" fi else TARGET_DIR="$HOME/.config/opencode/skills/$SKILL_NAME" fi # Check if skill already exists if [[ -d "$TARGET_DIR" ]]; then echo -e "${RED}Error: Skill already exists at $TARGET_DIR${NC}" exit 1 fi echo -e "${GREEN}Creating skill: $SKILL_NAME${NC}" echo " Location: $TARGET_DIR" echo "" # Create skill directory mkdir -p "$TARGET_DIR" # Create SKILL.md cat > "$TARGET_DIR/SKILL.md" << 'SKILL_TEMPLATE' --- name: SKILL_NAME_PLACEHOLDER description: This skill should be used when the user asks to "DESCRIPTION_HERE". Add specific trigger phrases that would activate this skill. license: MIT compatibility: opencode metadata: category: general version: "1.0.0" --- # SKILL_NAME_PLACEHOLDER Brief description of what this skill does and its purpose. ## What This Skill Provides 1. **Feature 1** - Brief description 2. **Feature 2** - Brief description 3. **Feature 3** - Brief description ## Quick Start Basic usage example: ```bash # Example command some-tool --option value ``` ## Common Tasks ### Task 1: Description Step-by-step instructions: 1. First step 2. Second step 3. Third step ### Task 2: Description Step-by-step instructions: 1. First step 2. Second step ## Important Notes - Keep this section brief - Use bullet points for clarity - Reference supporting files if available ## Resources SKILL_TEMPLATE # Add resource section if directories were created if [[ "$WITH_REFS" == true ]]; then cat >> "$TARGET_DIR/SKILL.md" << 'REF_SECTION' ### Reference Files - `references/detailed-guide.md` - Detailed documentation REF_SECTION fi if [[ "$WITH_SCRIPTS" == true ]]; then cat >> "$TARGET_DIR/SKILL.md" << 'SCRIPT_SECTION' ### Scripts - `scripts/helper.sh` - Utility script SCRIPT_SECTION fi if [[ "$WITH_ASSETS" == true ]]; then cat >> "$TARGET_DIR/SKILL.md" << 'ASSET_SECTION' ### Assets - `assets/template.txt` - Template file ASSET_SECTION fi # Replace placeholder with actual skill name sed -i "s/SKILL_NAME_PLACEHOLDER/$SKILL_NAME/g" "$TARGET_DIR/SKILL.md" # Create optional directories if [[ "$WITH_SCRIPTS" == true ]]; then mkdir -p "$TARGET_DIR/scripts" # Create example script cat > "$TARGET_DIR/scripts/helper.sh" << 'SCRIPT_EXAMPLE' #!/bin/bash # # Helper script for SKILL_NAME_PLACEHOLDER # set -euo pipefail echo "Helper script for SKILL_NAME_PLACEHOLDER" echo "Modify this script for your needs" SCRIPT_EXAMPLE sed -i "s/SKILL_NAME_PLACEHOLDER/$SKILL_NAME/g" "$TARGET_DIR/scripts/helper.sh" chmod +x "$TARGET_DIR/scripts/helper.sh" echo -e "${GREEN} ✓ Created scripts/ directory${NC}" fi if [[ "$WITH_REFS" == true ]]; then mkdir -p "$TARGET_DIR/references" # Create example reference cat > "$TARGET_DIR/references/detailed-guide.md" << 'REF_EXAMPLE' # Detailed Guide for SKILL_NAME_PLACEHOLDER This file contains detailed documentation that can be referenced on-demand. ## Advanced Usage Detailed instructions go here... ## Configuration Configuration options and examples... ## Troubleshooting Common issues and solutions... REF_EXAMPLE sed -i "s/SKILL_NAME_PLACEHOLDER/$SKILL_NAME/g" "$TARGET_DIR/references/detailed-guide.md" echo -e "${GREEN} ✓ Created references/ directory${NC}" fi if [[ "$WITH_ASSETS" == true ]]; then mkdir -p "$TARGET_DIR/assets" # Create example asset cat > "$TARGET_DIR/assets/template.txt" << 'ASSET_EXAMPLE' # Template file for SKILL_NAME_PLACEHOLDER This is a template file that can be used as a starting point. Modify it according to your needs. ASSET_EXAMPLE sed -i "s/SKILL_NAME_PLACEHOLDER/$SKILL_NAME/g" "$TARGET_DIR/assets/template.txt" echo -e "${GREEN} ✓ Created assets/ directory${NC}" fi if [[ "$WITH_TESTS" == true ]]; then mkdir -p "$TARGET_DIR/evals" # Create template evals.json cat > "$TARGET_DIR/evals/evals.json" << 'EVALS_TEMPLATE' { "skill_name": "SKILL_NAME_PLACEHOLDER", "evals": [ { "id": 1, "name": "common-case", "prompt": "Typical user request with realistic context, file paths, and specific details. This represents the most common way users will ask for help.", "expected_output": "Description of what the skill should produce for this request", "assertions": [ "Check that output contains specific expected content", "Verify file is created at expected location (if applicable)" ] }, { "id": 2, "name": "edge-case", "prompt": "Unusual or tricky scenario that tests edge cases, error handling, or complex requirements. Include something that might break the skill.", "expected_output": "Description of expected behavior for this edge case", "assertions": [ "Verify edge case is handled appropriately", "Check for graceful error handling if applicable" ] }, { "id": 3, "name": "varied-phrasing", "prompt": "Same intent as the common case but expressed with different words, casual language, or alternative phrasing. Tests skill robustness to language variation.", "expected_output": "Same expected output as common case", "assertions": [ "Output should match common case results", "Skill triggers correctly with different phrasing" ] } ] } EVALS_TEMPLATE sed -i "s/SKILL_NAME_PLACEHOLDER/$SKILL_NAME/g" "$TARGET_DIR/evals/evals.json" echo -e "${GREEN} ✓ Created evals/ directory with template evals.json${NC}" fi echo "" echo -e "${GREEN}✓ Skill '$SKILL_NAME' created successfully!${NC}" echo "" echo "Next steps:" echo " 1. Edit $TARGET_DIR/SKILL.md" echo " 2. Fill in the description with specific trigger phrases" echo " 3. Add your skill content" if [[ "$WITH_REFS" == true ]]; then echo " 4. Add detailed content to references/ files" fi if [[ "$WITH_SCRIPTS" == true ]]; then echo " 5. Implement scripts in scripts/ directory" fi if [[ "$WITH_TESTS" == true ]]; then echo " 6. Customize test cases in evals/evals.json" echo " 7. Run tests: ${SKILL_BUILDER_DIR}/scripts/run-tests.sh $TARGET_DIR" fi echo "" echo "Validate your skill:" echo " ${SKILL_BUILDER_DIR}/scripts/validate-skill.sh $TARGET_DIR"