
비엔지니어를 위한 Claude Code의 「훅(Hooks)」 설명 — AI에게 부탁하지 말고, 시스템으로 보호하라
요약
Claude Code의 '훅(Hooks)' 기능을 활용하여 AI의 판단에 의존하지 않고 특정 동작을 강제하는 시스템 구축 방법을 설명합니다. JSON 설정을 통해 도구 사용 후 테스트 실행이나 알림 등을 자동화하는 '포카요케(Poka-yoke)' 개념을 다룹니다.
핵심 포인트
- 훅은 AI의 판단을 거치지 않고 실행되는 확정적 제어 시스템임
- 설정은 '언제, 무엇에, 무엇을 하는가'의 3가지 요소로 구성됨
- 알림 훅을 통해 터미널을 계속 주시하지 않아도 작업 상태 확인 가능
- 훅의 정상 작동 여부를 확인하기 위한 별도의 테스트 작성이 권장됨
서론
Claude Code에게 "편집하면 반드시 테스트를 실행해 줘"라고 부탁했는데, 3번에 1번꼴로 잊어버리는 경우.
그런 경험 없으신가요?
원인은 Claude의 의욕 문제가 아닙니다. 부탁은 「판단 재료」가 될 뿐이기 때문입니다. AI는 매번 상황을 보고 판단하므로, 판단이 흔들리면 결과도 흔들립니다.
이 기사에서 다루는 「훅 (Hooks)」은 그 흔들림을 없애는 시스템입니다. 양자의 차이를 도표로 나타내면 다음과 같습니다.
차이는 AI의 판단을 경유하느냐 아니냐의 단 한 가지뿐입니다. 훅은 AI가 "하려고" 생각하지 않아도 동작합니다.
결론부터 말씀드리겠습니다.
훅은 「Claude Code가 ◯◯했을 때, 반드시 △△를 실행한다」라는 강제 규칙입니다. AI의 판단을 경유하지 않습니다. - 설정은 「언제・무엇에・무엇을 하는가」의 3가지만 적으면 됩니다. 어렵게 느껴지는 것은 JSON이라는 서식 때문입니다. - 처음 만든다면 **알림 훅 (Notification Hook)**을 추천합니다. 복사 붙여넣기 한 번으로 터미널(검은 화면의 작업창)을 계속 지켜보지 않아도 됩니다. - 단, 설정만 했다고 해서 신뢰할 수는 없습니다. 저는 「훅이 제대로 발화하는가」를 확인하는 테스트를 별도로 작성하고 있습니다. - 그리고 전부 차단하면 업무가 중단됩니다. 차단하는 것은 「확실하게 사고라고 판단되는 케이스」로만 제한해야 합니다.
전반부는 공식 문서 기반의 해설, 후반부(6장)는 제가 9개의 훅을 실운용하며 알게 된 점을 작성합니다.
1. 훅이란 무엇인가
비유
| 비유 | 훅에 해당하는 것 |
|---|---|
| 공장 라인 | 「제품이 검사 공정을 통과하면, 반드시 치수를 측정한다」는 센서 |
| ... |
포인트는 **「반드시」**라는 부분입니다.
저는 본업으로 제조업의 DX 추진을 하고 있는데, 현장에서 「주의해 주세요」라고 계속 말해도 불량은 줄어들지 않습니다. 줄어드는 것은, 애초에 틀릴 수 없는 지그(Jig)를 만들었을 때입니다. 이른바 포카요케 (Poka-yoke)입니다.
훅은 AI 개발에서의 포카요케입니다. 공식 문서가 「deterministic control (확정적 제어)」라고 부르는 것은 바로 이 「반드시 일어나는」 성질을 의미합니다.
구조는 3가지 요소뿐
훅의 설정은 궁극적으로 다음 3가지의 조합입니다.
이 3가지를 JSON이라는 서식의 텍스트 파일에 작성합니다. JSON은 「설정을 적기 위한 서식」으로, Excel 셀에 값을 넣는 것과 비슷한 감각으로 접근해도 무방합니다.
실제 모습은 다음과 같습니다.
{
"hooks": {
"PostToolUse": [
...
일본어로 직역하면 "도구를 사용한 후 (PostToolUse)에, 그것이 파일 편집 (Edit 또는 Write)이라면, 그 파일에 포맷팅 도구를 적용하라"입니다.
설정 파일의 구조를 먼저 파악하기
막히는 부분을 미리 해결해 두겠습니다. 설정 파일은 중첩(상자 안의 상자) 구조로 되어 있습니다.
2. 【핸즈온】 첫 번째 단계: 알림 훅
공식 측에서 「우선 이것부터」라고 권장하는 것이 알림 훅입니다. Claude가 확인을 기다리는 상태가 되었을 때 데스크톱 알림이 뜨므로, 터미널을 계속 주시하지 않아도 됩니다.
스텝 1: 설정 파일 열기
앞으로 할 일: 자신만의 설정 파일에 알림을 띄우는 규칙을 하나 추가합니다.
~/.claude/settings.json
을 엽니다 (~는 자신의 홈 디렉토리를 가리키는 기호입니다. 없다면 새로 생성하세요).
macOS의 경우, 다음을 작성합니다.
{
"hooks": {
"Notification": [
...
osascript는 macOS에 기본적으로 포함된, Mac을 조작하기 위한 도구입니다. Linux・Windows (PowerShell)용 커맨드는 공식 문서에 준비되어 있습니다.
잘 안될 때
| 증상 | 원인 | 대처 |
|---|---|---|
| 파일을 찾을 수 없음 | ~/.claude/는 점(.)으로 시작하는 숨김 폴더임 | Finder에서 Cmd+Shift+.을 누르면 숨김 파일이 표시됩니다 |
| 저장할 수 없음 | 권한 문제 | 에디터로 다시 열거나, chmod 600 ~/.claude/settings.json을 실행 |
| 이미 내용이 있음 | 덮어쓰면 기존 설정이 사라짐 | hooks 항목만 기존 JSON에 추가합니다. 판단이 어려우면 Claude에게 직접 "이 설정을 망가뜨리지 말고 알림 훅을 추가해 줘"라고 부탁하는 것이 안전합니다 |
단계 2: 설정이 읽혔는지 확인하기
이제 할 일: 작성한 설정을 Claude Code가 인식하고 있는지 눈으로 직접 확인합니다.
Claude Code에서 /hooks
을 입력합니다. 설정된 후크 목록이 표시되므로, Notification
항목에 자신의 설정이 나와 있다면 성공입니다.
잘 안 될 때 (문제 발생 시)
| 증상 | 원인 | 대처 방안 |
|---|---|---|
/hooks에 아무것도 안 나옴 | JSON 형식 오류. 끝의 쉼표(,)나 주석은 금지입니다 | `cat ~/.claude/settings.json |
| 몇 초 기다려도 반영되지 않음 | 설정 재로딩이 일어나지 않았습니다 | Claude Code의 세션을 재시작합니다 |
| 항목은 있지만 위치가 다름 | 이벤트 이름 철자 오류. 대소문자를 구분합니다 | |
notification이 아니라 Notification입니다 |
/hooks 메뉴는 보기 전용입니다. 추가나 변경은 설정 파일을 직접 편집하거나, Claude에게 부탁해야 합니다.
단계 3: 실제로 작동시켜 보기
이제 할 일: 일부러 확인 대기 상태를 만들어서 알림이 오는지 시험해봅니다.
Esc로 돌아가서 Claude에게 허가가 필요한 작업(파일 새로 생성 등)을 부탁하고, 다른 창으로 전환합니다. 알림이 온다면 완성입니다.
잘 안 될 때 (문제 발생 시)
| 증상 | 원인 | 대처 방안 |
|---|---|---|
| 알림이 오지 않음 | macOS의 알림 설정에서 터미널 앱이 차단되어 있습니다 | 시스템 설정 → '알림' → 사용 중인 터미널 앱을 찾아 알림을 허용합니다 |
| 애초에 확인 대기 상태가 안 됨 | 권한 설정이 느슨하여, 확인 과정 없이 실행되고 있습니다 | settings.json의 permissions를 확인합니다. 전부 허용하면 알림이 나올 기회가 없습니다 |
3. 우선은 5개만 외우세요
이벤트는 30가지 이상 있지만, 실무에서 사용하는 것은 거의 이 5가지입니다.
| 이벤트 | 발동 시점 | 주요 용도 |
|---|---|---|
PreToolUse | 도구를 사용하기 전 | 위험한 작업을 차단합니다 |
PostToolUse | 도구가 성공한 후 | 자동 포맷팅, 로그 기록 |
Notification | 알림이 나올 때 | 데스크톱 알림 |
SessionStart | 세션 시작/재개 시 | 사전 정보 주입 |
Stop | Claude가 응답을 마쳤을 때 | 완료 체크 |
나머지 25가지 이상은 기사 말미의 부록에 정리했습니다. 처음부터 전부 외울 필요는 없습니다.
발동 위치를 시간 축으로 보기
PreToolUse와 PostToolUse의 사용처 구분은 처음에 반드시 헷갈리는 부분입니다. Claude가 한 번 작업을 수행하는 흐름에 비유하면 이해하기 쉽습니다.
여기서가 가장 중요한 포인트입니다. 막고 싶다면 PreToolUse를 사용해야 합니다. PostToolUse는 이미 실행된 후이므로 취소할 수 없습니다.
'파일을 보호한다'는 목적으로 PostToolUse를 사용하면, 덮어쓰인 후에 '안 됩니다'라고 말하는 것과 같은 의미 없는 후크가 됩니다.
매처(Matcher)로 대상을 좁히기
매처를 작성하지 않으면, 해당 이벤트가 발생할 때마다 매번 후크가 작동합니다.
- `
| 이벤트 | 매처(Matcher)가 좁히는 대상 | 예시 |
|---|---|---|
PreToolUse / PostToolUse 계열 | 도구 이름 (Tool Name) | Bash, `Edit |
SessionStart | 시작 트리거 | startup, resume, clear, compact, fork |
Notification | 알림 종류 | permission_prompt, idle_prompt |
PreCompact / PostCompact | 요약(Compaction) 트리거 | manual, auto |
ConfigChange | 설정 종류 | user_settings, project_settings |
FileChanged | 감시할 파일명 | .envrc, .env |
UserPromptSubmit, Stop, CwdChanged 등은 매처(Matcher)를 지원하지 않으며, 항상 모든 이벤트에 대해 실행(fire)됩니다.
4. 바로 사용할 수 있는 레시피 3가지
레시피 ①: 편집한 파일을 자동 정렬
앞서 언급한 PostToolUse + Edit|Write의 예시가 이것입니다. 팀과 공유하고 싶으므로 프로젝트의 .claude/settings.json에 배치합니다.
잘 작동하지 않을 때
| 증상 | 원인 | 대처 |
|---|---|---|
jq: command not found | jq (JSON에서 값을 추출하는 도구)가 설치되지 않음 | macOS: brew install jq / Ubuntu: apt-get install jq |
| 정렬 도구를 찾을 수 없음 | 프로젝트에 prettier가 설치되어 있지 않음 | npm install -D prettier를 실행하거나, 사용 중인 정렬 도구로 교체합니다 |
| 대상 외 파일까지 정렬됨 | 매처(Matcher)가 도구 이름만 확인하고 있음 | 스크립트 파일로 분리하여 확장자에 따라 분류하는 로직을 작성합니다 |
레시피 ②: 중요 파일 보호하기
.env (비밀번호 등이 포함된 파일)나 package-lock.json을 Claude가 건드리지 못하게 하는 설정입니다.
먼저 .claude/hooks/protect-files.sh를 만듭니다.
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
...
실행 가능하도록 설정합니다.
chmod +x .claude/hooks/protect-files.sh
.claude/settings.json에 등록합니다.
{
"hooks": {
"PreToolUse": [
...
차단된 이유는 Claude에게도 전달되므로, Claude는 다른 방법을 다시 생각하게 됩니다.
잘 작동하지 않을 때
| 증상 | 원인 | 대처 |
|---|---|---|
Permission denied | 실행 권한이 없음 | chmod +x를 실행했는지 확인 |
command not found | 상대 경로로 작성함. 후크(Hook)의 실행 위치는 보장되지 않음 | $CLAUDE_PROJECT_DIR를 사용하여 절대 경로로 작성합니다 |
(상대 경로 = "여기서부터 위로 2단계"와 같이 현재 위치를 기준으로 하는 주소. 절대 경로 = "/Users/yamato/..."와 같이 처음부터 작성하는 완전한 주소. 후크는 어디서 실행될지 보장되지 않으므로 절대 경로가 안전합니다.)
| 차단되지 않음 | PostToolUse를 사용 중임 | PostToolUse로는 취소할 수 없습니다 (이미 실행되었기 때문). 방지하려면 PreToolUse를 사용해야 합니다 |
레시피 ③: 대화가 요약된 후에 전제 조건 재주입
Claude Code는 대화가 길어지면 내용을 자동으로 요약(Compaction)합니다. 이때 세부적인 전제 조건들이 손실되기 쉽습니다.
{
"hooks": {
"SessionStart": [
...
echo로 출력한 문장이 그대로 Claude의 기억에 추가됩니다. git log --oneline -5
「直近5件のコミット履歴」などに差し替えることもできます。
なお、毎回のセッション開始時に読ませたいだけなら、フックより CLAUDE.md を使うほうが簡単です。
5. フックとの「会話」の仕方
フックは、Claude Codeと以下のようにやり取りします。
やり取りに使えるのはこの2方向だけです。フックからスラッシュコマンドを叩いたり、Claudeに追加で質問したりはできません。
Bashコマンド実行前なら、こんなデータが渡ってきます。
{
"session_id": "abc123",
"cwd": "/Users/yamato/myproject",
...
終了コードで意思表示する
ここが一番大事です。終了コード(プログラムが終わるときに返す数字) で意思表示します。
| 終了コード | 意味 |
|---|---|
0 | 異議なし。処理は通常どおり進む(※許可したわけではなく、通常の権限確認は続く) |
2 | ブロック。標準エラー出力に書いた理由がClaudeに伝わり、Claudeはやり方を変える |
| その他 | 処理は進む。エラー表示だけ出る |
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
...
SessionStart
Setup
Notification
などブロックできないイベントもあります。その場合は終了コード2でもメッセージが表示されるだけで処理は続きます。
より細かく制御する(JSON出力)
終了コード0でJSONを出力すると、細かい指示ができます。
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
...
permissionDecision
の選択肢は `
| 프로젝트 | 훅 (Hook) | 역할 |
|---|---|---|
| 블로그 운영 | pre_bash_affiliate_guard.sh | 기사 게시 명령에 가짜 어필리에이트 (Affiliate) URL이 섞여 있으면 쓰기 전에 중단 |
| 블로그 운영 | pre_bash_cwd_guard.sh | 작업 폴더를 지정하지 않고 git commit 등을 입력하려고 하면 중단 |
| 블로그 운영 | post_edit_content_guard.sh | 기사를 편집한 후에 용어·프로필 모순을 검사 |
| 블로그 운영 | post_bash_db_guard.sh | 게시 후에 데이터베이스 측의 기사를 검사 |
| 경영 관리 | owner_outside_guard.sh | 계획서나 규칙 문서를 만졌을 때, 확인해야 할 관점을 상기시킴 |
| 기타 4개 | 정적 체크 (Static Check)・Lint 등 | 프로젝트별 검사 |
(Lint/정적 체크 (Static Check) = 프로그램을 실행하지 않고, 작성 방식의 오류나 위험한 패턴을 기계적으로 점검하는 것. 학교에서 말하는 교칙 체크와 같습니다)
화려한 것은 하나도 없습니다. "어제는 지켰던 규칙을 오늘은 잊어버린다", "수정했더니 다른 곳이 망가진다"에 대한 대책이 쌓인 결과입니다.
6-2. 「훅이 정말로 작동하는가」를 확인하는 테스트를 작성했다
이 부분이 가장 전달하고 싶은 내용입니다.
훅을 설정하면, 설정했다는 사실만으로 안심하게 됩니다. 하지만 훅은 소리 없이 망가집니다. 스크립트를 다시 썼을 때, 경로(Path)가 어긋났을 때, 조건식을 틀렸을 때. 그리고 "작동하지 않는 훅"은 "훅이 없는 것"과 마찬가지인데, 이쪽은 보호받고 있다고 착각하게 됩니다. 이 상태가 가장 위험합니다.
그래서 저는 가드용 훅에 대해 **회귀 테스트 (Regression Test)**를 작성하고 있습니다. 회귀 테스트란 "이전과 동일하게 동작하는지, 변경될 때마다 기계로 확인하는 테스트"를 말합니다.
bash .claude/hooks/tests/test_affiliate_guard.sh
bash .claude/hooks/tests/test_pre_bash_cwd_guard.sh
이 글을 쓰고 있는 2026년 7월 25일에 실행한 결과입니다.
=== 결과: PASS=16 FAIL=0 ===
=== 결과: PASS=20 FAIL=0 ===
합계 36개 항목. 내용은 "멈춰야 할 것이 멈추는가"와 "통과해야 할 것이 통과하는가"를 모두 확인하고 있습니다.
=== block expected (쓰기 계열에서 가짜 어필리에이트 시그널이 있는 경우) ===
PASS: a8ejpredirect= 付き update
PASS: 가짜 도메인 a8-tsushinkouza
...
"멈춰야 할 것이 멈추는" 테스트보다, "통과해야 할 것이 통과하는" 테스트의 수가 더 많다는 것이 포인트입니다. 후술하겠지만, 오작동(False Positive)하는 훅은 쓸모가 없기 때문입니다.
가드를 두는 것만으로는 불충분하며, 망가지지 않았는지 확인되어야 비로소 신뢰할 수 있는 메커니즘이 됩니다. "설정했을 터"가 아니라 "이번에도 작동했다"라고 말할 수 있는 상태로 만드는 것입니다.
6-3. 전부 차단하면, 업무가 중단된다
처음에 저지르기 쉬운 실수가 이것입니다.
오랫동안 운영한 프로젝트에는 이전부터 있던 경고나 형식 위반이 남아 있습니다. 거기에 전건 차단 훅을 넣으면, 이번 변경과 무관한 문제로 계속 중단됩니다. 작업이 1mm도 진행되지 않습니다.
제가 취한 방침은 "중대한 것만 차단, 나머지는 경고"입니다. 실제 README에는 이렇게 적어두었습니다.
강도는
중대한 것(가짜 어필리에이트 URL)만 차단/나머지는 경고.
그림으로 나타내면, 이런 판단을 하고 있습니다.
용어의 오용이나 프로필의 모순은 발견해도 멈추지 않습니다. 표준 에러 출력(Standard Error Output)에 경고를 낼 뿐입니다. 멈추는 것은 "실제로 가짜 어필리에이트 URL이 발견되었을 때"뿐입니다.
또 하나, 오작동을 피하기 위한 궁리로 "금지 패턴을 해설하고 있는 문서"는 검사 대상에서 제외하고 있습니다. 규칙을 설명한 문서 자체가 금지 패턴을 포함하게 되어, 자신의 훅에 걸리는——라는 어처구니없는 사고를 한 번 겪었습니다.
6-4. 퇴로를 미리 만들어 둔다
훅은 "절대 통과시키지 않는 벽"이 아니라 "실수를 막아주는 울타리"입니다. 넘을 수 있는 수단을 처음부터 마련해 두지 않으면, 막상 상황이 닥쳤을 때 설정 파일을 편집해야 하는 상황이 벌어집니다.
저의 가드에는 3종류의 퇴로를 영향 범위가 큰 순서대로 마련해 두었습니다.
| 방법 | 효과 |
|---|---|
환경 변수 HOOK_DISABLE_GUARDS=1 | |
| 해당 세션에서 모든 훅(Hook) 중지 | |
환경 변수 HOOK_DISABLE_CWD_GUARD=1 | |
| 특정 가드(Guard)만 중지 | |
명령어 끝에 # ok-cwd 추가 | |
| 해당 명령어 1회만 통과 |
여기서 한 가지 기교가 있습니다. 이스케이프(Escape)용 암호는 "끝부분 일치"일 때만 유효하도록 설정했습니다.
# 끝부분 일치만 허용 = 문장 중간에 문자열이 있는 것만으로는 통과시키지 않음
trimmed="$(printf '%s' "$cmd" | sed 's/[[:space:]]*$//')'
case "$trimmed" in *"# ok-cwd"|*"--no-cwd-check") exit 0 ;; esac
커밋 메시지에 우연히 ok-cwd라는 문자열이 포함되어 가드가 무효화되는 보안 허점을 막기 위해서입니다. 테스트 항목에도 "ok-cwd가 끝부분이 아닌 경우(메시지 내부 등)에는 통과시키지 않는다"를 포함해 두었습니다.
6-5. 검사할 수 없을 때는 멈추지 말고 경고할 것
훅(Hook)이 의존하는 도구가 없는 환경에서는 어떻게 해야 할까요?
저는 "묵묵히 통과"가 아니라 "경고를 내보내고 통과"하도록 설정했습니다.
command -v python3 >/dev/null 2>&1 || {
echo "[cwd-guard/WARN] python3를 찾을 수 없어 검사를 스킵합니다 (fail-open)" >&2
exit 0
...
이것은 fail-open (안전하게 열기)이라는 사고방식입니다. "인프라 사정 때문에 개발이 중단되지 않는 것"을 우선시하면서도, "이번에는 검사하지 않았다"라는 사실은 반드시 보이도록 합니다. 묵묵히 통과시켜 버리면, 검사되지 않았음에도 검사된 것으로 착각하게 되므로 이것이 가장 위험합니다.
참고로 공식 if 필드(Bash 명령어 내용까지 확인하여 필터링하는 기능)도 같은 철학을 가지고 있으며, 명령어를 해석할 수 없는 경우에는 fail-open이 된다고 명시되어 있습니다. 엄격하게 허가 및 금지를 강제하고 싶다면, 훅(Hook)이 아니라 권한(Permission) 기능을 사용하는 것이 정답입니다.
7. 과하게 하지 말 것
여기까지 읽으면 훅(Hook)을 많이 만들고 싶어질지도 모릅니다. 하지만 시스템에도 유지비가 따릅니다.
매처(Matcher)를 공란으로 둔 자동 승인은 위험함
Claude가 계획을 다 세웠을 때의 확인을 자동 승인하는 설정이 있습니다.
{
"hooks": {
"PermissionRequest": [
...
규칙을 너무 늘리면 AI도 사람도 읽을 수 없음
과거의 실패 사례를 모두 추가하다 보면 입구가 거대해집니다. 오래된 규칙과 새로운 규칙이 충돌하면 AI의 판단도 불안정해집니다.
입구는 짧게 유지하고, 자세한 절차는 별도 파일로 분리하세요. 한 달에 한 번 "지금도 필요한가"를 검토하는 정도면 충분합니다.
기타 제한 사항
- 훅(Hook)은 표준 출력(Standard Output)・표준 에러(Standard Error)・종료 코드(Exit Code)로만 대화할 수 있습니다. 슬래시 명령어(Slash command)나 도구 호출(Tool call)은 실행할 수 없습니다.
- 타임아웃(Timeout):
command,http,mcp_tool은 10분 (UserPromptSubmit은 30초,MessageDisplay는 10초) /prompt는 30초 /agent는 60초입니다.timeout으로 개별 변경 가능합니다. PermissionRequest는-p를 이용한 비대화형 모드에서는 발화하지 않습니다. 대신PreToolUse를 사용합니다.Stop은 사용자가 중단했을 때는 발화하지 않습니다.- 여러 개의 훅(Hook)이 동일한 도구의 인자(Argument)를 수정할 경우, 어떤 것이 적용될지 예측할 수 없습니다 (병렬 실행 때문).
8. 잘 안될 때의 체크리스트 (종합)
훅(Hook)이 작동하지 않을 때
/hooks에서 올바른 이벤트 아래에 표시되고 있는가- 매처(Matcher)의 철자(대소문자 구분 포함)가 도구 이름과 일치하는가
- 이벤트 선택이 올바른가 (
PreToolUse는 실행 전,PostToolUse는 실행 후)
"hook error"가 발생할 때
스크립트를 수동으로 테스트합니다.
echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh
echo $?
| 에러 | 대처 |
|---|---|
command not found | 절대 경로 또는 $CLAUDE_PROJECT_DIR를 사용한다 |
jq: command not found | jq를 설치한다 |
| 애초에 동작하지 않음 | chmod +x ./my-hook.sh로 실행 권한을 부여한다 |
JSON 파싱 에러가 발생하는 경우 (의외의 함정)
~/.zshrc나 ~/.bashrc에 echo 문이 있으면, 해당 출력이 훅 (Hook)의 JSON에 섞여 들어가 파싱에 실패합니다.
Shell ready on arm64 ← 이것이 섞임
{"decision": "block", ...}
대책은 셸 설정 파일의 echo를 대화형 모드 (interactive mode)로 한정하는 것입니다.
if [[ $- == *i* ]]; then
echo "Shell ready"
fi
Stop 훅이 멈추지 않는 경우
Stop 훅이 8회 연속으로 차단(block)되면, Claude Code가 강제로 종료합니다. 스크립트 측에서 "이미 계속 진행을 발동했는지"를 판정해야 합니다.
#!/bin/bash
INPUT=$(cat)
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
...
더 자세히 알아보기
Ctrl+O로 트랜스크립트 (transcript) 표시 (각 훅의 실행 결과를 한 줄로 볼 수 있습니다)claude --debug-file /tmp/claude.log로 실행 → 다른 터미널에서tail -f /tmp/claude.log실행- 실행 시 설정하는 것을 잊었다면, 세션 중에
/debug를 실행
요약
AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기