Claude Code 알림이 안 온다면 원인은 거의 항상 네 가지 중 하나예요. hook이 로드되지 않았거나, hook이 실행되지만 실패하거나, 의존하는 이벤트가 예상한 시점에 발생하지 않거나, 운영체제가 알림을 숨기는 경우죠. Claude Code 안에서 /hooks를 실행해 무엇이 로드됐는지 확인하고, claude --debug로 세션을 시작해 각 hook이 실제로 무엇을 했는지 본 다음, 컴퓨터나 휴대폰의 알림 설정을 확인하세요. Claude Code Notifier를 쓴다면 ccn doctor와 ccn test 두 명령으로 대부분을 점검할 수 있어요.
아래 체크리스트는 가장 흔한 원인부터 드문 원인 순으로 정리했어요. Mac, Windows, Linux 모두에서 적용돼요.
011. Claude Code가 hook을 로드했는지 확인하기
Claude Code prompt에서 /hooks를 입력하세요. Claude Code가 로드한 모든 hook을 보여 주는 읽기 전용 화면으로, 각 hook이 어디서 왔는지(사용자 설정, 프로젝트 설정, 로컬 설정, 플러그인, 현재 세션) 표시해 줘요. hook을 선택하면 정확한 명령과 정의된 파일을 볼 수 있어요.
목록에 hook이 없다면:
- JSON이 잘못됐어요. 설정 파일은 엄격한 JSON이에요. 끝에 붙은 쉼표나
//주석 하나로 파일이 깨지고, 다음 시작 시 Claude Code가 Settings Error를 표시해요.claude doctor를 실행하면 Claude Code가 거부한 항목을 볼 수 있어요. - 파일 위치가 잘못됐어요. 개인 hook은
~/.claude/settings.json(Windows에서는%USERPROFILE%\.claude\settings.json)에 넣어요. 프로젝트 hook은 프로젝트 안의.claude/settings.json에 넣어요./status를 실행하고Setting sources줄을 보면 어떤 파일이 로드됐는지 알 수 있어요. - 이벤트 이름이 틀렸어요. 이벤트 이름은 대소문자를 구분해요:
Notification,Stop,PermissionRequest. 알 수 없는 이벤트 이름은 Settings Warning으로 표시되고 건너뛰어요. - hook이 꺼져 있어요. 어느 설정 파일이든
"disableAllHooks": true가 있으면 모든 hook이 꺼져요./hooks에Only hooks from managed settings run here가 표시된다면 조직에서allowManagedHooksOnly를 설정한 것이라 직접 만든 hook은 실행되지 않아요. - 수정 사항이 반영되지 않았어요. Claude Code는 보통 설정을 자동으로 다시 불러와요. 몇 초가 지나도 hook이 보이지 않으면 세션을 다시 시작하세요.
022. 워크스페이스 신뢰 수락하기
대화형 세션에서 Claude Code는 해당 폴더의 워크스페이스 신뢰 대화상자를 수락하기 전까지 모든 설정 파일의 hook을 실행하지 않아요. 직접 만든 ~/.claude/settings.json도 마찬가지예요. 그 대화상자를 닫아 버렸거나 Claude Code를 한 번도 연 적 없는 폴더라면 hook이 실행되지 않아요. 그 폴더에서 claude를 실행하고 대화상자를 수락하세요.
033. 이벤트가 예상한 시점에 발생하는지 확인하기
"고장 난" 알림의 상당수는 사실 타이밍 문제예요. Anthropic의 hooks 레퍼런스에 따르면:
Notification + permission_prompt권한 prompt가 약 6초 동안 대기했고 그동안 입력이 없을 때예요. 키를 누를 때마다 타이머가 초기화돼요.idle_prompt를 지정한 NotificationClaude가 작업을 마친 뒤 약 60초 동안 입력이 없고 실행 중인 백그라운드 에이전트도 없을 때예요.StopClaude가 응답을 마칠 때마다 발생해요. 중단했을 때는 발생하지 않아요. API 오류 시에는 대신 StopFailure가 발생해요.PermissionRequestClaude Code가 권한을 요청하기 직전에 발생해요.그래서 terminal에서 입력하면서 Notification hook을 테스트하면 아예 발생하지 않을 수도 있어요. 다른 창으로 전환해서 기다려 보세요. 턴이 끝나는 즉시 알림을 받으려면 Stop을 쓰세요. 자세한 내용은 Stop hook 가이드에 있어요.
권한 모드도 확인하세요. 최신 버전의 Claude Code는 대화형 세션을 auto 모드로 시작하는데, 이 모드에서는 분류기가 대부분의 작업을 묻지 않고 승인해요. prompt가 없으면 permission_prompt 알림도, PermissionRequest hook도 발생하지 않아요. 권한 알림을 테스트하려면 상태 표시줄에 manual 모드가 나올 때까지 Shift+Tab을 누른 뒤, Claude에게 승인이 필요한 작업을 요청하세요. 자세한 내용은 권한 모드 설명을 참고하세요.
matcher도 대소문자를 구분해요. PermissionRequest matcher를 bash로 쓰면 Bash 도구와 매칭되지 않아요.
044. hook 명령을 직접 실행해 보기
/hooks에서 명령을 복사해 샘플 입력과 함께 terminal에서 실행해 보세요:
echo '{"hook_event_name":"Stop","cwd":"/tmp","last_assistant_message":"done"}' | ./my-hook.sh
echo $?
흔한 실패 원인:
command not found: 스크립트의 절대 경로를 쓰거나, 프로젝트 안의 스크립트라면${CLAUDE_PROJECT_DIR}를 사용하세요.- 스크립트가 아무 동작도 하지 않아요:
chmod +x ./my-hook.sh로 실행 권한을 주세요. jq: command not found:jq를 설치하거나, Python이나 Node.js로 JSON을 파싱하세요.
055. 디버그 로그 읽기
claude --debug로 Claude Code를 시작하세요. terminal에는 따로 출력되지 않고, 로그는 ~/.claude/debug/<session-id>.txt에 저장돼요. 경로를 직접 지정하려면 claude --debug-file /tmp/claude.log를 쓰고 다른 terminal에서 tail -f /tmp/claude.log를 실행하세요. 이미 세션이 실행 중이라면 /debug로 로깅을 켜고 로그 위치를 확인할 수 있어요.
Hooks:로 시작하는 줄을 찾아보세요. 각 줄에는 이벤트, 명령, 종료 상태(finished with status 0, timed out, failed to start), 소요 시간이 나와요. 매칭에 대한 더 자세한 정보가 필요하면 CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose를 설정하세요.
여기서만 드러나는 문제가 두 가지 있어요:
- 셸 프로필이 무언가를 출력해요.
~/.bashrc나~/.zshrc에서echo를 실행하고 셸이 이를 source하면, 그 텍스트가 hook의 JSON 출력 앞에 붙어서 Claude Code가 출력을 일반 텍스트로 처리해요. 로그에서Hook output does not start with {를 검색해 보세요. 프로필 출력을if [[ $- == *i* ]]; then ... fi로 감싸서 대화형 셸에서만 실행되게 하세요. - 출력할 terminal이 없어요. Mac과 Linux에서 command hook은 제어 terminal 없이 실행돼요. 벨을 울리거나
/dev/tty에 이스케이프 코드를 쓰려는 hook은 아무 오류 없이 실패해요. 대신 데스크톱 알림 명령이나 Claude Code 자체의preferredNotifChannel설정을 사용하세요. 자세한 내용은 terminal 벨 가이드에 있어요.
066. 운영체제 확인하기
디버그 로그에 hook이 status 0으로 끝났다고 나오는데도 아무것도 보이지 않았다면, 운영체제가 알림을 숨긴 거예요. 알림을 띄우는 앱에 알림 권한이 있는지, 그리고 집중 모드(Mac), 방해 금지(Windows), Linux 데스크톱의 방해 금지 토글이 꺼져 있는지 확인하세요. Linux에서는 알림 데몬이 실행 중이어야 해요.
07Claude Code Notifier를 사용한다면
Claude Code Notifier는 Anthropic이 만들지 않은 독립 도구로, 작은 프로그램인 ccn을 Claude Code hook으로 설치해요. ccn도 다른 hook과 똑같은 hook이라서 위 내용이 모두 그대로 적용돼요. 먼저 자체 점검부터 해 보세요.
ccn doctor는 hook, 자격 증명, 서버 연결, 자리 감지를 점검해요. 문제가 보고되면 그것부터 고치세요.ccn test는 테스트 알림을 보내요. 알림이 도착한다면 파이프라인이 아니라 이벤트나 설정이 문제예요.ccn devices는 이 컴퓨터와 페어링된 휴대폰 목록을 보여 줘요. 아무것도 없다면ccn pair로 다시 페어링하세요. 자세한 방법은 페어링 가이드에 있어요.ccn config show는 실제 적용 중인 설정을 출력해요.notify_on_done,notify_on_permission,notify_on_question이 켜져 있는지,quiet_hours가 현재 시간에 걸려 있지 않은지 확인하세요. 휴대폰에서 바꾼 설정은ccn sync로 컴퓨터에 반영돼요.
오류처럼 보이지만 의도된 동작도 있어요.
- 키보드 앞에 있는 경우. 최근 30초 안에 입력했다면 휴대폰을 기다리지 않고 terminal에서 평소처럼 물어봐요.
quiet_when_present가 켜져 있으면(기본값) Claude가 실행 중인 terminal에 있을 때는 휴대폰으로 아무것도 보내지 않고, 다른 앱을 쓰고 있을 때는 정보 카드만 보내요. - Mac에서 알림이 중복되거나 누락되는 경우. 예전 Mac 메뉴 막대 앱과
ccn을 같은 Mac에서 함께 실행하지 마세요. - 오랫동안 쓰지 않은 경우. 휴대폰이나 컴퓨터를 60일 동안 사용하지 않으면 서버가 페어링을 삭제하므로 다시 페어링해야 해요.
휴대폰에서는 앱에 알림이 허용되어 있는지, 집중 모드(iPhone)나 방해 금지(Android)가 알림을 막고 있지 않은지 확인하세요. Android에서는 배터리 최적화 때문에 일부 앱의 알림이 늦어질 수 있어요. 알림이 늦게 온다면 배터리 설정에서 앱을 제한 없이 실행하도록 허용하세요. settings.json을 직접 수정했다면 ccn doctor로 hook이 그대로 있는지 확인할 수 있어요. ccn upgrade로 최신 버전으로 업데이트할 수 있어요.
08FAQ
Notification hook이 가끔만 실행되는 이유는 뭔가요?
permission_prompt와 idle_prompt 타입은 자리를 비운 것으로 보일 때 맞춰 실행돼요. permission_prompt는 입력이 없는 상태로 약 6초를 기다리고, idle_prompt는 Claude가 작업을 마친 뒤 약 60초를 기다려요. 입력 중이면 뒤로 미뤄져요. 바로 신호를 받으려면 PermissionRequest나 Stop을 사용하세요.
Claude Code 디버그 로그는 어디에 있나요?
claude --debug로 실행하면 로그가 ~/.claude/debug/<session-id>.txt에 기록돼요. 위치를 직접 정하려면 claude --debug-file <path>를, 실행 중인 세션에서는 /debug를 사용하세요.
ccn test는 되는데 실제 알림은 오지 않아요. 왜 그런가요?
파이프라인은 정상이니 설정과 타이밍을 살펴보세요. ccn config show에서 notify_on_*와 quiet_hours를 확인하고, quiet_when_present가 켜져 있으면 terminal 앞에 있는 동안에는 아무것도 보내지 않는다는 점을 기억하세요. Claude Code의 권한 모드도 확인해 보세요.