claude-code-notifier
작동 방식 가이드 자주 묻는 질문
◐한국어
English العربية Deutsch Español Français עברית Italiano 日本語 한국어 Nederlands Polski Português (Brasil) Русский Türkçe Tiếng Việt 简体中文 繁體中文
시작하기
전체 가이드

Claude Code Stop hook: Claude가 작업을 마치면 무언가 실행하기

2026년 10월 31일 업데이트 · 6분 분량
이 페이지의 내용 01Stop이 실행되는 경우와 실행되지 않는 경우 02가장 간단한 Stop hook 03hook이 받는 데이터 04알림에 Claude의 마지막 메시지 넣기 05Claude가 계속 작업하게 하기 06실패 시에도 알림 받기 07Claude Code Notifier의 역할 08FAQ

Claude Code의 Stop hook은 메인 Claude 에이전트가 응답을 마칠 때마다 명령을 실행해요. 그래서 "완료" 알림을 보내거나, 결과를 기록하거나, 검사를 돌리기에 딱 맞는 곳이에요. Claude를 중단시키면 실행되지 않고, API 오류로 끝난 턴에서는 대신 StopFailure가 발생해요. hook은 Claude의 마지막 메시지를 last_assistant_message로 받고, decision: "block"과 reason을 반환하면 Claude가 멈추지 않고 계속 작업하게 할 수 있어요.

01Stop이 실행되는 경우와 실행되지 않는 경우

Stop은 전체 작업이 끝났을 때만이 아니라 매 턴이 끝날 때마다 실행돼요. Claude Code는 "작업"이라는 개념을 모르고, Claude가 응답을 멈추고 사용자를 기다린다는 것만 알아요. 짧은 질문 하나에도 Stop이 한 번, 두 시간짜리 리팩터링에도 한 번이에요.

다음 경우에는 실행되지 않아요.

  • Esc를 누르는 등 턴을 중단했을 때
  • rate limit, 과부하, 인증 실패 같은 API 오류로 턴이 끝났을 때. 이때 Claude Code는 StopFailure를 발생시키며, 매칭에 쓸 수 있는 error 필드(rate_limit, overloaded, server_error 등)가 함께 와요.
  • 서브에이전트가 끝났을 때. 이 경우는 SubagentStop이에요.

Stop은 matcher를 지원하지 않아요. matcher를 추가해도 무시되고 hook은 매 턴 실행돼요.

02가장 간단한 Stop hook

Claude가 끝날 때마다 명령을 실행하려면 ~/.claude/settings.json에 다음을 추가하세요. 이 예시는 macOS에서 소리를 재생해요.

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "afplay /System/Library/Sounds/Glass.aiff"
          }
        ]
      }
    ]
  }
}

Mac, Windows, Linux용 데스크톱 알림 명령은 Claude Code가 끝났을 때 알림 받는 방법을 참고하세요. 이 가이드의 나머지 부분에서는 hook의 입력과 출력으로 할 수 있는 일을 다뤄요.

03hook이 받는 데이터

공통 필드(session_id, transcript_path, cwd, permission_mode, hook_event_name) 외에 Stop hook은 다음을 받아요.

필드내용
last_assistant_message이번 턴에서 Claude가 보낸 마지막 응답 텍스트
stop_hook_activeStop hook이 차단해서 Claude가 이미 계속 작업 중이면 true
background_tasks백그라운드 셸이나 서브에이전트처럼 아직 실행 중인 작업
session_crons/loop 등으로 이 세션에 예약된 wake-up

transcript 파일을 읽지 말고 last_assistant_message를 사용하세요. transcript는 비동기로 기록되기 때문에 hook이 실행될 때 마지막 메시지가 아직 없을 수 있어요.

background_tasks와 session_crons를 보면 세션이 정말 끝났는지, 아니면 백그라운드 작업이 다시 깨울 때까지 잠시 멈춘 건지 알 수 있어요. 알림 스크립트에서 둘 다 비어 있는지 확인한 뒤에 "완료"라고 알리면 돼요.

04알림에 Claude의 마지막 메시지 넣기

이 스크립트(macOS, Linux용, jq 필요)는 Claude 응답의 앞부분을 보여 주고, 백그라운드 작업이 아직 실행 중이면 알림을 보내지 않아요.

#!/bin/bash
# ~/.claude/hooks/notify-done.sh
input=$(cat)

# Skip if background tasks are still in flight
busy=$(jq '(.background_tasks // []) | length' <<<"$input")
[ "$busy" -gt 0 ] && exit 0

msg=$(jq -r '(.last_assistant_message // "Claude has finished")
             | gsub("\\s+"; " ") | .[0:140]' <<<"$input")

if command -v osascript >/dev/null 2>&1; then
  osascript -e 'on run argv' \
            -e 'display notification (item 1 of argv) with title "Claude has finished"' \
            -e 'end run' "$msg"
elif command -v notify-send >/dev/null 2>&1; then
  notify-send "Claude has finished" "$msg"
fi
exit 0

저장한 뒤 chmod +x ~/.claude/hooks/notify-done.sh를 실행하고 hook이 이 스크립트를 가리키게 하세요.

{
  "hooks": {
    "Stop": [
      {
        "hooks": [{ "type": "command", "command": "~/.claude/hooks/notify-done.sh" }]
      }
    ]
  }
}

이 스크립트는 항상 0으로 종료해요. 이게 중요한데, Stop에서 종료 코드 2는 "멈추지 마"라는 뜻이라서, 알림 스크립트가 실수로 2로 종료하면 Claude가 계속 작업하게 돼요.

05Claude가 계속 작업하게 하기

Stop은 차단할 수 있는 이벤트 중 하나예요. 멈춤을 차단하면 Claude는 지정한 reason을 다음 지시로 삼아 턴을 이어 가요. 방법은 두 가지예요.

  • 2로 종료하면 Claude가 stderr 내용을 reason으로 받아요. 또는
  • 0으로 종료하고 JSON을 출력하세요.
{
  "decision": "block",
  "reason": "The test suite is failing. Run npm test, fix the failures, then finish."
}

hook이 오류를 알리는 게 아니라 안내를 주는 경우라면 hookSpecificOutput.additionalContext로도 대화를 이어 갈 수 있어요. 이때 transcript에는 hook 오류가 아니라 Stop hook 피드백으로 표시돼요.

{
  "hookSpecificOutput": {
    "hookEventName": "Stop",
    "additionalContext": "Please run the test suite before finishing"
  }
}

무한 루프 피하기

항상 차단하는 Stop hook은 Claude를 절대 멈추지 못하게 해요. 다음 두 가지가 이를 막아 줘요.

  1. Stop hook 때문에 Claude가 이미 계속 작업 중이면 stop_hook_active가 true가 돼요. 이 값을 확인하고 일찍 종료하세요.
  2. 도구 호출 없이 Stop hook이 연속 8번 차단하면 Claude Code는 어쨌든 턴을 끝내요. 이 한도는 CLAUDE_CODE_STOP_HOOK_BLOCK_CAP 환경 변수로 늘릴 수 있어요.

다음은 Claude에게 실패한 테스트를 한 번 고치게 한 뒤 멈추도록 하는 hook이에요.

#!/bin/bash
# ~/.claude/hooks/tests-must-pass.sh
input=$(cat)
[ "$(jq -r '.stop_hook_active' <<<"$input")" = "true" ] && exit 0

if ! npm test --silent >/dev/null 2>&1; then
  jq -nc '{decision: "block", reason: "npm test is failing. Fix the failures, then finish."}'
fi
exit 0

Hook은 세션의 작업 디렉터리에서 실행되므로 npm test는 프로젝트 안에서 실행돼요. 검사는 빠르게 유지하세요. 기본적으로 command hook은 최대 600초까지 실행될 수 있고, 그동안 Claude는 기다려요.

스크립트를 작성하지 않고 Claude가 목표를 향해 계속 작업하게 하고 싶다면, Claude Code에 내장된 /goal 명령이 세션 범위의 Stop hook을 대신 설정해 줘요.

06실패 시에도 알림 받기

API 오류는 Stop을 건너뛰기 때문에, "완료" 알림으로는 Claude가 rate limit 때문에 중단했다는 걸 알 수 없어요. 이런 경우에도 알림을 받고 싶다면 같은 스크립트를 StopFailure에도 추가하세요. 출력과 종료 코드는 무시되므로 알림이나 로그 용도로만 쓸 수 있어요. StopFailure에서는 last_assistant_message에 "API Error: Rate limit reached" 같은 오류 메시지가 담겨요.

07Claude Code Notifier의 역할

자리를 비운 동안 Claude가 작업을 끝냈는지 알고 싶다면, push 서비스를 호출하는 Stop hook으로 충분해요. 직접 구성하고 싶다면 ntfy 가이드부터 시작해 보세요.

Claude Code Notifier도 같은 Stop hook을 사용하지만, 한 가지 다른 점이 있어요. 응답을 돌려보낼 수 있다는 거예요. 무료 커맨드라인 도구인 ccn은 Mac, Windows, Linux에서 동작하며 자체적으로 데스크톱 알림을 띄워요. iPhone 또는 Android 앱을 연결하면 턴이 끝나는 즉시 "Claude has finished" push를 받고, 휴대폰에서 다음 지시를 입력할 수 있어요. ccn이 이를 Stop hook에서 Claude의 다음 지시로 반환하기 때문에, 키보드 앞에 없어도 세션이 계속 진행돼요. 최근 30초 안에 직접 입력했다면 휴대폰 응답을 기다리지 않아요. 이 도구는 독립적으로 만들어졌으며 Anthropic이 만든 것이 아니에요. 이 워크플로는 긴 작업 중 자리 비우기를, 설치는 ccn 페이지를 참고하세요.

08FAQ

Stop hook은 Claude가 전체 작업을 끝냈을 때 실행되나요, 아니면 응답할 때마다 실행되나요?

응답할 때마다 실행돼요. Stop은 요청 규모와 상관없이 메인 에이전트가 응답을 마칠 때마다 발생해요. 아직 예정된 작업이 남아 있는지 알고 싶다면 입력의 background_tasks와 session_crons를 확인하세요.

Stop hook이 왜 실행되지 않았나요?

턴을 중단했다면 Stop이 건너뛰어지고, API 오류로 끝났다면 대신 StopFailure가 발생해요. 그 외에는 /hooks에 hook이 표시되는지, 스크립트에 실행 권한이 있는지 확인하세요. 나머지는 문제 해결 체크리스트에서 다뤄요.

Stop hook이 실행된 뒤에도 Claude가 계속 작업하는 이유는 무엇인가요?

hook이 코드 2로 종료하거나 decision: "block"을 출력해서 종료를 막고 있는 거예요. 알림 전용 hook은 항상 0으로 종료하도록 하고, 차단하는 hook은 먼저 stop_hook_active를 확인하도록 하세요.

hook에서 Claude의 최종 답변은 어떻게 가져오나요?

stdin으로 들어오는 JSON에서 last_assistant_message를 읽으세요. 예를 들어 jq -r '.last_assistant_message'를 쓸 수 있어요. transcript_path에 의존하지 마세요. Stop이 발생하는 시점에는 파일에 마지막 메시지가 아직 없을 수 있어요.

Stop과 SubagentStop의 차이는 무엇인가요?

Stop은 메인 에이전트용이에요. SubagentStop은 서브에이전트가 끝날 때 발생하고, 에이전트 유형으로 매칭하며, 같은 차단 필드를 지원해요. "Claude has finished" 알림은 Stop에 두세요.

Claude Code Notifier Claude Code가 작업을 끝내거나 입력이 필요할 때 휴대폰으로 push 알림을 받고, 바로 승인·거부하거나 답할 수 있어요. ccn 커맨드라인 도구는 Mac, Windows, Linux에서 무료예요.
iOS용 다운로드 Android용 다운로드 ccn 설치하기

관련 가이드

  • Claude Code가 작업을 끝냈을 때 알림 받는 방법"작업 완료"에는 Stop hook을, "입력 필요"에는 Notification hook을 쓰세요. Mac, Windows, Linux용 복사-붙여넣기 설정과 휴대폰 알림까지 다뤄요.
  • Claude Code hook 완벽 정리: 모든 이벤트와 용도Claude Code hook이 무엇인지, settings.json의 어디에 넣는지, matcher와 입력, exit code가 어떻게 동작하는지, 그리고 각 hook 이벤트의 용도를 알아봐요.
  • Claude Code Notification hook: 언제 실행되고 어떻게 쓰는지Claude Code의 Notification hook이 언제 실행되는지, permission_prompt와 idle_prompt의 의미, 받는 입력, 그리고 실행 전에 기다리는 이유를 알아봐요.
  • Claude Code를 실행해 두고 자리 비우기: 워크플로긴 Claude Code 작업을 위한 실용적인 루틴: 컴퓨터를 깨어 있게 하고, 불필요한 prompt를 줄이고, 휴대폰으로 알림을 받아 바로 답장하세요.
claude-code-notifier

Claude Code Notifier는 독립적인 제3자 애플리케이션입니다. Anthropic, PBC와 제휴하거나 Anthropic, PBC의 보증 또는 후원을 받지 않습니다. "Claude" 및 "Claude Code"는 Anthropic, PBC의 상표입니다.

앱 iOS 앱 Android 앱 macOS, Windows, Linux용 ccn 전체 가이드
법적 고지 개인정보 처리방침 서비스 약관 다른 언어 © 2026 touchtap. 모든 권리 보유. TouchTap Ltd는 잉글랜드 및 웨일스에 등록되어 있습니다(회사 번호 13942589).