TL;DR — Claude Code hooks란
- Hooks는 결정론적입니다: Claude Code 라이프사이클의 고정 지점에서 매번 반드시 실행됩니다. '매번 편집 후 Prettier 실행해 줘'라는 CLAUDE.md 지시는 대체로 지켜지는 정도 — hook은 항상 지켜집니다.
- 이벤트는 다섯 개: UserPromptSubmit(프롬프트가 처리되기 전), PreToolUse(도구 호출 전), PostToolUse(도구 완료 후), Notification, 그리고 Stop(Claude가 응답을 끝냈을 때).
- exit code 2로 끝나는 PreToolUse hook은 그 도구 호출을 차단하고, stderr 메시지가 Claude에게 되돌아가 이유를 알려 줍니다. exit code 0이면 호출이 진행됩니다.
- Hooks는 settings.json에 정의합니다 — 이벤트, 선택적 도구 matcher, 명령어. 프로젝트의 .claude/settings.json에 두고 커밋하면 팀 전체가 같은 보장을 상속합니다.
Hooks in Claude Code
채널:Claude (official Anthropic channel)3:22
Claude Code Hooks, Explained Simply
채널:Agentic Lab8:32
Claude Code - Getting Started with Hooks
채널:Greg Baugues11:53
Hooks reference — Claude Code documentation
문서:code.claude.com
이 가이드의 프레임은 Anthropic 공식 hooks 해설 영상에서 왔습니다. 워크스루 글은 독자적으로 작성됐고 공식 hooks 레퍼런스와 대조해 검증했습니다.
스크린샷의 저작권은 제작자에게 있으며, 시각 문서로 출처를 밝혀 사용합니다. 각 단계는 원본 영상의 해당 시점으로 딥링크됩니다.
Claude Code hooks 단계별 설정
1 · 실전에서 hook이 돌아가는 모습
- 1
응답 끝에서 hook이 발화하는 걸 보기
상태 표시줄에 'Running stop hook · 39s · 484 tokens'라고 있습니다 — Claude Code가 Stop hook을 실행한 뒤에 턴을 돌려주는 중입니다. 스크린샷 한 장이 사상 전부입니다: 등록한 명령어가 라이프사이클의 고정 지점에서, 일치할 때마다, 모델이 '잊지 않고 해 줄' 것에 전혀 의존하지 않고 실행됩니다.

Claude의 답변 뒤에 실행되는 Stop hook — 39초 경과, 484 tokens 소모.0:10에 시청 - 2
다섯 hook 이벤트 익히기
UserPromptSubmit은 프롬프트를 제출한 순간, Claude가 처리하기 전에 실행됩니다. PreToolUse는 도구 호출마다 그 전에. PostToolUse는 도구 호출이 끝난 뒤에. Notification은 Claude가 알림을 보낼 때 발화하고, Stop은 Claude가 응답을 마쳤을 때 실행됩니다. 여러분이 쓰는 모든 hook은 이 다섯 지점 중 정확히 하나에 붙습니다.

Anthropic 공식 hooks 영상의 다섯 이벤트 — 모든 설정이 이 목록에 매달립니다.1:04에 시청
2 · 첫 hook 쓰기
- 3
settings.json에 hooks 블록 추가하기
hook은 settings.json 안의 세 가지 요소입니다: 이벤트 이름, 적용 대상 도구를 좁히는 선택적 matcher, 실행할 명령어. 스크린샷에서는 PreToolUse matcher에 Edit가 자동완성되는 중 — 이 hook은 파일 편집 도구 호출에서만 발화합니다. JSON을 손으로 쓰고 싶지 않다면 /hooks 메뉴에서 같은 설정을 대화형으로 편집할 수 있습니다.

matcher가 Edit로 자동완성되며 PreToolUse hook을 파일 편집 전용으로 한정.0:14에 시청 - 4
exit code 2로 위험 명령어 차단하기
PreToolUse hook은 도구 이름과 입력을 JSON으로 stdin에서 받습니다. 이 스크립트는 jq로 .tool_input.command를 꺼내 rm -rf, git push --force 같은 파괴적 패턴을 grep으로 대조하고, 일치하면 이유를 stderr에 출력하고 exit code 2로 끝납니다. exit code 2는 호출을 차단하고, stderr 텍스트는 피드백으로 Claude에게 돌아가 모델이 이유를 알고 조정할 수 있게 합니다.

jq가 stdin에서 명령어를 읽고, rm -rf나 --force에 일치하면 stderr 출력 후 exit 2.2:02에 시청 - 5
exit code 대신 구조화된 거절 보내기
더 정밀한 제어를 위해 hook은 exit code 대신 JSON 결정을 출력할 수 있습니다. 여기서는 PreToolUse hook이 DROP TABLE을 잡아내고, hookSpecificOutput이 permissionDecision 'deny'와 이유 — 'migration을 쓸 것' — 를 실어 모델의 컨텍스트로 전달합니다. 똑같은 강한 보장에 실행 가능한 지시가 붙습니다.

permissionDecision이 deny면 SQL 명령어가 차단되고 모델에게 대안이 전달됩니다.2:16에 시청 - 6
hook을 저장소에 커밋해 팀이 함께 쓰기
프로젝트의 .claude/settings.json에 설정된 hook은 프로젝트 레벨이라 커밋할 수 있습니다. 저장소를 클론한 모두가 차단 hook을 포함해 같은 hook을 자동으로 실행합니다. 헬퍼 스크립트는 .claude/hooks/에 두고 CLAUDE_PROJECT_DIR 환경 변수로 참조하면 Claude의 작업 디렉터리가 어디든 경로가 동일하게 해석됩니다.

프로젝트의 .claude 폴더에는 settings.json과 공유 스크립트를 담은 hooks/ 디렉터리가.0:17에 시청 - 7
완성형 hooks 설정 통째로 따오기
이 설정은 한 번에 두 가지 일을 합니다. PostToolUse 블록은 Edit|Write|MultiEdit에 일치해 30초 타임아웃으로 .claude/hooks/auto-format.sh를 실행 — Claude가 건드린 모든 파일이 포맷됩니다. 그 아래 두 번째 hook은 Bash에 일치해 실행된 모든 명령어를 기록 — 컴플라이언스 정석 패턴입니다. timeout과 async 필드 덕분에 느린 포매터가 세션을 막지 않습니다.

30초 타임아웃의 PostToolUse 자동 포맷 + 모든 명령어를 기록하는 Bash hook.2:46에 시청
3 · 팀처럼 운영하기
- 8
exit code 규약을 완전히 외우기
exit code 0은 진행. exit code 2는 차단 — stderr가 Claude가 행동에 옮길 수 있는 피드백으로 전달됩니다. 그 외의 exit code는 stderr를 여러분(사용자)에게 보여 줄 뿐 도구 호출은 계속됩니다. 에이전트를 강제로 막지 않으면서 보고 싶은 경고에 쓰세요.
- 9
/hooks 메뉴로 등록 확인하고 레시피 고르기
/hooks 명령은 같은 설정을 대화형으로 열어 줍니다 — 어떤 스코프에 어떤 hook이 등록됐는지 확인에 유용하죠. 이어서 네 가지 주력 레시피: 편집 후 자동 포맷(PostToolUse), 실행 명령어 전부 기록(Bash의 PostToolUse), 위험 작업 차단(exit 2 붙인 PreToolUse), 작업 완료 알림(Stop). 매번 반드시 일어나야 할 일은 프롬프트가 아니라 hook에 넣으세요.
exit code 규약, 표 한 장으로
모든 hook 명령어는 exit code로 의사소통합니다. 세 가지 케이스가 전부입니다:
- exit 0진행. 도구 호출은 평소처럼 실행됩니다. hook의 stdout은 트랜스크립트 모드(Ctrl-R)에서 볼 수 있습니다.
- exit 2차단. 도구 호출이 거부되고 hook의 stderr가 피드백으로 Claude에게 전달되어 모델이 방향을 고칠 수 있습니다 — exit-2 hook이 단순한 치명타가 아니라 '가르침'이 되는 이유입니다.
- exit 1그 외 코드: 막지 말고 경고. stderr는 여러분에게 보이지만 호출은 계속됩니다. '이 파일은 보통 생성물인데 정말 고칠까요?' 같은 안내형 hook용입니다.
상위 확장 경로가 하나 더 있습니다: exit code 대신 hook이 JSON 결정(permissionDecision을 담은 hookSpecificOutput)을 출력해 구조화된 이유와 함께 거절할 수 있습니다(5단계 참고). exit code는 단순 규약, JSON 결정은 타입 있는 규약입니다.
오늘 바로 커밋할 네 가지 레시피
공식 영상이 짚어 준 네 가지 유스 케이스를 바로 베껴 쓸 수 있는 형태로 정리했습니다:
- 1편집 후 자동 포맷 — Edit|MultiEdit에 일치하는 PostToolUse hook이 확장자를 보고 알맞은 포매터를 실행: TypeScript는 Prettier, Go는 gofmt, Python은 Ruff.
- 2실행 명령어 전부 기록 — Bash의 PostToolUse hook이 모든 명령어를 파일에 추가. 컴플라이언스 팀이 좋아하고, 지난 화요일에 뭐가 돌았는지 디버깅할 미래의 나도 좋아합니다.
- 3위험 작업 차단 — exit 2 붙은 PreToolUse hook으로 프로덕션 설정 디렉터리, rm -rf 패턴, main 커밋을 지킵니다. 이것들은 '제안'이 아니라 '보장'이 됩니다.
- 4작업 완료 알림 — Stop 또는 Notification hook이 데스크톱 알림이나 소리를 트리거해 긴 에이전트 실행을 지켜보지 않아도 되게 합니다.
네 가지 모두 한 .claude/settings.json에 들어갑니다. 포매터부터 시작하세요 — 저장할 때마다 체감되는 hook입니다.
