꿀팁 분석 환경 설정

Claude Code 범용 자동 설치 스크립트 만들기

데이터분석뉴비 2026. 3. 2. 23:08
728x90

다양한 코딩툴을 써보지만 claude code가 제일 좋은 것 같다. 

그래서 자주 다양한 문제에 쓰려는데 아래와 같은 문제가 있었다.

 

Docker, WSL, Ubuntu, macOS 어디서든 동일한 개발 환경을 자동 구성하는 스크립트 설계

개발 환경을 맞출 때 항상 이런 문제가 생긴다.

  • Docker에서는 되는데 로컬에서는 안 됨
  • macOS에서 되는데 WSL에서는 깨짐
  • 설정 파일이 중복되고 꼬임
  • PATH 문제
  • 인증이 세션마다 날아감
  • 포맷터/린터 hook이 환경마다 다름

그래서 만든 것이 Claude Code 범용 설치 스크립트다.

 

아직 모든 환경을 커버하진 않지만 기본적으로 docker container로 환경을 만들다보면 계속 설치해줘야 하는데, 그걸 간소화된 버전으로 하나 만들어봤다.

 

여러 환경을 분리해서 하는데 그때마다 설치할 때 불편해서 만들었고, 혹시 다른 방법이 있다면 공유 부탁드립니다.

#!/bin/bash
set -e

# ============================================================
# Claude Code 범용 설치 스크립트
# 지원 환경: Docker, WSL, Ubuntu Server, macOS, 일반 Linux
# ============================================================

# ── 플래그 파싱 ──────────────────────────────────────────────
DRY_RUN=false
QUIET=false
YES_ALL=false
for arg in "$@"; do
    case $arg in
        --dry-run) DRY_RUN=true ;;
        --quiet)   QUIET=true ;;
        --yes|-y)  YES_ALL=true ;;  # 모든 질문에 자동 yes
        --help)
            echo "Usage: bash install_claude.sh [--dry-run] [--quiet] [--yes]"
            echo "  --dry-run  변경 없이 수행할 작업만 출력"
            echo "  --quiet    최소한의 출력만 표시"
            echo "  --yes, -y  모든 선택 질문에 자동으로 yes 응답"
            exit 0
            ;;
    esac
done

# ── 출력 헬퍼 ────────────────────────────────────────────────
log()  { [ "$QUIET" = false ] && echo "$1"; }
info() { echo "ℹ️  $1"; }
ok()   { echo "✅ $1"; }
warn() { echo "⚠️  $1"; }
err()  { echo "❌ $1" >&2; }
run()  {
    if [ "$DRY_RUN" = true ]; then
        echo "  [dry-run] $*"
    else
        eval "$@"
    fi
}

# ── 인터랙티브 질문 헬퍼 ─────────────────────────────────────
# ask "질문" → 0(yes) / 1(no)
# --yes 플래그나 --quiet 모드면 자동 yes
ask() {
    local question="$1"
    local default="${2:-y}"   # 기본값: y

    if [ "$YES_ALL" = true ] || [ "$QUIET" = true ]; then
        log "  → [자동 yes] $question"
        return 0
    fi

    local prompt
    if [ "$default" = "y" ]; then
        prompt="[Y/n]"
    else
        prompt="[y/N]"
    fi

    echo ""
    printf "❓ %s %s: " "$question" "$prompt"
    read -r answer </dev/tty

    case "$answer" in
        [Yy]*) return 0 ;;
        [Nn]*) return 1 ;;
        "")    # 엔터 = 기본값
            [ "$default" = "y" ] && return 0 || return 1
            ;;
        *)     return 1 ;;
    esac
}

# ask_input "질문" "기본값" → 입력값을 REPLY에 저장
ask_input() {
    local question="$1"
    local default="$2"

    if [ "$YES_ALL" = true ] || [ "$QUIET" = true ]; then
        REPLY="$default"
        return
    fi

    echo ""
    if [ -n "$default" ]; then
        printf "📝 %s [기본값: %s]: " "$question" "$default"
    else
        printf "📝 %s: " "$question"
    fi
    read -r REPLY </dev/tty
    [ -z "$REPLY" ] && REPLY="$default"
}

[ "$DRY_RUN" = true ] && info "DRY-RUN 모드: 실제 변경은 일어나지 않습니다."

# ── 1. 환경 자동 감지 ────────────────────────────────────────
log ""
log "🔍 실행 환경 감지 중..."

CURRENT_USER=$(whoami)
HOME_DIR="$HOME"
PROJECT_DIR=$(pwd)
INSTALL_PATH="$HOME_DIR/.local/bin"

IS_DOCKER=false
IS_WSL=false
IS_MACOS=false

[ -f "/.dockerenv" ] && IS_DOCKER=true
grep -qi microsoft /proc/version 2>/dev/null && IS_WSL=true
[ "$(uname)" = "Darwin" ] && IS_MACOS=true

if [ "$IS_DOCKER" = true ]; then
    log "  → 🐳 Docker 컨테이너 환경"
elif [ "$IS_WSL" = true ]; then
    log "  → 🪟 WSL 환경"
elif [ "$IS_MACOS" = true ]; then
    log "  → 🍎 macOS 환경"
else
    log "  → 🐧 Linux 환경"
fi
log "  → 사용자: $CURRENT_USER | 프로젝트: $PROJECT_DIR"

# ── 2. SUDO 안전 처리 ────────────────────────────────────────
if [ "$CURRENT_USER" = "root" ]; then
    SUDO=""
    warn "Root 계정으로 실행 중입니다."
elif command -v sudo &>/dev/null; then
    SUDO="sudo"
else
    err "sudo가 없고 root도 아닙니다. root로 실행하거나 sudo를 설치하세요."
    exit 1
fi

# ── 3. 필수 패키지 설치 ──────────────────────────────────────
log ""
log "📦 필수 도구 설치 중 (curl, git, jq)..."

if [ "$IS_MACOS" = true ]; then
    if ! command -v brew &>/dev/null; then
        err "Homebrew가 없습니다. https://brew.sh 에서 먼저 설치하세요."
        exit 1
    fi
    for pkg in curl git jq; do
        command -v "$pkg" &>/dev/null || run brew install "$pkg"
    done
else
    run $SUDO apt-get update -y -qq
    run $SUDO apt-get install -y -qq curl git unzip ca-certificates jq
fi

# ── 4. Claude Code 설치 ──────────────────────────────────────
log ""
log "🚀 Claude Code 설치 확인 중..."

run mkdir -p "$INSTALL_PATH"
export PATH="$INSTALL_PATH:$PATH"

if ! command -v claude &>/dev/null; then
    log "  → Claude Code를 설치합니다..."
    run curl -fsSL https://claude.ai/install.sh | bash
else
    CLAUDE_VER=$(claude --version 2>/dev/null || echo "버전 확인 불가")
    ok "Claude Code 이미 설치됨: $CLAUDE_VER"
fi

# ── 5. ANTHROPIC_API_KEY 자동 감지 (auth 영속성) ─────────────
log ""
log "🔑 인증 설정 확인 중..."

if [ -f "$PROJECT_DIR/.env" ]; then
    set +e
    eval "$(grep -E '^[A-Z_]+=.+' "$PROJECT_DIR/.env" | sed 's/^/export /')" 2>/dev/null
    set -e
    log "  → .env 파일 로드됨"
fi

if [ -n "$ANTHROPIC_API_KEY" ]; then
    ok "ANTHROPIC_API_KEY 감지됨 — claude login 없이 자동 인증됩니다."
    for rc_file in "$HOME_DIR/.bashrc" "$HOME_DIR/.zshrc"; do
        if [ -f "$rc_file" ] && ! grep -q "ANTHROPIC_API_KEY" "$rc_file"; then
            run "echo 'export ANTHROPIC_API_KEY=\"$ANTHROPIC_API_KEY\"' >> $rc_file"
            log "  → $rc_file 에 ANTHROPIC_API_KEY 등록 완료"
        fi
    done
else
    warn "ANTHROPIC_API_KEY 미설정."
    if ask "지금 ANTHROPIC_API_KEY를 직접 입력하시겠습니까?" "n"; then
        ask_input "ANTHROPIC_API_KEY 값을 입력하세요" ""
        if [ -n "$REPLY" ]; then
            ANTHROPIC_API_KEY="$REPLY"
            export ANTHROPIC_API_KEY
            for rc_file in "$HOME_DIR/.bashrc" "$HOME_DIR/.zshrc"; do
                if [ -f "$rc_file" ] && ! grep -q "ANTHROPIC_API_KEY" "$rc_file"; then
                    run "echo 'export ANTHROPIC_API_KEY=\"$ANTHROPIC_API_KEY\"' >> $rc_file"
                fi
            done
            ok "ANTHROPIC_API_KEY 등록 완료"
        fi
    else
        info "설치 후 'claude login' 또는 .env에 키를 추가하세요."
    fi
fi

# ── 6. 선택적 도구 설치 (인터랙티브) ────────────────────────
log ""
log "🛠️  선택적 도구 설치 단계"

# ── 6-1. black (Python 포맷터) ───────────────────────────────
if ! command -v black &>/dev/null; then
    if ask "Python 코드 포맷터 'black'을 설치하시겠습니까? (자동 포맷 hook에 필요)"; then
        if [ "$IS_MACOS" = true ]; then
            run pip3 install black 2>/dev/null || run brew install black
        else
            run pip3 install black 2>/dev/null || run $SUDO apt-get install -y -qq black
        fi
        ok "black 설치 완료"
    fi
else
    ok "black 이미 설치됨: $(black --version 2>/dev/null | head -1)"
fi

# ── 6-2. ruff (Python linter) ────────────────────────────────
if ! command -v ruff &>/dev/null; then
    if ask "Python linter 'ruff'를 설치하시겠습니까? (flake8/isort 대체)"; then
        run pip3 install ruff 2>/dev/null || true
        ok "ruff 설치 완료"
    fi
else
    ok "ruff 이미 설치됨"
fi

# ── 6-3. Node.js / npx ───────────────────────────────────────
if ! command -v node &>/dev/null; then
    if ask "Node.js(npx/prettier)를 설치하시겠습니까? (JS/TS 자동 포맷에 필요)"; then
        if [ "$IS_MACOS" = true ]; then
            run brew install node
        else
            run curl -fsSL https://deb.nodesource.com/setup_lts.x | $SUDO bash -
            run $SUDO apt-get install -y -qq nodejs
        fi
        ok "Node.js 설치 완료: $(node --version 2>/dev/null)"
    fi
else
    ok "Node.js 이미 설치됨: $(node --version 2>/dev/null)"
fi

# ── 6-4. Git 전역 사용자 설정 ────────────────────────────────
if command -v git &>/dev/null; then
    GIT_USER=$(git config --global user.name 2>/dev/null || echo "")
    GIT_EMAIL=$(git config --global user.email 2>/dev/null || echo "")

    if [ -z "$GIT_USER" ] || [ -z "$GIT_EMAIL" ]; then
        if ask "Git 사용자 정보가 설정되지 않았습니다. 지금 설정하시겠습니까?"; then
            ask_input "Git 사용자 이름" "$(whoami)"
            GIT_NAME="$REPLY"
            ask_input "Git 이메일 주소" ""
            GIT_MAIL="$REPLY"
            [ -n "$GIT_NAME" ] && run git config --global user.name '"'"$GIT_NAME"'"'
            [ -n "$GIT_MAIL" ] && run git config --global user.email '"'"$GIT_MAIL"'"'
            ok "Git 사용자 정보 설정 완료"
        fi
    else
        ok "Git 설정됨: $GIT_USER <$GIT_EMAIL>"
    fi
fi

# ── 6-5. Docker CLI (컨테이너가 아닌 환경에서만) ─────────────
if [ "$IS_DOCKER" = false ] && ! command -v docker &>/dev/null; then
    if ask "Docker CLI를 설치하시겠습니까?"; then
        if [ "$IS_MACOS" = true ]; then
            run brew install --cask docker
        else
            run curl -fsSL https://get.docker.com | $SUDO bash
        fi
        ok "Docker 설치 완료"
    fi
fi

# ── 7. Hook 커맨드 동적 빌드 (설치된 도구 기반) ──────────────
log ""
log "🪝 자동화 Hook 빌드 중..."

HOOK_CMD_PARTS=()
if command -v black &>/dev/null; then
    HOOK_CMD_PARTS+=('[[ "$file_path" == *.py ]] && black "$file_path" 2>/dev/null || true')
    log "  → Python(black) hook 등록"
else
    warn "black 없음 — Python 자동 포맷 hook 제외"
fi

if command -v npx &>/dev/null; then
    HOOK_CMD_PARTS+=('[ -f "package.json" ] && npx prettier --write "$file_path" 2>/dev/null || true')
    log "  → JS/TS(prettier) hook 등록"
else
    warn "npx 없음 — JS 자동 포맷 hook 제외"
fi

# 배열 요소를 '; ' 로 결합
HOOK_CMD=""
for part in "${HOOK_CMD_PARTS[@]}"; do
    [ -n "$HOOK_CMD" ] && HOOK_CMD="$HOOK_CMD; "
    HOOK_CMD="$HOOK_CMD$part"
done

# ── 8. settings.json 빌드 및 적용 ────────────────────────────
log ""
log "⚙️  Claude 설정 구성 중..."

# jq로 안전하게 JSON 빌드 (특수문자 이스케이프 자동 처리)
BASE_SETTINGS='{
  "enabledPlugins": {"*": true},
  "maxThinkingTokens": 8000,
  "autoUpdatesChannel": "stable",
  "theme": "dark"
}'

if [ -n "$HOOK_CMD" ]; then
    DEFAULT_SETTINGS=$(echo "$BASE_SETTINGS" | jq \
        --arg cmd "$HOOK_CMD" \
        '. + {hooks: {PostToolUse: [{matcher: "Write|Edit", hooks: [{type: "command", command: $cmd}]}]}}')
    log "  → hook 포함 settings.json 빌드 완료"
else
    DEFAULT_SETTINGS="$BASE_SETTINGS"
    warn "등록된 포맷터 없음 — hooks 설정 생략"
fi

setup_config() {
    local TARGET_DIR=$1
    local CONFIG_FILE="$TARGET_DIR/settings.json"
    local BACKUP_FILE="$CONFIG_FILE.bak.$(date +%Y%m%d_%H%M%S)"

    run mkdir -p "$TARGET_DIR"

    if [ "$DRY_RUN" = true ]; then
        echo "  [dry-run] setup_config: $CONFIG_FILE 생성/병합 예정"
        return
    fi

    if [ ! -s "$CONFIG_FILE" ] || ! jq . "$CONFIG_FILE" >/dev/null 2>&1; then
        echo "$DEFAULT_SETTINGS" > "$CONFIG_FILE"
        ok "settings.json 생성: $TARGET_DIR"
    else
        cp "$CONFIG_FILE" "$BACKUP_FILE"
        TEMP_FILE=$(mktemp)
        jq -s '.[0] * .[1]' "$CONFIG_FILE" <(echo "$DEFAULT_SETTINGS") > "$TEMP_FILE"
        mv "$TEMP_FILE" "$CONFIG_FILE"
        ok "settings.json 병합 완료 (백업: $BACKUP_FILE)"
    fi
}

setup_config "$PROJECT_DIR/.claude"

# ── 9. ~/.claude → 프로젝트 디렉토리 심볼릭 링크 ─────────────
log ""
log "🔗 ~/.claude 심볼릭 링크 구성 중..."

GLOBAL_CLAUDE="$HOME_DIR/.claude"
PROJECT_CLAUDE="$PROJECT_DIR/.claude"

if [ "$DRY_RUN" = true ]; then
    echo "  [dry-run] $GLOBAL_CLAUDE → $PROJECT_CLAUDE 심볼릭 링크 생성 예정"
elif [ -L "$GLOBAL_CLAUDE" ]; then
    CURRENT_LINK=$(readlink "$GLOBAL_CLAUDE")
    if [ "$CURRENT_LINK" = "$PROJECT_CLAUDE" ]; then
        ok "~/.claude 이미 올바르게 링크됨 → $PROJECT_CLAUDE"
    else
        warn "~/.claude 가 다른 경로를 가리킵니다: $CURRENT_LINK"
        if ask "~/.claude 링크를 현재 프로젝트로 변경하시겠습니까?"; then
            rm "$GLOBAL_CLAUDE"
            ln -s "$PROJECT_CLAUDE" "$GLOBAL_CLAUDE"
            ok "~/.claude → $PROJECT_CLAUDE 로 링크 변경 완료"
        fi
    fi
elif [ -d "$GLOBAL_CLAUDE" ]; then
    BACKUP_CLAUDE="$GLOBAL_CLAUDE.bak.$(date +%Y%m%d_%H%M%S)"
    mv "$GLOBAL_CLAUDE" "$BACKUP_CLAUDE"
    ln -s "$PROJECT_CLAUDE" "$GLOBAL_CLAUDE"
    ok "~/.claude 백업 ($BACKUP_CLAUDE) 후 심볼릭 링크 생성 → $PROJECT_CLAUDE"
else
    ln -s "$PROJECT_CLAUDE" "$GLOBAL_CLAUDE"
    ok "~/.claude → $PROJECT_CLAUDE 심볼릭 링크 생성"
fi

# ── 10. settings.local.json 자동 생성 ────────────────────────
LOCAL_SETTINGS_FILE="$PROJECT_DIR/.claude/settings.local.json"
if [ ! -f "$LOCAL_SETTINGS_FILE" ]; then
    if [ "$DRY_RUN" = true ]; then
        echo "  [dry-run] settings.local.json 생성 예정"
    else
        cat <<LOCALEOF > "$LOCAL_SETTINGS_FILE"
{
  "permissions": {
    "allow": [
      "Bash(python3*)",
      "Bash(pip*)",
      "Bash(git*)",
      "Bash(black*)",
      "Bash(ruff*)"
    ]
  }
}
LOCALEOF
        ok "settings.local.json 생성 완료"
    fi
else
    log "  → settings.local.json 이미 존재, 건너뜀"
fi

# ── 11. .claudeignore 생성 ───────────────────────────────────
if [ ! -f ".claudeignore" ]; then
    run cat <<'IGNEOF' > ".claudeignore"
.git/
.cursor/
.vscode/
.claude/
*.log
.env
dist/
build/
node_modules/
__pycache__/
.venv/
*.pyc
*.pyo
IGNEOF
    ok ".claudeignore 생성 완료"
fi

# ── 12. CLAUDE.md 생성 / USER_CLAUDE_GUIDE.md 참조 추가 ──────
if [ ! -f "CLAUDE.md" ]; then
    IS_PYTHON=false
    IS_JS=false
    { [ -f "requirements.txt" ] || [ -f "pyproject.toml" ] || [ -d "venv" ]; } && IS_PYTHON=true
    { [ -f "package.json" ] || [ -f "tsconfig.json" ]; } && IS_JS=true
    ENV_NAME="General"
    [ "$IS_PYTHON" = true ] && ENV_NAME="Python"
    [ "$IS_JS" = true ] && ENV_NAME="JS/TS"

    if [ "$DRY_RUN" = true ]; then
        echo "  [dry-run] CLAUDE.md ($ENV_NAME) 생성 예정"
    else
        cat <<MDEOF > "CLAUDE.md"
# Project Guidelines ($ENV_NAME)

## ⚠️ 작업 시작 전 필수 확인
**모든 작업을 시작하기 전에 반드시 \`USER_CLAUDE_GUIDE.md\`를 먼저 읽으세요.**
- 작업 계획이 필요한 경우 \`USER_CLAUDE_GUIDE.md\`의 "작업 계획" 섹션에 직접 작성하세요.
- 계획 수행 시에도 해당 파일을 읽고 그 내용을 기준으로 작업하세요.
- 계획 완료 후 해당 섹션에 완료 여부를 표시하세요.

@USER_CLAUDE_GUIDE.md

## 💡 실전 꿀팁 (Pro-Tips)
- **플랜 모드**: 대규모 작업 시 \`Shift+Tab\`을 눌러 전략을 먼저 수립하세요.
- **토큰 관리**: 불필요한 대화가 길어지면 \`/compact\`를 입력해 메모리를 정리하세요.
$( [ "$IS_PYTHON" = true ] && printf '- **자동 포맷팅**: 파일 수정 시 Black이 자동 실행됩니다.' )
$( [ "$IS_JS" = true ] && printf '- **자동 포맷팅**: 파일 수정 시 Prettier가 자동 실행됩니다.' )

## Commands
$( [ "$IS_PYTHON" = true ] && printf '- Test: python test_xxx.py\n- Lint: black . && ruff check .' )
$( [ "$IS_JS" = true ] && printf '- Build: npm run build\n- Test: npm test\n- Lint: npm run lint' )

## Standards
- Follow modular design.
- Always check the .claudeignore before broad file reads.
MDEOF
        ok "CLAUDE.md 생성 완료 ($ENV_NAME)"
    fi
else
    # CLAUDE.md가 이미 있으면 USER_CLAUDE_GUIDE.md 참조 블록만 추가 (중복 방지)
    if ! grep -q "USER_CLAUDE_GUIDE.md" "CLAUDE.md"; then
        if ask "기존 CLAUDE.md에 USER_CLAUDE_GUIDE.md 참조를 추가하시겠습니까?"; then
            if [ "$DRY_RUN" = true ]; then
                echo "  [dry-run] CLAUDE.md 상단에 USER_CLAUDE_GUIDE.md 참조 추가 예정"
            else
                # 파일 상단에 삽입 (기존 내용 앞에)
                EXISTING=$(cat "CLAUDE.md")
                cat <<PREPENDEOF > "CLAUDE.md"
## ⚠️ 작업 시작 전 필수 확인
**모든 작업을 시작하기 전에 반드시 \`USER_CLAUDE_GUIDE.md\`를 먼저 읽으세요.**
- 작업 계획이 필요한 경우 \`USER_CLAUDE_GUIDE.md\`의 "작업 계획" 섹션에 직접 작성하세요.
- 계획 수행 시에도 해당 파일을 읽고 그 내용을 기준으로 작업하세요.
- 계획 완료 후 해당 섹션에 완료 여부를 표시하세요.

@USER_CLAUDE_GUIDE.md

$EXISTING
PREPENDEOF
                ok "CLAUDE.md에 USER_CLAUDE_GUIDE.md 참조 추가 완료"
            fi
        fi
    else
        log "  → CLAUDE.md에 이미 USER_CLAUDE_GUIDE.md 참조 존재, 건너뜀"
    fi
fi

# ── 12-1. USER_CLAUDE_GUIDE.md 템플릿 생성 ───────────────────
if ask "USER_CLAUDE_GUIDE.md 템플릿을 생성하시겠습니까? (프로젝트 가이드 & 작업 이력 관리용)"; then
    if [ ! -f "USER_CLAUDE_GUIDE.md" ]; then
        if [ "$DRY_RUN" = true ]; then
            echo "  [dry-run] USER_CLAUDE_GUIDE.md 생성 예정"
        else
            cat <<'GUIDEOF' > "USER_CLAUDE_GUIDE.md"
# 프로젝트 사용자 가이드

> 이 파일은 Claude가 매 세션마다 읽는 프로젝트 가이드입니다.
> 직접 편집하여 프로젝트 규칙, 컨벤션, 주의사항을 기록하세요.

## 프로젝트 개요
<!-- 프로젝트 목적과 핵심 개념을 간략히 적으세요 -->


## 아키텍처 & 주요 파일
<!-- 핵심 파일/폴더 구조와 역할을 적으세요 -->


## 작업 컨벤션
<!-- 코딩 스타일, 네이밍 규칙, 브랜치 전략 등 -->


## 주의사항 & 금지 사항
<!-- Claude가 절대 해서는 안 되는 것들 -->
- 운영 DB에 직접 쓰기 금지
- .env 파일 내용 출력 금지


## 작업 계획 (Plans)
<!-- Claude는 작업 계획이 필요할 때 이 섹션에 직접 작성하고, 수행 시 여기를 읽고 진행합니다 -->


## 진행 중인 작업 & 메모
<!-- 현재 진행 중이거나 보류 중인 작업을 직접 기록하세요 -->


GUIDEOF
            ok "USER_CLAUDE_GUIDE.md 생성 완료"
        fi
    else
        log "  → USER_CLAUDE_GUIDE.md 이미 존재, 건너뜀"
    fi

fi

# ── 13. PATH 영구 등록 ───────────────────────────────────────
for rc_file in "$HOME_DIR/.bashrc" "$HOME_DIR/.zshrc"; do
    if [ -f "$rc_file" ] && ! grep -q "$INSTALL_PATH" "$rc_file"; then
        run "echo 'export PATH=\"$INSTALL_PATH:\$PATH\"' >> $rc_file"
        log "  → PATH 등록: $rc_file"
    fi
done

# Docker 환경: /etc/profile.d 에도 등록 (컨테이너 재시작 대응)
if [ "$IS_DOCKER" = true ] && [ -d "/etc/profile.d" ]; then
    if [ "$DRY_RUN" = true ]; then
        echo "  [dry-run] /etc/profile.d/claude.sh 생성 예정"
    else
        cat <<PROFEOF > /etc/profile.d/claude.sh
export PATH="$INSTALL_PATH:\$PATH"
$( [ -n "$ANTHROPIC_API_KEY" ] && echo "export ANTHROPIC_API_KEY=\"$ANTHROPIC_API_KEY\"" )
PROFEOF
        ok "/etc/profile.d/claude.sh 등록 (컨테이너 재시작 대응)"
    fi
fi

# ── 14. 설치 후 검증 ─────────────────────────────────────────
log ""
log "🔍 설치 검증 중..."

if [ "$DRY_RUN" = false ]; then
    if command -v claude &>/dev/null; then
        CLAUDE_VER=$(claude --version 2>/dev/null || echo "버전 확인 불가")
        ok "Claude 실행 확인: $CLAUDE_VER"
    else
        warn "claude 명령어를 찾을 수 없습니다. 터미널 재시작 후 확인하세요."
        warn "수동 확인: export PATH=\"$INSTALL_PATH:\$PATH\" && claude --version"
    fi

    if [ -L "$HOME_DIR/.claude" ]; then
        LINK_TARGET=$(readlink "$HOME_DIR/.claude")
        ok "~/.claude → $LINK_TARGET (심볼릭 링크 정상)"
    fi
fi

# ── 완료 ─────────────────────────────────────────────────────
echo ""
echo "=================================================="
if [ "$DRY_RUN" = true ]; then
    echo "✅ DRY-RUN 완료 — 실제 변경 없음"
    echo "   실제 적용하려면: bash install_claude.sh"
else
    echo "🎉 모든 설정이 완료되었습니다!"
    echo "📍 프로젝트: $PROJECT_DIR"
    echo "🔗 글로벌 설정: ~/.claude → $PROJECT_DIR/.claude"
    if [ -z "$ANTHROPIC_API_KEY" ]; then
        echo "🔑 다음 단계: source ~/.bashrc && claude login"
    else
        echo "🔑 인증: ANTHROPIC_API_KEY 자동 적용됨"
        echo "🚀 시작: source ~/.bashrc && claude"
    fi
fi
echo "=================================================="