
Claude Code Hooks: 에이전트를 자동화하는 파워 유저 가이드
Claude Code 훅은 라이프사이클 이벤트에 맞춰 명령어를 자동으로 실행합니다 — 직접 개입하지 않아도 검증, 린트, 차단, 로깅이 가능합니다. 이벤트 종류, 설정 방법, 5가지 활용 레시피, 종료 코드(exit-code)의 함정, 그리고 별도 설정 없이 Claude Code를 실행하는 방법까지 다룹니다.
Claude Code 훅이란 무엇인가
Claude Code 훅은 도구 호출 전, 편집 후, 세션 시작 시, Claude가 턴을 마칠 때 등 Claude Code의 라이프사이클 내 특정 시점에서 자동으로 실행되는 사용자 정의 명령입니다. 덕분에 매번 직접 개입하지 않고도 작업을 검증, 포맷팅, 로깅, 또는 차단할 수 있습니다. 이는 제안만 하는 AI 코딩 에이전트와, 당신의 규칙을 결정론적으로 따르는 에이전트 사이의 차이를 만들어냅니다. 이 가이드에서는 훅이 무엇인지, 발동될 수 있는 모든 이벤트, 구성 방법, 그대로 따라 할 수 있는 다섯 가지 실용적인 레시피, 모두를 헷갈리게 만드는 종료 코드(exit-code)의 함정, 그리고 로컬 설치 없이 Claude Code의 강력한 기능을 온전히 활용하는 방법을 설명합니다.
Claude Code 훅이란 무엇인가?
훅은 특정 이벤트가 발생할 때 Claude Code가 자동으로 실행하는 핸들러입니다 — 셸 명령, HTTP 엔드포인트, MCP 도구 호출, 심지어 모델 프롬프트일 수도 있습니다. 핸들러는 구조화된 입력을 받고(명령 훅의 경우 stdin으로, HTTP 훅의 경우 POST 본문으로), 현재 일어나는 일을 확인하고, 조치를 취하고, 선택적으로 Claude의 다음 행동을 바꾸는 결정을 반환할 수 있습니다.
바로 이 마지막 부분이 훅을 단순히 편리한 것이 아니라 강력하게 만드는 요소입니다. 훅은 단순한 알림이 아닙니다 — 도구 호출을 차단하거나, 도구의 입력이나 출력을 재작성하거나, 추가 컨텍스트를 주입하거나, Claude를 완전히 중단시킬 수 있습니다. 다시 말해, 훅은 Claude Code를 똑똑한 어시스턴트에서 프로그래밍 가능한 어시스턴트로 바꿔줍니다 — 모델이 우연히 기억할 때만이 아니라, 팀의 가드레일을 결정론적으로 항상 강제하는 방식으로 말이죠.
훅이 발동되는 시점: 라이프사이클
훅은 이벤트에 연결되며, Claude Code는 매우 많은 이벤트를 노출합니다. 이는 발생 빈도별로 그룹화됩니다. 어떤 것은 세션당 한 번, 어떤 것은 턴당 한 번, 어떤 것은 모든 도구 호출마다 발동합니다.
Claude Code 세션 전반에 걸쳐 훅이 발동되는 위치 — SessionStart부터 SessionEnd까지.
가장 자주 사용하게 될 이벤트들:
SessionStart/SessionEnd— 세션이 시작하거나 끝날 때 한 번. 컨텍스트를 불러오거나(열려 있는 이슈, 브랜치 정보, 환경 변수) 정리 작업을 하기에 좋습니다.UserPromptSubmit— 프롬프트를 제출할 때, Claude가 처리하기 전에 발동합니다. 프롬프트를 필터링하거나 보강할 수 있습니다.PreToolUse— 모든 도구 호출 전. 위험한 작업을 차단하는 지점입니다.PostToolUse(그리고PostToolUseFailure) — 도구 호출이 성공(또는 실패)한 후. 린팅, 포맷팅, 검증을 하기에 적절한 곳입니다.Stop/StopFailure— Claude가 응답을 마쳤을 때, 또는 턴이 오류로 끝났을 때.Notification— Claude Code가 알림을 보낼 때(데스크톱 알림에 유용합니다).
이 외에도 Claude Code는 서브에이전트(SubagentStart/SubagentStop), 작업(TaskCreated/TaskCompleted), 컨텍스트 압축(PreCompact/PostCompact), 작업 디렉터리 변경(CwdChanged), 디스크 상의 파일 변경(FileChanged), 지침 로딩(InstructionsLoaded) 등에도 훅을 발동시킵니다. 이 폭넓음이 핵심입니다 — 에이전트의 루프 내 거의 모든 순간이 정책을 붙일 수 있는 지점입니다.
훅 핸들러의 다섯 가지 유형
하나의 훅 이벤트는 다섯 가지 종류의 핸들러를 트리거할 수 있으며, 이것이 시스템을 유연하게 만드는 요소입니다:
command— 셸 명령을 실행합니다. stdin으로 입력을 읽고, 종료 코드와 stdout을 통해 결정을 알립니다.http— 이벤트 JSON을 URL로 POST하고 JSON 응답을 읽습니다.mcp_tool— 연결된 MCP 서버의 도구를 호출합니다.prompt— yes/no JSON 결정을 반환하는 단일 턴 모델 평가(모호한 검사에 유용합니다).agent— 서브에이전트를 생성합니다(실험적).
대부분의 팀에게는 command 훅이 작업의 90%를 처리합니다 — 셸 스크립트만으로도 린팅, 차단, 로깅에 충분합니다.
훅 구성 방법
훅은 설정 파일에 위치하며(공식 Claude Code 훅 문서가 정식 참고 자료입니다), 어디에 두느냐가 범위를 결정합니다:
| 위치 | 범위 |
|---|---|
~/.claude/settings.json | 모든 프로젝트 |
.claude/settings.json | 하나의 프로젝트(커밋 가능 — 팀과 공유 가능) |
.claude/settings.local.json | 하나의 프로젝트, 로컬 전용(gitignore 처리됨) |
| 관리형 정책 설정 | 조직 전체(관리자) |
구조는 세 단계로 중첩됩니다: 이벤트를 선택하고, 매처(matcher) 그룹을 추가한 다음, 핸들러를 정의합니다. 매처는 훅이 어떤 도구 호출에 적용될지를 결정합니다 — "*"(또는 생략)는 모든 것에 매치되고, 단순한 Edit|Write는 정확히 그 도구들에 매치되며, 그 이상 복잡한 것은 정규 표현식으로 취급됩니다. (MCP 도구는 mcp__<server>__<tool> 패턴에 매치됩니다.)
다음은 모든 편집 이후 린트 검사를 실행하는 PostToolUse 훅입니다:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "/path/to/lint-check.sh" }]
}
]
}
}다섯 가지 실용적인 훅 레시피
팀들이 가장 먼저 찾는 패턴들입니다:
- 모든 편집 후 린트 또는 포맷팅.
Edit|Write에 매치된PostToolUse훅이 포매터나 린터를 실행하여, 에이전트의 코드가 항상 당신의 스타일 규칙을 충족하도록 합니다. - 파괴적인 명령 차단.
Bash에 매치된PreToolUse훅이 명령을 검사하여rm -rf류의 명령이 실행되기 전에 차단합니다. - 데스크톱 알림. Claude가 주의가 필요하거나 긴 작업을 마쳤을 때 알려주는
Notification훅. - 감사 로깅. 모든 도구 호출을 규정 준수 목적으로 기록하는
PostToolUse(또는 MCP 대상) 훅 — 무엇이 실행되었는지, 언제, 어떤 인자로. - 시작 시 프로젝트 컨텍스트 로드. 열려 있는 이슈, 현재 브랜치, 또는 환경 변수를 불러와서 에이전트가 각 세션을 이미 방향이 잡힌 상태로 시작하게 하는
SessionStart훅.
다섯 가지 일반적인 훅 레시피와 그것들이 연결되는 이벤트.
종료 코드(Exit-Code)의 함정
이것은 모두를 헷갈리게 만드는 세부 사항이므로 반드시 기억해 두세요: command 훅의 경우, 오직 종료 코드 2만 차단합니다. 종료 0은 성공을 의미하며(그리고 stdout이 JSON 결정을 위해 파싱됩니다). 종료 2는 차단성 오류입니다 — 그 stderr가 Claude에게 다시 전달됩니다. 다른 어떤 코드든, 종료 1을 포함해, 비차단성 오류입니다 — Claude는 계속 진행합니다.
따라서 "이것을 차단하라"는 훅을 작성하면서 exit 1을 사용하면, 이는 차단되지 않습니다 — 작업이 계속 진행됩니다. 명령 훅에서 실제로 정책을 강제하려면, exit 2를 사용하세요. (명령 훅은 stdout에 JSON으로 더 풍부한 제어를 반환할 수도 있습니다 — PreToolUse용 permissionDecision: "deny", 인자를 재작성하는 updatedInput, 정보를 주입하는 additionalContext, 그리고 Claude를 완전히 멈추는 continue: false.)
실전 예제: rm -rf 차단하기
파괴적 명령 가드를 처음부터 끝까지 만들어봅시다. 모든 구성 요소를 보여주기 때문입니다. 먼저 설정 — Bash에 매치된 PreToolUse 훅:
{ "hooks": { "PreToolUse": [{ "matcher": "Bash",
"hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard.sh" }] }] } }그런 다음 스크립트, guard.sh. Claude Code는 이벤트를 stdin에 JSON으로 전송하며, 여기에는 도구의 입력이 포함됩니다. 스크립트는 이를 읽고, 명령을 확인하고, 결정합니다:
#!/usr/bin/env bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
if echo "$cmd" | grep -Eq 'rm +-rf|mkfs'; then
echo "Blocked: destructive command refused by policy." >&2
exit 2 # exit 2 blocks — exit 1 would NOT
fi
exit 0결정적인 줄은 exit 2입니다. 0을 반환하면 명령이 실행되고, 1을 반환하면 — 직관에 반하게도 — 비차단성 오류로 여전히 실행됩니다. 오직 exit 2만이 차단하며 당신의 stderr 메시지를 Claude에게 다시 전달해 왜 차단되었는지 이해하게 합니다. 스크립트를 실행 가능하게 만들고, .claude/hooks/ 아래에 커밋하면, 이제 모든 Bash 호출이 당신의 가드를 통과합니다 — 프로젝트의 settings.json이 공유 가능하므로 팀 전체에 적용됩니다. 완전한 보장이 아니라 최선의 노력(best-effort) 안전망이 필요하다면, Claude Code의 권한 규칙과 함께 사용하세요. 결정론적이고 버전 관리되는 안전망으로서, 이 훅만으로도 이미 제 역할을 합니다.
훅이 답이 아닐 때
훅은 결정론적이고 반복 가능한 정책을 위한 것입니다 — "편집 후에는 항상 린트하라", "절대 rm -rf를 실행하지 말라"와 같은 것들. 판단력이 필요한 일에는 적합하지 않으며(모호한 판단에는 모델이나 prompt 훅을 사용하세요), 강력한 보안 보장에도 적합하지 않습니다(권한 시스템을 사용하세요, 명령 훅의 if 필터는 열려있는 방향으로 실패하기 때문입니다). 훅을 과도하게 사용하지도 마세요: 모든 명령 훅은 타임아웃이 있는 프로세스를 실행하며, 느린 훅이 잔뜩 쌓이면 모든 도구 호출에 지연이 추가됩니다. 훅은 빠르고, 적게, 그리고 정말로 중요한 규칙에만 집중되도록 유지하세요.
알아둘 만한 안전 관련 참고 사항
문서에서 명시적으로 언급하는 몇 가지 현실들입니다:
if필터는 열려있는 방향으로 실패합니다.if필드를 사용해 훅의 범위를 권한 규칙에 맞추는데 명령을 파싱할 수 없으면, 훅은 그래도 실행됩니다. 확실한 허용/거부 강제를 위해서는 훅이 아니라 Claude Code의 권한 시스템을 사용하세요.- 훅은 제어 터미널 없이 실행됩니다 —
/dev/tty에서 프롬프트를 표시할 수 없습니다. 사용자 대상 메시지에는systemMessage나 제한된terminalSequence출력을 사용하세요. - stdout은 깨끗해야 합니다. stdout에는 JSON 결정 객체만 있어야 합니다. 셸 프로필의 불필요한 출력이 파싱을 깨뜨릴 수 있습니다.
- 주입된 컨텍스트는 신중하게 다루세요.
additionalContext는 프롬프트 인젝션 방어와 잘 어울리도록 명령문이 아닌 사실 진술문으로 작성되어야 합니다.
훅은 축소판 하네스 엔지니어링이다
한 걸음 물러나서 보면, 훅은 더 큰 아이디어의 구체적인 예입니다: 모델이 에이전트의 전부가 아니라, 그 주변의 시스템이 함께 있다는 것입니다. 훅은 루프, 도구, 메모리, 샌드박스와 나란히, 코딩 에이전트를 신뢰할 수 있게 만드는 하네스의 일부입니다. (이 사고 모델에 대해서는 하네스 엔지니어링에서 깊이 다룹니다.) PreToolUse 차단이나 PostToolUse 린터를 작성할 때, 당신은 하네스 엔지니어링을 하고 있는 것입니다 — 모델이 알아서 행동하기를 바라는 대신 에이전트의 행동을 결정론적으로 형성하는 일 말입니다.
이 관점은 또한 훅에 노력을 들일 가치가 있는 때가 언제인지도 알려줍니다: 그렇지 않으면 매번 에이전트에게 상기시켜야 할 규칙이라면, 훅의 후보입니다.
로컬 설치 없이 Claude Code의 강력한 기능을 온전히 활용하기
훅은 Claude Code CLI 안에 존재하므로, 사용하려면 이를 설치하고 구성해야 합니다 — 터미널 환경이 갖춰지지 않은 사람에게는 장벽이며, 개발자가 아닌 팀원에게는 불가능한 일입니다. 로컬 설치를 관리하지 않고도 Claude Code의 에이전트 기능을 원한다면, Happycapy에서 브라우저에서 Claude Code를 실행할 수 있습니다: 관리형 클라우드 샌드박스에서 Claude Code를 실행하며, 훅이 연결되는 하네스 — 루프, 도구, 메모리, 격리 — 가 이미 준비되어 있습니다. 작업을 설명하면 에이전트가 시각적 데스크톱에서 작업하는 모습을 지켜볼 수 있으며, 터미널은 필요하지 않습니다.
이렇게 생각해 보세요: 훅은 숙련된 사용자가 Claude Code의 하네스를 직접 세밀하게 조정할 수 있게 해주고, Happycapy는 모두에게 즉시 사용 가능한 관리형 하네스를 제공합니다. CLI 설정 때문에 Claude Code를 사용하고 싶었지만 막혀 있었다면, **happycapy.ai에서 무료로 시작**하고 오늘 브라우저에서 실제 작업을 실행해 보세요.
자주 묻는 질문
Q: Claude Code 훅이란 무엇인가요?
이는 사용자 정의 핸들러입니다 — 셸 명령, HTTP 엔드포인트, MCP 도구 호출, 또는 모델 프롬프트 — 도구 호출 전(PreToolUse), 편집 후(PostToolUse), 세션 시작 시 등 라이프사이클 이벤트에서 Claude Code가 자동으로 실행합니다. 이들은 작업을 검증, 포맷팅, 로깅, 차단, 또는 재작성할 수 있습니다.
Q: Claude Code는 어떤 훅 이벤트를 지원하나요?
SessionStart/SessionEnd, UserPromptSubmit, PreToolUse, PostToolUse(그리고 PostToolUseFailure), Stop/StopFailure, Notification, 서브에이전트 및 작업 이벤트, 압축 이벤트를 포함해 많습니다. 이들은 세션당 한 번, 턴당 한 번, 또는 모든 도구 호출마다 발동합니다.
Q: 훅이 도구 호출을 차단하게 하려면 어떻게 하나요?
명령 훅의 경우, 코드 2로 종료하세요 — 오직 종료 2만 차단합니다(종료 1은 차단하지 않습니다). PreToolUse의 경우, permissionDecision: "deny"가 포함된 JSON을 반환할 수도 있습니다. 확실한 강제를 위해서는 Claude Code의 권한 시스템을 선호하세요, 훅의 if 필터는 열려있는 방향으로 실패하기 때문입니다.
Q: Claude Code 훅은 어디에 구성하나요?
설정 파일에서: ~/.claude/settings.json(모든 프로젝트), .claude/settings.json(하나의 프로젝트, 공유 가능), 또는 .claude/settings.local.json(로컬 전용). 이벤트를 선택하고, 매처를 추가하고, 핸들러를 정의합니다.
Q: CLI를 설치하지 않고도 Claude Code 훅을 사용할 수 있나요?
훅 자체는 Claude Code CLI가 필요합니다. 로컬 설치 없이 Claude Code를 사용하는 것이 목표라면, Happycapy 같은 관리형 브라우저 샌드박스에서 실행하세요. 이는 에이전트와 그 하네스를 바로 사용할 수 있게 제공합니다 — CLI를 직접 설치하고 구성하고 싶지 않을 때 이상적입니다.
Q: 처음 추가하기 좋은 훅은 무엇인가요?
Edit|Write에 매치된 PostToolUse 린터입니다 — 모든 코드 변경 후 포매터를 실행하여, 에이전트의 출력이 항상 당신의 스타일 규칙을 충족하도록 합니다. 위험이 낮으면서도 즉시 유용합니다.

