4.3 Hooks 실전 예제

위험 명령 차단, 자동 린트, 작업 완료 알림 등 바로 사용 가능한 Hooks 예제 6가지를 제공한다. 업데이트: 2026-03-08


핵심 요약

구분내용
📖 정의아래 예제의 스크립트는 .claude/hooks/ 폴더에 저장하고, settings.json에 경로를 등록하면 즉시 동작한다
💡 핵심command hook은 stdin으로 이벤트 JSON을 수신하며, jq로 필요한 값을 추출한다
🎯 대상Hooks를 실무에 즉시 적용하려는 개발자
⚠️ 주의exit 2를 반환하는 차단 hooks는 반드시 테스트 후 적용한다. 잘못 설정하면 정상 작업도 차단된다

문서 탐색


목차

  1. 예제: 위험 명령 차단
  2. 예제: 파일 수정 후 자동 린트
  3. 예제: 작업 완료 알림
  4. 예제: 세션 시작 시 컨텍스트 주입
  5. 예제: MCP 도구 작업 로깅
  6. 예제: 민감 파일 보호 (Prompt Hook)
  7. 어떤 작업에 Hooks를 활용하면 좋을까?

아래 예제는 모두 .claude/hooks/ 폴더에 스크립트를 저장하고, .claude/settings.json에 등록하는 구조다.

.claude/
├── hooks/
│   ├── block-dangerous.sh
│   ├── lint-on-save.sh
│   └── notify.sh
└── settings.json

1. 예제: 위험 명령 차단

사용 시점: rm -rf, DROP TABLE 등 되돌릴 수 없는 명령 실행을 원천 차단하고 싶을 때

#!/bin/bash
# .claude/hooks/block-dangerous.sh
command=$(jq -r '.tool_input.command' < /dev/stdin)
 
if echo "$command" | grep -qE 'rm -rf|DROP TABLE|format C:|> /dev/sda'; then
  echo "Blocked: destructive command detected" >&2
  exit 2
fi
 
exit 0
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/block-dangerous.sh"
          }
        ]
      }
    ]
  }
}

2. 예제: 파일 수정 후 자동 린트

사용 시점: TypeScript/JavaScript 파일을 수정할 때마다 ESLint를 자동 실행하고 싶을 때

#!/bin/bash
# .claude/hooks/lint-on-save.sh
file_path=$(jq -r '.tool_input.file_path // ""' < /dev/stdin)
 
if [[ "$file_path" == *.ts || "$file_path" == *.tsx || "$file_path" == *.js ]]; then
  npx eslint "$file_path" --fix 2>&1
fi
 
exit 0
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/lint-on-save.sh"
          }
        ]
      }
    ]
  }
}

💡 PostToolUse는 이미 파일이 저장된 후 실행되므로 --fix로 자동 수정이 가능하다.


3. 예제: 작업 완료 알림

사용 시점: Claude가 작업을 완료했을 때 다른 화면을 보고 있어도 알림을 받고 싶을 때

#!/bin/bash
# .claude/hooks/notify.sh
 
# macOS 데스크톱 알림
if command -v osascript &> /dev/null; then
  osascript -e 'display notification "Claude Code 작업 완료" with title "Claude Code"'
fi
 
# Slack 웹훅 (선택사항)
if [ -n "$SLACK_WEBHOOK_URL" ]; then
  curl -s -X POST "$SLACK_WEBHOOK_URL" \
    -H 'Content-type: application/json' \
    --data '{"text": "Claude Code 작업이 완료되었습니다."}'
fi
 
exit 0
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/notify.sh",
            "async": true
          }
        ]
      }
    ]
  }
}

💡 알림처럼 결과를 기다릴 필요 없는 작업은 "async": true로 설정해 Claude의 응답 지연을 방지한다.


4. 예제: 세션 시작 시 컨텍스트 주입

사용 시점: 세션을 열 때마다 현재 Git 상태와 최근 변경사항을 Claude에게 자동으로 알려주고 싶을 때

#!/bin/bash
# .claude/hooks/load-context.sh
echo "=== 현재 브랜치 ==="
git branch --show-current 2>/dev/null || echo "(git 저장소 아님)"
 
echo ""
echo "=== 최근 커밋 5개 ==="
git log --oneline -5 2>/dev/null
 
echo ""
echo "=== 수정된 파일 ==="
git diff --name-only 2>/dev/null
 
exit 0
{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/load-context.sh"
          }
        ]
      }
    ]
  }
}

5. 예제: MCP 도구 작업 로깅

사용 시점: MCP 서버를 통한 외부 도구 호출 이력을 감사 로그로 남기고 싶을 때

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__.*",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'echo \"[$(date -Iseconds)] MCP tool: $(echo $STDIN | jq -r .tool_name)\" >> ~/.claude-audit.log'",
            "async": true
          }
        ]
      }
    ]
  }
}

특정 서버만 로깅하려면 매처를 좁힌다:

매처대상
mcp__memory__.*memory 서버 전체
mcp__github__.*GitHub MCP 서버 전체
mcp__.*__write.*모든 서버의 write 관련 도구

6. 예제: 민감 파일 보호 (Prompt Hook)

사용 시점: auth, payment, middleware 경로의 파일 수정 전에 LLM이 판단해 사용자에게 확인을 요청하게 하고 싶을 때

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Check if file_path in $ARGUMENTS contains 'auth', 'payment', or 'middleware'. If yes, respond with JSON: {\"hookSpecificOutput\": {\"hookEventName\": \"PreToolUse\", \"permissionDecision\": \"ask\", \"permissionDecisionReason\": \"민감한 파일 수정은 사용자 확인이 필요합니다\"}}. Otherwise respond with: {\"hookSpecificOutput\": {\"hookEventName\": \"PreToolUse\", \"permissionDecision\": \"allow\"}}",
            "model": "claude-haiku-4"
          }
        ]
      }
    ]
  }
}

⚠️ Prompt Hook은 매 도구 호출마다 LLM을 호출하므로 비용이 발생한다. 단순 패턴 매칭은 command hook + grep이 더 효율적이다.


7. 어떤 작업에 Hooks를 활용하면 좋을까?

작업 유형이벤트예시
보안 차단PreToolUse위험 명령 차단, 민감 파일 보호
코드 품질PostToolUse자동 린트, 포맷팅, 테스트 실행
알림Stop, Notification작업 완료 데스크톱 알림, Slack 전송
컨텍스트SessionStartGit 상태 주입, 환경변수 설정
감사 로깅PreToolUse, PostToolUseMCP 호출 기록, 파일 수정 이력
완료 검증Stop테스트 통과 확인 후 응답 허용

문서 탐색


참고 자료