클로드 코드 훅(Hooks): 정해진 순간마다 자동으로 실행되는 명령
훅(Hooks)은 Claude Code가 도구 실행 직전, 도구 성공 직후처럼 정해진 순간(이벤트)마다 자동으로 실행하는 사용자 지정 명령입니다. Claude가 참고하는 CLAUDE.md 지침과 달리 Claude의 판단과 관계없이 실행되므로, 파일을 고친 뒤의 검사나 위험한 명령 막기처럼 매번 일어나야 하는 일을 맡깁니다.
같은 말:Hooks훅클로드 훅클로드 코드 훅클로드코드 훅클로드 hookclaude 훅claude hooksclaude code hooksai 훅클로드 코드 훅 사용법클로드 코드 훅 예시PreToolUsePostToolUseUserPromptSubmithook exited with code 1훅 종료 코드커밋 전 검사hooks settings.json
CLAUDE.md에 "보고서 폴더의 파일을 고친 뒤에는 검사 명령을 돌린다"라고 적어 두어도, Claude Code 공식 문서는 CLAUDE.md를 강제 설정이 아닌 맥락으로 설명합니다. CLAUDE.md는 Claude Code가 작업을 시작할 때 읽는 프로젝트 지침 파일이고, 그 지침을 따를지는 그때마다 Claude가 판단합니다. 공식 문서는 파일을 고친 직후나 커밋(바뀐 내용을 Git 기록으로 남기는 일) 직전처럼 특정 시점에 꼭 실행해야 하는 일은 훅으로 적으라고 안내합니다.
훅(Hooks)은 Claude Code가 도구 실행 직전, 도구 성공 직후처럼 정해진 순간(이벤트)마다 자동으로 실행하는 사용자 지정 명령입니다. 이 글은 2026년 10월 24일 기준 Claude Code 공식 훅 문서를 근거로, 같은 규칙을 CLAUDE.md에 적을 때와 훅으로 등록할 때를 나란히 놓고 설명합니다.
클로드 코드 훅(Hooks)
꼭 돌려야 하는 검사는
정해진 순간마다
Claude Code가 직접 실행하게 합니다
CLAUDE.md는 Claude Code가 작업을 시작할 때 읽는 프로젝트 지침 파일입니다. CLAUDE.md에 "파일을 고친 뒤에는 검사 명령을 돌린다"라고 적어 두면, 검사 명령을 돌릴지는 그때마다 Claude가 판단합니다.
이 글은 같은 규칙을 CLAUDE.md에 적을 때와 훅으로 등록할 때를 나란히 놓고 설명합니다.
지키고 싶은 규칙보고서 폴더의 파일을 고칠 때마다 검사 명령을 돌려 주세요
이 규칙을 적어 둘 곳 고르기
Claude가 고친 파일 세 개
3분기_보고서.md규칙을 아직 적지 않았습니다거래처_목록.csv규칙을 아직 적지 않았습니다회의록_1024.md규칙을 아직 적지 않았습니다
아직 규칙을 적어 둘 곳을 고르지 않아, 파일 세 개 옆의 신호등이 모두 꺼져 있습니다.
훅(Hooks)은 Claude Code가 정해진 순간마다 자동으로 실행하는 사용자 지정 명령입니다.
공식 문서는 Claude의 판단과 관계없이 막아야 하는 일, 파일을 고칠 때마다 돌려야 하는 일을 CLAUDE.md 대신 훅으로 적으라고 안내합니다.
이 그림에서 배우는 Claude(AI 모델)를, 무대감독은 Claude Code 프로그램을, 큐 시트는 설정 파일에 적은 훅을 뜻합니다. 도구는 Claude가 파일을 읽고 고치고 명령을 실행할 때 쓰는 기능입니다. 이 그림은 검사 명령 훅을 파일을 고치는 도구(Edit, Write)가 성공한 뒤 실행되도록 등록한 경우이고, 파일 이름 세 개와 검사 명령은 이 글에서 만든 가상 예시입니다.
훅이 실행되는 순간을
이벤트라고 부릅니다
연극의 큐 시트에 "막이 오를 때", "배우가 소품을 집기 직전"처럼 조명이 들어갈 순간을 적듯, 훅에는 실행될 순간을 정합니다. 공식 문서는 이 순간을 이벤트라고 부르고, 2026년 10월 24일 기준 33가지를 적어 둡니다.
진행표의 큐 지점을 눌러 자주 쓰는 일곱 가지가 언제 실행되고 동작을 막을 수 있는지 봅니다.
세션 하나의 진행표(세션은 claude를 실행한 뒤 끝낼 때까지 이어지는 한 번의 작업입니다)
큐 지점을 누르면 그 이벤트가 실행되는 순간, 동작을 막을 수 있는지, 업무에 쓰는 예가 이 결과 카드에 적힙니다.
이벤트 이름과 실행되는 순간, 막을 수 있는지는 2026년 10월 24일 Claude Code 훅 참조 문서(Hook lifecycle, Exit code 2 behavior per event)를 따릅니다. 이 그림에서 진행표의 큐 지점은 이벤트를, 배우가 소품을 집는 일은 Claude가 도구를 쓰는 일을 뜻합니다. 업무에 쓰는 예의 파일과 검사 명령은 가상 예시입니다.
모든 도구가 아니라
정한 도구를 쓸 때만 실행합니다
조명 큐에 "배우가 편지를 집을 때만"이라고 조건을 붙이듯, 도구 이벤트의 훅에는 matcher로 어떤 도구에 반응할지 정합니다. matcher는 훅이 실행될 도구 이름을 거르는 조건입니다.
큐 시트의 조건을 골라, 소품 탁자에 놓인 도구 호출 다섯 개 가운데 훅이 실행되는 호출을 봅니다.
matcher 조건 고르기
소품 탁자(Claude가 쓰려는 도구 호출 다섯 개)
Read 3분기_보고서.md파일 읽기Edit 3분기_보고서.md파일 고치기Write 요약.md파일 새로 쓰거나 덮어쓰기NotebookEdit 분석.ipynb노트북 파일 고치기Bash rm 임시.txt명령 실행
조건을 누르면 소품 탁자의 도구 호출 가운데 훅이 실행되는 호출에 조명이 켜지고, 그 이유가 이 결과 카드에 적힙니다.
matcher 규칙은 2026년 10월 24일 훅 참조 문서(Matcher patterns)를 따릅니다. Read, Edit, Write, NotebookEdit, Bash는 Claude Code의 실제 도구 이름이고, 파일 이름은 가상 예시입니다. NotebookEdit는 코드와 실행 결과를 한 문서에 담는 주피터 노트북 파일을 고치는 도구입니다. 이 그림에서 소품 탁자는 Claude가 쓰려는 도구 호출을, 조명이 켜진 소품은 훅이 실행되는 호출을 뜻합니다.
훅이 끝날 때 남긴 숫자로
동작을 막을지 정해집니다
프로그램은 끝나면서 종료 코드라는 숫자를 남깁니다. Claude Code는 훅이 남긴 종료 코드를 보고 Claude가 하려던 동작을 진행할지 정합니다.
위험한 명령을 막으려고 PreToolUse 이벤트에 건 훅이 어떤 결과를 남겼는지 골라, 큐 신호등과 대화 기록에 보이는 문구를 봅니다.
큐 시트에 등록한 훅
- 이벤트
PreToolUse- matcher
Bash- 실행할 명령
"$CLAUDE_PROJECT_DIR"/. claude/ hooks/ no-rm. sh
훅이 남긴 결과 고르기
Claude가 실행하려는 명령
rm -rf 임시폴더
대화 기록에 보이는 문구
결과를 누르면 큐 신호등이 켜지고, Claude가 하려던 명령이 어떻게 되는지 이 결과 카드에 적힙니다.
종료 코드별 처리와 화면 문구는 2026년 10월 24일 훅 참조 문서(Exit code output)의 원문이고, no-rm.sh는 그 문서 예시의 스크립트 이름입니다. 문서는 종료 코드 대신 JSON을 출력해 결정을 전하는 방법도 설명합니다. 이 그림에서 큐 신호등의 초록은 동작이 진행된다는 뜻이고, 빨강은 훅이 동작을 막았다는 뜻이며, 주황은 오류 안내만 남고 동작은 진행된다는 뜻입니다.
공식 가이드의 첫 훅은
Claude가 기다릴 때 알림을 띄우는 훅입니다
터미널을 계속 보지 않고 다른 일을 하려면, Claude가 허락이나 입력을 기다릴 때 알려 주는 장치가 필요합니다. 공식 가이드는 첫 훅으로 Claude Code가 알림을 보낼 때 macOS 데스크톱 알림을 띄우는 설정을 소개합니다.
다음 줄 채우기 버튼을 눌러 홈 폴더의 설정 파일 ~/.claude/settings.json에 들어갈 줄을 하나씩 채우고, 큐 시트의 칸이 어떻게 채워지는지 봅니다.
~/.claude/settings.json
큐 시트 한 줄
- 큐 시트
- 언제(이벤트)
- 조건(matcher)
- 실행 방식
- 실행할 명령
- 저장
다음 줄 채우기 버튼을 누르면 설정 파일의 첫 줄이 채워지고, 그 줄이 하는 일이 이 결과 카드에 적힙니다.
설정과 명령은 2026년 10월 24일 공식 가이드(Set up your first hook)의 macOS 예시 원문입니다. 이 그림에서 큐 시트 한 줄은 훅 하나를 뜻하고, 칸은 이벤트, matcher, 실행할 명령을 뜻합니다.
훅을 적은 설정 파일에 따라
적용되는 범위가 달라집니다
훅은 설정 파일 안에 적고, 어느 설정 파일에 적느냐에 따라 내 모든 프로젝트에 적용될지, 프로젝트 하나에만 적용될지가 정해집니다.
걸이에 걸린 설정 파일을 눌러 적용 범위와 공유 여부를 보고, 마지막 열쇠 버튼으로 남이 만든 폴더에서 훅이 언제 실행되는지 봅니다.
설정 파일 고르기
설정 파일을 누르면 그 파일에 적은 훅의 적용 범위, 공유 여부, 적는 때가 이 결과 카드에 적힙니다.
설정 위치와 폴더 신뢰는 2026년 10월 24일 훅 참조 문서(Hook locations, Workspace trust)를 따릅니다. 관리 정책 설정, 플러그인, 스킬과 서브에이전트 파일에도 훅을 적을 수 있고, 여러 곳의 훅은 서로 바꾸지 않고 합쳐집니다. 이 그림에서 걸이에 걸린 큐 시트는 설정 파일을, 열쇠는 폴더 신뢰를 뜻합니다.
클로드 코드 훅을 정리하면 이렇습니다
- 1
훅은 Claude Code가 정해진 순간(이벤트)마다 자동으로 실행하는 명령입니다. Claude가 참고하는 CLAUDE.md와 달리 Claude의 판단과 관계없이 실행되므로, 매번 돌려야 하는 검사나 막아야 하는 일을 맡깁니다.
- 2
자주 쓰는 이벤트는 도구 실행 직전의 PreToolUse, 도구 성공 직후의 PostToolUse, 알림을 보낼 때의 Notification, Claude가 응답을 마칠 때마다 실행되는 Stop입니다.
- 3
훅은 설정 파일의 hooks 안에 이벤트, matcher, 실행할 명령 순서로 적습니다.
Edit|Write는 두 도구에만 맞고,Edit.*처럼 기호가 들어간 matcher는 NotebookEdit에도 맞습니다. - 4
막을 수 있는 이벤트에서 훅이 종료 코드 2로 끝나면 동작이 멈추고, 1을 포함한 그 밖의 숫자로 끝나면 오류 안내만 남고 동작은 진행됩니다.
- 5
명령 훅은 내 사용자 권한으로 실행되므로, 남이 만든 저장소에서
claude -p를 쓰기 전에는 그 저장소의 훅을 먼저 읽거나disableAllHooks로 끕니다.
클로드 코드 훅(Hooks)이란: 정해진 순간마다 Claude Code가 실행하는 명령
연극에서 배우는 대본과 여백의 메모를 보며 연기하지만, 조명과 음향은 무대감독이 큐 시트에 적힌 순간마다 넣습니다. 배우가 메모를 잊어도 조명은 정해진 순간에 들어갑니다. Claude Code에서 배우에 해당하는 것은 AI 모델인 Claude이고, 무대감독에 해당하는 것은 Claude Code 프로그램입니다. 훅은 무대감독의 큐 시트처럼, Claude Code가 정해진 순간마다 실행하도록 설정 파일에 적어 둔 명령입니다.
공식 가이드는 훅을 "Claude Code가 작업 과정의 특정 시점에 실행하는 사용자 지정 셸 명령"으로 설명하고, 훅이 실행 여부를 미리 확실하게 정해 두는 방법(deterministic control)이라고 적습니다. 원문은 "certain actions always happen rather than relying on the LLM to choose to run them"으로, AI 모델이 실행하기로 고르는 데 기대지 않고 정해진 일이 일어나게 한다는 뜻입니다. 셸 명령은 터미널에 입력해 프로그램을 실행하는 명령입니다.
| 같은 규칙 "보고서 폴더의 파일을 고친 뒤 검사 명령을 돌린다" | CLAUDE.md에 적을 때 | 훅으로 등록할 때 |
|---|---|---|
| 실행을 정하는 쪽 | Claude가 지침을 읽고 판단합니다 | Claude Code가 이벤트마다 실행합니다 |
| 공식 문서의 설명 | 강제 설정이 아닌 맥락 | Claude의 판단과 관계없이 적용 |
| 맞는 일 | 글쓰기 방식, 폴더 구조 설명처럼 Claude가 참고할 지침 | 파일을 고친 뒤 검사, 위험한 명령 막기, 알림처럼 매번 일어나야 할 일 |
위 표의 검사 명령은 이 글에서 만든 가상 예시입니다. 공식 메모리 문서는 커밋 직전이나 파일을 고친 직후처럼 특정 시점에 꼭 실행해야 하는 지침은 훅으로 적으라고 안내합니다. CLAUDE.md를 쓰는 법은 CLAUDE.md 작성법 수업에서 다룹니다.
훅을 쓰는 이유와 주의할 점
공식 가이드가 꼽는 훅의 쓰임은 파일을 고친 뒤 형식 정리하기, 명령이 실행되기 전에 막기, Claude가 입력을 기다릴 때 알림 보내기, 세션을 시작할 때 Claude가 참고할 내용 넣기 등입니다. 공통점은 사람이 매번 요청하지 않아도, Claude가 그 규칙을 떠올리지 않아도 정해진 순간에 실행된다는 점입니다.
대신 명령 훅은 내 사용자 계정의 권한으로 셸 명령을 실행합니다. 공식 문서는 명령 훅이 내 계정으로 접근할 수 있는 파일을 바꾸거나 지우거나 읽을 수 있다고 경고하고, 훅 명령을 설정에 넣기 전에 내용을 검토하고 시험하라고 안내합니다. 또 조건에 맞는 훅은 그 이벤트가 일어날 때마다 실행되므로, 오래 걸리는 검사를 모든 도구 호출에 걸면 그만큼 작업이 느려질 수 있습니다.
훅이 실행되는 순간: 이벤트
훅이 실행되는 순간을 이벤트라고 부릅니다. 2026년 10월 24일 기준 공식 훅 참조 문서에는 33가지 이벤트가 있고, 문서는 이들을 세션마다(SessionStart, SessionEnd), 턴마다(UserPromptSubmit, Stop), 도구 호출마다(PreToolUse, PostToolUse) 실행되는 것으로 나눠 설명합니다. 세션은 claude를 실행한 뒤 끝낼 때까지 이어지는 한 번의 작업이고, 턴은 사용자가 요청을 보내고 Claude가 응답을 마칠 때까지입니다. 도구는 Claude가 파일을 읽고 고치고 명령을 실행할 때 쓰는 기능입니다. 종료 코드는 프로그램이 끝나며 남기는 숫자이고, 훅이 2를 남기면 막을 수 있는 이벤트에서 Claude Code가 그 동작을 멈춥니다.
| 이벤트 | 실행되는 순간 | 종료 코드 2로 막을 수 있는지 |
|---|---|---|
SessionStart | 세션이 시작되거나 이어서 열릴 때 | 막지 못함 |
UserPromptSubmit | 사용자가 보낸 요청을 Claude가 처리하기 전 | 막을 수 있음(요청이 Claude에게 가지 않음) |
PreToolUse | 도구 호출이 실행되기 직전 | 막을 수 있음(도구 호출이 실행되지 않음) |
PostToolUse | 도구 호출이 성공한 직후 | 막지 못함(도구가 이미 실행됨, 오류 문장은 Claude에게 전달) |
Notification | Claude Code가 알림을 보낼 때 | 막지 못함(종료 코드와 오류 문장 무시) |
Stop | Claude가 응답을 마칠 때마다 | 막을 수 있음(Claude가 멈추지 않고 이어 감) |
SessionEnd | 세션이 끝날 때 | 막지 못함 |
Stop은 세션이 끝날 때가 아니라 Claude가 답 하나를 마칠 때마다 실행되고, 사용자가 중간에 멈춘 경우에는 실행되지 않습니다. 세션 종료에 명령을 걸려면 SessionEnd를 씁니다. Stop 훅이 매번 막으면 Claude가 계속 작업을 이어 가므로, 공식 가이드는 훅이 받는 입력 JSON의 stop_hook_active 값을 보고 이미 한 번 이어 가게 했으면 막지 않도록 만들라고 안내합니다. Claude가 도구를 쓰지 않은 채 Stop 훅이 연속 8번 막으면 Claude Code가 그 훅을 넘기고 응답을 끝냅니다.
PostToolUse는 도구가 성공했을 때만 실행되고, 실패했을 때는 PostToolUseFailure가 실행됩니다. 이 밖의 이벤트 목록은 공식 훅 참조 문서의 Hook lifecycle 표에 있습니다.
훅 설정 구조: 이벤트, matcher, 실행할 명령
훅은 JSON 형식의 설정 파일에 적습니다. JSON은 이름과 값을 짝지어 적는 데이터 형식입니다. 설정 파일의 hooks 안에는 세 단계를 차례로 적습니다.
- 이벤트: 반응할 순간입니다.
PreToolUse,Stop처럼 적습니다. - matcher: 그 이벤트 가운데 언제 실행할지 거르는 조건입니다. 도구 이벤트에서는 도구 이름을 적습니다.
- 실행할 명령: 조건이 맞을 때 실행할 훅입니다. 공식 문서는 이 단계를 hook handler라고 부르고, 대부분
"type": "command"로 셸 명령을 실행합니다.
| 설정 파일 | 적용 범위 | 공유 |
|---|---|---|
~/.claude/settings.json | 내 컴퓨터의 모든 프로젝트 | 내 컴퓨터에만 있음 |
.claude/settings.json | 그 프로젝트 하나 | 저장소에 커밋해 함께 쓸 수 있음 |
.claude/settings.local.json | 그 프로젝트 하나 | 공유하지 않음 |
~는 홈 폴더를 뜻하고, .claude/는 프로젝트 폴더 안에 있는 Claude Code 설정 폴더입니다. 이 밖에 조직이 배포하는 관리 정책 설정, 플러그인의 hooks/hooks.json, 스킬과 서브에이전트 파일의 머리말(파일 맨 위에 설정을 적는 부분)에도 훅을 적을 수 있습니다. 여러 곳에 적은 훅은 서로 바꾸지 않고 합쳐지며, 한 이벤트에 맞는 훅이 여럿이면 Claude Code가 동시에 실행합니다.
지금 등록된 훅은 Claude Code 입력창에 /hooks를 입력해 봅니다. /hooks는 이벤트별 훅과 그 훅이 어느 설정 파일에서 왔는지 보여 주는 읽기 전용 화면이라, 추가와 수정은 설정 파일을 직접 고치거나 Claude에게 요청합니다. 공식 가이드는 원하는 훅을 말로 설명해 Claude에게 만들어 달라고 할 수도 있다고 안내합니다.
클로드 코드 훅 사용법: 첫 훅으로 알림 받기
공식 가이드의 첫 훅은 Claude Code가 알림을 보낼 때 데스크톱 알림을 띄우는 Notification 훅입니다. 아래는 macOS 예시이며, Linux와 Windows용 명령은 공식 가이드의 Get notified when Claude needs input 절에 있습니다.
- 텍스트 편집기로 홈 폴더의
~/.claude/settings.json을 엽니다. 파일이 없으면 새로 만듭니다. - 아래 내용을 적습니다. 파일에 이미 다른 설정이 있다면 맨 바깥
{ }안에"hooks"항목을 더하고, 이미"hooks"가 있다면 그 안에"Notification"만 더합니다.
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}- 파일을 저장하고, 터미널에서 Claude Code를 실행한 뒤 입력창에
/hooks를 입력합니다. 목록의Notification아래에 이 훅이 보이면 등록된 것입니다.Esc를 눌러 입력창으로 돌아옵니다. Shift+Tab을 눌러 상태 표시줄이⏸ manual mode on이 될 때까지 바꿉니다. Manual 모드는 Claude가 파일을 읽는 일 말고는 작업마다 사용자에게 허락을 묻는 권한 모드이고, Shift+Tab을 누를 때 권한 모드가 바뀌는 순서는 플랜 모드 수업에서 다뤘습니다.- 연습 폴더에 파일을 하나 만들어 달라고 요청하고, 허락을 묻는 화면이 뜨면 브라우저처럼 터미널이 아닌 다른 앱 창으로 옮깁니다. 허락 화면이 약 6초 동안 기다린 뒤 데스크톱 알림이 뜨면 훅이 실행된 것입니다.
matcher의 빈 값 ""는 모든 종류의 알림에 실행된다는 뜻입니다. 허락을 기다린 지 약 6초가 지났을 때만 받으려면 permission_prompt를, 응답을 마치고 약 60초 동안 입력이 없을 때만 받으려면 idle_prompt를 적습니다.
알림이 뜨지 않으면 macOS의 스크립트 편집기(Script Editor)에 알림 권한이 없는 경우일 수 있습니다. 공식 가이드는 이때 명령이 아무 안내 없이 실패한다고 설명합니다. 터미널에 osascript -e 'display notification "test"'를 한 번 입력한 뒤, System Settings > Notifications에서 Script Editor를 찾아 Allow Notifications를 켭니다. 같은 명령을 다시 입력해 시험 알림이 뜨는지 봅니다.
matcher와 if로 훅이 실행될 도구 좁히기
도구 이벤트(PreToolUse, PostToolUse 등)의 matcher에는 도구 이름을 적습니다. matcher는 글자 구성에 따라 다르게 해석됩니다.
| matcher 값 | 해석 | 예 |
|---|---|---|
"", "*", 적지 않음 | 모든 경우에 맞음 | 모든 도구 호출에 실행 |
영문자, 숫자, _, -, 공백, ,, |만 있음 | 정확한 이름 또는 이름 목록 | Edit|Write는 Edit와 Write에만 맞음 |
| 그 밖의 기호가 있음 | 정규식(글자 패턴을 적는 문법), 이름의 일부만 맞아도 됨 | Edit.*는 Edit와 NotebookEdit에 맞음, Edit만 맞추려면 ^Edit$ |
matcher는 대소문자를 가립니다. Read, Edit, Write, NotebookEdit, Bash는 Claude Code의 도구 이름입니다. Read는 파일을 읽는 도구이고, Edit는 있는 파일을 고치는 도구이며, Write는 파일을 새로 만들거나 있는 파일을 통째로 덮어쓰는 도구입니다. NotebookEdit는 주피터 노트북 파일(코드와 실행 결과를 한 문서에 담는 파일)을 고치는 도구이고, Bash는 Claude가 터미널 명령을 실행하는 도구입니다.
같은 도구 안에서 특정 명령이나 파일에만 실행하려면 if 필드를 더합니다. if는 권한 규칙과 같은 문법으로 적으며, "Bash(git *)"는 git으로 시작하는 Bash 명령에만, "Edit(*.ts)"는 .ts 파일을 고칠 때만 훅을 실행합니다. if는 도구 이벤트에서만 평가되고, 다른 이벤트의 훅에 if를 적으면 그 훅은 실행되지 않습니다.
클로드 코드 훅 설정법: 종료 코드로 통과와 차단 정하기
명령 훅은 실행될 때 이벤트 정보를 담은 JSON을 표준 입력(stdin, 프로그램에 데이터를 넘기는 통로)으로 받습니다. 모든 이벤트에 세션 ID, 작업 폴더(cwd), 이벤트 이름이 들어 있고, 도구 이벤트에는 도구 이름(tool_name)과 도구 입력(tool_input)이 더해집니다. 공식 가이드의 예시 스크립트는 JSON에서 값을 꺼내는 jq 프로그램을 써서 jq -r '.tool_input.command'처럼 Claude가 실행하려는 명령을 꺼냅니다. macOS에서는 brew install jq로 jq를 설치합니다.
훅은 끝나면서 종료 코드를 남기고, Claude Code는 이 숫자를 보고 Claude가 하려던 동작을 진행할지 정합니다.
| 종료 코드 | Claude Code의 처리 | 결과 |
|---|---|---|
| 0 | 성공 | 동작이 진행됩니다. 대화에는 아무것도 보이지 않습니다 |
| 2 | 막는 오류 | 막을 수 있는 이벤트에서는 동작을 멈추고, 훅이 stderr에 쓴 문장을 이유로 전달합니다 |
| 1 등 그 밖의 숫자 | 막지 않는 오류 | 동작이 그대로 진행되고, 대화 기록에 훅 오류 안내가 남습니다 |
stderr(표준 오류)는 프로그램이 오류 설명을 내보내는 통로입니다. 공식 문서는 1이 보통의 프로그램에서 실패를 뜻하는 숫자이지만, 올바른 JSON 출력 없이 1로 끝난 훅은 막지 않는 오류라고 경고합니다. 훅이 1처럼 0도 2도 아닌 숫자로 끝나면, 대화 기록에는 PreToolUse:Bash hook error처럼 이벤트와 도구 이름이 붙은 안내와 함께 Failed with non-blocking status code: 뒤에 stderr 첫 줄이 붙은 문구가 남습니다. 이 문구에 No such file or directory가 보이면 스크립트 경로가 틀려 훅이 아예 실행되지 않은 것이므로, 설정 파일에 적은 경로부터 고칩니다. 규칙을 강제하려는 훅은 검사에 걸렸을 때 exit 2로 끝냅니다.
공식 가이드의 보호 파일 예시는 .env(비밀번호와 키를 적어 두는 설정 파일), package-lock.json, .git/ 경로를 Claude가 고치려 하면 막습니다. 먼저 프로젝트 폴더에 .claude/hooks/protect-files.sh를 아래 내용으로 저장합니다.
#!/bin/bash
# protect-files.sh
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
# Normalize Windows backslash separators so the patterns below match
FILE_PATH="${FILE_PATH//\\//}"
PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")
for pattern in "${PROTECTED_PATTERNS[@]}"; do
if [[ "$FILE_PATH" == *"$pattern"* ]]; then
echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
exit 2
fi
done
exit 0macOS와 Linux에서는 터미널에서 chmod +x .claude/hooks/protect-files.sh로 실행 권한을 줍니다. 공식 가이드는 훅 스크립트에 실행 권한이 있어야 Claude Code가 실행할 수 있다고 적습니다. 그다음 프로젝트의 .claude/settings.json에 아래처럼 등록합니다.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
}
]
}
]
}
}$CLAUDE_PROJECT_DIR는 Claude Code가 훅에 넘겨주는 프로젝트 폴더 경로입니다. 공식 가이드는 Claude에게 .env 파일에 한 줄을 더해 달라고 요청해 시험하라고 안내하고, 이때 Claude Code가 편집을 실행하기 전에 막고 스크립트의 Blocked: 문장을 Claude에게 전달한다고 설명합니다. 실제 비밀번호가 든 파일 대신 연습 폴더에 만든 빈 .env 파일로 시험합니다.
저장 뒤 검사와 커밋 전 검사
저장 뒤 검사(PostToolUse): 공식 가이드의 형식 정리 예시는 Claude가 Edit나 Write로 파일을 고친 뒤, 형식 정리 프로그램 Prettier를 그 파일에 실행합니다. 프로젝트의 .claude/settings.json에 적습니다.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}PostToolUse 훅은 이미 끝난 편집을 막거나 되돌리지 못합니다. 검사 명령이 문제를 찾았을 때 Claude가 알고 다시 고치게 하려면, 훅이 stderr에 이유를 쓰고 종료 코드 2로 끝나게 만듭니다. 그러면 그 문장이 Claude에게 전달됩니다. 이 matcher는 Claude의 Edit와 Write 도구에만 반응하므로, Bash 명령이나 사람이 편집기에서 바꾼 파일에는 실행되지 않습니다.
커밋 전 검사(PreToolUse): Claude가 git commit으로 변경 내용을 기록하기 직전에 검사를 돌리려면, Bash 도구에 PreToolUse 훅을 걸고 if로 커밋 명령만 고릅니다. 아래 설정의 lint-before-commit.sh는 이 글에서 만든 가상 스크립트 이름이고, 그 스크립트가 검사에 걸렸을 때 stderr에 이유를 쓰고 exit 2로 끝나면 커밋 명령이 실행되지 않습니다.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(git commit *)",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/lint-before-commit.sh"
}
]
}
]
}
}이 훅은 Claude가 Bash 도구로 실행하는 커밋에만 걸립니다. 사람이 터미널에서 직접 하는 커밋까지 검사하려면 Git이 커밋 직전에 실행하는 자체 기능인 pre-commit 훅을 따로 둡니다. Claude Code와 Git으로 작업을 기록하는 흐름은 클로드 코드 Git 작업 흐름 수업에서 다룹니다.
훅과 권한 규칙의 관계
권한 규칙은 Claude가 묻지 않고 해도 되는 일(allow), 물어야 하는 일(ask), 할 수 없는 일(deny)을 정하는 설정입니다. 공식 권한 문서에 따르면 PreToolUse 훅의 결정은 권한 규칙을 넘어서지 못합니다. 훅이 허용을 돌려줘도 deny 규칙에 걸리면 막히고, ask 규칙에 걸리면 확인 창이 그대로 뜹니다.
반대로 PreToolUse 훅은 모든 권한 모드에서 권한 모드 확인보다 먼저 실행됩니다. 공식 가이드는 훅의 거부(deny) 결정이 권한 확인을 건너뛰는 bypassPermissions 모드에서도 유지된다고 설명합니다. 같은 가이드의 표현대로 훅은 권한 규칙보다 더 엄격하게 막는 데 쓸 수 있지만, 권한 규칙보다 느슨하게 푸는 데는 쓸 수 없습니다. 관리 설정이 없고 Team이나 Enterprise 플랜 계정으로 로그인하지 않은 세션에서는 mod(플러그인이 Claude Code 안에서 실행하는 확장 코드)가 PreToolUse 훅이 막은 호출을 승인할 수 있다는 예외도 공식 가이드에 함께 적혀 있습니다. 권한 모드와 규칙은 권한 모드 수업에서 다룹니다.
보안: 남이 만든 저장소와 claude -p
대화형 세션은 처음 여는 폴더에서 폴더 신뢰 확인 창을 띄우고, 사용자가 수락하기 전에는 내 홈 폴더의 설정 파일을 포함한 모든 설정 파일의 훅을 보류합니다. 반면 claude -p(대화 없이 요청 하나를 실행하고 끝내는 방식)와 Agent SDK(프로그램 안에서 Claude Code를 부르는 개발 도구)로 연 세션은 확인 창을 띄우지 않고 폴더를 신뢰한 것으로 보므로, 저장소의 .claude/settings.json에 들어 있는 훅이 바로 실행됩니다.
직접 만들지 않은 저장소에서 claude -p를 쓰기 전에는 .claude/ 안의 설정 파일을 먼저 읽습니다. 그 실행에서만 훅을 끄려면 --settings '{"disableAllHooks": true}'를 붙입니다. 공식 문서가 권하는 훅 작성 습관은 입력을 그대로 믿지 않기, 셸 변수를 "$VAR"처럼 따옴표로 감싸기, 경로에 상위 폴더로 올라가는 표기 ..가 들어 있으면 막기, 스크립트를 절대 경로로 적기, .env와 .git/ 같은 민감한 파일 건너뛰기입니다.
비밀번호와 API 키(서비스에 접속하는 비밀 값)는 훅 명령이나 함께 쓰는 설정 파일에 적지 않습니다. .claude/settings.json은 저장소에 커밋되어 다른 사람에게 공유될 수 있습니다.
슬래시 명령, 서브에이전트, mod와 다른 점
| 기능 | 실행하는 때 | 맞는 일 |
|---|---|---|
| 슬래시 명령 | 사용자가 /명령을 입력할 때 | 필요할 때 사용자가 부르는 작업 |
| 서브에이전트 | Claude가 맡기거나 사용자가 고를 때 | 별도 컨텍스트(Claude가 대화에서 참고하는 내용 전체)에서 조사하고 요약만 받기 |
| 훅 | 정해진 이벤트가 일어날 때마다 | 매번 돌려야 할 검사, 막아야 할 일, 알림 |
| mod | 플러그인이 등록한 함수가 이벤트를 받을 때 | Claude Code 화면에 창이나 버튼을 그리고 도구 호출을 바꾸기 |
공식 문서는 플러그인이 JavaScript 함수로 등록하는 훅을 mod라고 부르고, 이 글에서 다룬 설정 파일의 훅과 구분합니다. mod 글에서는 이 글의 훅을 "설정 훅"이라고 부릅니다. 설정 훅은 mod와 함께 계속 동작합니다.
훅은 Claude Code 안에서 이벤트가 일어나야 실행됩니다. 매일 아침 9시처럼 시간에 맞춰 실행하는 일은 훅이 아니라 예약 작업 기능이 맡습니다.
막혔을 때
| 상황 | 원인 | 할 일 |
|---|---|---|
/hooks에 등록한 훅이 보이지 않음 | JSON 형식 오류(끝에 붙은 쉼표, 주석)이거나 설정 파일 위치가 틀림 | JSON을 고치고 위치(~/.claude/settings.json, .claude/settings.json)를 봅니다. 몇 초가 지나도 안 보이면 Claude Code를 다시 시작합니다 |
| 등록은 됐는데 실행되지 않음 | matcher의 도구 이름이 다르거나(대소문자 포함) 이벤트를 잘못 고름 | matcher를 도구 이름과 똑같이 적고, 실행 전(PreToolUse)과 실행 후(PostToolUse)를 다시 봅니다 |
| 막으려던 명령이 실행됨 | 훅이 1로 끝났거나 스크립트 경로가 틀림 | 검사에 걸리면 exit 2로 끝내고, 대화 기록에 No such file or directory가 있으면 경로를 고칩니다 |
jq: command not found | jq가 설치되지 않음 | jq를 설치하거나 Python, Node.js로 JSON을 읽습니다 |
| 스크립트가 아예 실행되지 않음 | 실행 권한이 없음 | chmod +x로 실행 권한을 줍니다 |
| Claude가 멈추지 않고 계속 이어 감 | Stop 훅이 매번 막음 | 입력의 stop_hook_active가 true이면 exit 0으로 끝나게 만듭니다 |
스크립트만 따로 시험하려면 공식 가이드처럼 예시 JSON을 넣어 실행하고 종료 코드를 봅니다. 터미널에서 echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh를 실행한 뒤 바로 echo $?를 입력하면 직전 명령의 종료 코드가 나옵니다.
자주 묻는 질문
훅 하나만 잠시 끌 수 있나요?
설정에 남겨 둔 채 훅 하나만 끄는 방법은 없습니다. 그 훅을 설정 파일에서 지우거나, 설정 파일에 "disableAllHooks": true를 적어 모든 훅을 잠시 끕니다. 이 값은 설정 우선순위를 따르므로, 홈 폴더의 ~/.claude/settings.json에 true를 적어도 프로젝트의 .claude/settings.json에 false가 있으면 그 프로젝트에서는 훅이 실행됩니다. 프로젝트 설정과 관계없이 한 번의 실행에서만 훅을 끄려면 claude를 실행할 때 --settings '{"disableAllHooks": true}'를 붙입니다. 조직이 관리 정책으로 배포한 훅은 사용자나 프로젝트 설정의 disableAllHooks로 꺼지지 않고, 관리 정책 설정에서만 끌 수 있습니다.
훅이 실행됐는지 어떻게 확인하나요?
훅이 성공하면 대화에는 아무것도 보이지 않으므로, 형식이 바뀐 파일이나 막힌 명령처럼 훅이 만든 결과로 확인합니다. 공식 가이드는 Ctrl+O로 대화 기록 화면을 열어 훅 결과를 보고, 자세한 종료 코드와 출력은 claude --debug-file /tmp/claude.log로 실행해 디버그 기록에서 보라고 안내합니다. 세션 중에는 /debug로 기록을 켤 수 있습니다.
hook exited with code 1 같은 안내는 무슨 뜻인가요?
훅이 0도 2도 아닌 숫자로 끝나 막지 않는 오류가 났다는 뜻이고, Claude가 하려던 동작은 그대로 진행됐습니다. 공식 문서 기준으로 대화 기록에는 PreToolUse:Bash hook error처럼 이벤트와 도구 이름이 붙은 안내와 Failed with non-blocking status code: 문구가 남습니다. 막는 용도의 훅이라면 검사에 걸렸을 때 exit 2로 끝나게 고칩니다.
서브에이전트가 쓰는 도구에도 훅이 걸리나요?
걸립니다. 설정 파일, 관리 정책, 플러그인의 훅은 서브에이전트 안의 도구 호출에도 메인 대화와 똑같이 실행되고, 훅이 받는 입력에 어느 서브에이전트인지가 함께 들어옵니다.
클라우드 세션이나 데스크톱 앱에서도 훅이 실행되나요?
실행됩니다. 공식 문서는 터미널, VS Code 같은 코드 편집기의 확장, 데스크톱 앱, 클라우드 세션에서 같은 훅 이벤트가 일어난다고 설명합니다. 다만 클라우드 세션은 내 컴퓨터의 ~/.claude/settings.json을 읽지 않습니다.
참고 자료

제대로 이해했는지 한 문제로 확인해 볼까요?
답을 고르면 바로 풀이가 나와요.
PreToolUse 훅으로 위험한 명령을 막으려 합니다. 검사에 걸렸을 때 훅 스크립트가 어떻게 끝나야 그 명령이 실행되지 않을까요?
예제나 확인 질문을 직접 시도한 뒤 완료 표시해요. 더 연습할 내용이 남으면 표시하지 않고 다음 글을 읽어도 됩니다. 완료 버튼은 이해도를 채점하지 않으며 잘못 표시하면 취소할 수 있어요.







