심화 12분

Hook으로 자동화 워크플로 만들기

업데이트

Hook이 가능하게 하는 것

Hook은 코드를 수정하지 않고 Claude Code의 동작에 자동화 레이어를 덧붙이는 방법입니다. 대표적인 활용:

  • 파일 저장 후 자동 포매팅
  • 위험한 명령 차단 (rm -rf, git push --force)
  • 세션 종료 시 자동 보고
  • 컴팩션 전 중요 정보 보존
  • LLM에게 “이 변경 안전한가?” 물어보고 차단

설정 위치

파일범위
~/.claude/settings.json사용자 전체
.claude/settings.json프로젝트 (git 커밋)
.claude/settings.local.json개인 로컬 (gitignore)

기본 구조

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; prettier --write \"$f\"; } 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}

자주 쓰는 이벤트

이벤트시점사용 사례
PreToolUse도구 실행 전위험 명령 차단, 권한 검증
PostToolUse도구 실행 후자동 포매팅, 테스트 자동 실행
PostToolUseFailure도구 실패 후에러 로깅, 알림
UserPromptSubmit사용자 입력 시프롬프트 분석, 컨텍스트 주입
Stop세션 종료보고서 생성, 정리 작업
PreCompact컴팩션 직전중요 정보 별도 저장
SessionStart세션 시작환경 점검, 초기 메시지

세 가지 훅 타입

1. command — 셸 명령 실행

{
  "type": "command",
  "command": "jq -r '.tool_input.command' >> ~/.claude/bash-log.txt"
}

stdin으로 이벤트 JSON을 받습니다. jq로 필요한 필드를 추출해 사용합니다.

2. prompt — LLM에 질문

{
  "type": "prompt",
  "prompt": "이 명령이 시스템에 위험한 변경을 가하는지 판단: $ARGUMENTS"
}

LLM이 응답으로 차단·허용을 결정합니다. 작은 모델로 빠르게 처리됩니다.

3. agent — 에이전트 실행

{
  "type": "agent",
  "prompt": "변경된 파일에 대해 단위 테스트가 함께 추가됐는지 검증"
}

복잡한 검증이 필요할 때 사용합니다. 토큰 비용이 더 큽니다.

실전 예: 위험 명령 차단

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "다음 셸 명령이 데이터를 영구 삭제하거나 되돌리기 어려운 변경을 하는지 판단해서 'block' 또는 'allow' 중 하나로 답: $ARGUMENTS"
          }
        ]
      }
    ]
  }
}

실전 예: 파일 저장 후 자동 포매팅

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; case \"$f\" in *.ts|*.tsx|*.js|*.jsx|*.json|*.md) prettier --write \"$f\";; esac; } 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}

확장자별로 적용 도구를 다르게 할 수 있습니다.

실전 예: 세션 종료 시 자동 보고

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "echo '{\"systemMessage\": \"세션 종료 — 변경된 파일 확인 권장\"}'"
          }
        ]
      }
    ]
  }
}

훅이 JSON을 출력하면 사용자에게 메시지가 표시됩니다.

디버깅 절차

  1. JSON 문법jq . settings.json으로 유효성 확인
  2. 매처 패턴Write|Edit처럼 정확한 도구명 사용
  3. 명령 직접 테스트echo '{"tool_input":{"file_path":"test.ts"}}' | <훅 명령>
  4. 재시작 — 새 훅은 Claude Code 재시작 또는 /hooks 한 번 열기 필요
  5. debug 모드claude --debug로 훅 실행 로그 확인

hookify 도구 활용

hookify는 자연어로 훅을 생성해주는 플러그인입니다. 직접 JSON을 작성하기 부담스러우면 hookify로 초안을 만들고 settings.json에 적용하는 방식이 빠릅니다.

다음 단계

자주 묻는 질문

Hook은 무엇인가요?

특정 이벤트(도구 호출 전후, 세션 시작·종료, 컴팩션 등)에 반응해 자동 실행되는 셸 명령·LLM 프롬프트입니다. 코드를 변경하지 않고 Claude Code 동작에 자동화 레이어를 덧붙이는 방법입니다.

어디에 설정하나요?

`~/.claude/settings.json`(사용자 전체), `.claude/settings.json`(프로젝트 공유), `.claude/settings.local.json`(개인용 로컬)의 `hooks` 필드에 정의합니다. 각 이벤트에 매처와 명령을 연결합니다.

어떤 이벤트에 훅을 걸 수 있나요?

PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, Stop, SessionStart, SessionEnd, PreCompact, PostCompact 등이 있습니다. 도구 사용 전후 자동화는 PreToolUse·PostToolUse가 가장 자주 쓰입니다.

코드 실행 없이 LLM으로 검증하는 훅도 가능한가요?

네. 훅 type을 `prompt`로 지정하면 LLM에 검증 질문을 보내 결과로 차단·허용을 결정할 수 있습니다. 또는 `agent` 타입으로 작은 에이전트를 실행해 더 복잡한 검증도 가능합니다.

훅이 동작하지 않을 때는 어떻게 디버깅하나요?

settings.json JSON 문법 오류, 매처 패턴 불일치가 가장 흔한 원인입니다. `claude --debug`로 훅 실행 로그를 보고, `jq -e`로 JSON 구조를 검증합니다. 새 훅을 추가하면 Claude Code를 재시작하거나 `/hooks`를 한 번 열어야 watcher가 인식합니다.