Richte einen Stop Hook ein, damit Claude dich automatisch per Desktop-Benachrichtigung, Slack oder Telegram informiert
Aufgaben in Claude Code dauern oft mehrere Minuten oder länger. Du lässt ihn ein Modul refactoren, die Test-Suite durchlaufen oder einen Stapel Dateien verarbeiten — und wechselst in der Zwischenzeit zu etwas anderem. Das Problem: Du weißt nicht, wann er fertig ist.
Wenn du zurückschaust, ist er vielleicht schon seit zehn Minuten fertig. Oder er hängt an einem Bestätigungsdialog und wartet auf dich.
Mit dem Stop-Hook bekommst du automatisch eine Benachrichtigung, sobald Claude eine Aufgabe abgeschlossen hat oder dein Eingreifen braucht. Egal in welchem Fenster oder auf welchem Gerät du gerade bist — die Nachricht kommt direkt durch.
Claude Code hat ein Stop-Event, das jedes Mal ausgelöst wird, wenn Claude anhält — sei es, weil die Aufgabe erledigt ist, ein Fehler aufgetreten ist, der bestätigt werden muss, oder weil er auf eine Eingabe wartet.
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/notify.sh"
}
]
}
]
}
}
Der Hook erhält über stdin ein JSON mit stop_reason (Grund des Stopps) und stop_message (Claudes letzte Nachricht). Damit lässt sich der Inhalt der Benachrichtigung anpassen.
Struktur des JSON auf stdin:
{
"session_id": "xxx",
"stop_reason": "end_turn",
"stop_message": "重构完成,所有测试通过。"
}
Unter Linux mit notify-send, unter macOS mit osascript. Kein externer Dienst nötig:
#!/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
Vorteil: Null Konfiguration, funktioniert sofort.
Nachteil: Die Benachrichtigung kommt nur auf dem lokalen Rechner an. Auf einem anderen Gerät bekommst du nichts mit.
Mit einem Slack Incoming Webhook lassen sich Benachrichtigungen in einen Kanal oder als Direktnachricht senden.
Voraussetzungen:
1. Eine App auf der Slack-Verwaltungsseite erstellen
2. Incoming Webhooks aktivieren und die Webhook-URL kopieren
3. Die URL in der Umgebungsvariable SLACK_WEBHOOK_URL speichern
#!/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 &
Das & am Ende ist wichtig — es lässt curl im Hintergrund laufen, damit Claude nicht blockiert wird.
Ein Telegram-Bot eignet sich perfekt für den persönlichen Gebrauch: kostenlos, sofort, und die Nachricht kommt direkt aufs Handy.
Voraussetzungen:
1. Einen Bot über @BotFather erstellen und den Token kopieren
2. Die eigene Chat-ID ermitteln (dem Bot eine Nachricht schicken und die getUpdates-API aufrufen)
3. Die Umgebungsvariablen TELEGRAM_BOT_TOKEN und TELEGRAM_CHAT_ID setzen
#!/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 &
Wenn du auf demselben Rechner bist, aber das Fenster gewechselt hast, ist ein Ton oft wirkungsvoller als ein Popup:
#!/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
Lässt sich gut mit den anderen Varianten kombinieren — lokal ein Ton, remote eine Push-Benachrichtigung.
In der Praxis empfiehlt es sich, mehrere Methoden in einem einzigen Skript zu bündeln:
.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"
}
]
}
]
}
}
Alle Netzwerkanfragen im Hintergrund ausführen
Die curl-Aufrufe im Benachrichtigungsskript müssen immer mit & in den Hintergrund geschickt werden. Wenn das Netzwerk langsam ist oder ein Timeout auftritt, blockiert das die gesamte Claude-Session. > /dev/null 2>&1 & ist die Standardpraxis.
Stop heißt nicht „erfolgreich abgeschlossen"
Ein stop_reason von end_turn bedeutet in der Regel, dass die Aufgabe erledigt ist — kann aber auch heißen, dass Claude nicht weiß, was als Nächstes zu tun ist. Wenn du nur bei tatsächlichem Abschluss benachrichtigt werden willst, filtere im Skript:
[[ "$reason" != "end_turn" ]] && exit 0
Benachrichtigungsinhalt kürzen
Claudes letzte Nachricht kann sehr lang sein (Codeblöcke, umfangreiche Ausgaben). Bevor du sie an Slack oder Telegram schickst, kürze sie mit head -c 300, um riesige Nachrichten zu vermeiden.
Umgebungsvariablen gehören in die globale Konfiguration
Webhook-URLs und Bot-Tokens haben im Projekt-Repository nichts verloren. Am besten in ~/.zshrc (oder ~/.bashrc) ablegen oder mit direnv verwalten.
Nach der Einrichtung ändert sich dein Arbeitsablauf:
Kein Starren aufs Terminal, kein ständiges Hin- und Herwechseln, um den Fortschritt zu prüfen. Claude arbeitet, du arbeitest — und wenn er fertig ist, sagt er Bescheid.