#!/usr/bin/env bash # Scan a repository and classify every asset as skill/command/agent/hook/prompt/MCP. # Outputs a markdown table of findings plus a list of cross-reference warnings. # # Usage: inventory.sh set -euo pipefail if [[ $# -lt 1 ]]; then echo "Usage: inventory.sh " >&2 exit 1 fi ROOT="$(cd "$1" && pwd)" if [[ ! -d "$ROOT" ]]; then echo "Error: $ROOT is not a directory" >&2 exit 1 fi # ── classify assets ────────────────────────────────────────────────────────── declare -a ROWS=() declare -a CROSS_REFS=() while IFS= read -r -d '' path; do rel="${path#"$ROOT/"}" name="$(basename "$path")" dir="$(dirname "$rel")" parent="$(basename "$dir")" # Skip hidden dirs except .claude-plugin and .github skip=false IFS='/' read -ra parts <<< "$dir" for part in "${parts[@]}"; do if [[ "$part" == .* && "$part" != ".claude-plugin" && "$part" != ".github" && "$part" != ".agents" ]]; then skip=true; break fi done $skip && continue asset_type="" case "$name" in SKILL.md) asset_type="skill" ;; hooks.json) asset_type="hook" ;; .mcp.json) asset_type="mcp" ;; .lsp.json) asset_type="lsp" ;; plugin.json) asset_type="manifest-plugin" ;; marketplace.json) asset_type="manifest-marketplace" ;; *.agent.md) asset_type="agent-copilot" ;; *.md) if [[ "$parent" == "agents" ]]; then asset_type="agent-claude" elif [[ "$parent" == "commands" ]]; then asset_type="command" elif [[ "$rel" != *"/skills/"* && "$rel" != *"/commands/"* && "$rel" != *"/agents/"* ]]; then asset_type="prompt" fi ;; esac [[ -n "$asset_type" ]] && ROWS+=("$asset_type|$rel") # Check for cross-references in text files case "$name" in *.md|*.json|*.sh) if grep -q '\.\.\/' "$path" 2>/dev/null; then while IFS= read -r line; do lineno="${line%%:*}" content="${line#*:}" CROSS_REFS+=("$rel:$lineno: $content") done < <(grep -n '\.\.\/' "$path" 2>/dev/null | head -20) fi ;; esac done < <(find "$ROOT" -type f -print0 | sort -z) # ── report ─────────────────────────────────────────────────────────────────── echo "# Asset Inventory: $ROOT" echo "" echo "## Assets" echo "" echo "| Type | Path |" echo "|---|---|" for row in "${ROWS[@]+"${ROWS[@]}"}"; do type="${row%%|*}" path="${row#*|}" echo "| \`$type\` | \`$path\` |" done | sort total="${#ROWS[@]}" echo "" echo "**Total: $total assets**" echo "" # Summary by type echo "## Summary by type" echo "" for row in "${ROWS[@]+"${ROWS[@]}"}"; do echo "${row%%|*}" done | sort | uniq -c | while read -r count type; do echo "- \`$type\`: $count" done # Cross-reference warnings echo "" if [[ ${#CROSS_REFS[@]} -gt 0 ]]; then echo "## ⚠️ Cross-reference warnings (${#CROSS_REFS[@]} found)" echo "" echo "These \`../\` references will break after install-time caching:" echo "" for ref in "${CROSS_REFS[@]}"; do echo "- \`$ref\`" done else echo "## Cross-references" echo "" echo "No \`../\` cross-references found. Safe to proceed with plugin boundaries." fi