إعداد Stop Hook لإرسال إشعارات تلقائية عبر سطح المكتب أو Slack أو Telegram عند انتهاء Claude من المهمة
تنفيذ المهام في Claude Code يستغرق أحيانًا عدة دقائق أو أكثر. تطلب منه إعادة هيكلة وحدة برمجية، أو تشغيل مجموعة اختبارات، أو معالجة دفعة من الملفات — ثم تنتقل إلى نافذة أخرى لتعمل على شيء آخر. المشكلة: لا تعرف متى انتهى.
تعود لتجد أنه ربما أنهى العمل منذ عشر دقائق، أو ربما توقف عند نافذة تأكيد ينتظر ردك.
باستخدام Hook من نوع Stop، يمكنك تلقي إشعار تلقائي عندما ينتهي Claude من المهمة أو يحتاج تدخلك. الإشعار يصلك أينما كنت — في أي نافذة أو على أي جهاز.
يوفر Claude Code حدثًا يُسمى Stop — يُطلَق في كل مرة يتوقف فيها Claude، سواء أكمل المهمة، أو واجه خطأ يحتاج تأكيدًا، أو ينتظر إدخالًا من المستخدم.
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/notify.sh"
}
]
}
]
}
}
يتلقى الـ Hook بيانات JSON عبر stdin تتضمن stop_reason (سبب التوقف) وstop_message (آخر رسالة من Claude). بناءً على هذه المعلومات، يمكنك تخصيص محتوى الإشعار.
هيكل بيانات stdin:
{
"session_id": "xxx",
"stop_reason": "end_turn",
"stop_message": "重构完成,所有测试通过。"
}
على Linux استخدم notify-send، وعلى macOS استخدم osascript، دون الحاجة لأي خدمة خارجية:
#!/bin/bash
input=$(cat)
reason=$(echo "$input" | jq -r '.stop_reason // "unknown"')
message=$(echo "$input" | jq -r '.stop_message // "Claude 已停止"' | head -c 200)
case "$(uname)" in
Linux)
notify-send "Claude Code" "$message" --urgency=normal
;;
Darwin)
osascript -e "display notification \"$message\" with title \"Claude Code\""
;;
esac
المميزات: لا يحتاج أي إعداد، جاهز للاستخدام فورًا.
العيوب: الإشعار يظهر فقط على الجهاز الحالي، ولن تراه إذا انتقلت لجهاز آخر.
استخدم Slack Incoming Webhook لإرسال الإشعارات إلى قناة محددة أو كرسالة خاصة.
المتطلبات المسبقة:
1. أنشئ تطبيقًا في صفحة إدارة تطبيقات Slack
2. فعّل Incoming Webhooks واحصل على رابط الـ Webhook
3. خزّن الرابط في متغير البيئة SLACK_WEBHOOK_URL
#!/bin/bash
input=$(cat)
reason=$(echo "$input" | jq -r '.stop_reason // "unknown"')
message=$(echo "$input" | jq -r '.stop_message // "Claude 已停止"' | head -c 300)
webhook_url="${SLACK_WEBHOOK_URL}"
[[ -z "$webhook_url" ]] && exit 0
# 根据停止原因选 emoji
case "$reason" in
end_turn) emoji="✅" ;;
user_input) emoji="⏳" ;;
*) emoji="🔔" ;;
esac
payload=$(jq -n \
--arg text "$emoji *Claude Code* | \`$reason\`
$message" \
'{text: $text}')
curl -s -X POST "$webhook_url" \
-H 'Content-Type: application/json' \
-d "$payload" > /dev/null 2>&1 &
الرمز & في نهاية السطر مهم — يجعل curl يعمل في الخلفية دون أن يعطّل Claude.
بوت Telegram خيار ممتاز للاستخدام الشخصي: مجاني وفوري، والإشعارات تصل مباشرة إلى هاتفك.
المتطلبات المسبقة:
1. أنشئ بوتًا عبر @BotFather واحصل على التوكن
2. احصل على Chat ID الخاص بك (أرسل رسالة للبوت ثم استدعِ API الـ getUpdates)
3. عيّن متغيرات البيئة TELEGRAM_BOT_TOKEN وTELEGRAM_CHAT_ID
#!/bin/bash
input=$(cat)
reason=$(echo "$input" | jq -r '.stop_reason // "unknown"')
message=$(echo "$input" | jq -r '.stop_message // "Claude 已停止"' | head -c 300)
token="${TELEGRAM_BOT_TOKEN}"
chat_id="${TELEGRAM_CHAT_ID}"
[[ -z "$token" || -z "$chat_id" ]] && exit 0
text="🤖 *Claude Code*
状态:\`$reason\`
$message"
curl -s "https://api.telegram.org/bot${token}/sendMessage" \
-d chat_id="$chat_id" \
-d text="$text" \
-d parse_mode="Markdown" > /dev/null 2>&1 &
إذا كنت على نفس الجهاز لكنك انتقلت لنافذة أخرى، صوت تنبيه قصير أكثر فعالية من الإشعار البصري:
#!/bin/bash
input=$(cat)
reason=$(echo "$input" | jq -r '.stop_reason // "unknown"')
case "$(uname)" in
Linux)
paplay /usr/share/sounds/freedesktop/stereo/complete.oga 2>/dev/null &
;;
Darwin)
afplay /System/Library/Sounds/Glass.aiff &
;;
esac
يمكنك دمجه مع الطرق الأخرى — تشغيل صوت محليًا + إرسال إشعار عن بُعد.
في الاستخدام العملي، يُفضَّل جمع عدة طرق في سكريبت واحد:
.claude/hooks/notify.sh:
#!/bin/bash
input=$(cat)
reason=$(echo "$input" | jq -r '.stop_reason // "unknown"')
message=$(echo "$input" | jq -r '.stop_message // "Claude 已停止"' | head -c 300)
# 根据原因选 emoji
case "$reason" in
end_turn) emoji="✅"; title="任务完成" ;;
user_input) emoji="⏳"; title="等待输入" ;;
*) emoji="🔔"; title="Claude 已停止" ;;
esac
# 1. 桌面通知(本地)
case "$(uname)" in
Linux) notify-send "Claude Code: $title" "$message" --urgency=normal ;;
Darwin) osascript -e "display notification \"$message\" with title \"Claude Code: $title\"" ;;
esac
# 2. 声音提示
case "$(uname)" in
Linux) paplay /usr/share/sounds/freedesktop/stereo/complete.oga 2>/dev/null & ;;
Darwin) afplay /System/Library/Sounds/Glass.aiff & ;;
esac
# 3. Slack(如果配了 Webhook)
if [[ -n "$SLACK_WEBHOOK_URL" ]]; then
payload=$(jq -n --arg text "$emoji *$title*
$message" '{text: $text}')
curl -s -X POST "$SLACK_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d "$payload" > /dev/null 2>&1 &
fi
# 4. Telegram(如果配了 Bot)
if [[ -n "$TELEGRAM_BOT_TOKEN" && -n "$TELEGRAM_CHAT_ID" ]]; then
curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d text="$emoji *$title*
$message" \
-d parse_mode="Markdown" > /dev/null 2>&1 &
fi
.claude/settings.json:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/notify.sh"
}
]
}
]
}
}
جميع طلبات الشبكة يجب أن تعمل في الخلفية
أي أمر curl في سكريبت الإشعارات يجب أن ينتهي بـ & ليعمل في الخلفية. إذا كانت الشبكة بطيئة أو انتهت المهلة، سيتعطل Claude بالكامل. إضافة > /dev/null 2>&1 & هي الممارسة المعتادة.
التوقف لا يعني بالضرورة "إتمام ناجح"
قيمة stop_reason التي تساوي end_turn تعني عادةً أن المهمة اكتملت، لكنها قد تعني أيضًا أن Claude غير متأكد من الخطوة التالية. إذا أردت تلقي الإشعار فقط عند الانتهاء الفعلي، أضف فلترًا في السكريبت:
[[ "$reason" != "end_turn" ]] && exit 0
اقطع محتوى الإشعار
آخر رسالة من Claude قد تكون طويلة جدًا (تحتوي كتل برمجية أو مخرجات ضخمة). قبل إرسالها إلى Slack أو Telegram، استخدم head -c 300 لاقتطاعها وتجنب رسائل متضخمة.
متغيرات البيئة يُفضَّل وضعها في الإعدادات العامة
روابط Webhook وتوكنات البوت لا يجب أن تُحفَظ في مستودع المشروع. يُفضَّل وضعها في ~/.zshrc (أو ~/.bashrc)، أو إدارتها باستخدام direnv.
بعد هذا الإعداد، يتغير أسلوب عملك:
لا حاجة لمراقبة الطرفية، ولا للتبديل المتكرر بين النوافذ للاطمئنان على التقدم. Claude يعمل وأنت تعمل، وعندما ينتهي يُعلمك.