476| `async` | 아니요 | `true`이면 차단하지 않고 백그라운드에서 실행됩니다. [백그라운드에서 hook 실행](#run-hooks-in-the-background) 참조 |476| `async` | 아니요 | `true`이면 차단하지 않고 백그라운드에서 실행됩니다. [백그라운드에서 hook 실행](#run-hooks-in-the-background) 참조 |
477| `asyncRewake` | 아니요 | `true`이면 백그라운드에서 실행되고 종료 코드 2에서 Claude를 깨웁니다. 훅의 stderr 또는 stderr가 비어 있으면 stdout이 Claude에게 [시스템 리마인더](/docs/ko/glossary#system-reminder)로 표시되므로 장시간 실행되는 백그라운드 실패에 반응할 수 있습니다. |477| `asyncRewake` | 아니요 | `true`이면 백그라운드에서 실행되고 종료 코드 2에서 Claude를 깨웁니다. 훅의 stderr 또는 stderr가 비어 있으면 stdout이 Claude에게 [시스템 리마인더](/docs/ko/glossary#system-reminder)로 표시되므로 장시간 실행되는 백그라운드 실패에 반응할 수 있습니다. |
478| `shell` | 아니요 | 이 hook에 사용할 셸. `"bash"` 또는 `"powershell"`을 허용합니다. 기본값은 `"bash"` 또는 Git Bash가 설치되지 않은 경우 Windows에서 `"powershell"`입니다. `"powershell"`을 설정하면 Windows에서 PowerShell을 통해 명령을 실행합니다. `CLAUDE_CODE_USE_POWERSHELL_TOOL`이 필요하지 않습니다. hook이 PowerShell을 직접 생성하기 때문입니다. `args`가 설정되면 무시됩니다. |478| `shell` | 아니요 | 이 hook에 사용할 셸. `"bash"` 또는 `"powershell"`을 허용합니다. 기본값은 `"bash"` 또는 Git Bash가 설치되지 않은 경우 Windows에서 `"powershell"`입니다. `"powershell"`을 설정하면 Windows에서 PowerShell을 통해 명령을 실행합니다. `CLAUDE_CODE_USE_POWERSHELL_TOOL`이 필요하지 않습니다. hook이 PowerShell을 직접 생성하기 때문입니다. `args`가 설정되면 무시됩니다. |
479| `onFailure` | 아니요 | 훅이 실패할 때 해당 작업에 일어나는 동작: 기본값인 `"continue"` 또는 `"block"`. [훅이 실패할 때 작업 차단](#block-the-action-when-a-hook-fails)을 참조하십시오. Claude Code v2.1.295 이상이 필요합니다. |
479 480
480<a id="exec-form-and-shell-form" />481<a id="exec-form-and-shell-form" />
481 482
533| `url` | 예 | POST 요청을 보낼 URL |534| `url` | 예 | POST 요청을 보낼 URL |
534| `headers` | 아니요 | 키-값 쌍으로 추가 HTTP 헤더. 값은 `$VAR_NAME` 또는 `${VAR_NAME}` 구문을 사용한 환경 변수 보간을 지원합니다. `allowedEnvVars`에 나열된 변수만 해결됩니다. |535| `headers` | 아니요 | 키-값 쌍으로 추가 HTTP 헤더. 값은 `$VAR_NAME` 또는 `${VAR_NAME}` 구문을 사용한 환경 변수 보간을 지원합니다. `allowedEnvVars`에 나열된 변수만 해결됩니다. |
535| `allowedEnvVars` | 아니요 | 헤더 값에 보간될 수 있는 환경 변수 이름 목록. 나열되지 않은 변수에 대한 참조는 빈 문자열로 바뀝니다. 환경 변수 보간이 작동하려면 필수입니다. |536| `allowedEnvVars` | 아니요 | 헤더 값에 보간될 수 있는 환경 변수 이름 목록. 나열되지 않은 변수에 대한 참조는 빈 문자열로 바뀝니다. 환경 변수 보간이 작동하려면 필수입니다. |
537| `onFailure` | 아니요 | 훅이 실패할 때 해당 작업에 일어나는 동작: 기본값인 `"continue"` 또는 `"block"`. [훅이 실패할 때 작업 차단](#block-the-action-when-a-hook-fails)을 참조하십시오. Claude Code v2.1.295 이상이 필요합니다. |
536 538
537Claude Code는 hook의 [JSON 입력](#hook-input-and-output)을 `Content-Type: application/json`을 사용하여 POST 요청 본문으로 보냅니다. 응답 본문은 명령 hook과 동일한 [JSON 출력 형식](#json-output)을 사용합니다.539Claude Code는 hook의 [JSON 입력](#hook-input-and-output)을 `Content-Type: application/json`을 사용하여 POST 요청 본문으로 보냅니다. 응답 본문은 명령 hook과 동일한 [JSON 출력 형식](#json-output)을 사용합니다.
538 540
821 종료 코드 출력823 종료 코드 출력
822</h3>824</h3>
823 825
824hook 명령의 종료 코드는 Claude Code에 작업을 진행할지, 차단할지 또는 무시할지를 알려줍니다. 종료 코드는 단독으로 작동하지 않습니다. Claude Code는 0뿐만 아니라 모든 종료 코드에서 stdout의 [JSON 출력 필드](#json-output)를 읽으며, 표준 결정 모델을 사용하는 이벤트의 경우 스키마 검증을 통과하는 구문 분석된 객체가 코드와 함께 적용됩니다. Exit 2의 차단은 JSON이 재정의할 수 없는 유일한 결과입니다.826hook의 종료 코드는 도구 호출이나 프롬프트처럼 hook을 트리거한 작업을 계속 진행할지를 Claude Code에 알려줍니다. 완료된 실행의 결과는 다음 세 가지 중 하나입니다:
825 827
826두 개의 표가 이벤트별 예외를 다룹니다: [이벤트별 종료 코드 2 동작](#exit-code-2-behavior-per-event)은 각 이벤트에 대해 종료 코드가 수행하는 작업을 설명하고, [결정 제어](#decision-control)는 각 이벤트가 적용하는 결정 필드를 설명합니다. `systemMessage`와 같은 범용 필드는 대부분의 이벤트에서 작동하며 [JSON 출력](#json-output) 표에 나열됩니다.828* **성공**: hook이 0으로 종료합니다. Claude Code는 hook이 출력한 [JSON 출력](#json-output) 필드를 적용하며, 해당 필드가 작업을 차단하거나 거부하지 않는 한 작업이 진행됩니다.
829* **차단 오류**: hook이 2로 종료합니다. [차단할 수 있는 이벤트](#exit-code-2-behavior-per-event)에서 Claude Code는 작업을 중지합니다.
830* **차단하지 않는 오류**: hook이 그 밖의 코드로 종료하거나, 시작되지 않거나 잘못된 JSON을 출력하는 등 다른 방식으로 실패합니다. 작업은 진행되며, `PreToolUse`와 같은 이벤트에서는 트랜스크립트에 `<hook name> hook error` 알림이 표시됩니다. 실패한 hook이 작업을 차단하게 하려면 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)을 설정합니다.
831
832hook이 stdout에 출력하는 내용에 따라 결과가 달라질 수 있습니다. 예를 들어 `PreToolUse` hook이 1로 종료하지만 검증을 통과하는 JSON을 출력하면 실행은 성공이며 JSON 필드가 결과를 결정합니다. `PreToolUse`와 같은 이벤트에서 hook의 결과를 확인하려면 첫 번째 열에서 stdout에 출력한 내용을, 맨 위 행에서 종료 코드를 찾아 맞춰 봅니다:
833
834| Stdout | 종료 0 | 종료 2 | 그 밖의 종료 코드 |
835| :- | :- | :- | :- |
836| [스키마 검증](#json-output)을 통과하는 JSON 객체 | 성공. 필드가 적용됩니다 | 차단 오류. Claude Code는 여전히 필드를 읽지만 필드가 차단을 재정의할 수는 없습니다 | 성공. Claude Code는 종료 코드를 무시하고 필드만으로 결과를 결정합니다. [`onFailure: "block"`](#block-the-action-when-a-hook-fails)을 설정하면 실패로 간주됩니다 |
837| [구문 분석할 수 없거나](#exit-code-0) 스키마 검증에 실패하는 JSON | 차단하지 않는 오류. 알림에 구문 분석 또는 검증 메시지가 표시됩니다 | 차단 오류. stderr이 이유가 됩니다 | 차단하지 않는 오류. 알림에 구문 분석 또는 검증 메시지가 표시됩니다 |
838| [일반 텍스트](#exit-code-0) 또는 출력 없음 | 성공 | 차단 오류. stderr이 이유가 됩니다 | 차단하지 않는 오류. 알림에 stderr의 첫 번째 줄이 표시됩니다 |
839
840일부 이벤트에는 자체 규칙이 있습니다:
841
842* **`WorktreeCreate`**: JSON 내용과 관계없이 0이 아닌 종료 코드는 worktree 생성을 실패하게 합니다.
843* **`WorktreeRemove`**: 0이 아닌 종료 코드는 이후에도 디렉터리가 여전히 존재하면 worktree 제거를 실패하게 합니다.
844* **`Stop`, `SubagentStop`, `TaskCompleted`, 플러그인의 `UserPromptSubmit` hook**: hook이 stdout에 아무것도 출력하지 않고 2로 종료하며 stderr에 `No such file or directory`처럼 파일이 없다는 내용이 있으면 Claude Code는 실행을 차단하지 않는 오류로 취급합니다.
845* **`Elicitation` 및 `ElicitationResult`**: Claude Code는 hook이 0으로 종료할 때 `hookSpecificOutput`을 적용하고, 그 밖의 종료 코드에서는 무시합니다.
846* **`StopFailure`와 같이 hook 출력을 버리는 이벤트**: Claude Code는 모든 종료 코드에서 JSON을 무시합니다. 단, `terminalSequence`와 같은 부수 효과 필드는 여전히 동작합니다.
847
848이벤트에서 종료 코드 2가 수행하는 작업은 [이벤트별 종료 코드 2 동작](#exit-code-2-behavior-per-event)을 참조하세요. 이벤트가 적용하는 결정 필드는 [결정 제어](#decision-control)를 참조하세요.
827 849
828<h4 id="exit-code-0">850<h4 id="exit-code-0">
829 종료 코드 0851 종료 코드 0
835 857
836Claude Code가 stdout을 [JSON 출력](#json-output)으로 읽는지 일반 텍스트로 읽는지는 주변 공백을 무시하고 시작 및 끝 문자에 따라 달라집니다:858Claude Code가 stdout을 [JSON 출력](#json-output)으로 읽는지 일반 텍스트로 읽는지는 주변 공백을 무시하고 시작 및 끝 문자에 따라 달라집니다:
837 859
838* **`{`로 시작하고 `}`로 끝남**: Claude Code는 이를 JSON으로 구문 분석합니다. 출력이 각각 자체적으로 JSON으로 구문 분석되는 두 줄 이상이고 필드를 설정하는 [JSON 출력](#json-output) 객체인 줄이 없는 경우 Claude Code는 전체 출력을 일반 텍스트로 취급합니다. 이러한 줄 중 하나가 필드를 설정하면 전체 출력은 아래에 설명된 구문 분석 실패가 됩니다.860* **`{`로 시작하고 `}`로 끝남**: Claude Code는 이를 JSON으로 구문 분석합니다. 출력이 각각 자체적으로 JSON으로 구문 분석되는 두 줄 이상이고 필드를 설정하는 [JSON 출력](#json-output) 객체인 줄이 없는 경우 Claude Code는 전체 출력을 일반 텍스트로 취급합니다. 이러한 줄 중 하나가 필드를 설정하면 전체 출력은 구문 분석 실패가 됩니다.
839* **`{`로 시작하지만 `}`로 끝나지 않음**: Claude Code는 이를 일반 텍스트로 취급합니다.861* **`{`로 시작하지만 `}`로 끝나지 않음**: Claude Code는 이를 일반 텍스트로 취급합니다.
840* **다른 것으로 시작**: Claude Code는 JSON 배열이나 따옴표로 묶인 JSON 문자열을 포함하여 이를 일반 텍스트로 취급합니다.862* **다른 것으로 시작**: Claude Code는 JSON 배열이나 따옴표로 묶인 JSON 문자열을 포함하여 이를 일반 텍스트로 취급합니다.
841 863
842표준 결정 모델을 사용하는 이벤트의 경우 스키마 검증에 실패하는 구문 분석된 객체와 함께 종료 0으로 나가면 차단하지 않는 오류입니다: 작업이 진행되고 트랜스크립트는 검증 메시지와 함께 `<hook name> hook error` 알림을 표시합니다. 2 이외의 다른 종료 코드에서도 동일한 일이 발생하며, [종료 2는 여전히 차단합니다](#exit-code-2).864Claude Code가 stdout을 JSON으로 구문 분석하려고 시도했지만 실패하거나, 구문 분석된 객체가 [스키마 검증](#json-output)에 실패하면 실행은 [차단하지 않는 오류](#exit-code-output)가 됩니다. `<hook name> hook error` 알림에 구문 분석 또는 검증 메시지가 표시됩니다. 일반 텍스트 stdout을 컨텍스트로 추가하는 이벤트에서 Claude Code는 구문 분석에 실패한 stdout을 추가하지 않습니다.
843
844표준 결정 모델을 사용하는 이벤트의 경우 Claude Code가 stdout을 JSON으로 구문 분석하려고 시도하고 실패하면 2 이외의 모든 종료 코드에서 차단하지 않는 오류를 보고합니다. 트랜스크립트는 구문 분석 메시지와 함께 `<hook name> hook error` 알림을 표시합니다. 일반 텍스트 stdout을 컨텍스트로 추가하는 이벤트에서 Claude Code는 텍스트를 추가하지 않습니다. v2.1.248 이전에는 Claude Code가 해당 stdout을 일반 텍스트로 취급했습니다.
845 865
846종료 0으로 나가는 hook의 stderr은 디버그 로그로만 가며 트랜스크립트로는 가지 않고, Claude는 이를 보지 못합니다. 직접 읽으려면 [디버그 로깅](#debug-hooks)을 활성화합니다. `PostToolUse` 또는 `PostToolUseFailure` hook에서 Claude에 경고를 표시하려면 대신 종료 2로 나가면 도구가 이미 실행되었더라도 [Claude가 stderr을 봅니다](#exit-code-2-behavior-per-event).866Claude는 0으로 종료하는 hook의 stderr을 보지 못합니다. `PreToolUse`와 같은 이벤트에서 직접 읽으려면 [디버그 로깅](#debug-hooks)을 활성화합니다. `PostToolUse` 또는 `PostToolUseFailure` hook에서 Claude에 경고를 표시하려면 대신 종료 2로 나가면 도구가 이미 실행되었더라도 [Claude가 stderr을 봅니다](#exit-code-2-behavior-per-event).
847 867
848<h4 id="exit-code-2">868<h4 id="exit-code-2">
849 종료 코드 2869 종료 코드 2
850</h4>870</h4>
851 871
852종료 2는 차단 오류를 의미합니다. [차단할 수 있는 이벤트](#exit-code-2-behavior-per-event)에서 종료 2는 JSON을 출력하는지 여부와 관계없이 차단합니다: JSON `permissionDecision`의 `"allow"`도 이를 재정의할 수 없습니다. Claude Code는 여전히 stdout에서 유효한 [JSON 출력](#json-output)을 읽습니다. `Elicitation` 및 `ElicitationResult`에서는 종료 2 hook의 `hookSpecificOutput`이 무시됩니다.872작업을 차단하려면 코드 2로 종료합니다. [차단할 수 있는 이벤트](#exit-code-2-behavior-per-event)에서 Claude Code는 작업을 중지합니다. 예를 들어 `PreToolUse` hook은 도구 호출을 차단하고 `UserPromptSubmit` hook은 프롬프트를 거부합니다.
853 873
854차단 메시지는 JSON이 차단 결정을 하는 경우 해당 결정의 이유이며, 그렇지 않으면 stderr 텍스트입니다. 차단이 수행하는 작업은 이벤트에 따라 다릅니다: `PreToolUse`는 도구 호출을 차단하고 `UserPromptSubmit`은 프롬프트를 거부하는 식입니다. [이벤트별 종료 코드 2 동작](#exit-code-2-behavior-per-event)은 모든 이벤트의 효과를 나열하며, 각 이벤트의 섹션에서 메시지가 어디로 가는지 설명합니다.874차단과 함께 전달되는 메시지는 hook의 stderr입니다. hook이 차단 결정을 하는 JSON도 출력했다면 Claude Code는 대신 해당 결정의 이유를 사용합니다.
855 875
856[JSON 출력](#json-output) 스키마 검증에 실패하는 JSON을 출력하면서 종료 2로 나가는 hook은 여전히 차단합니다: Claude Code는 stderr을 차단 이유로 사용하고 검증 실패를 디버그 로그에 기록합니다. v2.1.214 이전에는 Claude Code가 해당 조합을 차단하지 않는 오류로 취급하여 작업이 진행되었습니다.876hook이 JSON을 출력하더라도 종료 2는 차단합니다:
877
878* **스키마 검증을 통과하는 JSON**: Claude Code는 여전히 [JSON 출력](#json-output) 필드를 읽지만 필드가 차단을 재정의할 수는 없습니다. `permissionDecision`의 `"allow"`도 작업을 통과시키지 않습니다. `Elicitation` 및 `ElicitationResult`에서는 종료 2 hook의 `hookSpecificOutput`이 무시됩니다.
879* **스키마 검증에 실패하는 JSON**: hook은 여전히 차단합니다. Claude Code는 stderr을 차단 이유로 사용하고 검증 실패를 디버그 로그에 기록합니다.
857 880
858이 스크립트는 종료 2로 `rm` 명령을 차단하고 다른 모든 명령은 일반 권한 흐름에 맡깁니다:881이 스크립트는 종료 2로 `rm` 명령을 차단하고 다른 모든 명령은 일반 권한 흐름에 맡깁니다:
859 882
871exit 0 # No decision: the normal permission flow applies894exit 0 # No decision: the normal permission flow applies
872```895```
873 896
897이 스크립트를 `Bash`에 대한 `PreToolUse` hook으로 등록하면 `rm`으로 시작하는 명령이 차단되고, Claude는 이벤트 이름, 도구 이름, hook의 명령이 접두사로 붙은 hook의 stderr을 도구의 오류로 받습니다:
898
899```text theme={null}
900PreToolUse:Bash hook error: [${CLAUDE_PROJECT_DIR}/.claude/hooks/no-rm.sh]: Blocked: rm commands are not allowed
901```
902
874<h4 id="other-exit-codes">903<h4 id="other-exit-codes">
875 다른 종료 코드904 다른 종료 코드
876</h4>905</h4>
877 906
878다른 종료 코드는 대부분의 hook 이벤트에서 그 자체로는 차단하지 않습니다. 발생하는 일은 stdout에 따라 다릅니다:907hook이 0 또는 2 이외의 코드로 종료하고 stdout에 일반 텍스트를 출력하거나 아무것도 출력하지 않으면 실행은 [차단하지 않는 오류](#exit-code-output)가 됩니다. 트랜스크립트에는 `Failed with non-blocking status code:`와 hook의 stderr 첫 번째 줄이 포함된 `<hook name> hook error` 알림이 표시됩니다. 예를 들어 `Bash`에 대한 `PreToolUse` hook이 stderr에 `something broke`를 출력하고 1로 종료하면 `PreToolUse:Bash hook error` 알림에 다음 줄이 표시됩니다:
879 908
880* 스키마 검증을 통과하는 구문 분석된 객체가 있으면, 표준 결정 모델을 사용하는 이벤트의 경우 Claude Code는 종료 코드를 무시하고 JSON만으로 결과를 결정합니다:909```text theme={null}
881 * 이벤트가 지원하는 각 필드는 `permissionDecision`, `additionalContext`, `updatedInput`, `systemMessage`를 포함하여 적용되며 hook은 오류로 보고되지 않습니다.910Failed with non-blocking status code: something broke
882 * [결정 제어](#decision-control)는 이벤트별 결정 필드를 나열합니다. `systemMessage`와 같은 범용 필드는 [JSON 출력](#json-output) 표를 따릅니다.911```
883* 스키마 검증에 실패하는 구문 분석된 객체가 있으면, 표준 결정 모델을 사용하는 이벤트의 경우 [종료 0](#exit-code-0)과 동일한 차단하지 않는 오류입니다: 작업이 진행되고 `<hook name> hook error` 알림에 검증 메시지가 표시됩니다.
884* Claude Code가 [JSON으로 구문 분석하려고 시도하고 실패](#exit-code-0)하는 stdout이 있으면, 표준 결정 모델을 사용하는 이벤트에 대해 Claude Code는 종료 0과 동일한 차단하지 않는 오류를 보고합니다. 작업이 진행되고 알림에 구문 분석 메시지가 표시됩니다.
885* Claude Code가 [일반 텍스트로 취급](#exit-code-0)하는 stdout이 있거나 stdout이 비어 있으면 대부분의 hook 이벤트에서 차단하지 않는 오류입니다: 작업이 진행되고 트랜스크립트는 `<hook name> hook error` 알림과 함께 `Failed with non-blocking status code:` 접두사가 붙은 stderr의 첫 번째 줄을 표시합니다. 전체 stderr을 캡처하려면 [디버그 로깅](#debug-hooks)을 활성화합니다.
886 912
887표준 결정 모델 외부의 이벤트는 [이벤트별 표](#exit-code-2-behavior-per-event)의 자체 행을 따릅니다: `WorktreeCreate`는 JSON 내용과 관계없이 0이 아닌 종료 코드에서 생성을 실패시키고, `StopFailure`와 같이 hook 출력을 완전히 버리는 이벤트는 모든 종료 코드에서 JSON을 무시합니다. 단, `terminalSequence`와 같은 부수 효과 필드는 여전히 동작합니다.913첫 번째 줄이 아닌 전체 stderr을 캡처하려면 [디버그 로깅](#debug-hooks)을 활성화합니다.
888 914
889시작할 수 없는 hook도 동일한 차단하지 않는 범주에 속합니다. 스크립트 경로가 존재하지 않거나 실행 가능하지 않으면 셸은 127과 같은 코드로 종료되고 인터프리터의 메시지와 함께 동일한 알림이 표시됩니다. 예: `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`. 대부분의 hook 이벤트에서 작업이 진행됩니다. 정책 hook을 설정할 때 첫 번째 실행에서 이 알림을 확인하세요: `settings.json`의 경로에 오타가 있으면 게이트가 조용히 비활성화됩니다.915시작할 수 없는 hook도 차단하지 않는 오류입니다. 셸 형식에서 스크립트 경로가 존재하지 않거나 실행 가능하지 않으면 셸은 127과 같은 코드로 종료되고 알림에 인터프리터의 메시지가 표시됩니다. 예: `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`. 정책 hook을 설정할 때는 첫 번째 실행에서 이 알림을 확인하세요. `settings.json`의 경로에 오타가 있으면 hook이 전혀 실행되지 않습니다. 대신 작업을 차단하려면 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)을 설정합니다.
890 916
891<Warning>917<Warning>
892 대부분의 hook 이벤트에서 종료 코드 2는 코드만으로 차단하는 유일한 종료 코드입니다. stdout에 유효한 JSON이 없으면 Claude Code는 1이 관례적인 Unix 실패 코드임에도 불구하고 종료 코드 1을 차단하지 않는 오류로 취급하고 작업을 진행합니다. hook이 정책을 적용하기 위한 것이라면 `exit 2`를 사용합니다. worktree 이벤트는 다릅니다: `WorktreeCreate`의 0이 아닌 종료 코드는 worktree 생성을 중단하고, `WorktreeRemove`의 0이 아닌 종료 코드는 이후에도 디렉터리가 여전히 존재하면 worktree 제거를 실패하게 합니다.918 stdout에 유효한 JSON이 없으면 Claude Code는 1이 관례적인 Unix 실패 코드임에도 불구하고 종료 코드 1을 차단하지 않는 오류로 취급합니다. hook이 정책을 적용하기 위한 것이라면 `exit 2`를 사용합니다.
893</Warning>919</Warning>
894 920
895<h4 id="timeouts">921<h4 id="timeouts">
900 926
901[`PreModelSwitch`](#premodelswitch)에서는 타임아웃으로 취소된 hook이 모델 전환을 차단합니다. `PreToolUse`에서는 두 hook 유형이 다르게 동작합니다:927[`PreModelSwitch`](#premodelswitch)에서는 타임아웃으로 취소된 hook이 모델 전환을 차단합니다. `PreToolUse`에서는 두 hook 유형이 다르게 동작합니다:
902 928
903* 시간 초과된 `command`, `http`, `mcp_tool` hook은 도구 호출을 차단하지 않습니다. 호출은 일반 [권한 흐름](/docs/ko/permissions)을 통해 계속되므로 멈춘 hook이 게이트 역할을 할 것이라고 기대하지 마세요.929* 시간 초과된 `command`, `http`, `mcp_tool` hook은 도구 호출을 차단하지 않습니다. 호출은 일반 [권한 흐름](/docs/ko/permissions)을 통해 계속되므로 멈춘 hook이 게이트 역할을 할 것이라고 기대하지 마세요. `command` 또는 `http` hook이 시간 초과될 때 호출을 차단하려면 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)을 설정합니다.
904* 타임아웃을 초과한 [Agent SDK 콜백 hook](/docs/ko/agent-sdk/hooks)은 [도구 호출을 차단합니다](#pretooluse).930* 타임아웃을 초과한 [Agent SDK 콜백 hook](/docs/ko/agent-sdk/hooks)은 [도구 호출을 차단합니다](#pretooluse).
905 931
932<h4 id="block-the-action-when-a-hook-fails">
933 hook이 실패할 때 작업 차단
934</h4>
935
936대부분의 이벤트에서 hook이 실패하거나 시간 초과되어도 Claude Code는 작업을 계속 수행하므로, 경로가 잘못되었거나 스크립트가 충돌하는 정책 hook은 모든 것을 통과시킵니다. 대신 작업을 차단하려면 `command` 또는 `http` hook에 `"onFailure": "block"`을 설정합니다. 기본값은 `"continue"`입니다. Claude Code v2.1.295 이상이 필요합니다.
937
938`.claude/settings.json`의 이 `PreToolUse` hook은 각 Bash 명령 전에 프로젝트 스크립트를 실행하고, 스크립트가 실패하면 명령을 차단합니다:
939
940```json theme={null}
941{
942 "hooks": {
943 "PreToolUse": [
944 {
945 "matcher": "Bash",
946 "hooks": [
947 {
948 "type": "command",
949 "command": "node",
950 "args": ["${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js"],
951 "onFailure": "block"
952 }
953 ]
954 }
955 ]
956 }
957}
958```
959
960테스트하려면 `check-command.js`를 없는 상태로 두고 Claude에 `ls`와 같은 Bash 명령을 실행하도록 요청합니다. Claude Code는 호출을 차단하며, 오류에는 `failed; blocking because onFailure is "block"`과 그 뒤에 node 자체의 오류 출력이 포함됩니다. 여기서는 한 줄로 줄였습니다:
961
962```text theme={null}
963PreToolUse:Bash hook error: [node ${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js]: failed; blocking because onFailure is "block"
964Error: Cannot find module '/path/to/project/.claude/hooks/check-command.js'
965```
966
967타임아웃 후에는 메시지에 `failed` 대신 `timed out`이 표시됩니다. `onFailure`를 설정하지 않으면 동일하게 스크립트가 없는 경우에도 차단하지 않는 오류가 되며 `ls`가 실행됩니다.
968
969다음 각 항목은 실패로 간주됩니다:
970
971* **시작할 수 없음**: 예를 들어 스크립트나 실행 파일이 존재하지 않아 명령 hook이 시작되지 않는 경우
972* **0 또는 2 이외의 종료 코드**: 명령 hook이 `permissionDecision: "allow"`처럼 작업을 허용하는 JSON을 출력했더라도 실패로 간주됩니다. JSON 결정을 반환하려면 0으로 종료합니다
973* **HTTP 오류**: HTTP hook의 연결이 실패하거나 응답 상태가 2xx가 아닌 경우
974* **타임아웃**: hook이 [`timeout`](#common-fields)에 도달한 경우
975* **잘못된 출력**: JSON 출력을 [구문 분석할 수 없거나](#exit-code-0) [스키마 검증](#json-output)에 실패하는 경우. HTTP hook의 경우 비어 있지도 않고 JSON 객체도 아닌 2xx 본문도 포함됩니다. 명령 hook의 일반 텍스트 stdout은 실패가 아닙니다
976
977`"block"`이 설정되면 실패는 [해당 이벤트에서 종료 코드 2가 하는 일](#exit-code-2-behavior-per-event)을 수행합니다. 단, `PermissionRequest`에서는 요청을 거부합니다. 예를 들어 `PreToolUse` 실패는 도구 호출을 차단하고 `UserPromptSubmit` 실패는 프롬프트를 차단합니다.
978
979이 필드는 다음 hook에는 효과가 없습니다:
980
981* **`Stop`, `SubagentStop`, `TaskCompleted`, `TeammateIdle` hook**: 이러한 이벤트에서 종료 코드 2는 Claude가 계속 작업하도록 되돌려 보내며, Claude는 실행되지 않는 hook을 고칠 수 없습니다
982* **백그라운드 명령 hook**: [`async` 또는 `asyncRewake`](#run-hooks-in-the-background)를 설정한 명령 hook
983
906<h4 id="exit-code-2-behavior-per-event">984<h4 id="exit-code-2-behavior-per-event">
907 이벤트별 종료 코드 2 동작985 이벤트별 종료 코드 2 동작
908</h4>986</h4>
960* **연결 실패**: 차단하지 않는 오류, 실행이 계속됨1038* **연결 실패**: 차단하지 않는 오류, 실행이 계속됨
961* **타임아웃**: [타임아웃](#timeouts)에 설명된 대로 hook이 취소됩니다1039* **타임아웃**: [타임아웃](#timeouts)에 설명된 대로 hook이 취소됩니다
962 1040
963명령 hook과 달리 HTTP hook은 상태 코드만으로 차단 오류를 신호할 수 없습니다. 도구 호출을 차단하거나 권한을 거부하려면 적절한 결정 필드를 포함하는 JSON 본문과 함께 2xx 응답을 반환합니다.1041HTTP hook은 상태 코드만으로 차단 오류를 신호할 수 없습니다. 2xx가 아닌 상태나 실패한 연결은 [차단하지 않는 오류](#exit-code-output)입니다. 도구 호출을 차단하거나 권한을 거부하려면 적절한 결정 필드를 포함하는 JSON 본문과 함께 2xx 응답을 반환합니다. 요청이 실패하거나 2xx가 아닌 상태를 반환할 때 작업을 차단하려면 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)을 설정합니다.
964 1042
965<h3 id="json-output">1043<h3 id="json-output">
966 JSON 출력1044 JSON 출력
1237 SessionStart 결정 제어1315 SessionStart 결정 제어
1238</h4>1316</h4>
1239 1317
1240Claude Code는 [일반 텍스트로 처리하는](#exit-code-0) stdout을 Claude의 컨텍스트에 추가합니다. 모든 훅에서 사용할 수 있는 [JSON 출력 필드](#json-output) 외에도 다음 이벤트별 필드를 반환할 수 있습니다:1318SessionStart 훅은 Claude를 위한 컨텍스트 추가, 첫 사용자 메시지 제공, 세션 제목 설정, 파일 감시, 스킬 다시 로드를 할 수 있습니다. 모든 훅에서 사용할 수 있는 [JSON 출력 필드](#json-output) 외에 각 항목에 해당하는 필드를 반환합니다.
1241 1319
1242| 필드 | 설명 |1320| 필드 | 설명 |
1243| :- | :- |1321| :- | :- |
1244| `additionalContext` | 대화 시작 시 첫 프롬프트 전에 Claude의 컨텍스트에 추가되는 문자열. 텍스트가 전달되는 방식과 넣을 내용은 [Claude를 위한 컨텍스트 추가](#add-context-for-claude)를 참조하세요 |1322| `additionalContext` | 대화 시작 시 첫 프롬프트 전에 Claude의 컨텍스트에 추가되는 문자열. 텍스트가 전달되는 방식과 넣을 내용은 [Claude를 위한 컨텍스트 추가](#add-context-for-claude)를 참조하세요 |
1245| `initialUserMessage` | 세션의 첫 사용자 메시지로 사용되는 문자열. `-p` 플래그를 사용하는 [비대화형 모드](/docs/ko/headless)에 적용되며, 프롬프트가 제공되지 않아도 첫 턴이 됩니다. 프롬프트가 제공되면 그다음 턴으로 이어집니다. 기존 턴에 첨부되는 `additionalContext`와 달리 이 필드는 턴을 생성합니다 |1323| `initialUserMessage` | `-p` 플래그를 사용하는 [비대화형 모드](/docs/ko/headless)에서 세션의 첫 사용자 메시지로 사용되는 문자열입니다. 프롬프트를 전달하지 않아도 첫 턴이 됩니다. 프롬프트를 전달하면 그 프롬프트는 다음 턴으로 이어집니다 |
1246| `sessionTitle` | 세션 제목을 설정하며 `/rename`과 동일한 효과가 있습니다. 실행 폴더, git 브랜치 또는 worktree 이름으로 세션 이름을 자동 지정하는 데 사용합니다. `source`가 `"startup"`, `"resume"` 또는 `"fork"`일 때 적용되며, `"clear"`와 `"compact"`에서는 무시됩니다 |1324| `sessionTitle` | 세션 제목을 설정하며, `/rename`과 같은 효과를 냅니다. `source`가 `"startup"`, `"resume"` 또는 `"fork"`일 때 적용됩니다 |
1247| `watchPaths` | 이 세션 동안 [FileChanged](#filechanged) 이벤트를 감시할 절대 경로 배열 |1325| `watchPaths` | 이 세션 동안 [FileChanged](#filechanged) 이벤트를 감시할 절대 경로 배열 |
1248| `reloadSkills` | 불리언. `true`이면 Claude Code는 SessionStart 훅이 완료된 후 [스킬](/docs/ko/skills) 및 명령 디렉터리를 다시 스캔하므로, 훅이 설치한 스킬을 첫 프롬프트부터 같은 세션에서 사용할 수 있습니다 |1326| `reloadSkills` | 불리언입니다. `true`이면 SessionStart 훅이 완료된 후 Claude Code가 [스킬](/docs/ko/skills) 및 명령 디렉터리를 다시 스캔합니다. [훅이 설치한 스킬 다시 로드](#reload-skills-that-a-hook-installs)를 참조하세요 |
1327
1328이 출력은 컨텍스트를 추가하고 세션 이름을 지정합니다.
1249 1329
1250```json theme={null}1330```json theme={null}
1251{1331{
1257}1337}
1258```1338```
1259 1339
1260이 이벤트에서는 일반 stdout이 이미 Claude에 전달되므로, 컨텍스트만 로드하는 훅은 JSON을 만들지 않고 stdout에 바로 출력할 수 있습니다. 컨텍스트를 `sessionTitle` 같은 다른 필드와 결합해야 할 때 JSON 형식을 사용하세요.1340컨텍스트만 추가하는 훅은 JSON을 만들지 않고 출력만 해도 됩니다. Claude Code는 SessionStart 훅의 [일반 텍스트 stdout](#exit-code-0)을 Claude의 컨텍스트에 추가하기 때문입니다.
1341
1342플러그인의 SessionStart 훅이 `initialUserMessage` 또는 `sessionTitle`을 제공한다면 세션이 시작되기 전에 플러그인을 설치하세요. SessionStart 훅이 실행된 후에 설치가 완료된 플러그인의 두 필드는 Claude Code가 무시합니다.
1343
1344<h4 id="reload-skills-that-a-hook-installs">
1345 훅이 설치한 스킬 다시 로드
1346</h4>
1347
1348SessionStart 훅이 설치한 스킬을 같은 세션에서 사용할 수 있게 하려면 `reloadSkills`를 반환하세요. 스킬 검색은 일반적으로 SessionStart 훅이 완료되기 전에 실행되므로, 이 필드가 없으면 훅이 `~/.claude/skills/` 또는 `.claude/skills/`에 쓴 파일이 첫 프롬프트 실행 시 누락될 수 있습니다.
1261 1349
1262SessionStart 훅이 스킬을 설치하거나 업데이트할 때는 `reloadSkills`를 사용하세요. 스킬 검색은 일반적으로 SessionStart 훅이 완료되기 전에 실행되므로, 이 필드가 없으면 훅이 `~/.claude/skills/` 또는 `.claude/skills/`에 쓴 파일은 다음 세션에서만 나타납니다. 이 예시는 공유 스킬 저장소를 동기화하고 다시 스캔을 요청합니다:1350이 예시는 공유 스킬 저장소를 동기화하고 다시 스캔을 요청합니다.
1263 1351
1264```bash theme={null}1352```bash theme={null}
1265#!/bin/bash1353#!/bin/bash
1270echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'1358echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'
1271```1359```
1272 1360
1273저장소 URL은 자리 표시자이므로 자체 스킬 저장소로 바꾸세요. 자리 표시자를 그대로 두면 clone이 실패하고 stderr에 `fatal:` 메시지가 출력됩니다. 0으로 종료되는 SessionStart 훅의 stderr는 정보 제공용일 뿐이므로 `reloadSkills` 요청은 여전히 적용됩니다.1361저장소 URL은 예시용입니다. 자신의 스킬 저장소로 바꾸세요.
1274 1362
1275<h4 id="persist-environment-variables">1363<h4 id="persist-environment-variables">
1276 환경 변수 유지1364 환경 변수 유지
1419 1507
1420`UserPromptSubmit` 훅은 `command`, `http`, `mcp_tool` 유형의 기본 타임아웃이 30초로, 대부분의 다른 이벤트에서 이러한 유형의 기본값인 600초보다 짧습니다. 이 훅은 모든 프롬프트 전에 실행되고 완료될 때까지 모델 처리를 차단하므로, 멈춘 훅은 세션을 정지시킵니다. 훅에 더 많은 시간이 필요하면 훅 항목에서 `timeout` 필드를 설정하세요.1508`UserPromptSubmit` 훅은 `command`, `http`, `mcp_tool` 유형의 기본 타임아웃이 30초로, 대부분의 다른 이벤트에서 이러한 유형의 기본값인 600초보다 짧습니다. 이 훅은 모든 프롬프트 전에 실행되고 완료될 때까지 모델 처리를 차단하므로, 멈춘 훅은 세션을 정지시킵니다. 훅에 더 많은 시간이 필요하면 훅 항목에서 `timeout` 필드를 설정하세요.
1421 1509
1422[`async: true`](#run-hooks-in-the-background)로 실행하는 command 훅을 제외하고, 타임아웃에 도달한 `UserPromptSubmit` command, HTTP 또는 MCP 도구 훅은 취소되며 `additionalContext`를 포함한 출력은 버려집니다. 프롬프트는 해당 컨텍스트 없이 여전히 Claude에 전달됩니다. 트랜스크립트에는 훅 이름, 발생한 타임아웃, 출력이 버려졌다는 사실을 알리는 알림이 표시됩니다.1510[`async: true`](#run-hooks-in-the-background)로 실행하는 command 훅을 제외하고, 타임아웃에 도달한 `UserPromptSubmit` command, HTTP 또는 MCP 도구 훅은 취소되며 `additionalContext`를 포함한 출력이 버려집니다. 프롬프트는 해당 컨텍스트 없이 Claude에 전달됩니다. 대신 프롬프트를 차단하려면 command 또는 HTTP 훅에 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)을 설정하십시오. 트랜스크립트에는 훅 이름, 발생한 타임아웃, 출력이 버려졌다는 사실을 알리는 알림이 표시됩니다.
1423 1511
1424`UserPromptSubmit`의 [Agent SDK 콜백 훅](/docs/ko/agent-sdk/hooks)이 타임아웃에 도달하면 훅과 타임아웃을 명시하는 메시지와 함께 프롬프트가 차단됩니다. 이 위치의 콜백은 실패 시 열려서는 안 되는(fail open) 정책 게이트 역할을 할 수 있기 때문입니다. 세션은 계속됩니다. v2.1.208 이전에는 이 이벤트에서 콜백 타임아웃이 발생하면 실행 오류와 함께 턴이 종료되었습니다.1512`UserPromptSubmit`의 [Agent SDK 콜백 훅](/docs/ko/agent-sdk/hooks)이 타임아웃에 도달하면 훅과 타임아웃을 명시하는 메시지와 함께 프롬프트가 차단됩니다. 이 위치의 콜백은 실패 시 열려서는 안 되는(fail open) 정책 게이트 역할을 할 수 있기 때문입니다. 세션은 계속됩니다. v2.1.208 이전에는 이 이벤트에서 콜백 타임아웃이 발생하면 실행 오류와 함께 턴이 종료되었습니다.
1425 1513
1860| :- | :- | :- | :- |1948| :- | :- | :- | :- |
1861| `url` | string | `"https://example.com/api"` | 콘텐츠를 가져올 URL |1949| `url` | string | `"https://example.com/api"` | 콘텐츠를 가져올 URL |
1862| `prompt` | string | `"Extract the API endpoints"` | 가져온 콘텐츠에 대해 실행할 프롬프트 |1950| `prompt` | string | `"Extract the API endpoints"` | 가져온 콘텐츠에 대해 실행할 프롬프트 |
1951| `offset` | number | `100000` | 페이지 시작 부분부터 건너뛸 선택적 문자 수입니다. Claude는 긴 페이지를 계속 읽기 위해 이 값을 설정합니다. Claude Code v2.1.290 이상이 필요합니다 |
1863 1952
1864<h5 id="websearch">1953<h5 id="websearch">
1865 WebSearch1954 WebSearch
2112| `message` | `"deny"` 전용: 권한이 거부된 이유를 Claude에게 알립니다 |2201| `message` | `"deny"` 전용: 권한이 거부된 이유를 Claude에게 알립니다 |
2113| `interrupt` | `"deny"` 전용: `true`이면 Claude를 중지합니다 |2202| `interrupt` | `"deny"` 전용: `true`이면 Claude를 중지합니다 |
2114 2203
2115`decision` 객체 없이 종료 코드 2로 종료하는 훅은 권한 흐름을 변경하지 않으며, stderr는 버려집니다. `decision` 객체만 요청을 허용하거나 거부할 수 있습니다.2204`decision` 객체 없이 종료 코드 2로 종료하는 훅은 권한 흐름을 변경하지 않으며, 해당 stderr는 버려집니다. 요청을 허용하거나 거부하려면 `decision` 객체를 반환하십시오.
2116 2205
2117```json theme={null}2206```json theme={null}
2118{2207{
2678 TaskCreated 결정 제어2767 TaskCreated 결정 제어
2679</h4>2768</h4>
2680 2769
2681TaskCreated 훅은 두 가지 방법으로 생성을 차단할 수 있습니다. 어느 방법이든 Claude Code는 작업을 삭제하고 메시지를 도구 오류로 Claude에게 반환합니다. Claude Code는 이 이벤트의 `continue: false`를 무시하며 Claude는 계속 작업합니다.2770TaskCreated 훅은 종료 코드 2 또는 JSON 결정으로 생성을 차단할 수 있습니다. 어느 경우든 Claude Code는 작업을 삭제하고 메시지를 도구의 오류로 Claude에 반환합니다. Claude Code는 이 이벤트의 `continue: false`를 무시하며 Claude는 계속 작업합니다.
2682 2771
2683* **종료 코드 2**: Claude Code가 stderr 텍스트를 메시지로 반환합니다.2772* **종료 코드 2**: Claude Code가 stderr 텍스트를 메시지로 반환합니다.
2684* **JSON `{"decision": "block", "reason": "..."}`**: Claude Code가 `reason`을 메시지로 반환합니다.2773* **JSON `{"decision": "block", "reason": "..."}`**: Claude Code가 `reason`을 메시지로 반환합니다.
3561 3650
3562Claude Code는 결정과 관계없이 훅이 반환한 `systemMessage`를 사용자에게 표시하므로, 비용 보고 훅은 `{"systemMessage": "..."}`를 반환하고 0으로 종료할 수 있습니다.3651Claude Code는 결정과 관계없이 훅이 반환한 `systemMessage`를 사용자에게 표시하므로, 비용 보고 훅은 `{"systemMessage": "..."}`를 반환하고 0으로 종료할 수 있습니다.
3563 3652
3564타임아웃 전에 응답하지 않는 PreModelSwitch 훅은 전환을 차단합니다. 반면 [PreToolUse](#timeouts)에서는 시간 초과된 명령 훅이 도구 호출을 계속 진행하도록 허용합니다. 이 이벤트의 기본 타임아웃은 30초입니다. `PreModelSwitch`는 `command`, `http`, `mcp_tool` 훅만 실행하므로 `prompt` 및 `agent`의 기본값은 적용되지 않습니다.3653타임아웃 전에 응답하지 않는 PreModelSwitch 훅은 전환을 차단합니다. 다른 이벤트에서 타임아웃이 미치는 영향은 [Timeouts](#timeouts)를 참조하십시오. 이 이벤트의 기본 타임아웃은 30초입니다. `PreModelSwitch`는 `command`, `http`, `mcp_tool` 훅만 실행하므로 `prompt` 및 `agent` 기본값은 적용되지 않습니다.
3565 3654
35660이나 2가 아닌 코드로 종료하고 JSON 결정을 출력하지 않는 훅은 차단하지 않습니다. [기타 종료 코드](#other-exit-codes)에서 설명한 대로 Claude Code는 stderr를 표시하고 전환을 적용합니다.36550 또는 2가 아닌 코드로 종료하고 JSON 결정을 출력하지 않는 훅은 [기타 종료 코드](#other-exit-codes)에 설명된 대로 차단하지 않는 오류입니다.
3567 3656
3568<h3 id="postmodelswitch">3657<h3 id="postmodelswitch">
3569 PostModelSwitch3658 PostModelSwitch
4279비동기 hook은 동기 hook과 비교하여 여러 제약이 있습니다:4368비동기 hook은 동기 hook과 비교하여 여러 제약이 있습니다:
4280 4369
4281* Hook 출력은 다음 대화 턴에 전달됩니다. 세션이 유휴 상태이면 응답은 다음 사용자 상호 작용까지 기다립니다. 예외: `asyncRewake` hook이 종료 코드 2로 종료되면 세션이 유휴 상태일 때도 Claude를 즉시 깨웁니다.4370* Hook 출력은 다음 대화 턴에 전달됩니다. 세션이 유휴 상태이면 응답은 다음 사용자 상호 작용까지 기다립니다. 예외: `asyncRewake` hook이 종료 코드 2로 종료되면 세션이 유휴 상태일 때도 Claude를 즉시 깨웁니다.
4282* 각 실행은 별도의 백그라운드 프로세스를 생성합니다. 동일한 비동기 hook의 여러 발생에 걸쳐 중복 제거가 없습니다.4371* 각 실행은 별도의 백그라운드 프로세스를 생성합니다.
4283 4372
4284<h2 id="security-considerations">4373<h2 id="security-considerations">
4285 보안 고려 사항4374 보안 고려 사항