증상 → Hook이 실행되지 않음: 설정 파일과 이벤트·matcher부터 확인하고, 다음으로 원격 계정의 실행 환경과 반환 결과를 점검합니다. Claude Code를 먼저 다시 설치하지 마세요.
이 절차는 원격 Mac에서 Hook을 설정했지만 검사나 명령 차단이 보이지 않는 경우에 적합합니다. Hook의 차단 결과를 운영체제 권한이나 CI의 최종 테스트를 대신하는 안전 경계로 사용하지 마세요.
- 원격 Mac에서 코드 수정, 검사, Xcode 확인을 수행하는 개발자
- Hook 실행 여부를 확인하고 뒤이은 빌드와 테스트 증거를 관리하는 DevOps 엔지니어
- 공유 노드에서 사용자 설정, 프로젝트 설정, 관리 정책을 구분해야 하는 플랫폼 담당자
1. 실패가 발생한 단계 구분
Hook 문제는 하나의 증상처럼 보여도 원인은 다를 수 있습니다. 이벤트가 발생하지 않았거나, 이벤트는 발생했지만 matcher가 조건을 잡지 못했거나, 스크립트가 시작되지 않았을 수 있습니다. 스크립트가 실행된 뒤에도 반환 형식이나 결정 값이 맞지 않으면 차단이 적용되지 않을 수 있습니다.
먼저 재현 동작을 하나만 정하세요. 예를 들어 특정 파일을 수정하거나 하나의 도구 호출만 수행합니다. 그때의 Claude Code 세션 기록과 진단 정보를 기준선으로 남기고, 설정을 바꾸기 전후의 차이를 비교합니다. 공식 Hooks 문서의 디버깅 및 진단 안내를 참고해 이벤트와 처리 결과를 확인하세요.
| 관찰한 증상 | 우선 확인할 항목 | 다음 조치 |
|---|---|---|
| 아무 기록도 남지 않음 | 설정을 읽는 계정과 이벤트 | 실제 설정 경로와 이벤트 이름을 확인합니다 |
| 이벤트는 보이나 Hook이 실행되지 않음 | matcher와 도구 이름 | 조건을 줄여 단일 도구 호출로 재현합니다 |
| 스크립트 시작 오류가 남음 | 권한, 인터프리터, PATH, 작업 경로 | Hook 계정에서 같은 명령을 시험합니다 |
| 스크립트가 끝났지만 차단되지 않음 | 표준 입력, 출력, 종료 코드, 결정 필드 | 성공과 명시적 차단 결과를 각각 검증합니다 |
오류가 보이지 않는다는 이유만으로 Hook이 성공했다고 판단하지 마세요. 이 표처럼 관찰 가능한 단계부터 좁히면 재설치나 전체 설정 초기화 없이 원인을 분리할 수 있습니다.
2. 원격 Mac이 읽는 설정 범위 확인
Claude Code 설정은 사용자, 프로젝트, 프로젝트 로컬, 관리 정책처럼 적용 범위가 다릅니다. 공식 설정 문서는 각 설정 파일의 위치와 범위를 설명합니다. 작업 디렉터리에 파일이 있다는 사실만으로 현재 프로세스가 그 파일을 읽는다고 단정하지 마세요.
| 설정 범위 | 점검할 위치와 조건 | 원격 환경에서 생길 수 있는 차이 |
|---|---|---|
| 사용자 설정 | Claude Code를 실행하는 계정의 사용자 설정 | SSH 계정과 서비스 계정의 홈 디렉터리가 다를 수 있습니다 |
| 프로젝트 설정 | 저장소의 프로젝트 설정 파일 | 실제 저장소 경로나 작업 디렉터리가 다르면 적용되지 않을 수 있습니다 |
| 프로젝트 로컬 설정 | 해당 작업 환경에만 쓰는 로컬 설정 | 다른 계정이나 새 실행 환경에 자동으로 복사되지 않습니다 |
| 관리 정책 | 조직에서 관리하는 설정 | 사용자 설정과 별도로 적용되는 정책이 있는지 확인해야 합니다 |
SSH 터미널에서 성공했는데 CI에서는 실패한다면 두 실행 환경을 같은 것으로 취급하지 마세요. 실행 계정, 홈 디렉터리, 저장소 경로, 설정 파일 경로를 각각 기록해 비교합니다. 프로젝트 로컬 설정이 다른 서비스 계정에도 존재하는지 확인하고, 관리 정책이 있다면 그 정책을 변경할 권한이 있는 담당자와 함께 확인하세요.
3. 이벤트와 matcher를 한 동작씩 대조
예상한 작업과 실제 이벤트가 맞는지 확인합니다. 도구 호출 전 단계의 PreToolUse와 도구 호출 후 단계의 이벤트는 서로 대신할 수 없습니다. 세션 종료 시점의 Stop도 도구 호출 전 검사를 확인하는 수단이 아닙니다. 이벤트의 의미와 입력 필드는 공식 Hooks 문서에 맞춰 점검하세요.
다음 순서로 matcher를 좁힙니다.
- 실제로 수행한 동작과 확인하려는 시점을 적습니다. 실행 전 차단인지, 실행 뒤 검사인지, 세션 종료 검사인지 구분합니다.
- 설정에서 해당 시점에 맞는 이벤트 이름을 확인합니다.
- matcher가 대상으로 삼는 도구 이름과 필드를 확인합니다. 도구 이름의 오타나 예상과 다른 조건이 없는지 살펴봅니다.
- 조건을 여러 개 넣었다면 하나씩 제거하고, 단일 이벤트와 단일 도구 호출로 시험합니다.
- 진단 기록에서 이벤트가 발생했는지, matcher가 조건을 만족했는지, 명령이 시작됐는지를 각각 확인합니다.
이 방식은 “Hook이 안 돈다”는 표현을 세 가지 질문으로 나눕니다. 이벤트가 없었는지, 조건이 맞지 않았는지, 실행 단계에서 실패했는지 기록으로 답할 수 있어야 합니다.
4. SSH와 Runner의 실행 환경 비교
Hook 설정이 맞아도 스크립트가 의존하는 환경이 다르면 원격 Mac에서 실패합니다. 특히 SSH 대화형 셸과 백그라운드 Runner 서비스 계정은 PATH, 셸 초기화 파일, 작업 디렉터리, 파일 권한이 다를 수 있습니다. 대화형 터미널에서만 동작하는 별칭이나 셸 함수에 Hook을 의존시키지 마세요.
확인할 항목은 다음과 같습니다.
- 스크립트가 실행 가능한 권한을 갖고 있는지 확인합니다.
- 인터프리터 경로가 해당 계정에서도 유효한지 확인합니다.
git, 빌드 도구, 검사 도구 등 필요한 명령을 Hook 계정에서 직접 확인합니다.- 현재 작업 디렉터리와 상대 경로가 예상한 저장소를 가리키는지 살펴봅니다.
- 입력 파일을 읽고 결과를 쓸 권한이 있는지 확인합니다.
- 진단 출력에는 실행 여부와 오류만 남기고 비밀 키, 토큰, 인증 정보를 기록하지 않습니다.
SSH에서는 통과하고 Runner에서 실패한다면, 두 환경의 계정과 환경 변수를 나란히 비교합니다. 사용자 설정을 복사하는 것만으로 해결될 것이라고 가정하지 말고, Hook이 실행되는 실제 프로세스에서 필요한 명령을 찾을 수 있는지 확인하세요.
5. 반환 결과와 차단 동작 검증
Hook이 실행됐다는 사실과 요청한 동작을 차단했다는 사실은 별개입니다. 공식 문서가 정의하는 표준 입력, JSON 출력, 종료 코드, 결정 필드를 확인해야 합니다. 권한 설정 문서도 함께 확인해 Hook과 Claude Code 권한 설정의 역할을 혼동하지 마세요.
공식 Hook 계약에는 서로 구분되는 종료 결과가 있습니다. 0은 정상 처리, 2는 차단 오류, 그 밖의 0이 아닌 값은 일반 Hook 오류로 다뤄집니다. 이 차이를 무시하고 모든 비정상 종료를 같은 차단 동작이라고 보면 원인을 잘못 판단할 수 있습니다. 세부 의미는 공식 종료 동작 설명에서 확인하세요.
검증은 의도한 결과에 따라 나눕니다. 결정이 없는 정상 반환, 명시적으로 차단해야 하는 반환, 스크립트 자체의 실행 실패를 각각 시험합니다. 그다음 Claude Code에서의 Hook 오류와 후속 도구 실패, CI의 테스트 실패를 로그상으로 구분합니다. Hook이 명시적 차단을 반환했는지, 이후 단계가 별도로 실패했는지 기록에서 추적할 수 있어야 합니다.
6. Xcode 검증과 보안 경계 분리
Hook은 정해진 시점의 검사나 도구 호출 제어에 사용할 수 있습니다. 그러나 이를 운영체제 권한 격리, 사람의 승인, CI의 빌드 및 테스트 검증을 대신하는 장치로 취급하면 안 됩니다. Hook 스크립트에 접근 권한이 있다면 그 권한 자체는 호스트의 계정과 파일 권한에서 비롯됩니다. Claude Code의 권한 구성 안내와 실제 운영체제 권한을 따로 점검하세요.
Xcode 자동화 테스트는 Hook의 실행 기록과 분리해 검수합니다. 파일 수정 뒤의 포맷 검사는 빠른 피드백으로 활용하고, 정식 빌드와 테스트 결과는 CI에서 별도로 보존합니다. Apple의 SSH를 통한 Xcode 테스트 자동화 안내는 원격 환경의 자동화 흐름을 설명합니다. 테스트 결과 확인은 Apple의 결과 해석 문서, 명령줄 실행은 Xcode 명령줄 도구 참고 자료를 기준으로 정리하세요.
| 검수 단계 | 통과 조건 | 남길 증거 |
|---|---|---|
| 실제 트리거 | 의도한 이벤트와 matcher가 동작함 | 세션 진단 기록 |
| 정상 경로 | 허용할 작업이 예상대로 진행됨 | Hook 출력과 실행 결과 |
| 차단 경로 | 차단 설정이 해당 동작을 막음 | 종료 결과와 차단 기록 |
| Xcode 검증 | 테스트 명령의 결과를 CI에서 확인함 | 테스트 결과와 빌드 로그 |
| 재시작 뒤 확인 | 노드 재시작 뒤에도 계정과 설정이 유지됨 | 재검수 기록 |
Hook을 고칠지, 스크립트를 고칠지, 강제 검사를 CI로 옮길지는 이 검수 결과로 결정합니다. 재시작 뒤 설정이나 계정이 달라진다면, Hook 자체를 더 복잡하게 만들기 전에 노드의 계정 관리와 설정 배포부터 바로잡으세요.
자주 확인하는 질문
원격 Mac에서 Claude Code Hooks가 동작하지 않으면 어디부터 확인하나요?
설정 파일의 적용 범위와 실행 계정을 먼저 확인한 뒤, 실제 작업에 맞는 이벤트와 matcher를 검증합니다. 그다음 스크립트 경로와 의존 명령, 권한, 반환 결과를 확인합니다. 한 번에 하나의 조건만 바꾸면 이벤트 누락과 실행 환경 문제를 구분하기 쉽습니다.
PreToolUse matcher가 도구 호출을 잡지 못하는 이유는 무엇인가요?
설정한 matcher의 도구 이름이나 조건이 실제 호출과 다를 수 있습니다. 이벤트가 실행 전 단계인지도 확인하세요. matcher 조건을 최소화한 뒤 단일 도구 호출을 수행하고, 진단 기록에서 이벤트 발생과 조건 일치 여부를 각각 확인합니다.
SSH에서 Hook 스크립트가 명령을 찾지 못하면 어떻게 하나요?
Hook을 실행하는 계정에서 명령 경로와 PATH를 확인하세요. SSH 셸의 초기화 파일에만 등록된 경로나 별칭은 서비스 계정에서 제공되지 않을 수 있습니다. 인터프리터, 실행 권한, 작업 디렉터리, 파일 권한도 함께 점검하고 민감한 환경 변수는 로그에 남기지 않습니다.
Stop Hook으로 Xcode 테스트 통과를 입증할 수 있나요?
Stop Hook이 동작했다는 사실만으로 Xcode 테스트가 통과했다고 볼 수 없습니다. 테스트 명령의 실제 결과와 CI 빌드 상태를 따로 확인하고, 테스트 결과와 로그를 보존하세요. Hook은 검사 흐름을 보조할 수 있지만, 정식 테스트 판정과 그 증거를 대신하지 않습니다.
원격 Mac 환경을 실제로 검수할 때
공유 개발 환경에서 SSH와 CI가 서로 다른 계정으로 동작하면 사용자 설정과 PATH가 달라지고, Xcode 검증 결과도 Hook 기록만으로는 입증되지 않습니다. 반면 원격 Mac은 실제 macOS 도구 체인을 사용하는 환경을 제공하지만, 계정 권한과 CI 검수 절차를 대신 설계해 주지는 않습니다. 원격 Mac의 제공 방식과 이용 정보를 먼저 살펴보려면 MACCOME 한국어 안내를 확인한 뒤, 원격 Mac 이용 안내에서 프로젝트 기간에 맞는 사용 방식을 확인하세요. 계정과 환경이 맞지 않아 재현할 Mac이 필요하다면 이 경로로 사용 방식을 검토할 수 있습니다. 지속적인 고정 부하나 물리 장치 연결이 필요하다면 자체 Mac 운영이 더 적합할 수 있습니다.