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

Claude Code 훅 이벤트를 이벤트 하나씩 찾아보는 페이지다. 모든 내용은 공식 Hooks reference Claude Code 훅 레퍼런스(원본 날짜 미상, 수집 2026-10-18) 기준이고, 이벤트 이름·필드·matcher(훅이 돌 경우를 거르는 조건, 용어 사전) 값은 원본 그대로 적었다. 훅이 무엇이고 언제 쓰는지는 훅, 모든 이벤트에 공통인 입력·종료 코드·JSON 출력 규칙은 훅 입출력 규칙, 따라 할 설정은 Claude Code 훅 설정 레시피.

이벤트가 도는 주기#

원본은 이벤트를 세 가지 주기로 나눈다. Claude Code 훅 레퍼런스

  • 세션마다: SessionStart, SessionEnd
  • 턴마다: UserPromptSubmit, Stop, StopFailure
  • 에이전트 루프 안의 도구 호출마다: PreToolUse, PostToolUse. 단 EndConversation 호출은 둘 다 건너뛴다.

원본의 생명주기 그림 설명에 따르면 Setup(선택)이 SessionStart로 이어지고, 턴 루프 안에 UserPromptSubmit, 명령일 때 UserPromptExpansion, 도구 루프(PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, PostToolBatch, SubagentStart/SubagentStop, TaskCreated, TaskCompleted), 그리고 Stop 또는 StopFailure가 있다. 그 뒤로 TeammateIdle, PreCompact, PostCompact, SessionEnd가 온다. Elicitation·ElicitationResult는 MCP 도구 실행 안에, PermissionDenied는 자동 모드 거부 때 PermissionRequest의 곁가지로 있다. WorktreeCreate, WorktreeRemove, Notification, ConfigChange, InstructionsLoaded, CwdChanged, FileChanged, DirectoryAdded는 독립된 비동기 이벤트, PreModelSwitch는 전환 전 순차 이벤트, PostModelSwitch는 전환 뒤 비동기 이벤트, MessageDisplay는 표시 전용 이벤트다. Claude Code 훅 레퍼런스

한눈에 보는 표#

원본의 여러 표(이벤트 요약, matcher 대상, 종료 코드 2 동작, 결정 제어, 지원 핸들러 종류)를 이벤트 기준으로 한 표에 모았다. 칸의 내용은 모두 원본에 있고, 한 표로 합친 것은 편집자다. "핸들러" 열의 "5종"은 command·http·mcp_tool·prompt·agent 모두를 뜻한다. Claude Code 훅 레퍼런스

이벤트언제matcher가 거르는 것종료 코드 2JSON 결정 방식핸들러
SessionStart세션 시작·재개시작 방식(startup, resume, clear, compact, fork)막지 못함, stderr는 사용자에게만컨텍스트만(additionalContext, initialUserMessage, watchPaths, sessionTitle, reloadSkills)command·mcp_tool
Setup--init-only, 또는 -p와 --init·--maintenance트리거 플래그(init, maintenance)무시없음(JSON 필드 버림)command·mcp_tool(mcp_tool은 항상 건너뜀)
UserPromptSubmit프롬프트 제출 뒤, Claude 처리 전지원 안 함프롬프트 막음최상위 decision5종
UserPromptExpansion입력한 명령이 프롬프트로 펼쳐질 때명령 이름확장 막음최상위 decision5종
PreToolUse도구 호출 실행 전도구 이름도구 호출 막음hookSpecificOutput.permissionDecision(allow/deny/ask/defer)5종
PermissionRequest권한 결정이 필요할 때도구 이름받지 않음(흐름 그대로)hookSpecificOutput.decision.behavior(allow/deny)agent 제외 4종
PermissionDenied자동 모드가 호출을 거부할 때도구 이름무시(이미 거부됨)hookSpecificOutput.retry5종(prompt·agent 출력은 버림)
PostToolUse도구 호출 성공 뒤도구 이름막지 못함, stderr를 Claude에게최상위 decision5종
PostToolUseFailure도구 호출 실패 뒤도구 이름막지 못함, stderr를 Claude에게최상위 decision5종
PostToolBatch병렬 도구 호출 묶음이 모두 끝난 뒤, 다음 모델 호출 전지원 안 함다음 모델 호출 전에 루프 멈춤최상위 decision5종
Notification알림을 보낼 때알림 종류무시없음command·http·mcp_tool
MessageDisplay응답 텍스트가 화면에 표시되는 동안지원 안 함원래 텍스트 표시displayContent(표시만 바꿈)command·http·mcp_tool
SubagentStart서브에이전트 생성에이전트 종류막지 못함, stderr는 사용자에게만컨텍스트만command·http·mcp_tool
SubagentStop서브에이전트 종료에이전트 종류서브에이전트가 멈추지 않게 함최상위 decision5종
TaskCreatedTaskCreate로 작업 생성 중지원 안 함작업 생성 되돌림종료 코드 또는 최상위 decision5종
TaskCompleted작업을 완료로 표시하는 중지원 안 함완료 표시 막음종료 코드 또는 continue: false(TaskUpdate 도구가 일으킨 경우 continue: false는 무시, 종료 코드 2만 막음)5종
StopClaude가 응답을 마칠 때지원 안 함멈추지 않고 대화 계속최상위 decision5종
StopFailureAPI 오류로 턴이 끝날 때오류 종류무시(terminalSequence만 적용)없음command·http·mcp_tool
TeammateIdle에이전트 팀 팀원이 쉬려 할 때지원 안 함팀원이 계속 일함종료 코드 또는 continue: false5종
InstructionsLoadedCLAUDE.md·.claude/rules/*.md가 로드될 때로드 이유무시없음command·http·mcp_tool
ConfigChange세션 중 설정 파일이 바뀔 때설정 출처변경 적용 막음(policy_settings 제외)최상위 decisioncommand·http·mcp_tool
CwdChanged작업 디렉터리가 바뀔 때지원 안 함막지 못함, stderr는 사용자에게만없음(watchPaths는 받음)command·http·mcp_tool
DirectoryAdded세션 중 /add-dir 등으로 디렉터리 추가추가 방식막지 못함, stderr는 디버그 로그없음command·http·mcp_tool
FileChanged감시하는 파일이 디스크에서 바뀔 때감시할 파일 이름막지 못함, stderr는 사용자에게만없음(watchPaths는 받음)command·http·mcp_tool
WorktreeCreate워크트리를 만들 때(기본 git 동작을 대체)지원 안 함0이 아니면 생성 실패경로 반환command·http·mcp_tool
WorktreeRemove훅이 만든 워크트리를 지울 때지원 안 함0이 아니고 디렉터리가 남으면 제거 실패종료 코드(JSON 버림)command·http·mcp_tool
PreCompact컴팩션 전manual, auto컴팩션 막음최상위 decisioncommand·http·mcp_tool
PostCompact컴팩션 뒤manual, auto막지 못함, stderr는 사용자에게만없음command·http·mcp_tool
PreModelSwitch요청된 모델 전환을 적용하기 전전환 대상 모델의 정식 이름전환 막음, stderr는 사용자에게permissionDecision(allow/deny/ask) 또는 최상위 decisioncommand·http·mcp_tool
PostModelSwitch세션 모델이 바뀐 뒤전환된 모델의 정식 이름막지 못함, stderr는 사용자에게만컨텍스트만command·http·mcp_tool
ElicitationMCP 서버가 도구 호출 중 입력을 요청할 때MCP 서버 이름요청 거절(대화상자 안 뜸)hookSpecificOutput.action 또는 최상위 decisioncommand·http·mcp_tool
ElicitationResult사용자가 답한 뒤, 서버로 보내기 전MCP 서버 이름응답 막음(거절로 바뀜)hookSpecificOutput.action 또는 최상위 decisioncommand·http·mcp_tool
SessionEnd세션 종료종료 이유(clear, resume, logout, prompt_input_exit, other)막지 못함, stderr는 사용자에게만없음command·http·mcp_tool

표 보충 (원본): Claude Code 훅 레퍼런스

  • 원본 표는 이벤트 33개를 나열한다(개수는 편집자가 셈).
  • matcher를 지원하지 않는 이벤트에 matcher를 붙이면 조용히 무시된다.
  • SessionStart, SubagentStart, PostModelSwitch에서 종료 코드 2의 stderr는 막지 않는 오류처럼 <hook name> hook error 알림으로 보이고 Claude는 보지 못한다. SubagentStart의 알림은 부모 대화가 아니라 서브에이전트 트랜스크립트에 뜬다.
  • 내용을 바꿔 쓰는 이벤트: PreToolUse의 updatedInput(도구 인자 교체), PermissionRequest의 decision.updatedInput, PostToolUse의 updatedToolOutput(도구 결과 교체). UserPromptSubmit은 프롬프트를 바꾸지 못하고 옆에 additionalContext만 넣는다. 원본은 가리기(redaction)·변환은 나가는 도구 입력은 PreToolUse, 들어오는 도구 결과는 PostToolUse에서 하라고 한다.

세션 이벤트#

SessionStart Claude Code 훅 레퍼런스

  • 정적인 컨텍스트에는 스크립트가 필요 없는 메모리(CLAUDE.md)를 쓰라고 원본이 말한다. 모든 세션에서 돌므로 빠르게 유지한다.
  • fork matcher: --fork-session과 --resume·--continue, /fork, /branch, 백그라운드로 옮긴 대화. v2.1.214 전에는 포크 세션이 "resume"으로 보고됐다.
  • 대화형 시작·실행 시 재개·/clear 때는 훅이 백그라운드로 돌아 바로 입력할 수 있지만, Claude의 첫 응답은 훅이 끝날 때까지 기다린다. 세션 안의 /resume 전환은 훅이 끝날 때까지 기다린다. 기다리는 동안 Esc로 프롬프트를 입력창으로 되돌릴 수 있다.
  • 입력: source, 그리고 선택적으로 model(빠질 수 있으니 확인 후 읽기), agent_type(claude --agent <name>일 때), session_title(사용자 지정 제목이 있을 때). 재개·포크이고 Claude 응답이 하나 이상 있으면 seconds_since_last_response, context_tokens, prompt_cache_likely_expired, estimated_cache_write_usd도 받는다(v2.1.251 이상). 원본 예: 마지막 응답 90분 뒤 재개 시 context_tokens 182,340, 추정 캐시 쓰기 비용 1.1396달러.
  • 출력: additionalContext, initialUserMessage(-p 모드의 첫 사용자 메시지), sessionTitle(/rename과 같은 효과, startup·resume·fork일 때), watchPaths(FileChanged 감시 경로), reloadSkills(훅이 설치한 스킬을 같은 세션에서 쓰게 다시 스캔). 컨텍스트만 넣을 거면 JSON 없이 일반 텍스트 stdout으로 충분하다.
  • 플러그인의 SessionStart 훅이 initialUserMessage·sessionTitle을 주려면 세션 시작 전에 플러그인이 설치돼 있어야 한다.
  • CLAUDE_ENV_FILE: 이 파일에 export 문을 덧붙이면(>>) 세션 뒤의 Bash 명령에 환경 변수가 이어진다. SessionStart, Setup, CwdChanged, FileChanged 훅만 이 변수를 받고, PowerShell로 도는 훅은 받지 못한다. PowerShell 명령은 v2.1.296 이상에서 파일의 모든 줄이 단순 대입일 때만 변수를 받는다(예: export PATH="$PATH:..."처럼 이스케이프 안 한 $가 있으면 하나도 못 받음).

Setup: 평소 시작에는 돌지 않는다. CI·스크립트에서 명시적으로 부르는 일회성 의존성 설치·정리용이다. claude --init-only는 Setup 훅과 startup matcher의 SessionStart 훅을 돌리고 대화 없이 끝난다. 막을 수 없고 JSON 출력 필드를 모두 버린다. 원본은 매번 돌지 않으니 플러그인 의존성 설치를 Setup에만 기대지 말고 "처음 쓸 때 확인하고 없으면 설치"하라고 한다. Claude Code 훅 레퍼런스

SessionEnd: 종료 이유로 거른다. 기본 1.5초 예산을 나눠 쓰며, 훅별 timeout을 길게 두면 예산이 최대 60초까지 올라간다(플러그인 훅의 timeout은 예산을 올리지 않음). CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS로 예산을 직접 정하면 그 값이 timeout 없는 훅의 타임아웃도 된다(v2.1.268 전에는 예산만 올렸음). Claude Code 훅 레퍼런스

프롬프트 이벤트#

UserPromptSubmit Claude Code 훅 레퍼런스

  • 직접 입력한 프롬프트만이 아니라 예약 작업(/loop 포함), 백그라운드 서브에이전트의 보고, 다른 세션이 보낸 메시지에도 돈다.
  • 기본 타임아웃 30초. 모든 프롬프트 앞에서 모델 처리를 막고 기다리므로 멈춘 훅은 세션을 멈춘다. 시간을 넘긴 훅은 취소되고 additionalContext도 버려진 채 프롬프트가 그대로 간다. 막으려면 onFailure: "block".
  • 입력 prompt: 접힌 붙여넣기는 펼쳐서 온다. 스킬·명령을 입력했으면 펼친 내용이 아니라 입력한 줄(예: /deploy staging)이 온다.
  • 출력: decision: "block"(프롬프트를 Claude 전에 멈춤), reason(사용자에게만 보이고 컨텍스트에 안 들어감), additionalContext, sessionTitle, suppressOriginalPrompt.
  • 막힌 프롬프트의 흔적: 기본으로 차단 메시지 끝에 Original prompt:와 원문이 붙고 트랜스크립트 파일에 쓰인다. suppressOriginalPrompt: true는 차단 메시지만 바꾸고, 원문은 트랜스크립트·프롬프트 기록 같은 로컬 파일에 남을 수 있다. 원본: 차단 훅은 비밀을 디스크에서 지키는 방법이 아니다.

UserPromptExpansion: command_name으로 거르고, 입력은 expansion_type(slash_command 또는 mcp_prompt), command_name, command_args, command_source, prompt. Skill 도구에 맞춘 PreToolUse는 Claude가 도구를 부를 때만 돌고 /skillname 직접 입력은 PreToolUse를 거치지 않으므로, 그 경로는 이 이벤트가 받는다. 원본 예: 승인 파일이 없으면 /deploy를 막기, 리뷰 스킬에 팀 체크리스트를 additionalContext로 붙이기. Claude Code 훅 레퍼런스 → 스킬

MessageDisplay: 응답이 화면에 흐르는 동안 새로 완성된 줄 묶음마다 돌아 displayContent로 표시 텍스트를 바꾼다. 표시 전용이라 트랜스크립트와 Claude가 보는 내용은 원문 그대로다. 기본 타임아웃 10초, 실패하면 원문이 보인다. 원본 용도: 마크다운 지우기, Agent SDK 앱이 사용자에게 보여 줄 텍스트 변환, 응답의 API 키·내부 호스트 이름 가리기. 비대화형(-p, SDK)에서는 메시지마다 한 번, 전체 텍스트로 돈다. Claude Code 훅 레퍼런스

도구 이벤트#

PreToolUse Claude Code 훅 레퍼런스

  • EndConversation을 뺀 모든 도구 이름에 맞는다(내장 Bash, PowerShell, Edit, Write, Read, Glob, Grep, Agent, Workflow, WebFetch, WebSearch, AskUserQuestion, ExitPlanMode와 MCP 도구).
  • 입력: tool_name, tool_input, tool_use_id. MCP 도구는 mcp_server(name과 정의 출처 source, v2.1.274 이상)도 받는다. 원본은 신뢰 판단을 name이나 mcp__<server>__ 접두어가 아니라 source로 하라고 한다.
  • Write·Edit·Read의 tool_input.file_path는 항상 절대 경로다. ~와 상대 경로를 훅 전에 펼치므로 그 표기로 우회할 수 없다. Windows에서는 역슬래시로 오므로 비교 전에 구분자를 정규화한다.
  • 도구별 tool_input 필드 표가 있다(Bash: command, description, timeout, run_in_background / Write: file_path, content / Edit: file_path, old_string, new_string, replace_all / Read: file_path, offset, limit / Glob, Grep, WebFetch, WebSearch, Agent, AskUserQuestion, ExitPlanMode).
  • "allow"는 확인 창을 건너뛰지만, 어떤 모드도 자동 승인하지 않는 동작과 네트워크 경로 읽기는 예외이고 deny·ask 규칙은 훅이 무엇을 돌려주든 평가된다. plan 모드는 공식 권한 문서의 "Hook approvals in plan mode"로 넘긴다.
    • (2026-10-21 기준) 권한 문서의 plan 모드 규칙: ExitPlanMode를 빼면 파일 편집처럼 읽기 전용이 아닌 호출에는 "allow"가 효과가 없다. 훅이 없을 때와 같은 확인·차단·승인을 받되, 훅이 돌려준 updatedInput은 적용된다. ExitPlanMode에 "allow"와 updatedInput을 함께 돌려주면 그 도구는 확인 없이 돈다. tool.check를 다루는 mod도 plan 모드에서 읽기 전용이 아닌 호출을 승인하지 못한다(막을 수는 있다). 계획을 승인하거나 다른 모드로 바꾸면 이 제한이 풀린다. Claude Code 권한 설정 → Claude Code 훅 설정 레시피
    • (2026-10-21 기준) 종료 코드 2로 막는 훅은 권한 규칙을 평가하기 전에 호출을 멈추므로, allow 규칙이 허용할 호출도 막는다. 원본 예: Bash 전체를 allow에 두고 몇 명령만 이 훅으로 거부하기. 설치한 mod의 tool.check 승인이 훅 차단을 넘는 조건은 권한 문서 기준으로 정리했다(훅의 ‘원본끼리 달랐던 점’ 상자). Claude Code 권한 설정 → Claude Code 권한 규칙 문법
  • 결정 필드: permissionDecision, permissionDecisionReason(ask면 확인 창에, deny면 Claude에게, allow·defer면 디버그 로그에만), updatedInput(입력 객체 전체를 교체, 권한 규칙은 훅이 돌려준 입력으로 평가), additionalContext(defer면 무시).
  • 여러 훅의 결정이 다르면 deny > defer > ask > allow. 종료 코드 2는 "deny"처럼 처리되고 stderr가 거부 이유가 된다.
  • "ask"가 띄운 확인 창에는 출처 표시가 붙는다: [settings], [plugin:<name>], [skill]. "ask"는 자동 모드에서도 확인 창을 강제한다(분류기는 거부할 수는 있어도 조용히 승인하지 못함). v2.1.211 전에는 분류기가 샌드박스 밖 Bash를 확인 창 없이 승인할 수 있었다.
  • 예전 최상위 decision·reason("approve", "block")은 이 이벤트에서 폐기됐고 "allow"·"deny"로 대응된다.
  • AskUserQuestion·ExitPlanMode는 사용자 상호작용이 필요해서 "allow"만으로는 안 되고, 답을 담은 updatedInput과 함께 돌려줘야 한다. MCP 서버가 _meta["anthropic/requiresUserInteraction"]로 표시한 도구는 훅의 "allow"로 확인 창을 건너뛸 수 없다.
  • "defer"는 -p 비대화형에서만 유효하다. 턴에 도구 호출이 하나일 때만 되고(여럿이면 경고 후 무시), 프로세스는 stop_reason: "tool_deferred"로 끝나고 호출 측이 deferred_tool_use를 읽어 답을 모은 뒤 claude -p --resume <session-id>로 재개한다. 시간 제한은 없고, 세션 파일은 cleanupPeriodDays(기본 30일) 정리 대상이다.
  • Agent SDK 콜백 훅이 PreToolUse에서 시간을 넘기면 호출을 막는다(command·http·mcp_tool 훅은 onFailure: "block"이 없으면 시간 초과로 막지 않는 것과 다름).

PermissionRequest Claude Code 훅 레퍼런스 → 권한 모드

  • Claude Code가 권한을 물으려 할 때, 또는 확인 창을 못 띄우는 세션에서 자동 거부하려 할 때 돈다. 확인 창이 없는 세션에서 어떤 훅도 결정하지 않으면 거부한다. PreToolUse는 권한이 필요하든 아니든 모든 호출 전에 돈다는 점이 다르다.
  • 호출이 --permission-prompt-tool이나 Agent SDK canUseTool 콜백에 닿으면 훅은 그 호스트와 나란히 돌고 먼저 결정한 쪽이 적용된다.
  • 샌드박스 명령의 네트워크 요청 확인에는 돌지 않는다(그때는 Notification의 permission_prompt).
  • 입력: tool_name, tool_input(tool_use_id 없음), MCP면 mcp_server, 선택적 permission_suggestions. 이 배열은 화면에 보이는 선택지와 정확히 같지 않다.
  • 출력 decision: behavior(allow/deny, allow여도 deny·ask 규칙은 평가됨), updatedInput(allow만, 다시 deny·ask 규칙으로 평가), updatedPermissions(allow만), message·interrupt(deny만). decision 없이 종료 코드 2로 끝나면 흐름은 그대로이고 stderr는 버려진다.
  • 권한 갱신 항목 type: addRules, replaceRules, removeRules, setMode, addDirectories, removeDirectories. destination: session(메모리만), localSettings, projectSettings, userSettings. setMode의 bypassPermissions는 bypass를 쓸 수 있게 시작한 세션에서만 적용되고, permissions.disableBypassPermissionsMode나 restricted mode에서는 효과가 없으며, destination과 상관없이 defaultMode로 저장되지 않는다.

PermissionDenied: 자동 모드가 호출을 거부할 때만 돈다. 사용자가 확인 창에서 거부했을 때, PreToolUse 훅이 막았을 때, deny 규칙이 맞았을 때는 돌지 않는다. 입력 reason은 분류기 판정이면 대개 [Data Exfiltration] 같은 규칙 이름, 판정이 없으면 Auto mode could not evaluate this action ..., 분류기 모델을 못 쓰면 Classifier unavailable. retry: true는 다시 시도해도 된다는 메시지를 대화에 더할 뿐 거부를 되돌리지 않고, 판정 없는 거부에서는 무시된다. Claude Code 훅 레퍼런스 (2026-10-21 기준) 공식 자동 모드 설정 문서는 이 훅의 쓰임을 든다: 입력창 근처 알림과 /permissions의 Recently denied 탭은 거부된 명령·URL을 보여 주지 않으므로, 정확한 입력을 프로그램으로 남기려면 이 훅을 더한다(입력을 tool_input으로 받는다). Claude Code 자동 모드 설정 → Claude Code 자동 모드 설정하기

PostToolUse Claude Code 훅 레퍼런스

  • 입력: tool_input, tool_response(도구의 구조화된 출력), tool_use_id, duration_ms(권한 확인과 PreToolUse 시간 제외).
  • 출력: decision: "block"(도구 결과 옆에 reason을 붙이되 원래 출력도 Claude가 봄), additionalContext, classifierContext(자동 모드 분류기용 메모, v2.1.236 이상), updatedToolOutput(Claude가 보는 결과 교체), updatedMCPToolOutput(MCP 전용, updatedToolOutput 권장).
  • updatedToolOutput은 Claude가 보는 것만 바꾼다. 파일 쓰기·명령·네트워크 요청은 이미 일어났고, OpenTelemetry 같은 원격 측정도 원래 출력을 이미 기록했다. 내장 도구는 출력 형태가 맞지 않으면 무시되고, MCP 출력은 검증 없이 전달된다.
  • Bash가 Git 저장소의 파일을 바꾸면 tool_response.bashEditDiff(changedFiles 최대 200개, files 최대 5개의 diff 등)를 받을 수 있다(v2.1.269 이상). 기록 조건: bashEditDiffEnabled 설정으로 켜면 모든 권한 모드에서 기록하고, 그렇지 않으면 자동 모드와 bypassPermissions 모드에서 Claude Code가 Claude에게 Bash로 파일을 편집하라고 지시할 때만 기록한다. false로 두면 끈다. 백그라운드·읽기 전용 명령에는 diff가 없다. 원본은 이 목록이 최선 노력이고 공개 베타라 정책 강제가 아니라 검토 대상 찾기에 쓰라고 한다.
  • Agent 호출이 포그라운드로 끝나면 tool_response에 status, agentId, content, resolvedModel, modelsUsed, totalTokens(마지막 요청만), totalDurationMs, totalToolUseCount, usage가 온다. 서브에이전트는 기본이 백그라운드라 status: "async_launched"면 사용량 필드가 없다. → 서브에이전트
  • 이름으로 거르기 어려우면 matcher를 비우고 git status --porcelain으로 바뀐 것을 스스로 찾거나, 파일 자체를 보려면 FileChanged를 쓰라고 원본이 말한다.

PostToolUseFailure: 실행을 시작한 도구가 실패했을 때(오류 발생, MCP 도구의 오류 결과). 알 수 없는 도구 이름, 입력 검증 실패, 권한 거부처럼 실행 전에 거절된 호출에는 돌지 않는다. 입력 error의 형식은 도구마다 다르므로 tool_name, is_interrupt, 첫 줄 Exit code N만 기준으로 쓰라고 한다. Claude Code 훅 레퍼런스

PostToolBatch: 병렬 호출 묶음 전체가 끝난 뒤 한 번 돈다(PostToolUse는 도구마다 동시에 돎). 입력 tool_calls 배열의 tool_response는 모델이 받는 직렬화된 tool_result 내용이라 PostToolUse의 구조화 출력과 형태가 다르다. decision: "block"이나 continue: false는 다음 모델 호출 전에 루프를 멈춘다. Claude Code 훅 레퍼런스

알림·응답 종료 이벤트#

Notification Claude Code 훅 레퍼런스

  • 데스크톱 알림을 꺼도(preferredNotifChannel의 notifications_disabled 포함) 훅은 돈다.
  • matcher 값: permission_prompt, idle_prompt, auth_success, elicitation_dialog, elicitation_url_dialog, elicitation_complete, elicitation_response, agent_needs_input, agent_completed, quota_auto_resume_fired·quota_auto_resume_stale·quota_auto_resume_disabled(v2.1.234 이상).
  • 터미널에서 permission_prompt는 입력이 없는 채 약 6초가 지나야 오고 키를 누를 때마다 미뤄진다. 즉시 신호가 필요하면 PermissionRequest를 쓴다. Claude Desktop·VS Code 확장처럼 canUseTool 콜백으로 권한을 받는 세션에서는 약 6초 뒤 미뤄지지 않고 오며, CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS=1로 끈다(v2.1.233 전에는 이 세션에서 안 왔음).
  • 막거나 바꾸지 못한다. systemMessage·continue는 버리지만 terminalSequence는 낸다.

Stop Claude Code 훅 레퍼런스

  • 메인 에이전트가 응답을 마칠 때. 사용자 중단에는 안 돌고 API 오류는 StopFailure로 간다. 원본은 /goal 명령을 세션 범위 prompt 기반 Stop 훅의 내장 지름길로 소개한다.
  • 입력: stop_hook_active(이미 Stop 훅 때문에 계속 중이면 true), last_assistant_message(트랜스크립트 파일은 이 시점에 마지막 메시지를 담는다는 보장이 없으니 이 필드를 쓰라고 함), background_tasks, session_crons(세션이 끝난 것인지 백그라운드 일을 기다리며 쉬는 것인지 구분용).
  • 연속 계속 상한 8회: Stop 훅이 연달아 8번 턴을 이어 가면 다음 차단을 무시하고 턴을 끝낸다. Claude가 도구를 부를 때마다 횟수가 초기화된다. CLAUDE_CODE_STOP_HOOK_BLOCK_CAP으로 올린다.
  • 출력: decision: "block" + reason(필수, 계속해야 할 이유), 또는 hookSpecificOutput.additionalContext(오류가 아닌 피드백, 트랜스크립트에 Stop hook feedback으로 표시, 같은 반복 보호를 받음).

SubagentStop: Stop과 같은 결정 형식. 입력에 agent_transcript_path(서브에이전트 자신의 트랜스크립트), last_assistant_message가 있다. 프롬프트 제안, /btw 같은 Claude Code 내부 에이전트가 끝날 때도 돌며 그때 agent_type은 세션 자신의 에이전트 이름이거나 빈 문자열이다. 서브에이전트가 돌아온 뒤 부모 세션에 컨텍스트를 넣으려면 Agent 도구의 PostToolUse를 쓰라고 한다. Claude Code 훅 레퍼런스

StopFailure: 출력과 종료 코드를 무시한다(terminalSequence만 예외). matcher·입력 error 값: rate_limit, overloaded, authentication_failed, oauth_org_not_allowed, account_on_hold, billing_error, invalid_request, model_not_found, server_error, max_output_tokens, cloud_credential_error(v2.1.267 이상), unknown. 로그·알림·복구용이다. Claude Code 훅 레퍼런스

서브에이전트·작업·팀 이벤트#

  • SubagentStart: Agent 도구로 서브에이전트를 띄울 때, 서브에이전트를 재개할 때, 인프로세스 팀원이 새 메시지를 처리할 때마다 돈다. 커스텀 서브에이전트의 matcher 값은 파일 이름이 아니라 frontmatter name, 플러그인 서브에이전트는 my-plugin:reviewer 같은 범위 이름이고 콜론 때문에 정규식 경로로 가므로 ^my-plugin:reviewer$처럼 고정한다. 생성을 막지는 못하지만 additionalContext를 서브에이전트 대화 시작에 넣는다. 같은 서브에이전트에 다시 돌면 이미 사본이 있을 때는 넣지 않고(프롬프트 캐시 보존), 자동 컴팩션이 그 사본을 버린 뒤에는 다시 넣는다. Claude Code 훅 레퍼런스 → 서브에이전트
  • (2026-10-18 기준) 공식 서브에이전트 문서는 SubagentStart·SubagentStop을 settings.json에 두는 예(특정 서브에이전트 시작 때 준비 스크립트, 모든 서브에이전트 종료 때 정리 스크립트)와 같은 matcher 규칙을 싣는다. 서브에이전트 frontmatter의 Stop 훅은 런타임에 SubagentStop으로 바뀐다. 예시 원문은 Claude Code 서브에이전트 만들기·운영. Claude Code 서브에이전트
  • TaskCreated: TaskCreate 도구로 작업을 만들 때. 종료 코드 2나 decision: "block"이면 작업을 지우고 메시지를 도구 오류로 Claude에게 돌려준다. continue: false는 무시한다. 원본 예: 제목이 [TICKET-123] 형식이 아니면 막기. Claude Code 훅 레퍼런스
  • TaskCompleted: TaskUpdate로 완료 표시할 때, 또는 팀원이 진행 중 작업을 남기고 턴을 끝낼 때. 종료 코드 2면 완료로 표시하지 않고 stderr를 모델에게 준다. {"continue": false, "stopReason": ...}는 팀원이 턴을 끝내며 일으킨 경우에만 팀원을 완전히 멈추고, TaskUpdate 도구가 일으킨 경우에는 무시된다(이때도 종료 코드 2는 완료를 막는다). 원본: "When the TaskUpdate tool triggered the event, Claude Code ignores continue: false; exit code 2 still blocks the completion." 원본 예: npm test가 실패하면 완료 막기. Claude Code 훅 레퍼런스
  • TeammateIdle: 에이전트 팀의 팀원이 쉬려 할 때. 종료 코드 2면 stderr를 피드백으로 받고 계속 일하고, {"continue": false, "stopReason": ...}면 팀원을 완전히 멈춘다. 원본 예: 빌드 산출물이 없으면 쉬지 못하게 하기. Claude Code 훅 레퍼런스

지시·설정·파일 이벤트#

  • InstructionsLoaded: CLAUDE.md나 .claude/rules/*.md가 컨텍스트에 로드될 때(시작 시 즉시 로드, 이후 지연 로드). 비동기 관찰용이라 막거나 바꾸지 못하고 JSON 출력을 버린다. 입력: file_path, memory_type(User, Project, Local, Managed), load_reason, globs(path_glob_match일 때), trigger_file_path(지연 로드), parent_file_path(include일 때). Project instructions 설정으로 AGENTS.md를 직접 읽을 때는 돌지 않지만, CLAUDE.md가 AGENTS.md를 import하면 include로, CLAUDE.md가 AGENTS.md로의 심볼릭 링크면 일반 CLAUDE.md 로드로 돈다. 원본 용도: 감사 로그, 준법 추적, 관찰. Claude Code 훅 레퍼런스 → 메모리(CLAUDE.md)
  • ConfigChange: settings 파일, managed 정책 파일(managed-settings.json이나 managed-settings.d/의 파일), 스킬 파일이 바뀔 때. 서버 관리 설정, macOS managed preferences, Windows 레지스트리 정책 변경에는 돌지 않는다. matcher: user_settings, project_settings, local_settings, policy_settings, skills. 막으면 새 설정이 실행 중 세션에 적용되지 않는다. policy_settings는 막을 수 없어 로그만 가능하다(기업 managed 설정이 항상 적용되게). 막혀도 사용자·Claude에게 메시지가 없고 디버그 로그에 한 줄만 남는다(reason은 받지만 보이지 않음). Claude Code 훅 레퍼런스 → managed settings 공식 Settings 문서(2026-10-21)도 설정 파일 변경마다 이 훅이 돌고, MDM·claude.ai 콘솔로 오는 managed settings에는 돌지 않는다고 확인한다. Claude Code 설정 파일과 우선순위
  • CwdChanged: 메인 대화의 셸 명령이 작업 디렉터리를 바꿀 때(예: cd). old_cwd, new_cwd를 받고 watchPaths로 FileChanged 감시 목록을 바꾼다. CLAUDE_ENV_FILE 변수는 다음 CwdChanged까지 유지되고 그때 지워진다. 원본 용도: direnv 같은 디렉터리별 환경. Claude Code 훅 레퍼런스
  • DirectoryAdded: 세션 중 /add-dir(matcher slash_command)이나 SDK register_repo_root(matcher register_repo_root)로 디렉터리를 더한 뒤. --add-dir 시작 플래그, /permissions Workspace 탭, 이미 작업 디렉터리 안인 경로에는 돌지 않는다. 기다리지 않고 백그라운드에서 돈다. 훅 명령 자체는 샌드박스 밖에서 돈다(샌드박스). slash_command일 때 systemMessage는 사용자가 아니라 다음 턴에 Claude에게 컨텍스트로 간다. Claude Code 훅 레퍼런스
  • FileChanged: 파일 시스템 감시로 감지하므로 Edit·Write, Bash 스크립트, Claude Code 밖 프로세스 무엇이 바꿨든 돈다. matcher는 두 역할을 한다: |로 나눈 각 값을 작업 디렉터리의 문자 그대로 파일 이름으로 감시 목록에 올리고(정규식은 소용없음, "*"는 *라는 파일로 등록됨), 바뀐 파일의 basename에 일반 matcher 규칙으로 훅 그룹을 거른다. 입력 file_path, event(change, add, unlink). 막지 못한다. 원본 경고: 바꾸지 않아도 파일을 다시 쓰는 명령(perl -i)을 느슨한 조건으로 돌리면 훅이 자기 변경에 다시 돌아 무한 반복한다. Claude Code 훅 레퍼런스

워크트리 이벤트#

  • WorktreeCreate: claude --worktree, EnterWorktree 도구, 서브에이전트의 isolation: "worktree", 워크플로 에이전트, 백그라운드 세션, claude remote-control의 worktree 모드에서. Claude가 Bash로 git worktree add를 돌리면 돌지 않는다. 훅을 두면 기본 git 동작을 통째로 대체하므로 SVN·Perforce·Mercurial을 쓸 수 있고, .worktreeinclude는 처리되지 않는다. command 훅은 stdout 마지막 비어 있지 않은 줄에 경로를 찍고(JSON 불가), HTTP 훅은 hookSpecificOutput.worktreePath를 돌려준다. .·..가 든 절대 경로와 저장소 아래 심볼릭 링크를 지나는 경로는 거부된다(v2.1.216 이상). Claude Code 훅 레퍼런스
  • WorktreeRemove: 훅이 만든 워크트리를 정리할 때. 서브에이전트·워크플로 에이전트가 끝날 때는 워크트리를 남기고 이 훅을 돌리지 않는다. ExitWorktree·claude remote-control 정리 경로에서는 확인 없이 훅이 돌고, git 체크아웃이 아닌 워크트리는 변경 사항을 찾지 못하므로 훅이 지우기 전에 직접 확인하라고 한다. 종료 코드 0이면 지운 것으로 치므로 실제로 지웠는지 확인한다. 훅이 만든 브랜치는 Claude Code가 지우지 않는다. Claude Code 훅 레퍼런스

컴팩션 이벤트#

  • PreCompact: manual(/compact), auto(자동 컴팩션 창 도달, idle compaction). 입력 trigger, custom_instructions(/compact에 준 내용, 없거나 자동이면 null). 종료 코드 2나 decision: "block"으로 막는다. 자동 컴팩션을 막으면, 한도 전에 미리 하려던 것이면 건너뛰고 대화가 그대로 이어지지만, API가 이미 컨텍스트 한도 오류를 낸 뒤 복구용이면 그 오류가 드러나고 현재 요청이 실패한다. Claude Code 훅 레퍼런스
  • PostCompact: 입력 compact_summary(생성된 요약). 결정 제어 없이 요약 기록이나 외부 상태 갱신에 쓴다. Claude Code 훅 레퍼런스 → 장기 작업 컨텍스트 관리

모델 전환 이벤트 (v2.1.251 이상)#

  • PreModelSwitch: /model, 모델 선택기(Option+P·Alt+P), /config의 Model, 모델을 바꾸는 fast mode 켜기, SDK·Remote Control의 set_model 요청에 돈다. 자동 폴백이나 재개 시 모델 복원에는 돌지 않는다. matcher는 대상 모델의 정식 이름에 맞추며(opus 같은 별칭, 날짜 붙은 ID, Bedrock ID가 모두 같은 이름으로 모임), 정식 이름을 모르면(예: 게이트웨이만 아는 커스텀 ID) matcher와 상관없이 모든 훅이 도므로 막는 훅은 to_model을 직접 확인하라고 한다. 입력은 from_model, to_model, requested_model, source, 그리고 전환 비용 필드(context_tokens, prompt_cache_warm, cache_ttl, estimated_cache_write_usd, pricing). "ask"는 대화형 /model에서만 확인 창을 띄우고 나머지에서는 거부로 다룬다. 우선순위 deny > ask > allow. 시간 초과(기본 30초)면 전환을 막는다. Claude Code 훅 레퍼런스
  • PostModelSwitch: 요청한 전환, 자동 폴백, opusplan의 plan 모드 출입, 재개 시 복원 뒤에 돈다. 한 턴만 쓰는 폴백 체인 모델에는 돌지 않는다. 일반 텍스트 stdout이나 additionalContext를 전환 뒤 다음 요청과 함께 Claude에게 준다(다음 프롬프트 뒤 5초 안에 안 끝나면 그다음 요청에 붙임). 원본 용도: 모든 CLAUDE.md를 고치지 않고 특정 모델에서만 적용할 조직 지침 주기. Claude Code 훅 레퍼런스

MCP 입력 요청 이벤트#

  • Elicitation: MCP 서버가 작업 중 사용자 입력을 요청할 때. 입력 mcp_server_name, message, 선택적 mode(form, url), url, elicitation_id, requested_schema. 종료 코드 0과 hookSpecificOutput.action(accept+content, decline, cancel)으로 대신 답하면 대화상자가 뜨지 않는다. 출력 없이 0이면 사용자에게 맡긴다. URL 모드에 accept를 돌려주면 URL이 열리지 않는다. 종료 코드 2나 최상위 decision: "block"도 거절이 되고, 여러 훅 중 하나의 거절이 다른 훅의 accept·cancel을 이긴다. 거절 이유는 사용자도 서버도 보지 못한다. Claude Code 훅 레퍼런스 → MCP
  • ElicitationResult: 사용자가 답한 뒤 서버로 보내기 전. Elicitation 훅이 이미 답한 요청에는 돌지 않는다. accept+content로 값을 바꾸면 사용자의 content 전체를 대체한다. 사용자가 거절·취소했을 때도 돌고 훅의 action이 사용자의 것을 대체하므로, 입력 action이 accept인지 확인하지 않으면 거절된 요청을 수락으로 바꿀 수 있다고 원본이 경고한다. cancel은 사용자가 낸 값을 함께 보내므로 값을 숨기려면 decline을 쓴다. Claude Code 훅 레퍼런스

관련#