#!/usr/bin/env sh # list-skills.sh — 列出本機所有 domain 存取庫的技能,供選技能與稽核用。 # # 用法: list-skills.sh(不吃參數) # # 掃描: {root}/*/skills/*/SKILL.md,讀 frontmatter 的 name 與 description。 # domain 取存取庫目錄名,開頭的 jsc- 會去掉。 # **只列正本 marketplace 上的 domain**:工作區可能還放著不屬於技能組的 # 存取庫(例 shared、persona、code、doc),列出來會讓選技能的流程 # 誤把它們當成技能組的一部分。domain 清單取自 marketplace.json,不寫死。 # 清單只反映本機檔案;要確保檔案齊全請先跑 sync-domains.sh。 # # 根目錄: 預設取本腳本位置的上兩層(meta/tools -> meta -> 根)。 # 用 JSC_PLUGINS_ROOT 覆寫,換機器不必改腳本。 # # 輸出: 一行一個技能,格式 {domain}{name}{description},依 domain、name 排序。 # 結束碼: 0=至少列出一個技能 1=找不到根目錄、讀不到 domain 清單,或一個技能都沒有 set -u HERE=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) ROOT="${JSC_PLUGINS_ROOT:-$(CDPATH= cd -- "$HERE/../.." && pwd)}" [ -d "$ROOT" ] || { echo "找不到 plugins 根目錄:$ROOT(可用 JSC_PLUGINS_ROOT 指定)" >&2; exit 1; } # 正本 domain 清單:優先讀本機任一份 marketplace 副本(每個 repo 都帶同一份)。 mkt="" for cand in "$HERE/../.claude-plugin/marketplace.json" "$ROOT"/*/.claude-plugin/marketplace.json; do [ -f "$cand" ] && { mkt="$cand"; break; } done [ -n "$mkt" ] || { echo "找不到 marketplace.json,無法判定 domain 清單" >&2; exit 1; } DOMAINS=$(sed -n 's/.*"name"[[:space:]]*:[[:space:]]*"jsc-\([a-z0-9-]*\)".*/\1/p' "$mkt" | sort -u) [ -n "$DOMAINS" ] || { echo "marketplace.json 裡沒有 jsc-{domain} 條目:$mkt" >&2; exit 1; } OUT=$( for f in "$ROOT"/*/skills/*/SKILL.md; do [ -f "$f" ] || continue repo=${f#"$ROOT"/} repo=${repo%%/*} domain=${repo#jsc-} # 不在正本清單上的存取庫直接跳過。 printf '%s\n' "$DOMAINS" | grep -qx "$domain" || continue name=$(awk 'BEGIN{f=0} /^---$/{f++; next} f==1 && /^name:/{sub(/^name: */,""); print; exit}' "$f") desc=$(awk 'BEGIN{f=0} /^---$/{f++; next} f==1 && /^description:/{sub(/^description: */,""); print; exit}' "$f") [ -n "$name" ] || continue printf '%s\t%s\t%s\n' "$domain" "$name" "$desc" done | sort -t"$(printf '\t')" -k1,1 -k2,2 ) [ -n "$OUT" ] || { echo "掃不到任何 SKILL.md:$ROOT/*/skills/*/SKILL.md(先跑 sync-domains.sh)" >&2; exit 1; } printf '%s\n' "$OUT" count=$(printf '%s\n' "$OUT" | wc -l | tr -d ' ') echo "共 $count 個技能" >&2 exit 0