muaco Tech Note

Claude Codegithub.com

Claude Code 훅 onFailure 설정훅이 고장 나면 작업을 막는 법

Claude Code 2.1.295에 새로 생긴 onFailure: "block"을 settings 파일에 넣어 두면, 훅이 실행되지 않거나 시간을 넘기거나 예상하지 못한 종료 코드로 끝났을 때 작업이 막힙니다.

안녕하세요, muaco입니다.

이 글로 할 수 있는 것

이 글을 따라 하면 훅이 고장 났을 때 Claude Code가 작업을 멈추게 만들 수 있습니다. 2.1.295 버전부터 command 훅과 HTTP 훅에 onFailure: "block" 설정을 넣을 수 있습니다.

지금까지는 훅이 고장 나도 작업은 그대로 진행됐습니다. 경비원이 자리를 비우면 아무나 드나드는 셈입니다. 이 설정을 넣으면 경비원이 없는 동안 문이 잠깁니다.

9월 30일에 올린 훅 설정 글의 후속편입니다. 훅을 아직 한 번도 만들어 보지 않았다면 그 글을 먼저 보고 오세요.

미리 갖춰야 할 것

  • Claude Code 2.1.295 이상. 이 설정은 2.1.295 릴리스 노트에 처음 나옵니다. 더 낮은 버전에서 어떻게 동작하는지는 문서에 나와 있지 않습니다.
  • 이미 돌아가는 command 훅이나 HTTP 훅 하나. 지난 글에서 만든 훅을 그대로 쓰면 됩니다.
  • 그 훅이 들어 있는 설정 파일. 공식 문서가 밝힌 위치는 아래 세 곳입니다.
파일적용 범위남과 공유
~/.claude/settings.json내 모든 프로젝트안 됨, 내 컴퓨터에만
.claude/settings.json이 프로젝트 하나됨, 저장소에 올릴 수 있음
.claude/settings.local.json이 프로젝트 하나안 됨, 나만 씀

훅이 실패하면 지금은 통과됩니다

command 훅이 작업을 막는 길은 하나뿐입니다. 종료 코드 2로 끝나야 합니다. 종료 코드는 프로그램이 끝나며 남기는 숫자 신호이고 0이면 성공을 뜻합니다.

그 밖의 코드는 어떨까요? 문서는 1 같은 코드를 "막지 않는 오류"로 다룹니다. 작업은 그대로 진행되고 기록에 hook error 알림만 남습니다.

시간 초과도 같습니다. 문서에 따르면 시간을 넘긴 command·HTTP 훅은 취소되고 작업을 막지 않습니다. 기본 제한 시간은 둘 다 600초입니다.

HTTP 훅도 비슷합니다. 서버가 오류 상태를 돌려주거나 연결이 끊겨도 작업은 계속됩니다. 문서에도 멈춘 훅을 관문으로 믿지 말라는 경고가 있습니다.

감시용 훅이라면 여기서 문제가 생깁니다. 스크립트 오타 하나로 감시가 꺼져도 겉보기엔 멀쩡합니다. onFailure: "block"이 이 빈틈을 메웁니다.

전체 흐름은 이렇습니다.

따라 하기: onFailure 넣고 시험하기

준비

따라 하기
  1. Claude Code에서 /hooks를 입력하세요. 걸려 있는 훅 목록이 뜨고 훅마다 user settings, project settings처럼 어디서 왔는지 붙어 나옵니다.
  2. 고칠 훅을 골라 정의된 파일을 확인합니다. 훅을 선택하면 실행할 내용 전체와 정의된 위치가 보입니다.
  3. 그 설정 파일을 편집기로 엽니다. 안에 "hooks"라는 글자와 방금 본 훅 내용이 있으면 제대로 연 파일입니다.

설정

따라 하기
  1. 훅 하나를 적은 칸, 곧 "type": "command"가 있는 중괄호 안에 "onFailure": "block"을 넣습니다. 앞 줄 끝에 쉼표를 붙여야 파일이 깨지지 않습니다.
    {
      "hooks": {
        "PreToolUse": [
          {
            "matcher": "Bash",
            "hooks": [
              {
                "type": "command",
                "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh",
                "timeout": 30,
                "onFailure": "block"
              }
            ]
          }
        ]
      }
    }
  2. 위치는 릴리스 노트를 근거로 정했습니다. 노트는 이 설정이 command·HTTP 훅에 붙는다고만 적었고 공식 훅 문서에는 10월 9일 현재 이 키가 아직 없습니다. 그래서 type과 같은 칸에 넣었습니다.
  3. timeout도 함께 짧게 잡으세요. 기본값 600초를 그대로 두면 훅이 멈춘 뒤 10분이 지나서야 막힙니다. 위 예시의 30은 30초입니다.
  4. HTTP 훅이라면 같은 자리에 같은 한 줄을 넣습니다. 서버 주소는 각자 쓰는 값으로 바꾸세요.
    {
      "type": "http",
      "url": "http://localhost:8080/hooks/pre-tool-use",
      "timeout": 30,
      "onFailure": "block"
    }
  5. 파일을 저장하고 /hooks에서 그 훅을 다시 엽니다. 고친 파일이 정의된 위치로 나오면 맞는 곳을 고친 셈입니다.

확인

따라 하기
  1. 팀과 공유하는 .claude/settings.json이라면 시험하는 동안 커밋하지 마세요. 다음 단계에서 훅을 일부러 고장 내므로, 그대로 올리면 동료의 Bash 명령까지 막힙니다.
  2. command의 스크립트 이름을 없는 이름으로 바꿉니다. 예를 들어 block-rm.sh를 block-rm-test.sh로 고칩니다. 이러면 훅이 제대로 시작하지 못합니다.
  3. Claude에게 "현재 폴더 파일 목록을 보여 줘"처럼 Bash가 필요한 일을 시킵니다. 명령이 실행되지 않고 막히면 설정이 먹은 겁니다. 막혔을 때 화면에 뜨는 문구는 문서에 나와 있지 않습니다.
  4. 스크립트 이름을 원래대로 되돌리고 같은 요청을 다시 합니다. 파일 목록이 나오면 끝입니다.
  5. 차이를 눈으로 보고 싶다면 onFailure 줄을 빼고 2번을 반복해 보세요. 이번엔 작업이 그대로 진행되고 hook error 알림만 남습니다.

막히기 쉬운 세 군데

설정한 뒤로 모든 명령이 막힙니다

보이는 모습. 훅 스크립트를 되돌렸는데도 Bash 명령이 하나도 실행되지 않습니다.

왜 그런가. 스크립트가 0이나 2가 아닌 코드로 끝나고 있을 수 있습니다. 전에는 1로 끝나도 조용히 지나갔으니 몰랐던 문제입니다. 다만 1이 "예상하지 못한 코드"에 드는지는 릴리스 노트에 정확히 적혀 있지 않습니다.

어떻게 하나. 스크립트가 끝나는 모든 갈래를 exit 0이나 exit 2로 맞추세요. 공식 문서의 예시 스크립트도 통과는 0, 차단은 2로 끝냅니다.

한참 멈췄다가 막힙니다

보이는 모습. Claude가 몇 분 동안 아무 반응 없이 기다리다 작업을 멈춥니다.

왜 그런가. timeout을 적지 않으면 command·HTTP 훅은 600초를 기다립니다. 시간이 다 차야 실패로 판정되고 그제야 막힙니다.

어떻게 하나. 훅이 평소 몇 초 안에 끝난다면 timeout을 30 안팎으로 적어 두세요. 단위는 초입니다.

HTTP 서버를 껐을 때 결과가 예상과 다릅니다

보이는 모습. 훅 서버를 잠깐 내렸더니 작업이 막히거나, 반대로 그냥 통과합니다.

왜 그런가. 원래 연결 실패는 막지 않는 오류입니다. 그런데 이 설정이 연결 실패를 "시작하지 못함"으로 보는지는 릴리스 노트에 나와 있지 않습니다.

어떻게 하나. 서버를 끈 채로 위 확인 단계를 직접 돌려 어느 쪽인지 확인하세요. 서버 점검이 잦다면 그동안 작업이 막힐 수 있다고 미리 팀에 알려 두는 편이 안전합니다.

여기서 더 나아가려면

이 설정은 고장에 대비하는 장치입니다. 평소에 무언가를 막으려면 command 훅은 exit 2로, HTTP 훅은 2xx 응답에 "permissionDecision": "deny"를 담은 JSON으로 막습니다.

바로 전 2.1.294에서는 지시문으로 쓴 prompt·agent 훅이 막아야 할 일을 통과시키던 문제가 고쳐졌습니다. 다만 onFailure는 command·HTTP 훅용으로만 소개됐습니다. 팀 전체에 쓰려면 .claude/settings.json에 넣고 시험을 마친 뒤 커밋하세요.

이상으로 글 마치겠습니다.

출처

#Claude Code#훅#hooks#onFailure#실패 시 차단#settings.json#HTTP 훅

같은 분류의 글