From 20446c5224b67ed4467b151f03b6b46302461564 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 11 Feb 2026 12:11:01 -0600 Subject: [PATCH] feat: auto-discover custom skills from assets/skills/ - setup.sh skills command now does two things: 1. Installs registry skills from -skills.txt 2. Auto-discovers and copies custom skill folders from assets/skills/ - Added SKILLS_DIR config (default: ~/.copilot/skills/) - Added download_dir_to helper for copying skill folders remotely - Created assets/skills/ for team-maintained custom skills --- assets/README.md | 20 +++++--- assets/setup.sh | 109 ++++++++++++++++++++++++++++++++-------- assets/skills/README.md | 15 ++++++ docs/ai/skills.md | 3 +- 4 files changed, 117 insertions(+), 30 deletions(-) create mode 100644 assets/skills/README.md diff --git a/assets/README.md b/assets/README.md index 9dcb6f1..a6304fe 100644 --- a/assets/README.md +++ b/assets/README.md @@ -41,7 +41,7 @@ That's it. | Command | What It Does | |---------|-------------| -| `setup.sh skills [platform]` | Install skills from a curated list | +| `setup.sh skills [platform]` | Install registry skills + custom skills (auto-discovered) | | `setup.sh agents` | Install all agent prompt files (auto-discovered) | | `setup.sh instructions` | Install all instruction rule files (auto-discovered) | | `setup.sh all [platform]` | All of the above in one shot | @@ -59,19 +59,21 @@ That's it. | Asset | Default Location | Override | |-------|-----------------|----------| -| Skills | Managed by `npx skills` CLI | — | +| Registry skills | Managed by `npx skills` CLI | — | +| Custom skills | `~/.copilot/skills/` | `SKILLS_DIR` | | Agents | `~/.copilot/agents/` | `AGENTS_DIR` | | Instructions | `./instructions/` | `INSTRUCTIONS_DIR` | ## Adding New Assets -- **Agents or instructions** — Drop the file into `assets/agents/` or `assets/instructions/` and push. The script discovers files from the directory automatically. No manifest to update. -- **Skills** — Add the install command to the appropriate `.txt` file (e.g., `ios-skills.txt`). One command per line. +- **Agents or instructions** — Drop the file into `assets/agents/` or `assets/instructions/` and push. Auto-discovered. +- **Custom skills** — Add a folder with a `SKILL.md` to `assets/skills/` and push. Auto-discovered. +- **Registry skills** — Add the install entry to the appropriate `.txt` file (e.g., `ios-skills.txt`). One per line. ## How It Works -| Mode | Agents / Instructions | Skills | -|------|----------------------|--------| +| Mode | Agents / Instructions / Custom Skills | Registry Skills | +|------|---------------------------------------|----------------| | **Local** (cloned repo) | `find` scans the directory | Reads the `.txt` file | | **Remote** (no clone) | Queries GitLab/GitHub API to list files | Downloads the `.txt` file | @@ -83,6 +85,9 @@ assets/ ios-skills.txt ← curated iOS skills (one per line) android-skills.txt ← curated Android skills shared-skills.txt ← curated cross-platform skills + skills/ ← custom skill folders (auto-discovered) + my-skill/ + SKILL.md agents/ ← agent prompt files (auto-discovered) instructions/ ← instruction rule files (auto-discovered) ``` @@ -92,6 +97,5 @@ assets/ | Variable | Purpose | Required? | |----------|---------|-----------| | `ASSETS_BASE_URL` | Base URL for remote downloads | Only without a clone | -| `AGENTS_DIR` | Custom agents install path | No | -| `INSTRUCTIONS_DIR` | Custom instructions install path | No | +| `AGENTS_DIR` | Custom agents install path | No || `SKILLS_DIR` | Custom skills install path | No || `INSTRUCTIONS_DIR` | Custom instructions install path | No | | `REPO_TOKEN` | Auth token for private repos | Only if API rejects | \ No newline at end of file diff --git a/assets/setup.sh b/assets/setup.sh index fbf3770..bb92c15 100755 --- a/assets/setup.sh +++ b/assets/setup.sh @@ -13,11 +13,12 @@ set -euo pipefail # bash <(curl -fsSL "$ASSETS_BASE_URL/setup.sh") all ios # ───────────────────────────────────────────────────────────────────── -VERSION="2.0.0" +VERSION="2.1.0" # ── Configuration (override with env vars) ─────────────────────────── ASSETS_BASE_URL="${ASSETS_BASE_URL:-}" AGENTS_DIR="${AGENTS_DIR:-$HOME/.copilot/agents}" +SKILLS_DIR="${SKILLS_DIR:-$HOME/.copilot/skills}" INSTRUCTIONS_DIR="${INSTRUCTIONS_DIR:-./instructions}" REPO_TOKEN="${REPO_TOKEN:-}" @@ -135,34 +136,99 @@ download_to() { fi } +# Download an entire remote directory (one level deep). +download_dir_to() { + local src_subdir="$1" dest_dir="$2" + mkdir -p "$dest_dir" + if [[ "$MODE" == "local" ]]; then + cp -R "$ASSETS_DIR/$src_subdir/"* "$dest_dir/" 2>/dev/null || true + else + local files + files=$(list_remote_files "$src_subdir" "") + while IFS= read -r file; do + [[ -z "$file" ]] && continue + curl -fsSL ${REPO_TOKEN:+-H "Authorization: Bearer $REPO_TOKEN"} "$ASSETS_BASE_URL/$src_subdir/$file" -o "$dest_dir/$file" + done <<< "$files" + fi +} + # ── Commands ───────────────────────────────────────────────────────── # -- skills [platform] ──────────────────────────────────────────────── -# Reads a plain-text skills file. Each non-empty, non-comment line is -# passed to `npx skills add`. +# 1. Install registry skills from -skills.txt +# 2. Auto-discover and copy custom skills from assets/skills/ cmd_skills() { local platform="${1:-shared}" local manifest="${platform}-skills.txt" - heading "Skills ($platform)" + # ── Registry skills ── + heading "Registry Skills ($platform)" local content - content="$(fetch "$manifest")" || fail "Could not fetch $manifest" + content="$(fetch "$manifest" 2>/dev/null)" || content="" - local count=0 - while IFS= read -r line; do - [[ -z "$line" || "$line" == \#* ]] && continue - info "npx skills add $line" - read -r -a args <<< "$line" - npx skills add "${args[@]}" - count=$((count + 1)) - done <<< "$content" - - if [[ $count -eq 0 ]]; then - warn "No entries in $manifest — nothing to install." - else - ok "$count skill(s) installed. Restart your editor if they don't appear." + local reg_count=0 + if [[ -n "$content" ]]; then + while IFS= read -r line; do + [[ -z "$line" || "$line" == \#* ]] && continue + info "npx skills add $line" + read -r -a args <<< "$line" + npx skills add "${args[@]}" + reg_count=$((reg_count + 1)) + done <<< "$content" fi + + if [[ $reg_count -eq 0 ]]; then + warn "No entries in $manifest." + else + ok "$reg_count registry skill(s) installed." + fi + + # ── Custom / local skills ── + heading "Custom Skills → $SKILLS_DIR" + mkdir -p "$SKILLS_DIR" + + local skill_dirs count=0 + + if [[ "$MODE" == "local" ]]; then + if [[ -d "$ASSETS_DIR/skills" ]]; then + skill_dirs=$(find "$ASSETS_DIR/skills" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort) + else + skill_dirs="" + fi + else + # Remote: list subdirectories in skills/ via API. + # The API returns entries — filter for directories (type "tree" in GitLab, "dir" in GitHub). + local api_url + api_url=$(derive_api_url "skills") || { warn "Cannot list remote skills directories."; return 0; } + + local auth_header="" + [[ -n "$REPO_TOKEN" ]] && auth_header="Authorization: Bearer $REPO_TOKEN" + + local response + response=$(curl -fsSL ${auth_header:+-H "$auth_header"} "$api_url" 2>/dev/null) || { warn "Could not list remote skills."; return 0; } + + # GitLab uses "type":"tree" for dirs, GitHub uses "type":"dir" + skill_dirs=$(echo "$response" \ + | grep -o '"name":"[^"]*"[^}]*"type":"\(tree\|dir\)"' \ + | grep -o '"name":"[^"]*"' \ + | sed 's/"name":"//;s/"//' || true) + fi + + if [[ -z "$skill_dirs" ]]; then + warn "No custom skill folders found in assets/skills/." + else + while IFS= read -r skill; do + [[ -z "$skill" ]] && continue + info "$skill" + download_dir_to "skills/$skill" "$SKILLS_DIR/$skill" + count=$((count + 1)) + done <<< "$skill_dirs" + ok "$count custom skill(s) installed." + fi + + printf "\n" + ok "Restart your editor if skills don't appear." } # -- agents ─────────────────────────────────────────────────────────── @@ -243,9 +309,9 @@ ${BOLD}USAGE${NC} setup.sh [platform] ${BOLD}COMMANDS${NC} - skills [platform] Install skills from a curated list - agents Install all agent prompt files (auto-discovered) - instructions Install all instruction files (auto-discovered) + skills [platform] Install registry + custom skills (auto-discovered) + agents Install all agent prompt files (auto-discovered) + instructions Install all instruction files (auto-discovered) all [platform] Install everything at once help Show this message @@ -269,6 +335,7 @@ ${BOLD}EXAMPLES${NC} ${BOLD}ENVIRONMENT VARIABLES${NC} ASSETS_BASE_URL Base URL for remote downloads (required without clone) AGENTS_DIR Install location for agents (default: ~/.copilot/agents) + SKILLS_DIR Install location for custom skills (default: ~/.copilot/skills) INSTRUCTIONS_DIR Install location for instructions (default: ./instructions) REPO_TOKEN Auth token for private repos (optional) diff --git a/assets/skills/README.md b/assets/skills/README.md new file mode 100644 index 0000000..563229d --- /dev/null +++ b/assets/skills/README.md @@ -0,0 +1,15 @@ +# Custom Skills + +Drop skill folders here. Each folder should contain a `SKILL.md` file. + +``` +assets/skills/ + my-custom-skill/ + SKILL.md + references/ (optional) + another-skill/ + SKILL.md +``` + +The setup script auto-discovers and installs every folder in this directory. +No manifest to update — just add the folder and push. diff --git a/docs/ai/skills.md b/docs/ai/skills.md index 99c7311..d0fe30c 100644 --- a/docs/ai/skills.md +++ b/docs/ai/skills.md @@ -46,10 +46,11 @@ Keep the approved list in a single repo and organize by platform. This repo alre ```text /assets/ - setup.sh ← the installer (auto-discovers agents & instructions) + setup.sh ← the installer (auto-discovers everything) ios-skills.txt ← curated iOS skills (one per line) android-skills.txt ← curated Android skills shared-skills.txt ← curated cross-platform skills + skills/ ← custom skill folders (auto-discovered) agents/ ← agent prompt files (auto-discovered) instructions/ ← instruction rule files (auto-discovered) ```