- Single script handles skills, agents, and instructions - Works locally (cloned repo) and remotely (curl, no clone) - Auto-generated manifests (agents.list, instructions.list) - update-lists command regenerates manifests from directory contents - Removed sync-skills.sh (folded into setup.sh) - Rewrote assets README to be concise and actionable - Updated all references in Agents.md and skills.md
249 lines
8.4 KiB
Bash
Executable File
249 lines
8.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ─────────────────────────────────────────────────────────────────────
|
|
# Mobile AI Assets Installer
|
|
#
|
|
# One script to install skills, agents, and instructions.
|
|
# Works both locally (cloned repo) and remotely (curl, no clone).
|
|
#
|
|
# Local: ./assets/setup.sh agents
|
|
# Remote: export ASSETS_BASE_URL="https://..."
|
|
# bash <(curl -fsSL "$ASSETS_BASE_URL/setup.sh") agents
|
|
# ─────────────────────────────────────────────────────────────────────
|
|
|
|
VERSION="1.0.0"
|
|
|
|
# ── Configuration (override with env vars) ───────────────────────────
|
|
ASSETS_BASE_URL="${ASSETS_BASE_URL:-}"
|
|
AGENTS_DIR="${AGENTS_DIR:-$HOME/.copilot/agents}"
|
|
INSTRUCTIONS_DIR="${INSTRUCTIONS_DIR:-./instructions}"
|
|
|
|
# ── Colors ───────────────────────────────────────────────────────────
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m'
|
|
|
|
# ── Helpers ──────────────────────────────────────────────────────────
|
|
info() { printf "${BLUE}▸${NC} %s\n" "$*"; }
|
|
ok() { printf "${GREEN}✓${NC} %s\n" "$*"; }
|
|
warn() { printf "${YELLOW}!${NC} %s\n" "$*"; }
|
|
fail() { printf "${RED}✗${NC} %s\n" "$*" >&2; exit 1; }
|
|
heading() { printf "\n${BOLD}── %s ──${NC}\n" "$*"; }
|
|
|
|
# ── Mode Detection ───────────────────────────────────────────────────
|
|
# Detect if running from a cloned repo or remotely via curl.
|
|
MODE=""
|
|
ASSETS_DIR=""
|
|
|
|
detect_mode() {
|
|
local script_dir
|
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" || script_dir=""
|
|
|
|
if [[ -n "$script_dir" && -f "$script_dir/agents.list" ]]; then
|
|
MODE="local"
|
|
ASSETS_DIR="$script_dir"
|
|
elif [[ -n "$ASSETS_BASE_URL" ]]; then
|
|
MODE="remote"
|
|
else
|
|
fail "Set ASSETS_BASE_URL to run without a clone. Example:
|
|
export ASSETS_BASE_URL=\"https://gitlab.com/org/repo/-/raw/main/assets\"
|
|
bash <(curl -fsSL \"\$ASSETS_BASE_URL/setup.sh\") agents"
|
|
fi
|
|
}
|
|
|
|
# ── Fetch / Download ────────────────────────────────────────────────
|
|
# Read a file from the local clone or download it from the remote URL.
|
|
fetch() {
|
|
local path="$1"
|
|
if [[ "$MODE" == "local" ]]; then
|
|
cat "$ASSETS_DIR/$path"
|
|
else
|
|
curl -fsSL "$ASSETS_BASE_URL/$path"
|
|
fi
|
|
}
|
|
|
|
# Download a file to a destination path.
|
|
download_to() {
|
|
local src="$1" dest="$2"
|
|
mkdir -p "$(dirname "$dest")"
|
|
if [[ "$MODE" == "local" ]]; then
|
|
cp "$ASSETS_DIR/$src" "$dest"
|
|
else
|
|
curl -fsSL "$ASSETS_BASE_URL/$src" -o "$dest"
|
|
fi
|
|
}
|
|
|
|
# ── Commands ─────────────────────────────────────────────────────────
|
|
|
|
# -- skills [platform] ------------------------------------------------
|
|
cmd_skills() {
|
|
local platform="${1:-shared}"
|
|
local manifest="${platform}-skills.yaml"
|
|
|
|
heading "Skills ($platform)"
|
|
|
|
local yaml
|
|
yaml="$(fetch "$manifest")" || fail "Could not fetch $manifest"
|
|
|
|
local installs
|
|
installs=$(echo "$yaml" | sed -n 's/^[[:space:]]*install:[[:space:]]*//p' | sed 's/^"//;s/"$//')
|
|
|
|
if [[ -z "$installs" ]]; then
|
|
warn "No install entries in $manifest — nothing to do."
|
|
return 0
|
|
fi
|
|
|
|
local count=0
|
|
while IFS= read -r entry; do
|
|
[[ -z "$entry" ]] && continue
|
|
read -r -a args <<< "$entry"
|
|
info "npx skills add ${args[*]}"
|
|
npx skills add "${args[@]}"
|
|
count=$((count + 1))
|
|
done <<< "$installs"
|
|
|
|
ok "$count skill(s) installed. Restart your editor if they don't appear."
|
|
}
|
|
|
|
# -- agents ------------------------------------------------------------
|
|
cmd_agents() {
|
|
heading "Agents → $AGENTS_DIR"
|
|
|
|
local list
|
|
list="$(fetch "agents.list")" || fail "Could not fetch agents.list"
|
|
|
|
mkdir -p "$AGENTS_DIR"
|
|
|
|
local count=0
|
|
while IFS= read -r file; do
|
|
[[ -z "$file" || "$file" == \#* ]] && continue
|
|
info "$file"
|
|
download_to "agents/$file" "$AGENTS_DIR/$file"
|
|
count=$((count + 1))
|
|
done <<< "$list"
|
|
|
|
ok "$count agent(s) installed."
|
|
}
|
|
|
|
# -- instructions ------------------------------------------------------
|
|
cmd_instructions() {
|
|
heading "Instructions → $INSTRUCTIONS_DIR"
|
|
|
|
local list
|
|
list="$(fetch "instructions.list")" || fail "Could not fetch instructions.list"
|
|
|
|
mkdir -p "$INSTRUCTIONS_DIR"
|
|
|
|
local count=0
|
|
while IFS= read -r file; do
|
|
[[ -z "$file" || "$file" == \#* ]] && continue
|
|
info "$file"
|
|
download_to "instructions/$file" "$INSTRUCTIONS_DIR/$file"
|
|
count=$((count + 1))
|
|
done <<< "$list"
|
|
|
|
ok "$count instruction(s) installed."
|
|
}
|
|
|
|
# -- all [platform] ----------------------------------------------------
|
|
cmd_all() {
|
|
local platform="${1:-shared}"
|
|
cmd_skills "$platform"
|
|
cmd_agents
|
|
cmd_instructions
|
|
printf "\n"
|
|
ok "All done."
|
|
}
|
|
|
|
# -- update-lists (local only) -----------------------------------------
|
|
# Regenerate agents.list and instructions.list from directory contents.
|
|
cmd_update_lists() {
|
|
if [[ "$MODE" != "local" ]]; then
|
|
fail "update-lists only works from a cloned repo."
|
|
fi
|
|
|
|
heading "Updating manifests"
|
|
|
|
# agents.list
|
|
local agents_dir="$ASSETS_DIR/agents"
|
|
if [[ -d "$agents_dir" ]]; then
|
|
find "$agents_dir" -maxdepth 1 -type f -name '*.agent.md' \
|
|
| xargs -I{} basename {} \
|
|
| sort > "$ASSETS_DIR/agents.list"
|
|
ok "agents.list → $(wc -l < "$ASSETS_DIR/agents.list" | tr -d ' ') file(s)"
|
|
else
|
|
warn "No agents/ directory found — skipping."
|
|
fi
|
|
|
|
# instructions.list
|
|
local instr_dir="$ASSETS_DIR/instructions"
|
|
if [[ -d "$instr_dir" ]]; then
|
|
find "$instr_dir" -maxdepth 1 -type f -name '*.instructions.md' \
|
|
| xargs -I{} basename {} \
|
|
| sort > "$ASSETS_DIR/instructions.list"
|
|
ok "instructions.list → $(wc -l < "$ASSETS_DIR/instructions.list" | tr -d ' ') file(s)"
|
|
else
|
|
warn "No instructions/ directory found — skipping."
|
|
fi
|
|
}
|
|
|
|
# -- help --------------------------------------------------------------
|
|
cmd_help() {
|
|
cat <<EOF
|
|
|
|
${BOLD}Mobile AI Assets Installer${NC} v${VERSION}
|
|
|
|
${BOLD}USAGE${NC}
|
|
setup.sh <command> [platform]
|
|
|
|
${BOLD}COMMANDS${NC}
|
|
skills [platform] Install skills from a curated list
|
|
agents Install all agent prompt files
|
|
instructions Install all instruction files
|
|
all [platform] Install everything at once
|
|
update-lists Regenerate agents.list / instructions.list (local only)
|
|
help Show this message
|
|
|
|
${BOLD}PLATFORMS${NC} (for skills)
|
|
ios iOS-specific skills
|
|
android Android-specific skills
|
|
shared Cross-platform skills (default)
|
|
|
|
${BOLD}EXAMPLES${NC}
|
|
${GREEN}# Cloned repo${NC}
|
|
./assets/setup.sh skills ios
|
|
./assets/setup.sh agents
|
|
./assets/setup.sh all ios
|
|
|
|
${GREEN}# No clone — run directly from the remote repo${NC}
|
|
export ASSETS_BASE_URL="https://gitlab.com/org/repo/-/raw/main/assets"
|
|
bash <(curl -fsSL "\$ASSETS_BASE_URL/setup.sh") skills ios
|
|
bash <(curl -fsSL "\$ASSETS_BASE_URL/setup.sh") agents
|
|
bash <(curl -fsSL "\$ASSETS_BASE_URL/setup.sh") all ios
|
|
|
|
${BOLD}ENVIRONMENT VARIABLES${NC}
|
|
ASSETS_BASE_URL Base URL for remote downloads (required without clone)
|
|
AGENTS_DIR Install location for agents (default: ~/.copilot/agents)
|
|
INSTRUCTIONS_DIR Install location for instructions (default: ./instructions)
|
|
SKILLS_FILE Override the skills YAML path (local mode only)
|
|
|
|
EOF
|
|
}
|
|
|
|
# ── Main ─────────────────────────────────────────────────────────────
|
|
detect_mode
|
|
|
|
case "${1:-help}" in
|
|
skills) cmd_skills "${2:-shared}" ;;
|
|
agents) cmd_agents ;;
|
|
instructions) cmd_instructions ;;
|
|
all) cmd_all "${2:-shared}" ;;
|
|
update-lists) cmd_update_lists ;;
|
|
help|--help|-h) cmd_help ;;
|
|
*) fail "Unknown command: $1. Run 'setup.sh help' for usage." ;;
|
|
esac
|