기술

Claude Code가 rm -rf 치기 전에 막아 두는 훅 하나

Claude Code의 PreToolUse 훅은 도구를 쓰기 직전에 내 스크립트를 먼저 돌립니다. exit 2를 돌려주면 그 명령은 실행되지 않습니다. 막아 본 결과와, 글자 비교만으로는 빠져나가는 함정까지 정리했습니다.

Claude Code에 Bash 권한을 넓게 주고 쓰다 보면 rm -rf가 무서워집니다. 권한 확인 창을 매번 누르는 대신, 위험한 명령만 골라 아예 실행 전에 막는 방법이 있습니다. 훅(hooks)입니다.

근거: Claude Code 문서 Hooks reference, Automate workflows with hooks (2026년 11월 2일 확인). 아래 실행 결과는 Claude Code 2.1.316에서 확인했습니다.

훅이 하는 일

PreToolUse 훅은 Claude가 도구(Bash, Edit, Write 등)를 쓰기 직전에 내가 등록한 명령을 먼저 실행합니다. 훅은 실행하려는 도구 호출을 JSON으로 표준 입력에서 받습니다. Bash라면 tool_input.command에 실행할 명령이 들어 있습니다.

훅이 종료 코드 2로 끝나면 그 도구 호출은 막히고, Claude는 표준 에러(stderr)에 쓴 문장을 이유로 받습니다. 그걸 보고 다른 방법을 찾습니다. 종료 코드 0이면 평소처럼 진행합니다.

1. 훅 스크립트

.claude/hooks/block-rm.sh에 저장합니다. jq가 필요합니다(macOS는 brew install jq).

#!/bin/bash
CMD=$(jq -r '.tool_input.command // empty')
if echo "$CMD" | grep -Eq '(^|[;&|[:space:]])rm[[:space:]].*(-[a-zA-Z]*[rR]|--recursive)'; then
  echo "막음: 재귀 삭제(rm -r)는 직접 실행하세요: $CMD" >&2
  exit 2
fi
exit 0
chmod +x .claude/hooks/block-rm.sh

2. 등록

프로젝트의 .claude/settings.json에 넣습니다. 모든 프로젝트에 걸고 싶다면 ~/.claude/settings.json에 넣습니다.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rm.sh"
          }
        ]
      }
    ]
  }
}

시켜 봤다

빈 폴더에 build/app.js를 만들고, 훅을 건 상태에서 Claude Code에 rm -rf build를 그대로 실행하라고 시켰습니다.

$ claude -p "Run exactly this shell command with the Bash tool: rm -rf build"
프로젝트의 PreToolUse 훅(block-rm-rf.sh)이 rm -rf build 실행을 막았고, 명령은 실행되지 않았습니다.
$ ls build
app.js

명령은 실행되지 않았고 파일은 그대로 남았습니다.

함정: 글자 비교는 빠져나간다

문서의 예시처럼 *"rm -rf"* 같은 글자 비교로만 막으면, 옵션 순서만 바꿔도 통과합니다.

명령*"rm -rf"* 비교위 스크립트(정규식)
rm -rf build막힘막힘
rm -fr build통과막힘
rm -r -f build통과막힘
rm --recursive build통과막힘
cd a && rm -rf b막힘막힘
rm file.txt통과통과

위 스크립트도 완벽하지는 않습니다. 같은 줄에 rm과 -r 옵션을 가진 다른 명령이 함께 있으면(예: rm a.txt && ls -r) 함께 막힙니다. 반대로 find . -delete나 파이썬 스크립트 안의 삭제는 이 훅이 보지 못합니다. 훅은 실수를 막는 장치입니다. 작정하고 돌아가는 명령까지 막지는 못합니다. 중요한 작업 전에는 git 커밋을 함께 해 두세요.

알아둘 것

  • 같은 이벤트에 훅이 여러 개 걸려 있으면 모두 실행되고, 하나라도 거부(deny)하면 막힙니다.
  • 종료 코드 2의 의미는 이벤트마다 다릅니다. PreToolUse에서는 막지만, PostToolUse는 도구가 이미 실행된 뒤라 막지 못하고 메시지만 전달합니다.
  • 훅 스크립트는 실행 권한이 있어야 합니다(chmod +x).

오늘 할 일

자주 쓰는 프로젝트에 .claude/hooks/block-rm.sh 하나와 설정 몇 줄을 넣어 두세요. 그리고 rm -fr 같은 변형으로 한 번 시험해서 막히는지 확인하세요.

김현빈 Developer & Writer

기술, 포스팅 관련 질문, 프로젝트 협업 등 연락주시면 언제든지 회신 드립니다.

esc

↑↓ 고르기↵ 열기? 단축키

해변에서 주운 것

읽으러 가기 →
guest@beachcombers — zsh

단축키

⌘K 또는 /
글·작업·개발일지 찾기
R
해변 산책 — 아무 글 하나 줍기
`
터미널 열기
←→
쪽 넘기기 (휠·스와이프도 됩니다)
?
이 안내
esc
닫기