PreToolUse·PostToolUse 훅 — 도구 실행 전후 처리
PreToolUse 훅은 도구 실행 직전, PostToolUse 훅은 도구 실행 직후에 발화하는 훅입니다. matcher로 대상 도구를 지정하고 파일 편집 후 Prettier 자동 포맷을 거는 실전 예를 다룹니다.
PreToolUse 훅은 Claude Code가 도구(Bash, Edit, Write 등)를 실행하기 직전에, PostToolUse 훅은 도구를 실행한 직후에 발화하는 훅입니다. 파일을 편집할 때마다 손으로 포맷을 돌리거나 위험한 명령 앞에서 한 박자 멈춰 확인하는 수작업을 이 두 훅으로 자동화할 수 있습니다. Stop 훅까지 만들어 본 ~/Desktop/hooks-test 디렉터리를 이어서 씁니다.
핵심 요약
- PreToolUse 훅은 도구 실행 전에 발화하며 사전 체크나 경고 표시에 씁니다.
- PostToolUse 훅은 도구 실행 후에 발화하며 자동 포맷이나 lint에 가장 잘 맞습니다.
matcher로 어느 도구(Bash, Edit, Write 등)에 발화할지 지정합니다.- JavaScript 정규 표현식(예:
^Notebook)으로 유연한 패턴 매칭이 가능합니다. - 설정은 settings.json에 적고 프로젝트 단위 또는 개인 단위로 관리합니다.
PreToolUse 훅은 무엇을 하나
PreToolUse 훅은 도구가 실행되기 전에 끼어들어 사전 처리를 합니다. 주된 용도는 세 가지입니다.
- 위험한 명령 실행 전 경고 표시
- 특정 파일 변경 전 백업 작성
- 실행 조건 체크와 제어
예를 들어 "rm 명령을 실행하려 하는데 정말 괜찮은가"라는 확인을 자동화할 수 있습니다. 말하자면 '가드레일' 역할입니다. 실제로 실행을 차단하는 방법은 종료 코드로 제어에서 다룹니다.
PostToolUse 훅은 무엇을 하나
PostToolUse 훅은 도구의 실행 결과를 받아 후처리를 자동 실행합니다. 주된 용도는 다음과 같습니다.
- 파일 편집 후의 자동 포맷
- 코드 변경 후의 lint 실행
- 변경 로그 기록
Claude Code가 코드를 편집할 때마다 Prettier나 ESLint가 자동으로 돌아가는 워크플로를 만들 수 있어, 코드 품질을 자동으로 담보하고 수동 확인 작업이 크게 줄어듭니다.
PreToolUse·PostToolUse 훅은 메인 에이전트뿐 아니라 서브에이전트(Agent 도구로 기동되는 에이전트)의 도구 실행에도 발화합니다. 훅 입력에 agent_id·agent_type이 포함되므로 어느 서브에이전트의 도구 실행인지 판별할 수 있습니다. 서브에이전트의 완료 시점 자체를 감지하려면 SubagentStop 훅을 씁니다.
matcher 로 도구 지정하기
훅을 어느 도구에 발화시킬지는 matcher로 지정합니다. 자주 쓰는 값은 "Bash", "Edit", "Write" 같은 도구명입니다.
| matcher | 매치하는 도구 |
|---|---|
"Bash" | 모든 Bash 실행 |
"Edit" | 모든 Edit 조작 |
"Write" | 모든 Write 조작 |
"Edit"와 "Write"를 파이프로 연결 | Edit 또는 Write |
파이프 기호로 연결하면 OR 조건이 됩니다.
"matcher": "Edit|Write"와일드카드와 정규 표현식 등 매처의 상세는 Hooks 매처에서 다룹니다.
실전: 파일 편집 후 Prettier 자동 포맷
JavaScript 계열 프로젝트에서 파일을 편집할 때마다 Prettier(코드를 정해진 규칙대로 정형하는 도구)로 자동 포맷하는 훅을 만듭니다. 설정 파일의 기본 구조와 sh 파일화는 Hooks 설정 방법에서 다뤘습니다.
- 포맷용 스크립트를 프로젝트의
.claude/hooks/format-on-edit.sh에 만듭니다. 표준 입력으로 들어온 JSON에서 파일 경로를 꺼내, 대상 확장자면 Prettier를 실행합니다.
#!/bin/bash
# ~/Desktop/hooks-test/.claude/hooks/format-on-edit.sh
# PostToolUse를 써서 편집된 파일을 포맷하는 Hooks 스크립트
set -e
# 표준 입력에서 JSON을 읽고 파일 경로를 추출
file_path=$(jq -r '.tool_input.file_path // empty')
# 파일 경로가 빈 경우엔 종료
[[ -z "$file_path" ]] && exit 0
# 파일이 존재하지 않는 경우엔 종료
[[ ! -f "$file_path" ]] && exit 0
# 대상 확장자를 체크
case "$file_path" in
*.ts|*.tsx|*.js|*.jsx|*.json)
npx prettier --write "$file_path" 2>/dev/null || true
;;
esachello.sh에 비하면 길어 보이지만, 하는 일은 "편집된 파일 경로를 얻어 대상 확장자면 Prettier를 실행한다"뿐입니다.
- 실행 권한을 부여합니다.
chmod +x ~/Desktop/hooks-test/.claude/hooks/format-on-edit.sh~/Desktop/hooks-test/.claude/settings.json에서 이 스크립트를 호출합니다. matcher에는 파일 생성(Write)과 편집(Edit)을 지정합니다.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "~/Desktop/hooks-test/.claude/hooks/format-on-edit.sh"
}
]
}
]
}
}sh 파일 경로에는 ${CLAUDE_PROJECT_DIR} 같은 플레이스홀더 변수를 쓰는 것이 권장됩니다. 절대 경로는 팀에서 설정을 공유할 때 머신마다 경로가 달라 동작이 깨질 수 있기 때문입니다. 자세한 내용은 Hooks 환경 변수를 참고하세요.
여기까지 설정하면 다음 흐름으로 동작합니다.
- Claude Code가 파일을 편집합니다.
- 훅의 매처가 Write·Edit을 감지합니다.
format-on-edit.sh가 실행됩니다.- 스크립트가 파일 경로를 읽고 대상 확장자인지 확인합니다.
- Prettier로 포맷이 실행됩니다.
- 포맷된 파일이 저장됩니다.
실제로 시험해 보기
일부러 포맷이 무너진 코드를 Claude Code 없이 ~/Desktop/hooks-test/test.js에 만듭니다.
function test() {
let a = 1; // 인덴트가 무너진 코드
console.log(a);
return a
}Claude Code를 실행해 이 파일을 편집하게 합니다.
> test.js 라는 파일의 끝에 test() 라는 한 줄을 추가해 주세요.test() 한 줄이 추가되면서 Prettier가 실행되어, 불필요한 줄바꿈과 인덴트가 정리됩니다.
function test() {
let a = 1;
console.log(a);
return a;
}
test();포맷은 알기 쉬운 예일 뿐이고, 같은 방식으로 테스트 실행이나 lint 실행도 걸 수 있습니다.
훅이 실행됐는지 어떻게 확인하나
위 예에서는 Claude Code 화면에 아래 같은 메시지가 표시됩니다.
⎿ Running PostToolUse hooks… (1/2 done)1/2 done은 PostToolUse에 등록된 두 스크립트, 즉 처음에 만든 로그 작성 스크립트(hello.sh)와 이번의 포맷 스크립트(format-on-edit.sh)가 실행됐다는 뜻입니다.
다만 hello.sh만 있을 때는 이 메시지가 표시되지 않았습니다. 포맷처럼 완료까지 몇 초 걸리는 처리일 때만 표시되는 것으로 보이므로, 훅 실행 여부의 판단에는 참고 수준으로만 삼고 확실한 확인은 로그 파일로 하세요.
모든 도구에 훅을 걸 수 있나
matcher에 빈 문자열("")을 지정하면 모든 도구에 발화합니다. 다만 훅은 도구 호출마다 실행되므로 과도한 설정은 응답 속도 저하로 이어집니다. 필요한 도구만 지정하는 것을 권장합니다.
정리
- PreToolUse 훅은 도구 실행 전에 발화하며 경고 표시나 사전 체크에 씁니다.
- PostToolUse 훅은 도구 실행 후에 발화하며 자동 포맷이나 lint에 가장 잘 맞습니다.
matcher로 발화 대상 도구를 지정하고, 파이프로 연결하면 OR 조건이 됩니다.- 훅 스크립트는 표준 입력의 JSON에서
tool_input.file_path를 꺼내 편집된 파일을 알 수 있습니다. - 먼저 "편집 후 자동 포맷"부터 시작하고, 실행을 실제로 막는 방법은 종료 코드로 제어에서 이어집니다.
자주 묻는 질문
팀에 Claude Code를 도입하려면 실제 코드베이스에 맞춘 설계가 필요합니다.
무료 상담 신청