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을 출력하면 사용자에게 메시지가 표시됩니다.
디버깅 절차
- JSON 문법 —
jq . settings.json으로 유효성 확인 - 매처 패턴 —
Write|Edit처럼 정확한 도구명 사용 - 명령 직접 테스트 —
echo '{"tool_input":{"file_path":"test.ts"}}' | <훅 명령> - 재시작 — 새 훅은 Claude Code 재시작 또는
/hooks한 번 열기 필요 - debug 모드 —
claude --debug로 훅 실행 로그 확인
hookify 도구 활용
hookify는 자연어로 훅을 생성해주는 플러그인입니다. 직접 JSON을 작성하기 부담스러우면 hookify로 초안을 만들고 settings.json에 적용하는 방식이 빠릅니다.
다음 단계
- hookify — 자연어로 훅 정의
- Claude Code Setup — 프로젝트에 맞는 훅 자동 추천
- CLAUDE.md 잘 쓰는 법 — 훅과 CLAUDE.md 규칙의 역할 분리
자주 묻는 질문
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가 인식합니다.