Powiadomienia Claude Code na telefonie przez hooki

Dostań alert na telefon, gdy Claude Code potrzebuje zgody lub kończy zadanie. Gotowa konfiguracja z hookami Notification i Stop oraz webhookiem.

Aktualizacja

Spis treści

Claude Code zatrzymuje się w dwóch istotnych sytuacjach: utknął w oczekiwaniu na Ciebie (prośba o zgodę, pytanie) albo skończył pracę. Jeśli nie patrzysz w terminal, obie wyglądają tak samo — nic się nie dzieje, a sesja stoi bezczynnie, aż wrócisz. Rozwiązaniem jest hook: kilka linijek w settings.json, które w chwili wystąpienia jednej z tych sytuacji wysyłają webhook na Twój telefon.

Ten przewodnik daje konfigurację do skopiowania, wyjaśnia, którego zdarzenia hooka użyć w której sytuacji, i omawia szczegóły, dzięki którym całość działa niezawodnie: odczyt danych wejściowych hooka, cudzysłowy w powłoce i unikanie zalewu powiadomień.

Który hook do jakiej sytuacji

Claude Code uruchamia hooki przy zdarzeniach cyklu życia. Ten problem pokrywają dwa z nich (dokumentacja hooków):

Chcesz wiedzieć, kiedy…Zdarzenie hookaMatcher / filtr
Claude czeka na decyzję o zgodzieNotificationpermission_prompt
Claude jest bezczynny i czeka na Twoje daneNotificationidle_prompt
Claude skończył odpowiadaćStopniepotrzebny

Pole matcher hooka Notification filtruje po typie powiadomienia, więc możesz dokładnie wybrać, które z nich trafią na telefon. Dane wejściowe przychodzą jako JSON na stdin i zawierają notification_type, message, cwd oraz session_id. Hooki Notification nie mogą niczego zablokować ani zmienić — są tylko obserwatorami, a tutaj właśnie tego chcesz.

Dane wejściowe Stop zawierają last_assistant_message, czyli ostatni tekst wygenerowany przez Claude'a. To gotowa linijka podsumowania do powiadomienia.

Czego potrzebujesz

  • Echobella na telefonie (App Store / Google Play)
  • curl i jq na maszynie, na której działa Claude Code
  • Dwóch minut

Krok 1 — Utwórz dwa kanały

Nie wysyłaj wszystkiego do jednego kanału. W Echobellu utwórz:

  • Claude zablokowany, typ Time Sensitive lub Calling — dla próśb o zgodę, gdy agent stoi, a każda minuta to zmarnowana moc obliczeniowa i czas
  • Claude skończył, typ Normal — zwykły push, do przeczytania, kiedy wygodnie

Skopiuj adres URL webhooka każdego kanału. Wygląda tak: https://hook.echobell.one/t/<channel-token>. Traktuj go jak hasło: każdy, kto go ma, może zadzwonić na Twój telefon.

Zapisz oba jako zmienne środowiskowe, żeby nigdy nie trafiły do commitowanego pliku konfiguracyjnego:

export ECHOBELL_CLAUDE_BLOCKED_URL="https://hook.echobell.one/t/<blocked-token>"
export ECHOBELL_CLAUDE_DONE_URL="https://hook.echobell.one/t/<done-token>"

Dodaj je do profilu powłoki, żeby Claude Code je odziedziczył.

Krok 2 — Dodaj hooki

Dodaj poniższe do ~/.claude/settings.json, by działało w każdym projekcie, albo do .claude/settings.local.json dla jednego repozytorium:

{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "jq -c '{title: \"Claude potrzebuje zgody\", body: .message, project: (.cwd | split(\"/\") | last)}' | curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- \"$ECHOBELL_CLAUDE_BLOCKED_URL\""
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "jq -c '{title: \"Claude skończył\", body: (.last_assistant_message // \"Gotowe\" | .[0:200]), project: (.cwd | split(\"/\") | last)}' | curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- \"$ECHOBELL_CLAUDE_DONE_URL\""
          }
        ]
      }
    ]
  }
}

Co robi każdy element:

  • jq -c '{...}' czyta JSON hooka ze stdin i buduje mały payload, dzięki czemu Echobell dostaje dokładnie te pola, które chcesz, a nie cały dokument hooka.
  • .cwd | split("/") | last zamienia /home/me/code/api na api, więc powiadomienie mówi, który projekt o Ciebie prosi.
  • .[0:200] skraca ostatnią wiadomość. Treść powiadomienia jest ograniczona przez workera Echobella do 1500 bajtów, a ekran blokady i tak pokazuje znacznie mniej.
  • -m 10 daje curlowi 10-sekundowy limit czasu, żeby problem z siecią nie zostawił Claude Code czekającego na Twój hook.

Echobell renderuje wysłane klucze przez szablony kanału, a nowy kanał nie ma szablonu, który by je odczytywał — ustaw je w ustawieniach kanału: szablon tytułu {{title}}, szablon treści {{body}}. Dodaj {{project}} do któregoś z nich, jeśli chcesz widzieć nazwę projektu, na przykład {{title}} ({{project}}).

Krok 3 — Przetestuj bez czekania na prawdziwą prośbę

Uruchom ten sam potok ręcznie z fałszywym payloadem hooka:

echo '{"message":"Claude potrzebuje Twojej zgody na użycie Bash","cwd":"/home/me/code/api","notification_type":"permission_prompt"}' \
  | jq -c '{title: "Claude potrzebuje zgody", body: .message, project: (.cwd | split("/") | last)}' \
  | curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- "$ECHOBELL_CLAUDE_BLOCKED_URL"

Jeśli telefon się zaświeci, strona Echobella działa, a ewentualny problem leży w sposobie, w jaki Claude Code czyta konfigurację. W Claude Code uruchom /hooks, by potwierdzić załadowanie hooków; zmiany ustawień wprowadzone w trakcie sesji mogą wymagać wejścia do menu hooków albo restartu.

Krok 4 — Spraw, by kanał blokady dzwonił

Zwykły push przegrywa z trybem Nie przeszkadzać. Kanał Calling zachowuje się jak połączenie przychodzące i przebija tryb Skupienia w iOS, co ma największe znaczenie, gdy zaczynasz długie zadanie i wychodzisz na cały wieczór. Jeśli chcesz, by przerywano Ci tylko przy niektórych prośbach, zamiast edytować hook użyj warunku kanału w Echobellu na wysyłanych zmiennych, na przykład project == "api". Pełną listę zmiennych znajdziesz w dokumentacji warunków.

Jak uniknąć przeładowania powiadomieniami

Intensywna sesja potrafi wywołać wiele zdarzeń Stop — każda odpowiedź kończy się jednym. Trzy sposoby, by zachować sygnał:

  • Nie wysyłaj Stop na dzwoniący kanał. Ukończenie nie jest pilne; zostaw je na Normal.
  • Użyj idle_prompt zamiast Stop, jeśli chcesz wiedzieć tylko o tym, że Claude się zatrzymał i czeka na Ciebie, a nie po każdej odpowiedzi.
  • Zawęź po projekcie warunkiem, żeby repozytorium do eksperymentów w ogóle nie powiadamiało.

Claude Code zdalnie lub w CI

To samo podejście działa w środowiskach chmurowych i zdalnych, bo hook to zwykłe wychodzące żądanie HTTPS. Nic nie musi być dostępne z internetu. Ustaw dwie zmienne środowiskowe w sekretach środowiska zamiast w profilu powłoki, a powiadomienie dotrze na telefon niezależnie od tego, gdzie działa sesja.

Rozwiązywanie problemów

Nic nie przychodzi, a test ręczny też zawodzi. Sprawdź, czy zmienna z adresem URL jest ustawiona w powłoce, która uruchamia Claude Code: echo "$ECHOBELL_CLAUDE_BLOCKED_URL". Pusta zmienna sprawia, że curl zawodzi po cichu.

Test ręczny działa, ale hook się nie uruchamia. Sprawdź matcher: permission_prompt i idle_prompt to różne wartości, a matcher, który nie pasuje, po prostu nigdy się nie uruchomi. Wykonaj /hooks i sprawdź, czy JSON jest poprawny — zbędny przecinek na końcu wyłącza wszystkie hooki z całego pliku ustawień.

Treść powiadomienia jest pusta. Filtr jq odwołał się do pola, które nie istnieje dla tego zdarzenia. message występuje w danych Notification, a last_assistant_message w danych Stop. Użyj //, by podać wartość domyślną, jak w konfiguracji powyżej.

Uruchamia się zbyt często. Zobacz sekcję wyżej — przejdź ze Stop na idle_prompt albo dodaj warunek.

Najczęstsze pytania

Jak dostać powiadomienie, gdy Claude Code potrzebuje zgody?

Dodaj hook Notification z matcherem permission_prompt, który wysyła webhook na kanał. Echobell zamienia to żądanie na push albo alert w formie połączenia na Twoim telefonie.

Skąd wiem, że Claude Code skończył zadanie?

Dodaj hook Stop. Uruchamia się, gdy Claude kończy odpowiadać, a jego dane wejściowe zawierają last_assistant_message, którego możesz użyć jako treści powiadomienia.

Czy powiadomienie może przebić tryb Nie przeszkadzać?

Tak, jeśli kanał odbierający jest kanałem Calling. Zachowuje się jak połączenie przychodzące, które tryb Skupienia w iOS przepuszcza. Zwykły push z dowolnej aplikacji tego nie potrafi.

Czy to działa w Claude Code w przeglądarce albo w sesjach zdalnych?

Tak. Hook wykonuje tylko wychodzące żądanie HTTPS, więc działa wszędzie tam, gdzie sesja ma dostęp do internetu. Adresy URL kanałów przekaż przez sekrety środowiska.

Czy adres URL webhooka można bezpiecznie trzymać w settings.json?

Lepiej użyć zmiennej środowiskowej, jak wyżej, żeby token nie trafił do repozytorium. Jeśli wycieknie, utwórz nowy kanał i wycofaj stary.

Podsumowanie

Dwa kanały, dwa hooki i potok jq | curl: kanał Calling lub Time Sensitive dla permission_prompt, kanał Normal dla Stop. Potem możesz zacząć długie zadanie agenta, wyjść z pokoju i wracać tylko wtedy, gdy agent naprawdę Cię potrzebuje.

Pobierz Echobella na iPhone'a albo weź go z Google Play, a potem uruchom powyższy test ręczny, zanim powierzysz tej ścieżce długie zadanie.

Powiązane artykuły