본문 바로가기
claudecode.to
문서 목록
Hooks 코스중급

Hooks 종료 코드로 도구 실행 차단하기

훅 스크립트의 종료 코드는 Claude Code의 다음 동작을 결정하는 신호입니다. 0은 허가, 2는 차단, 그 외는 에러이며, PreToolUse 훅에서 2를 반환해 rm -rf 같은 위험 명령을 막는 방법을 다룹니다.

9분2026-08-22 갱신

훅 스크립트가 반환하는 종료 코드는 Claude Code가 다음에 무엇을 할지 결정하는 신호입니다. PreToolUse 훅에서 종료 코드 2를 반환하면 그 도구 호출 자체가 차단되므로, 위험한 작업을 막는 '가드레일'을 만들 수 있습니다. PreToolUse·PostToolUse 훅에서 다룬 사전 체크를 실제 차단으로 발전시키는 단계로, ~/Desktop/hooks-test 디렉터리를 이어서 씁니다.

핵심 요약

  • 종료 코드 0은 훅의 '이의 없음'을 뜻할 뿐이며, PreToolUse에서는 통상적인 권한 플로(확인 프롬프트 등)가 계속 적용됩니다.
  • 종료 코드 2는 차단이며, PreToolUse뿐 아니라 많은 이벤트에서 처리를 저지합니다(PostToolUse 등 일부 제외).
  • 그 외의 종료 코드는 에러 취급입니다.

테스트 디렉터리 준비

아직 만들지 않았다면 아래 명령으로 만듭니다.

mkdir -p ~/Desktop/hooks-test/.claude
cd ~/Desktop/hooks-test

종료 코드 0·2·그 외는 각각 무엇을 뜻하나

훅에서 실행되는 명령은 끝날 때 '종료 코드'라는 숫자를 반환하고, 이 값에 따라 Claude Code의 동작이 달라집니다.

종료 코드의미동작
0성공도구 실행을 허가
2차단도구 실행을 저지(PreToolUse뿐 아니라 많은 이벤트에서 유효. PostToolUse 등 일부 제외)
그 외에러통상 모드에서도 stderr(표준 에러 출력)의 내용이 표시됨(non-blocking이므로 명령 자체는 실행됨)

가장 중요한 것은 종료 코드 2입니다. PreToolUse 훅에서 2를 반환하면 그 도구 호출 자체가 차단됩니다.

종료 코드 2에 의한 차단은 PreToolUse뿐 아니라 UserPromptSubmit·Stop·SubagentStop·PreCompact·WorktreeCreate 등 많은 이벤트에서 유효합니다. 다만 PostToolUse는 예외로, 2를 반환해도 단순한 에러로 취급될 뿐 차단 효과는 없습니다. 이미 실행이 끝난 뒤이기 때문입니다.

먼저 모든 Bash 명령을 차단해 보기

동작 원리를 확인하기 위해 모든 Bash 명령을 차단하는 가장 단순한 훅부터 만듭니다. ~/Desktop/hooks-test/.claude/settings.json에 아래 설정을 추가합니다.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "echo '차단: Bash 명령 실행은 허가되지 않았습니다' >&2; exit 2"
          }
        ]
      }
    ]
  }
}

~/Desktop/hooks-test에서 Claude Code를 실행하고 "ls를 실행해줘"라고 요청하면 다음처럼 차단됩니다.

> ls를 실행해줘

⏺ Bash(ls)
  ⎿  Error: PreToolUse:Bash hook error: [echo '차단: Bash 명령 실행은 허가되지 않았습니다' >&2; exit 2]: 차단:
     Bash 명령 실행은 허가되지 않았습니다

⏺ Bash 명령이 hook에 의해 차단됐습니다.

>&2로 stderr에 적은 메시지가 그대로 Claude에게 전달되고, exit 2가 도구 실행을 막았습니다. 이 상태로 두면 모든 Bash 명령이 막히니, 확인이 끝나면 설정을 지우거나 다음 실전 예로 교체하세요.

실전: rm -rf 만 차단하기

더 실전적인 예로, 폴더째 삭제하는 rm -rf는 막되 일반 rm file.txt는 허용하는 훅을 만듭니다.

  1. 검증용 프로젝트의 hooks 디렉터리에 스크립트를 만듭니다. 표준 입력의 JSON에서 명령을 꺼내 -r이나 -f 옵션이 있으면 차단합니다.
#!/bin/bash
# ~/Desktop/hooks-test/.claude/hooks/block-rm-rf.sh
# rm -rf 를 차단 (rm 은 허가)

# 표준 입력에서 JSON을 읽고 명령을 추출
input=$(cat)
command=$(echo "$input" | jq -r '.tool_input.command // empty')

# -r 이나 -f 옵션이 있으면 차단 (rm file.txt 는 허가)
if [[ "$command" =~ -[rf] ]]; then
    echo "차단: rm -rf / rm -r 은 허가되지 않았습니다" >&2
    exit 2
fi

exit 0
  1. 실행 권한을 부여합니다.
chmod +x ~/Desktop/hooks-test/.claude/hooks/block-rm-rf.sh
  1. settings.json에서 이 스크립트를 PreToolUse 훅에 등록합니다. matcher는 Bash로 두고, 명령 내용의 판단은 스크립트 안에서 합니다. 매처 패턴의 상세는 Hooks 매처를 참고하세요.
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/Desktop/hooks-test/.claude/hooks/block-rm-rf.sh"
          }
        ]
      }
    ]
  }
}
  1. 삭제 테스트용 폴더와 파일을 만들어 둡니다.
mkdir test-folder
touch test-folder/test.txt
  1. Claude Code를 실행하고 rm -rf test-folder를 요청하면 다음처럼 차단됩니다.
> `rm -rf test-folder` 를 실행해줘

⏺ I'll execute that command to remove the test-folder directory.

⏺ Bash(rm -rf test-folder)
  ⎿  Error: PreToolUse:Bash hook error: [~/Desktop/hooks-test/.claude/hooks/block-rm-rf.sh]: 차단:
     rm -rf / rm -r 은 허가되지 않았습니다

⏺ Bash 명령이 hook에 의해 차단됐습니다. rm -rf / rm -r의 실행은 허가되지 않았습니다.
  통상적인 파일 삭제가 필요한 경우엔 다른 방법을 시도해 주세요. 예를 들어 파일 탐색기에서 삭제하거나 다른 도구를 사용해 주세요.

Error: PreToolUse:Bash hook error: [...]: 차단: ... 부분이 종료 코드 2로 인한 차단입니다. stderr에 적은 이유가 전달됐기 때문에 Claude는 막힌 이유를 이해하고 다른 방법을 제안합니다. 실수로 중요한 파일을 지울 위험이 크게 줄어드니 훨씬 과감하게 작업을 맡길 수 있습니다.

permissions 와 훅 차단은 어떻게 가려 쓰나

단순한 Bash 명령 가드라면 퍼미션 설정의 deny 규칙만으로도 충분합니다. 옵션 조합처럼 명령 내용을 해석해서 판단해야 하는 복잡한 가드가 필요할 때 PreToolUse 훅에서 종료 코드 2를 반환하는 방식이 빛을 발합니다. 두 방법은 대체 관계가 아니라 층을 이루는 관계이므로, 기본 가드는 permissions에 두고 세밀한 조건은 훅으로 보강하는 식으로 조합하세요.

정리

  • 종료 코드 0은 성공이며 도구 실행을 허가합니다(PreToolUse에서는 통상 권한 플로가 계속 적용).
  • 종료 코드 2는 차단이며 PreToolUse 외 많은 이벤트에서 유효하지만, PostToolUse에서는 에러로만 취급됩니다.
  • 그 외 종료 코드는 에러 취급으로 stderr가 표시될 뿐 실행은 막지 않습니다.
  • 차단 이유는 >&2로 stderr에 적어야 Claude가 다른 방법을 찾을 수 있습니다.
  • 먼저 "rm -rf 차단"부터 시작해 가드레일을 넓혀 가고, 스크립트에서 프로젝트 정보와 파일 경로를 얻는 방법은 Hooks 환경 변수에서 이어집니다.

자주 묻는 질문

Hooks종료 코드PreToolUserm -rf가드레일

팀에 Claude Code를 도입하려면 실제 코드베이스에 맞춘 설계가 필요합니다.

무료 상담 신청