이 페이지의 목차
확인 2026-10-18근거 자료 2건갱신 2026-10-26언급 11곳
이 페이지의 목차

Claude Code 훅이 무엇을 받고, 무엇을 돌려주면 어떻게 되는지를 이벤트와 상관없이 공통 규칙으로 모은 페이지다. 모든 내용은 공식 Hooks reference Claude Code 훅 레퍼런스(원본 날짜 미상, 수집 2026-10-18) 기준이다. 이벤트별 차이는 훅 이벤트 레퍼런스, 개념은 훅.

설정 구조: 이벤트 → matcher 그룹 → 핸들러#

원본은 설정의 세 층을 이렇게 부른다: 생명주기 지점인 hook event, 거르는 조건인 matcher group(matcher는 용어 사전), 실제로 도는 hook handler(셸 명령, HTTP 엔드포인트, MCP 도구, 프롬프트, 에이전트). Claude Code 훅 레퍼런스

원본이 든 해석 순서 예: PreToolUse 이벤트 → matcher "Bash"가 도구 이름과 맞음 → 핸들러의 if: "Bash(rm *)"가 하위 명령과 맞음 → 스크립트가 rm -rf를 찾아 permissionDecision: "deny" 출력 → Claude Code가 호출을 막고 이유를 Claude에게 보임. npm test였다면 if에서 걸러져 프로세스를 아예 띄우지 않는다. Claude Code 훅 레퍼런스

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "if": "Bash(rm *)",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh",
            "args": []
          }
        ]
      }
    ]
  }
}

matcher 규칙#

matcher 값해석예
"*", "", 생략모두 맞음이벤트마다 실행
글자·숫자·_·-·공백·,·|만정확한 문자열, 또는 |·,로 나눈 목록Bash, Edit|Write, Edit, Write, code-reviewer
그 밖의 문자가 있음앵커 없는 JavaScript 정규식^Notebook, mcp__memory__.*

근거: Claude Code 훅 레퍼런스

  • 정규식은 값 어디서든 맞으면 성공이다. Edit.*는 NotebookEdit에도 맞으므로 전체 일치가 필요하면 ^Edit$처럼 쓴다.
  • FileChanged와 StopFailure는 정확 일치 문자 집합이 더 좁다(글자·숫자·_·|만). 하이픈·공백·쉼표가 있으면 정규식으로 간다.
  • MCP 도구는 mcp__<server>__<tool>. 한 서버 전체는 .*가 필수다. mcp__memory는 정확 문자열로 비교돼 아무 도구에도 맞지 않는다. 플러그인에 묶인 서버는 mcp__plugin_<plugin-name>_<server-name>__<tool>이라 서버 키만으로 쓴 matcher는 돌지 않는다. → MCP
  • matcher를 지원하지 않는 이벤트에 붙인 matcher는 조용히 무시된다.

핸들러 공통 필드와 종류별 필드 (2026-10-18 기준)#

공통 필드 Claude Code 훅 레퍼런스

필드필수설명
type예"command", "http", "mcp_tool", "prompt", "agent"
if아니오권한 규칙 문법 하나("Bash(git *)", "Edit(*.ts)"). 도구 이벤트(PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied)에서만 평가되고, 다른 이벤트에 붙이면 훅이 절대 실행되지 않는다
timeout아니오초. 기본 command·http·mcp_tool 600, prompt 30, agent 60. UserPromptSubmit·PreModelSwitch·PostModelSwitch는 30, MessageDisplay는 10으로 낮춘다. SessionEnd는 1.5초 예산 공유(최대 60초까지 상향)
statusMessage아니오훅이 도는 동안 보일 스피너 메시지
once아니오true면 첫 성공 뒤 제거. 스킬 frontmatter 훅에서만 유효하고 settings 파일·에이전트 frontmatter에서는 무시. 실패·차단·시간 초과면 남는다
  • if는 규칙 하나만 담는다. &&, ||, 목록 문법이 없으니 조건마다 핸들러를 따로 만든다.
  • if의 Bash 패턴: 앞의 VAR=value를 떼고 맞추며, &&로 이은 하위 명령을 각각 보고, $()·백틱 안의 명령도 본다. 명령 이름보다 더 구체적인 패턴(Bash(git push *))은 $()·백틱·$VAR가 있으면 일단 훅을 돌린다. 어떤 명령이 도는지 판단할 수 없으면 패턴과 상관없이 훅을 돌린다. 원본은 그래서 if가 최선 노력이고 확실한 허용·거부는 권한 시스템으로 하라고 한다.
  • 파일 도구의 if에서 "Edit(src/**)"는 작업 디렉터리 바로 아래 src만 맞는다. 아무 깊이의 src는 "Edit(**/src/**)". v2.1.214 전에는 앞의 것이 아무 깊이에 맞았다.

command 훅: command(필수), args, async, asyncRewake(백그라운드로 돌다가 종료 코드 2면 Claude를 깨우고 stderr를 system reminder로 보임), shell("bash"·"powershell", 기본 bash이고 Git Bash 없는 Windows는 powershell), onFailure("continue"·"block", v2.1.295 이상). Claude Code 훅 레퍼런스

HTTP 훅: url(필수), headers(값에 $VAR_NAME·${VAR_NAME}, allowedEnvVars에 적은 변수만 풀림), allowedEnvVars(없으면 어떤 환경 변수도 풀리지 않음), onFailure(기본 "continue"). 입력 JSON을 Content-Type: application/json POST 본문으로 보낸다. Claude Code 훅 레퍼런스

MCP 도구 훅: server(필수, 플러그인 서버는 plugin:<plugin-name>:<server-name>), tool(필수), input(문자열 값에 "${tool_input.file_path}"처럼 훅 입력 경로 치환). 도구의 텍스트 결과를 command 훅 stdout처럼 읽고, isError: true면 막지 않는 오류다. 막거나 결과를 바꿀 수 있는 이벤트(PreToolUse, Stop 등)에서는 연결 중인 서버를 MCP_TIMEOUT과 훅 timeout 안에서 기다리고, 관찰 이벤트(Notification, SessionEnd 등)에서는 기다리지 않는다. 훅은 OAuth를 시작하지 않으니 /mcp에서 먼저 인증한다. 시작 시 SessionStart(재개 포함)와 모든 Setup은 MCP 서버를 쓸 수 있기 전에 발생해 mcp_tool 훅을 건너뛰므로, 시작 때 필요한 일은 command 훅으로 한다. Claude Code 훅 레퍼런스 → MCP

prompt·agent 훅: prompt(필수, $ARGUMENTS가 훅 입력 JSON 자리, 없으면 끝에 붙음, \$1.00처럼 이스케이프), model(기본은 Claude Code의 백그라운드 기능용 모델), prompt 훅만 continueOnBlock. 아래 "prompt·agent 훅의 응답"을 본다. Claude Code 훅 레퍼런스

같은 핸들러가 여러 곳에 있으면: 맞는 훅은 모두 병렬로 돈다. 같은 핸들러를 settings 파일 여러 곳에 두면 한 번만 돌고, 플러그인이나 스킬에 있는 같은 핸들러 사본은 따로 돈다. Claude Code 훅 레퍼런스

exec form과 shell form#

exec formshell form
조건args가 있을 때args가 없을 때
실행command를 PATH의 실행 파일로 찾아 셸 없이 args를 인자로 바로 띄움macOS·Linux sh -c, Windows는 Git Bash, 없으면 PowerShell
특수 문자따옴표·$·백틱이 그대로 전달, 토큰 분리 없음셸이 변수 확장·파이프·&&·리다이렉트·glob 해석
언제경로 placeholder를 쓸 때파이프·&&가 필요할 때

근거: Claude Code 훅 레퍼런스

  • 경로 placeholder: ${CLAUDE_PROJECT_DIR}(세션을 시작한 프로젝트 루트), ${CLAUDE_PLUGIN_ROOT}(플러그인 설치 디렉터리), ${CLAUDE_PLUGIN_DATA}(플러그인 업데이트 뒤에도 남는 데이터 디렉터리). 두 형식 모두 이 값을 같은 이름의 환경 변수로도 내보낸다. 원본은 placeholder를 쓰는 훅은 exec form을, shell form이면 placeholder를 큰따옴표로 감싸라고 한다.
  • 워크트리: Claude가 워크트리에 들어가도 ${CLAUDE_PROJECT_DIR}는 원래 프로젝트 루트를 가리키고, 입력 JSON의 cwd가 워크트리 루트(또는 cd한 새 디렉터리)를 따라간다.
  • Windows exec form은 command가 진짜 실행 파일(.exe)이어야 한다. node_modules/.bin의 .cmd·.bat는 셸 없이 띄울 수 없으니 "command": "node"와 스크립트 경로를 args로 주거나 shell form을 쓴다.
  • 플러그인 ${user_config.*}는 exec form에서만 치환된다. shell form에서 쓰면 오류가 나므로 $CLAUDE_PLUGIN_OPTION_<KEY> 환경 변수를 읽는다(v2.1.207 전에는 shell form도 치환했음). → 플러그인
  • 훅은 Claude Code의 환경으로 현재 디렉터리에서 돈다. 현재 디렉터리가 사라졌으면 세션 시작 디렉터리, 프로젝트 루트, 홈, 시스템 임시 디렉터리 순으로 처음 남은 곳에서 돌고 디버그 로그에 경고를 남긴다.
  • PowerShell shell form에서는 ${CLAUDE_PROJECT_DIR}나 $env:CLAUDE_PROJECT_DIR를 쓴다(큰따옴표 안에서만 확장). 맨 $CLAUDE_PROJECT_DIR는 $null로 풀려 경로가 깨진다.

입력: 공통 필드#

command 훅은 stdin으로, HTTP 훅은 POST 본문으로 같은 JSON을 받는다. Claude Code 훅 레퍼런스

필드설명
session_id세션 식별자
prompt_id처리 중인 사용자 프롬프트 UUID. OpenTelemetry 이벤트의 prompt.id와 같아 원격 측정과 맞춰 볼 수 있다. 첫 입력 전에는 없음
transcript_path대화 JSON 경로. 비동기로 쓰여 최신 메시지가 아직 없을 수 있다. 이번 턴의 마지막 응답은 Stop·SubagentStop의 last_assistant_message를 쓴다
cwd훅이 불릴 때의 작업 디렉터리
scratchpad_dir세션 스크래치패드 경로(v2.1.257 이상, 없을 수 있음)
permission_mode"default", "plan", "acceptEdits", "auto", "dontAsk", "bypassPermissions". Manual로 표시되는 모드는 "default"로 온다. 모든 이벤트가 받지는 않는다
effort{"level": ...}("low"~"max"). 도구 사용 맥락의 이벤트에서, 모델이 effort를 지원할 때. $CLAUDE_EFFORT 환경 변수로도
hook_event_name발생한 이벤트 이름
agent_id, agent_type서브에이전트·인프로세스 팀원·--agent 안에서 돌 때. 서브에이전트 종류가 --agent 값보다 우선
  • 모델: SessionStart만 model을 받을 수 있고(항상은 아님), 모델 전환 이벤트는 from_model·to_model을 받는다. $CLAUDE_MODEL 환경 변수는 없다.
  • 환경: 훅 프로세스는 부모 환경을 물려받는다. 예외는 Claude Code가 모든 하위 프로세스에서 지우는 OTEL_* 내보내기 변수, CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1일 때 지우는 변수, HIPAA 구성 세션에서 지우는 Anthropic 자격 증명이다.
  • 원격 웹 환경에서는 $CLAUDE_CODE_REMOTE가 "true"다.
  • 터미널: macOS·Linux에서 command 훅은 제어 터미널 없는 자기 세션에서 돌아 /dev/tty를 열거나 이스케이프 시퀀스를 직접 보낼 수 없다. 사용자에게 메시지는 systemMessage, 데스크톱 알림·창 제목·벨은 terminalSequence로 한다.

종료 코드와 stdout의 조합#

원본 요약: 종료 코드 0은 성공(출력한 JSON 필드를 적용), 2는 막는 오류(막을 수 있는 이벤트에서 동작 중단), 그 밖의 코드나 시작 실패·잘못된 JSON은 막지 않는 오류(동작 진행, 단 실패 시 막도록 지정한 훅은 예외). PreToolUse 같은 이벤트에서는 stdout과 종료 코드를 함께 봐야 결과가 정해진다: Claude Code 훅 레퍼런스

stdout \ 종료 코드02그 밖
스키마 검증을 통과한 JSON 객체성공, 필드 적용막음. 필드는 읽지만 막기를 뒤집지 못함("allow"여도 통과 못 함)성공. 종료 코드를 무시하고 필드만으로 결정. 단 실패 시 막는 훅이면 실패로 침
파싱 불가 또는 검증 실패 JSON막지 않는 오류(알림에 파싱·검증 메시지)막음. stderr가 이유막지 않는 오류
일반 텍스트 또는 없음성공막음. stderr가 이유막지 않는 오류(알림에 stderr 첫 줄)
  • 종료 코드 0에 출력이 없으면 결정이 없다는 뜻이다. 원본: "The hook can deny the call, but staying silent doesn't approve it."
  • 종료 코드 1은 관례상 실패 코드지만 올바른 JSON이 없으면 막지 않는 오류다(실패하면 막도록 설정한 훅, 즉 onFailure: "block"은 예외). 원본: "If your hook is meant to enforce a policy, use exit 2."
  • 종료 코드 0에서 Claude는 stderr를 보지 않는다. PostToolUse·PostToolUseFailure에서 Claude에게 경고하려면 종료 코드 2를 쓴다(도구는 이미 실행됨).
  • 종료 코드 2 차단 때 Claude가 받는 메시지 형식 예: PreToolUse:Bash hook error: [<command>]: Blocked: rm commands are not allowed.
  • 이벤트별 예외: WorktreeCreate는 0이 아니면 무조건 생성 실패. WorktreeRemove는 0이 아니고 디렉터리가 남으면 실패. Stop·SubagentStop·TaskCompleted·플러그인의 UserPromptSubmit은 stdout 없이 2로 끝나고 stderr가 파일 없음(No such file or directory)을 말하면 막지 않는 오류로 친다. Elicitation·ElicitationResult는 0일 때만 hookSpecificOutput을 적용. StopFailure처럼 출력을 버리는 이벤트는 terminalSequence 같은 부수 효과 필드만 적용.

종료 코드 0의 stdout 파싱 규칙 (async 아닌 훅): 전체 출력이 앞뒤 공백 말고는 JSON 객체 하나일 때만 JSON으로 읽는다. {로 시작하지 않거나 }로 끝나지 않으면 일반 텍스트(JSON 배열, 따옴표 문자열 포함). 줄마다 JSON인 여러 줄은 필드를 정하는 출력 객체가 없으면 일반 텍스트, 있으면 파싱 실패. 그 밖에 {…}인데 올바르지 않은 JSON은 파싱 실패. 대부분의 이벤트에서 stdout은 디버그 로그로만 가고, UserPromptSubmit·UserPromptExpansion·SessionStart·PostModelSwitch만 일반 텍스트 stdout을 Claude의 컨텍스트에 더한다(파싱에 실패한 stdout은 더하지 않음). Claude Code 훅 레퍼런스 가이드 요약도 이 네 이벤트를 같게 든다. Claude Code 훅 가이드

HTTP 응답 처리#

응답결과
2xx, 빈 본문성공(종료 코드 0, 출력 없음과 같음)
2xx, JSON 객체 본문command 훅과 같은 JSON 출력 스키마로 해석. 검증 실패면 막지 않는 오류
2xx, 그 밖의 본문(일반 텍스트 등)막지 않는 오류. 텍스트는 Claude 컨텍스트에 안 들어감
2xx 아닌 상태, 연결 실패막지 않는 오류
시간 초과취소

HTTP 훅으로 막거나 거부하려면 2xx와 결정 필드가 든 JSON 본문을 돌려준다. 요청 실패나 2xx 아닌 상태에서 막으려면 onFailure: "block". Claude Code 훅 레퍼런스

JSON 출력#

원본: 종료 코드는 막거나 조용히 있는 것만 할 수 있고, JSON은 더 세밀하게 통제한다. 한 훅에서는 둘 중 하나만 고르라고 하며, 섞으면 종료 코드 2의 차단 효과는 유지된다. stdout에는 JSON 객체만 찍는다. Claude Code 훅 레퍼런스

필드 세 종류: 모든 이벤트가 받는 공통 필드(일부 이벤트는 버림), 일부 이벤트가 쓰는 최상위 decision·reason, 그리고 hookEventName이 필수인 hookSpecificOutput. Claude Code 훅 레퍼런스

공통 필드기본설명
continuetruefalse면 훅 뒤에 Claude가 처리를 완전히 멈춘다. 이벤트별 결정 필드보다 우선
stopReason없음continue: false일 때 사용자에게 보이는 메시지. 대화에 남아 이어지면 Claude도 본다
suppressOutputfalse효과 없음. 받기만 하고 쓰지 않는다. 성공한 훅의 stdout은 원래 트랜스크립트에 보이지 않는다
systemMessage없음사용자에게 보이는 경고. Agent SDK·stream-json 출력에서는 SDKInformationalMessage로 올 수 있다
terminalSequence없음Claude Code가 대신 내보낼 터미널 이스케이프 시퀀스. OSC 0/1/2/9/99/777과 BEL만 허용, 그 밖의 것이 섞이면 필드 전체 무시. 대화형 세션에서 화면이 떠 있을 때만 쓰이고 -p·Agent SDK에서는 무시

근거: Claude Code 훅 레퍼런스

문자열 길이 상한: additionalContext, systemMessage, initialUserMessage 문자열과 일반 stdout은 각각 10,000자까지다. 여러 훅이 같은 이벤트에 돌아도 문자열마다 따로 잰다. 넘으면 세션 디렉터리의 파일에 저장하고 파일 경로와 앞 2,000자 미리보기로 바꾼다. 이 상한은 올리는 설정·환경 변수가 없고, Claude Code는 Claude에게 그 파일을 읽으라고 하지 않으므로 Claude가 꼭 봐야 할 것은 상한 안에 둔다. Claude Code 훅 레퍼런스

additionalContext: Claude에게 정보 주기#

  • 문자열을 system reminder로 감싸 훅이 발생한 지점에 넣는다. Claude는 다음 모델 요청에서 읽지만 채팅 메시지로 보이지는 않는다. 반드시 hookSpecificOutput 안에 둔다. Claude Code 훅 레퍼런스
  • 들어가는 위치: SessionStart·SubagentStart는 대화 시작(첫 프롬프트 전), UserPromptSubmit·UserPromptExpansion은 제출된 프롬프트 옆, PreToolUse·PostToolUse·PostToolUseFailure·PostToolBatch는 도구 결과 옆, Stop·SubagentStop은 턴 끝(대화가 이어짐), PostModelSwitch는 전환 뒤 다음 요청. Claude Code 훅 레퍼런스
  • 여러 훅이 돌려주면 모두 전달된다. 문자열 안의 <system-reminder> 태그는 <가 &lt;로 바뀐다. Claude Code 훅 레퍼런스
  • 무엇을 넣나(원본): 환경 상태(현재 브랜치, 배포 대상, 켜진 기능 플래그), 조건부 프로젝트 규칙(방금 편집한 파일에 맞는 테스트 명령, 이 워크트리의 읽기 전용 디렉터리), 외부 데이터(나에게 배정된 이슈, 최근 CI 결과, 사내 서비스에서 가져온 내용). 바뀌지 않는 지시는 메모리(CLAUDE.md)를 쓰라고 한다. Claude Code 훅 레퍼런스
  • 어떻게 쓰나(원본): 명령형 시스템 지시가 아니라 사실 진술로 쓴다("The deployment target is production", "This repo uses bun test"). 대역 밖 시스템 명령처럼 쓴 텍스트는 Claude의 프롬프트 인젝션 방어를 건드려, Claude가 컨텍스트로 쓰지 않고 사용자에게 그 텍스트를 보고할 수 있다. Claude Code 훅 레퍼런스
  • 재개 때: 주입된 텍스트는 트랜스크립트에 저장된다. PostToolUse·UserPromptSubmit 같은 세션 중 이벤트는 --continue·--resume으로 재개할 때 훅을 다시 돌리지 않고 저장된 텍스트를 다시 쓰므로 타임스탬프·커밋 SHA 같은 값이 낡는다. SessionStart는 재개 때 source: "resume"(또는 "fork")로 다시 돌아 갱신할 수 있다. Claude Code 훅 레퍼런스

결정 제어 요약#

이벤트결정 방식핵심 필드
UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact최상위 decisiondecision: "block"(유일한 값), reason. 허용은 decision을 빼거나 JSON 없이 0
TeammateIdle, TaskCompleted종료 코드 또는 continue: false종료 코드 2는 stderr 피드백과 함께 막음. continue: false는 Stop처럼 팀원을 완전히 멈춤. 단 TaskCompleted는 TaskUpdate 도구가 일으킨 경우 continue: false를 무시하고 종료 코드 2만 막음
TaskCreated종료 코드 또는 최상위 decision작업 취소, continue: false는 무시
PreToolUsehookSpecificOutputpermissionDecision(allow/deny/ask/defer), permissionDecisionReason
PreModelSwitchhookSpecificOutput 또는 최상위 decisionpermissionDecision(allow/deny/ask)
PermissionRequesthookSpecificOutputdecision.behavior(allow/deny)
PermissionDeniedhookSpecificOutputretry: true
WorktreeCreate경로 반환command는 stdout에 경로, HTTP는 hookSpecificOutput.worktreePath
WorktreeRemove종료 코드JSON 버림
Elicitation, ElicitationResulthookSpecificOutput 또는 최상위 decisionaction(accept/decline/cancel), content
MessageDisplayhookSpecificOutputdisplayContent(표시만)
SessionStart, SubagentStart, PostModelSwitch컨텍스트만additionalContext
Setup, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, DirectoryAdded, FileChanged없음로그·정리 같은 부수 효과용

근거: Claude Code 훅 레퍼런스. 이벤트별 세부는 훅 이벤트 레퍼런스.

타임아웃과 실패#

  • async가 아닌 command·http·mcp_tool 훅이 timeout에 닿으면 취소되고 출력은 버려진다. 대부분의 이벤트에서 결정이 없는 것이 된다. Claude Code 훅 레퍼런스
  • PreToolUse에서 시간 초과된 command·http·mcp_tool 훅은 호출을 막지 않고 일반 권한 흐름으로 보낸다. 원본: "don't count on a stalled hook to act as a gate." 반면 Agent SDK 콜백 훅은 시간 초과면 막는다(UserPromptSubmit에서는 프롬프트를 막고 세션은 계속된다). PreModelSwitch는 시간 초과면 전환을 막는다. Claude Code 훅 레퍼런스
  • 실패로 치는 것(onFailure의 기준): 시작 실패, 0·2 아닌 종료 코드(허용 JSON을 찍었어도), HTTP 오류·2xx 아닌 상태, 시간 초과, 잘못된 출력. command 훅의 일반 텍스트 stdout은 실패가 아니다. "block"이면 그 이벤트의 종료 코드 2 동작을 하고, PermissionRequest에서는 요청을 거부한다. Stop·SubagentStop·TaskCompleted·TeammateIdle 훅과 백그라운드 훅에는 효과가 없다. Claude Code 훅 레퍼런스 → Claude Code 차단 훅 단단하게 만들기

prompt·agent 훅의 응답#

  • 모델은 {"ok": true|false, "reason": "...", "impossible": true|false}로 답한다. reason은 ok: false일 때 필수, impossible은 Stop·SubagentStop에서만 쓰여 조건을 영영 못 채운다고 판단하면 멈춤을 허용한다. Claude Code 훅 레퍼런스
  • ok: false의 효과(원본 목록): Stop·SubagentStop은 이유를 다음 지시로 주고 계속. PreToolUse는 거부하고 기본으로 턴을 끝냄(continueOnBlock: true면 도구 오류로 돌려주고 계속, v2.1.210 전에는 이것이 기본). PostToolUse는 기본으로 턴 끝(continueOnBlock: true면 계속). PostToolBatch·UserPromptSubmit·UserPromptExpansion은 턴 끝. PostToolUseFailure·TaskCreated는 도구 오류로 돌려주고 계속. TaskCompleted는 턴 중 완료 표시면 도구 오류로 계속, 팀원 멈춤이면 TeammateIdle처럼. TeammateIdle은 기본으로 팀원을 멈춤(continueOnBlock: true면 계속). PermissionRequest·PermissionDenied에서는 효과 없음. Claude Code 훅 레퍼런스
  • agent 훅은 Read·Grep·Glob 같은 도구로 최대 50턴 조사한 뒤 {"ok": ...}를 돌려준다. ok: false면 같은 이벤트의 continueOnBlock: true prompt 훅처럼 처리한다. continueOnBlock·impossible 필드가 없고, PermissionRequest에서는 건너뛴다. 원본은 agent 훅이 실험 기능이라 운영 워크플로에는 command 훅을 권한다. Claude Code 훅 레퍼런스
  • 원본은 prompt를 막을 규칙("Block any Bash command that reads .env files")이나 성립해야 할 조건("All unit tests pass")으로 쓸 수 있다고 한다. Claude Code 훅 레퍼런스

백그라운드(async) 훅#

  • "async": true(command 훅만)는 Claude를 막지 않고 뒤에서 돈다. 이미 동작이 끝났으므로 decision, permissionDecision, continue 같은 필드는 효과가 없다. timeout도 강제하지 않는다(asyncRewake에는 강제). Claude Code 훅 레퍼런스
  • 끝나면 JSON의 additionalContext와 systemMessage를 다음 대화 턴에 Claude에게 준다. 동기 훅과 달리 systemMessage는 사용자에게 보이지 않는다. 세션이 쉬고 있으면 다음 사용자 입력까지 기다린다(종료 코드 2로 끝난 asyncRewake 훅만 쉬는 세션도 바로 깨운다). Claude Code 훅 레퍼런스
  • 응답 JSON은 stdout에 혼자 있거나(여러 줄 가능, v2.1.295 이상) 한 줄에 단독으로 있어야 한다. 타입이 틀린 필드는 버리고 --debug에 경고를 남긴다. 완료 알림은 기본으로 숨겨지고 Ctrl+O·--verbose로 본다. Claude Code 훅 레퍼런스
  • -p 비대화형에서는 종료 때 아직 도는 async 훅을 죽이고 cancelled로 마감한다. 세션보다 오래 가야 하는 일은 완전히 분리된 프로세스로 띄운다. Claude Code 훅 레퍼런스

관련#