
사용하는 이벤트 목록
- Stop (작업완료)
- PreToolUse (도구호출 직전)
- PostToolUse (도구호출 완료)
아래 예시는 완료필터(Stop), 작업도구 필터(PreToolUse,PostToolUse) 총 2가지 부류로 필터해 이벤트를 수행하게 해 두었다.
PreToolUse에서 자동수행으로 설정하게 되면 도구를 묻지않는 상태도 발생하기 때문에 PreToolUse 이벤트에서 10초의 딜레이를 발생하였다.
10초내에 PostToolUse에서 완료처리가 되었다면 이벤트 메시지 발송을 취소하도록 처리하여 불필요한 메시지 전송을 방지하였다.
딜레이를 발생시켜도 큐에 담지 않는 이상은 정상적인 처리가 불가하다고 판단하여. 위 기능은 폐기하도록 함.
Bash|Write|Edit는 메시지를 많이 발생시키지만 종종 이 도구들이 확인을 묻는 경우가 발생함. 훅이 확인해야하는지 안해야하는지 까지 판별하지 못하기 때문에 거슬리면 삭제하여 한번씩 확인하던지, 예정/완료 메시지를 교차로 확인해 완료가 안되고 있으면 확인해보던지 둘중 하나의 방법으로 임시 처리함.(나중에 시간되면 더 좋은 방식으로 처리할 예정)
path .claud/settings.json
{
"alwaysThinkingEnabled": true,
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "/home/persol/.claude/hooks/telegram-notify.sh",
"timeout": 10000
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash|Write|Edit|AskUserQuestion|ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "/home/persol/.claude/hooks/telegram-notify.sh",
"timeout": 10000
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash|Write|Edit|AskUserQuestion|ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "/home/persol/.claude/hooks/telegram-notify.sh",
"timeout": 10000
}
]
}
]
}
}
이후 쉘스크립트로 취향에 맞게 텔레그램,슬랙 등 메시지를 받을 주체를 선택해서 스크립트를 작성하면 된다.
telegram-notify.sh
#!/bin/bash
# 텔레그램 설정 - 환경변수 또는 직접 설정
TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN:-8487791962:AAGSMwdIDZDhPX6JYP_MvWoDRvXwee2ikhY}"
TELEGRAM_CHAT_ID="${TELEGRAM_CHAT_ID:-290471427}"
# stdin에서 JSON 데이터 읽기
INPUT=$(cat)
# 디버깅용 로그 (나중에 삭제)
echo "$INPUT" >> /tmp/claude-hook-debug.log
# grep과 sed를 사용하여 JSON 파싱 (jq 대체)
# Perl 정규식(-P)으로 더 정확한 매칭
get_json_value() {
echo "$INPUT" | grep -oP "\"$1\"\s*:\s*\"\K[^\"]*" 2>/dev/null | head -1
}
# hook 이벤트 타입 추출
EVENT=$(get_json_value "hook_event_name")
NOTIFICATION_TYPE=$(get_json_value "type")
SESSION_ID=$(get_json_value "session_id")
PERMISSION_MODE=$(get_json_value "permission_mode")
TOOL_NAME=$(get_json_value "tool_name")
# cwd에서 프로젝트명 추출
CWD=$(get_json_value "cwd")
PROJECT_NAME=$(basename "$CWD")
PROJECT_PREFIX=""
if [ -n "$PROJECT_NAME" ]; then
PROJECT_PREFIX="📁 [$PROJECT_NAME]
"
fi
# 이벤트별 메시지 생성
case "$EVENT" in
"PreToolUse")
MESSAGE="${PROJECT_PREFIX}[PreToolUse] 🔨 $TOOL_NAME 도구 실행 예정"
;;
"PostToolUse")
MESSAGE="${PROJECT_PREFIX}[PostToolUse] ✅ $TOOL_NAME 도구 완료"
;;
"PermissionRequest")
case "$PERMISSION_MODE" in
"plan")
# 플랜 모드에서의 권한 요청은 무시 (Stop에서 처리)
exit 0
;;
"acceptEdits")
# 편집 모드에서의 권한 요청은 무시 (Stop에서 처리)
exit 0
;;
*)
# 실제 권한 요청만 알림
MESSAGE="${PROJECT_PREFIX}[PermissionRequest] 🔐 $TOOL_NAME 사용 권한이 필요합니다."
;;
esac
;;
"Notification")
TITLE=$(get_json_value "title")
BODY=$(get_json_value "body")
# 알림 타입별 메시지 생성
case "$NOTIFICATION_TYPE" in
"permission_prompt")
MESSAGE="${PROJECT_PREFIX}[Notification] 🔐 권한 승인 필요
확인해주세요."
;;
"idle_prompt")
MESSAGE="${PROJECT_PREFIX}[Notification] ⏳ 입력 대기 중
입력을 기다리고 있습니다."
;;
"elicitation_dialog")
MESSAGE="${PROJECT_PREFIX}[Notification] ❓ 선택 필요
$TITLE"
;;
*)
MESSAGE="${PROJECT_PREFIX}[Notification] 🔔 $TITLE"
;;
esac
;;
"UserPromptSubmit")
PROMPT=$(get_json_value "prompt")
# 프롬프트가 길면 앞부분만 표시
PROMPT_SHORT=$(echo "$PROMPT" | head -c 50)
if [ ${#PROMPT} -gt 50 ]; then
PROMPT_SHORT="${PROMPT_SHORT}..."
fi
MESSAGE="${PROJECT_PREFIX}[UserPromptSubmit] 📝 사용자 입력: $PROMPT_SHORT"
;;
"Stop")
# Stop 이벤트는 이벤트명 없이 기존 형식 유지
STOP_REASON=$(get_json_value "stop_hook_reason")
case "$STOP_REASON" in
"end_turn")
MESSAGE="${PROJECT_PREFIX}✅ 작업 완료
결과를 확인해주세요."
;;
"user_stop")
MESSAGE="${PROJECT_PREFIX}⏹️ 작업 중단
사용자에 의해 중단되었습니다."
;;
*)
# 빈 stop_reason이거나 알 수 없는 경우 = 확인 필요
MESSAGE="${PROJECT_PREFIX}🔔 확인 필요
Claude가 대기 중입니다."
;;
esac
;;
"SubagentStop")
MESSAGE="${PROJECT_PREFIX}[SubagentStop] ⏹️ 서브에이전트 작업 완료"
;;
"SessionStart")
SOURCE=$(get_json_value "source")
MESSAGE="${PROJECT_PREFIX}[SessionStart] 🚀 세션 시작 (Source: $SOURCE)"
;;
"SessionEnd")
REASON=$(get_json_value "reason")
MESSAGE="${PROJECT_PREFIX}[SessionEnd] 🛑 세션 종료 (Reason: $REASON)"
;;
"PreCompact")
TRIGGER=$(get_json_value "trigger")
MESSAGE="${PROJECT_PREFIX}[PreCompact] 📦 컨텍스트 압축 예정 (Trigger: $TRIGGER)"
;;
*)
# 알 수 없는 이벤트도 일단 알림
MESSAGE="${PROJECT_PREFIX}[Unknown] ❓ 알 수 없는 이벤트: $EVENT"
;;
esac
# 텔레그램 API로 메시지 전송
if [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Sending message: $MESSAGE" >> /tmp/claude-hook-curl.log
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d text="$MESSAGE" \
-d parse_mode="HTML" >> /tmp/claude-hook-curl.log 2>&1
echo "" >> /tmp/claude-hook-curl.log
fi
exit 0