Compare commits

...

2 commits

Author SHA1 Message Date
78a3104bae
also copy sibling files 2026-04-07 16:48:47 +02:00
014c3c3016
add source reference 2026-04-07 16:22:55 +02:00
2 changed files with 65 additions and 5 deletions

View file

@ -22,7 +22,7 @@ Use this skill to install another skill from a local path, a directory, or a Git
- Local `SKILL.md` file
- Local skill directory
- GitHub blob URL to a `SKILL.md` file
- GitHub blob URL to a `SKILL.md` file, including sibling supporting files
## Install script
@ -50,5 +50,7 @@ The installer prompts for:
1. Source path or URL
2. Target scope: repo or global
3. Skill name if it cannot be inferred
4. Whether to copy supporting files
4. Whether to copy supporting files for a local directory source
5. Whether to overwrite an existing install
For GitHub blob URLs, supporting files in the same skill directory are downloaded automatically.

View file

@ -35,6 +35,16 @@ rewrite_github_blob_url() {
fi
}
parse_github_blob_url() {
local url="$1"
if [[ "$url" =~ ^https://github\.com/([^/]+)/([^/]+)/blob/([^/]+)/(.*)$ ]]; then
printf '%s\t%s\t%s\t%s\n' "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}" "${BASH_REMATCH[4]}"
return 0
fi
return 1
}
extract_skill_name() {
local file="$1"
sed -n 's/^name:[[:space:]]*//p' "$file" | head -n 1
@ -46,6 +56,45 @@ download_source() {
curl -fsSL "$url" -o "$out"
}
list_github_contents() {
local owner="$1"
local repo="$2"
local ref="$3"
local path="$4"
curl -fsSL -H 'Accept: application/vnd.github+json' \
"https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${ref}" | \
python3 -c $'import json,sys\ndata = json.load(sys.stdin)\nitems = data if isinstance(data, list) else [data]\nfor item in items:\n print("%s\\t%s\\t%s" % (item.get("type", ""), item.get("path", ""), item.get("download_url", "")))'
}
download_github_contents() {
local owner="$1"
local repo="$2"
local ref="$3"
local path="$4"
local target_root="$5"
while IFS=$'\t' read -r item_type item_path download_url; do
[[ -z "$item_type" ]] && continue
local relative_path="${item_path#${path}/}"
local destination_path="$target_root/$relative_path"
case "$item_type" in
dir)
download_github_contents "$owner" "$repo" "$ref" "$item_path" "$target_root"
;;
file)
mkdir -p "$(dirname "$destination_path")"
download_source "$download_url" "$destination_path"
;;
*)
printf 'Skipping unsupported GitHub content type: %s (%s)\n' "$item_type" "$item_path" >&2
;;
esac
done < <(list_github_contents "$owner" "$repo" "$ref" "$path")
}
copy_skill_dir() {
local source_dir="$1"
local target_dir="$2"
@ -82,9 +131,16 @@ 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"
if github_blob_parts="$(parse_github_blob_url "$source_input")"; then
source_kind="github-blob-url"
IFS=$'\t' read -r github_owner github_repo github_ref github_path <<<"$github_blob_parts"
github_skill_dir="$(dirname "$github_path")"
download_github_contents "$github_owner" "$github_repo" "$github_ref" "$github_skill_dir" "$staging_dir"
else
source_kind="url"
source_path="$(rewrite_github_blob_url "$source_input")"
download_source "$source_path" "$staging_dir/SKILL.md"
fi
elif [[ -d "$source_input" ]]; then
source_kind="directory"
skill_file="$source_input/SKILL.md"
@ -142,4 +198,6 @@ if [[ ! -f "$target_dir/SKILL.md" ]]; then
exit 1
fi
echo "<$source_input>" >"$target_dir/source.md"
printf 'Installed %s skill to %s\n' "$skill_name" "$target_dir"