147 lines
3.7 KiB
Bash
Executable file
147 lines
3.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../" && pwd)"
|
|
repo_skills_dir="$repo_root/.github/skills"
|
|
global_skills_dir="${HOME}/.copilot/skills"
|
|
|
|
source_input="${1:-}"
|
|
scope_input="${2:-}"
|
|
name_input="${3:-}"
|
|
|
|
prompt() {
|
|
local message="$1"
|
|
local default_value="${2:-}"
|
|
local reply
|
|
if [[ -n "$default_value" ]]; then
|
|
read -r -p "${message} [${default_value}]: " reply
|
|
printf '%s\n' "${reply:-$default_value}"
|
|
else
|
|
read -r -p "${message}: " reply
|
|
printf '%s\n' "$reply"
|
|
fi
|
|
}
|
|
|
|
normalize_name() {
|
|
tr '[:upper:] ' '[:lower:]-' | tr -cd 'a-z0-9-'
|
|
}
|
|
|
|
rewrite_github_blob_url() {
|
|
local url="$1"
|
|
if [[ "$url" =~ ^https://github\.com/([^/]+)/([^/]+)/blob/([^/]+)/(.*)$ ]]; then
|
|
printf 'https://raw.githubusercontent.com/%s/%s/%s/%s\n' "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}" "${BASH_REMATCH[4]}"
|
|
else
|
|
printf '%s\n' "$url"
|
|
fi
|
|
}
|
|
|
|
extract_skill_name() {
|
|
local file="$1"
|
|
sed -n 's/^name:[[:space:]]*//p' "$file" | head -n 1
|
|
}
|
|
|
|
download_source() {
|
|
local url="$1"
|
|
local out="$2"
|
|
curl -fsSL "$url" -o "$out"
|
|
}
|
|
|
|
copy_skill_dir() {
|
|
local source_dir="$1"
|
|
local target_dir="$2"
|
|
local include_supporting_files="$3"
|
|
|
|
mkdir -p "$target_dir"
|
|
if [[ "$include_supporting_files" == "yes" ]]; then
|
|
cp -R "$source_dir"/. "$target_dir"/
|
|
else
|
|
cp "$source_dir/SKILL.md" "$target_dir/SKILL.md"
|
|
fi
|
|
}
|
|
|
|
if [[ -z "$source_input" ]]; then
|
|
source_input="$(prompt "Source path, directory, or GitHub SKILL.md URL")"
|
|
fi
|
|
|
|
if [[ -z "$scope_input" ]]; then
|
|
scope_input="$(prompt "Target scope (repo/global)" "repo")"
|
|
fi
|
|
|
|
if [[ "$scope_input" != "repo" && "$scope_input" != "global" ]]; then
|
|
printf 'Invalid scope: %s\n' "$scope_input" >&2
|
|
exit 1
|
|
fi
|
|
|
|
tmpdir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmpdir"' EXIT
|
|
|
|
staging_dir="$tmpdir/staging"
|
|
mkdir -p "$staging_dir"
|
|
|
|
source_kind=""
|
|
source_path="$source_input"
|
|
|
|
if [[ "$source_input" =~ ^https?:// ]]; then
|
|
source_kind="url"
|
|
source_path="$(rewrite_github_blob_url "$source_input")"
|
|
download_source "$source_path" "$staging_dir/SKILL.md"
|
|
elif [[ -d "$source_input" ]]; then
|
|
source_kind="directory"
|
|
skill_file="$source_input/SKILL.md"
|
|
if [[ ! -f "$skill_file" ]]; then
|
|
printf 'Missing SKILL.md in source directory: %s\n' "$source_input" >&2
|
|
exit 1
|
|
fi
|
|
include_supporting_files="$(prompt "Copy supporting files too? (yes/no)" "no")"
|
|
copy_skill_dir "$source_input" "$staging_dir" "$include_supporting_files"
|
|
elif [[ -f "$source_input" ]]; then
|
|
source_kind="file"
|
|
cp "$source_input" "$staging_dir/SKILL.md"
|
|
else
|
|
printf 'Source not found: %s\n' "$source_input" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$staging_dir/SKILL.md" ]]; then
|
|
printf 'No SKILL.md was staged from %s source.\n' "$source_kind" >&2
|
|
exit 1
|
|
fi
|
|
|
|
inferred_name="$(extract_skill_name "$staging_dir/SKILL.md")"
|
|
if [[ -z "$name_input" ]]; then
|
|
name_input="$(prompt "Skill name" "${inferred_name:-skill}")"
|
|
fi
|
|
skill_name="$(printf '%s' "$name_input" | normalize_name)"
|
|
|
|
if [[ -z "$skill_name" ]]; then
|
|
printf 'Skill name cannot be empty.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$scope_input" == "repo" ]]; then
|
|
target_base="$repo_skills_dir"
|
|
else
|
|
target_base="$global_skills_dir"
|
|
fi
|
|
|
|
target_dir="$target_base/$skill_name"
|
|
if [[ -e "$target_dir" ]]; then
|
|
overwrite="$(prompt "Target exists at ${target_dir}. Overwrite? (yes/no)" "no")"
|
|
if [[ "$overwrite" != "yes" ]]; then
|
|
printf 'Aborted.\n'
|
|
exit 1
|
|
fi
|
|
rm -rf "$target_dir"
|
|
fi
|
|
|
|
mkdir -p "$target_dir"
|
|
cp -R "$staging_dir"/. "$target_dir"/
|
|
|
|
if [[ ! -f "$target_dir/SKILL.md" ]]; then
|
|
printf 'Install failed: %s/SKILL.md missing after copy.\n' "$target_dir" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "<$source_input>" >"$target_dir/source.md"
|
|
|
|
printf 'Installed %s skill to %s\n' "$skill_name" "$target_dir"
|