#!/usr/bin/env bash # # gameservice-fe-agent skill linker # 공통 저장소의 skills/* 를 프로젝트의 .claude/skills/* 로 심볼릭 링크합니다. # 심볼릭 링크이므로 submodule 업데이트 시 skill 도 자동으로 최신 버전이 됩니다. # # 사용법: # bash .claude/common/scripts/link-skills.sh # 모든 skill 링크 # bash .claude/common/scripts/link-skills.sh # 특정 skill 만 # bash .claude/common/scripts/link-skills.sh --dry-run # 실제 링크 없이 미리보기 # bash .claude/common/scripts/link-skills.sh --force # 기존 링크/폴더 덮어쓰기 # bash .claude/common/scripts/link-skills.sh --unlink # 공통 skill 링크 제거 # set -euo pipefail COMMON_PATH=".claude/common" SKILLS_SRC="$COMMON_PATH/skills" SKILLS_DEST=".claude/skills" MODE="safe" # safe | force | dry-run | unlink TARGET="" for arg in "$@"; do case "$arg" in --dry-run) MODE="dry-run" ;; --force) MODE="force" ;; --unlink) MODE="unlink" ;; -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//' exit 0 ;; -*) echo "❌ 알 수 없는 옵션: $arg" >&2 exit 1 ;; *) TARGET="$arg" ;; esac done if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then echo "❌ 현재 디렉토리는 Git 저장소가 아닙니다." >&2 exit 1 fi cd "$(git rev-parse --show-toplevel)" if [[ ! -d "$SKILLS_SRC" ]]; then echo "❌ $SKILLS_SRC 가 없습니다. 먼저 submodule 을 설치/업데이트하세요:" >&2 echo " git submodule update --init --recursive" >&2 exit 1 fi mkdir -p "$SKILLS_DEST" # 링크 대상 결정 declare -a skills if [[ -n "$TARGET" ]]; then if [[ ! -d "$SKILLS_SRC/$TARGET" ]]; then echo "❌ '$TARGET' skill 을 $SKILLS_SRC 에서 찾지 못했습니다." >&2 echo " 사용 가능한 skill:" >&2 ls -1 "$SKILLS_SRC" 2>/dev/null | grep -v '^README' | sed 's/^/ - /' >&2 exit 1 fi skills=("$TARGET") else shopt -s nullglob for dir in "$SKILLS_SRC"/*/; do name="$(basename "$dir")" # README 같은 파일은 이미 걸러지지만 추가 보호 [[ "$name" == "README"* ]] && continue skills+=("$name") done fi if [[ ${#skills[@]} -eq 0 ]]; then echo "ℹ️ 링크할 skill 이 없습니다." exit 0 fi echo "🔗 공통 skill 링크 (mode=$MODE)" echo " source: $SKILLS_SRC" echo " dest: $SKILLS_DEST" echo "" linked=0 skipped=0 removed=0 for name in "${skills[@]}"; do src="../common/skills/$name" # 심볼릭 링크의 상대 경로 (.claude/skills 기준) dest="$SKILLS_DEST/$name" case "$MODE" in unlink) if [[ -L "$dest" ]]; then rm "$dest" echo " 🗑 $dest (링크 제거)" removed=$((removed + 1)) else echo " ⏭ $dest (링크 아님 - 건너뜀)" fi ;; dry-run) if [[ -e "$dest" || -L "$dest" ]]; then echo " ⏭ $dest (이미 존재)" else echo " ➕ ln -s $src $dest" fi ;; force) rm -rf "$dest" ln -s "$src" "$dest" echo " ✅ $dest → $src (덮어씀)" linked=$((linked + 1)) ;; safe) if [[ -L "$dest" ]]; then echo " ⏭ $dest (이미 링크됨)" skipped=$((skipped + 1)) elif [[ -e "$dest" ]]; then echo " ⚠️ $dest (실제 파일/폴더가 존재. --force 로 덮어쓰세요)" skipped=$((skipped + 1)) else ln -s "$src" "$dest" echo " ✅ $dest → $src" linked=$((linked + 1)) fi ;; esac done echo "" case "$MODE" in unlink) echo "🎉 제거 완료: $removed 개 링크 제거됨";; dry-run) echo "🔍 미리보기 완료 (실제 변경 없음)";; *) echo "🎉 완료: 링크 $linked개 / 건너뜀 $skipped개";; esac