7.1 KiB
훅 (Hooks)
Claude가 도구를 사용하거나 세션 마일스톤에 도달할 때 셸 커맨드, HTTP 요청, 프롬프트를 자동으로 실행합니다.
훅은 Claude Code의 도구 라이프사이클에 자동화를 연결합니다. Claude가 파일을 읽거나, bash 커맨드를 실행하거나, 응답을 완료할 때 설정된 훅이 자동으로 실행됩니다. 코드 스타일 강제, 테스트 실행, 도구 사용 로깅, Claude가 할 수 있는 작업 제어에 훅을 사용하세요.
훅 작동 방식
훅은 특정 이벤트에 바인딩된 커맨드(셸 스크립트, HTTP 엔드포인트, LLM 프롬프트)입니다. 이벤트가 발생하면 Claude Code가 매칭된 모든 훅을 실행하고 종료 코드와 출력을 사용해 다음 동작을 결정합니다.
각 훅의 입력은 무슨 일이 일어났는지 설명하는 JSON 객체입니다.
종료 코드 의미:
| 종료 코드 | 의미 |
|---|---|
0 |
성공. stdout이 Claude에게 표시될 수 있음(이벤트별 다름) |
2 |
차단 또는 주입. stderr를 Claude에게 표시하고(PreToolUse) 도구 호출 방지 |
| 기타 | stderr를 사용자에게만 표시; 실행 계속 |
훅 이벤트
| 이벤트 | 설명 |
|---|---|
| PreToolUse | 모든 도구 호출 직전에 발생. 도구 입력 검사, 승인/차단, 입력 수정 가능. 종료코드 2 → 도구 호출 차단 |
| PostToolUse | 모든 성공적인 도구 호출 후 발생. 도구 출력 관찰 또는 Claude가 처리할 컨텍스트 주입 가능 |
| PostToolUseFailure | 도구 호출이 오류로 종료될 때 발생 |
| Stop | Claude가 응답을 종료하기 직전에 발생. 종료코드 2 → stderr를 Claude에게 표시하고 대화 계속 |
| SubagentStop | 서브에이전트가 결론 내리기 직전에 발생 (Stop과 동일하지만 서브에이전트용) |
| SubagentStart | 새 서브에이전트가 시작될 때 발생 |
| SessionStart | 세션 시작, 재개, /clear, /compact 후에 발생 |
| UserPromptSubmit | 사용자가 프롬프트를 제출할 때 발생. 종료코드 2 → 프롬프트 차단 |
| PreCompact | 컨텍스트 컴팩션 시작 직전에 발생. 종료코드 2 → 컴팩션 차단 |
| PostCompact | 컴팩션 완료 후 발생 |
| Setup | 저장소 초기화(init) 및 주기적 유지보수(maintenance) 시 발생 |
| PermissionRequest | 권한 다이얼로그가 표시될 때 발생. 프로그래밍 방식으로 승인/거부 가능 |
| PermissionDenied | 도구 호출이 거부된 후 발생 |
| Notification | 권한 프롬프트, 유휴 프롬프트, 인증 성공 등의 알림 시 발생 |
| CwdChanged | 작업 디렉토리 변경 후 발생 |
| FileChanged | 감시 중인 파일이 변경될 때 발생 |
| SessionEnd | 세션이 종료될 때 발생 |
| ConfigChange | 세션 중 설정 파일이 변경될 때 발생 |
훅 설정
세션 내에서 /hooks를 실행해 훅 설정 메뉴를 열 수 있습니다. 훅은 설정 파일의 hooks 필드에 저장됩니다:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "prettier --write $CLAUDE_FILE_PATH"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "echo 'Session complete' >> ~/.claude-log.txt"
}
]
}
]
}
}
각 이벤트는 매처 객체 배열에 매핑됩니다:
matcher(선택사항) — 이벤트의 매칭 가능한 필드와 매칭되는 문자열 패턴hooks— 매처가 일치할 때 실행할 훅 커맨드 배열
빈 또는 없는 matcher는 해당 이벤트의 모든 입력과 일치합니다.
훅 커맨드 타입
셸 커맨드 (type: "command"):
{
"type": "command",
"command": "npm test",
"timeout": 60,
"shell": "bash",
"async": false
}
필드:
command— 실행할 셸 커맨드 (필수)timeout— 타임아웃(초)shell—"bash"(기본) 또는"powershell"async— 백그라운드에서 실행 (출력 무시)once— 한 번 실행 후 자동으로 훅 제거if— 조건부로 훅 건너뛰기 위한 권한 규칙 구문statusMessage— 훅 실행 중 스피너에 표시되는 커스텀 메시지
HTTP 요청 (type: "http"):
{
"type": "http",
"url": "https://hooks.example.com/claude-event",
"headers": {
"Authorization": "Bearer $MY_TOKEN"
},
"allowedEnvVars": ["MY_TOKEN"],
"timeout": 10
}
Claude Code가 훅 입력 JSON을 URL에 POST합니다.
LLM 프롬프트 (type: "prompt"):
{
"type": "prompt",
"prompt": "이 bash 커맨드에 보안 문제가 있는지 확인하세요: $ARGUMENTS. 문제가 있으면 설명하고 코드 2로 종료하세요.",
"model": "claude-haiku-4-5",
"timeout": 30
}
에이전트 훅 (type: "agent"):
{
"type": "agent",
"prompt": "단위 테스트가 실행되고 통과했는지 확인하세요.",
"timeout": 60
}
도구 접근 권한이 있는 짧은 에이전틱 루프로 실행됩니다. 파일을 읽거나 커맨드를 실행해야 하는 검증 작업에 유용합니다.
훅 예시
파일 편집 후 자동 포맷:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
}
]
}
]
}
}
위험한 커맨드 차단:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "if echo \"$CLAUDE_TOOL_INPUT\" | grep -q 'rm -rf'; then echo '차단: rm -rf는 허용되지 않습니다' >&2; exit 2; fi"
}
]
}
]
}
}
모든 도구 사용 로깅:
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) $CLAUDE_TOOL_NAME\" >> ~/.claude-tool-log.txt",
"async": true
}
]
}
]
}
}
디렉토리 변경 시 환경 변수 주입:
{
"hooks": {
"CwdChanged": [
{
"hooks": [
{
"type": "command",
"command": "if [ -f .envrc ]; then grep '^export ' .envrc >> \"$CLAUDE_ENV_FILE\"; fi"
}
]
}
]
}
}
훅 vs 스킬
| 기능 | 훅 | 스킬 |
|---|---|---|
| 실행 시점 | 도구 이벤트에 자동 | Claude나 사용자가 /skill-name으로 명시적 호출 |
| 목적 | 부작용, 게이팅, 관찰 | 온디맨드 워크플로우와 기능 |
| 설정 | 설정 JSON | .claude/skills/의 마크다운 파일 |
자동으로 발생해야 하는 것(포맷팅, 로깅, 강제)에는 훅을 사용하고, 의도적으로 트리거하려는 반복 가능한 워크플로우에는 스킬을 사용하세요.