feat: auto-discover custom skills from assets/skills/

- setup.sh skills command now does two things:
  1. Installs registry skills from <platform>-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
This commit is contained in:
Matt Bruce 2026-02-11 12:11:01 -06:00
parent b5e7de10e7
commit 20446c5224
4 changed files with 117 additions and 30 deletions

View File

@ -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 |

View File

@ -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 <platform>-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
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[@]}"
count=$((count + 1))
reg_count=$((reg_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."
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,7 +309,7 @@ ${BOLD}USAGE${NC}
setup.sh <command> [platform]
${BOLD}COMMANDS${NC}
skills [platform] Install skills from a curated list
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
@ -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)

15
assets/skills/README.md Normal file
View File

@ -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.

View File

@ -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)
```