Claude Code 실행 주기의 특정 시점에 자동으로 실행되는 사용자 정의 명령어.
LLM이 "할 수도 있고 안 할 수도 있는" 게 아니라, 조건이 맞으면 무조건 실행됨.
Hook 이벤트 종류
| 이벤트 | 설명 |
|---|
PreToolUse | 도구 실행 전 (차단 가능) |
PostToolUse | 도구 실행 후 |
PostToolUseFailure | 도구 실행 실패 후 |
PermissionRequest | 권한 요청 시 (자동 승인/거부 가능) |
UserPromptSubmit | 프롬프트 제출 시 |
Notification | 알림 발생 시 |
SessionStart | 세션 시작/재개 시 |
SessionEnd | 세션 종료 시 |
Stop | Claude 응답 완료 시 |
StopFailure | API 오류로 턴 종료 시 |
PreCompact | 컨텍스트 압축 전 |
PostCompact | 컨텍스트 압축 후 |
SubagentStart | Subagent 생성 시 |
SubagentStop | Subagent 완료 시 |
WorktreeCreate | Worktree 생성 시 |
WorktreeRemove | Worktree 삭제 시 |
ConfigChange | 설정 파일 변경 시 |
설정 위치
~/.claude/settings.json # 전역 (모든 프로젝트)
.claude/settings.json # 프로젝트 공유
.claude/settings.local.json # 프로젝트 로컬 (gitignored)
기본 구조
{
"hooks": {
"EventName": [
{
"matcher": "regex_pattern",
"hooks": [
{
"type": "command",
"command": "/path/to/script.sh",
"timeout": 30
}
]
}
]
}
}
Hook 타입
| 타입 | 설명 |
|---|
command | 셸 명령어 실행 (가장 일반적) |
http | HTTP 엔드포인트 호출 |
prompt | LLM 프롬프트로 판단 |
agent | 서브에이전트 실행 |
Exit Code 동작
| Exit Code | 동작 |
|---|
0 | 성공, 액션 진행 |
2 | 차단 — 액션 실행 안 함, stderr를 Claude에게 피드백으로 전달 |
1, 3+ | 오류 (비차단) — 액션은 진행 |
{
"session_id": "abc123",
"cwd": "/Users/me/myproject",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "npm test"
},
"tool_use_id": "toolu_..."
}
Output (exit 0 + stdout JSON)
{
"continue": true,
"suppressOutput": false,
"systemMessage": "optional message to Claude",
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow|deny|ask",
"permissionDecisionReason": "reason"
}
}
Matcher 패턴
| 이벤트 | 매칭 대상 | 예시 |
|---|
PreToolUse / PostToolUse | 도구 이름 | "Bash", "Edit\|Write" |
SessionStart / SessionEnd | 세션 이유 | "startup", "resume", "compact" |
ConfigChange | 설정 소스 | "user_settings", "project_settings" |
Notification | 알림 타입 | "permission_prompt", "idle_prompt" |
| MCP 도구 | 도구 이름 | "mcp__github__.*", "mcp__.*__write.*" |
실용 예시
1. 민감 파일 보호
#!/bin/bash
FILE=$(cat | jq -r '.tool_input.file_path // empty')
for pattern in ".env" "package-lock.json" ".git/"; do
if [[ "$FILE" == *"$pattern"* ]]; then
echo "Blocked: $FILE matches protected pattern '$pattern'" >&2
exit 2
fi
done
exit 0
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
}
]
}
]
}
}
2. 파일 편집 후 자동 포맷팅
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
3. 권한 자동 승인
{
"hooks": {
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"PermissionRequest\", \"decision\": {\"behavior\": \"allow\"}}}'"
}
]
}
]
}
}
4. 작업 완료 시 macOS 알림
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude needs attention\" with title \"Claude Code\"'"
}
]
}
]
}
}
5. Linux 알림
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude Code' 'Claude needs your attention'"
}
]
}
]
}
}
6. MCP 도구 호출 로깅
{
"hooks": {
"PostToolUse": [
{
"matcher": "mcp__github__.*",
"hooks": [
{
"type": "command",
"command": "echo \"GitHub tool called: $(jq -r '.tool_name')\" >> ~/.claude/tool-log.txt"
}
]
}
]
}
}
HTTP Hook
{
"type": "http",
"url": "http://localhost:8080/hooks",
"headers": {
"Authorization": "Bearer $MY_TOKEN"
},
"allowedEnvVars": ["MY_TOKEN"],
"timeout": 30
}
유용한 환경 변수
| 변수 | 설명 |
|---|
$CLAUDE_PROJECT_DIR | 프로젝트 루트 디렉토리 |
$CLAUDE_PLUGIN_ROOT | 플러그인 디렉토리 |
$CLAUDE_PLUGIN_DATA | 플러그인 지속 데이터 디렉토리 |
$CLAUDE_ENV_FILE | 환경변수 저장 파일 (SessionStart 전용) |
주의사항
관리 명령어
/hooks
모든 hook 비활성화:
{
"disableAllHooks": true
}