Уведомления Claude Code на телефон через хуки

Получайте оповещение на телефон, когда Claude Code просит разрешение или завершает задачу. Готовый конфиг хуков Notification и Stop с вебхуком.

Обновлено

Содержание

Claude Code останавливается в двух важных случаях: он заблокирован и ждёт вас (запрос разрешения, вопрос) или закончил работу. Если вы не смотрите в терминал, оба случая выглядят одинаково — ничего не происходит, и сессия простаивает, пока вы не вернётесь. Решение — хук: несколько строк в settings.json, которые отправляют вебхук на ваш телефон в ту же секунду, как наступает любое из этих событий.

В этом руководстве — конфиг, который можно скопировать, объяснение, какое событие хука использовать в каком случае, и детали, благодаря которым всё работает надёжно: чтение входных данных хука, кавычки в shell и как не утонуть в уведомлениях.

Какой хук для какой ситуации

Claude Code запускает хуки на событиях жизненного цикла. Две задачи из этой статьи закрывают два из них (справочник по хукам):

Вы хотите знать, когда…Событие хукаMatcher / фильтр
Claude ждёт решения по разрешениюNotificationpermission_prompt
Claude простаивает и ждёт вашего вводаNotificationidle_prompt
Claude закончил отвечатьStopне нужен

matcher хука Notification фильтрует по типу уведомления, так что вы сами выбираете, какие из них дойдут до телефона. Входные данные приходят как JSON в stdin и включают notification_type, message, cwd и session_id. Хуки Notification не могут ничего блокировать или менять — они только наблюдают, что здесь и нужно.

Вход Stop содержит last_assistant_message — последний текст, который выдал Claude. Это готовая строка-резюме для уведомления.

Что понадобится

  • Echobell на телефоне (App Store / Google Play)
  • curl и jq на машине, где запускается Claude Code
  • Две минуты

Шаг 1 — Создайте два канала

Не отправляйте всё в один канал. В Echobell создайте:

  • Claude Blocked, тип Time Sensitive или Calling — для запросов разрешения: агент застрял, и каждая минута — впустую потраченные вычисления и время
  • Claude Done, тип Normal — обычный пуш, который можно прочитать когда удобно

Скопируйте вебхук-URL каждого канала. Он выглядит как https://hook.echobell.one/t/<channel-token>. Относитесь к нему как к паролю: любой, у кого он есть, может заставить ваш телефон звонить.

Сохраните оба как переменные окружения, чтобы они не попали в закоммиченный конфиг:

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

Добавьте их в профиль shell, чтобы Claude Code их унаследовал.

Шаг 2 — Добавьте хуки

Добавьте это в ~/.claude/settings.json, чтобы действовало во всех проектах, или в .claude/settings.local.json для одного репозитория:

{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "jq -c '{title: \"Claude требуется разрешение\", 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 закончил\", body: (.last_assistant_message // \"Готово\" | .[0:200]), project: (.cwd | split(\"/\") | last)}' | curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- \"$ECHOBELL_CLAUDE_DONE_URL\""
          }
        ]
      }
    ]
  }
}

Что делает каждая часть:

  • jq -c '{...}' читает JSON хука из stdin и собирает небольшой payload, так что Echobell получает ровно те поля, которые вам нужны, а не весь документ хука.
  • .cwd | split("/") | last превращает /home/me/code/api в api, чтобы в уведомлении было видно, какой проект просит внимания.
  • .[0:200] обрезает финальное сообщение. Воркер Echobell ограничивает тело уведомления 1500 байтами, а экран блокировки показывает гораздо меньше.
  • -m 10 задаёт curl таймаут в 10 секунд, чтобы проблемы с сетью никогда не заставляли Claude Code ждать ваш хук.

Echobell подставляет отправленные ключи через шаблоны канала, а у нового канала нет шаблона, который бы их читал, — задайте их в настройках канала: шаблон заголовка {{title}}, шаблон текста {{body}}. Добавьте {{project}} в любой из них, если нужно видеть имя проекта, например {{title}} ({{project}}).

Шаг 3 — Проверьте, не дожидаясь настоящего запроса

Запустите тот же конвейер вручную с поддельным payload хука:

echo '{"message":"Claude нужно ваше разрешение на использование Bash","cwd":"/home/me/code/api","notification_type":"permission_prompt"}' \
  | jq -c '{title: "Claude требуется разрешение", body: .message, project: (.cwd | split("/") | last)}' \
  | curl -sS -m 10 -X POST -H 'Content-Type: application/json' -d @- "$ECHOBELL_CLAUDE_BLOCKED_URL"

Если телефон засветился, сторона Echobell работает, а оставшаяся проблема — в том, как Claude Code читает конфиг. В Claude Code выполните /hooks, чтобы убедиться, что хуки загружены; изменения настроек, сделанные во время работающей сессии, могут потребовать меню хуков или перезапуска.

Шаг 4 — Заставьте канал блокировки звонить

Обычный пуш проигрывает режиму «Не беспокоить». Канал Calling ведёт себя как входящий звонок и пробивает режим фокусирования iOS — это важнее всего, когда вы запускаете долгую задачу и уходите на весь вечер. Если вам нужно, чтобы прерывали только по некоторым запросам, фильтруйте условием канала Echobell по отправляемым переменным, например project == "api", вместо правки хука. Полный список переменных — в справочнике по условиям.

Как не утонуть в уведомлениях

Активная сессия может породить множество событий Stop — каждый ответ заканчивается одним из них. Три способа сохранить полезный сигнал:

  • Не отправляйте Stop в звонящий канал. Завершение не срочно; оставьте его на Normal.
  • Используйте idle_prompt вместо Stop, если хотите знать только о том, что Claude остановился и ждёт вас, а не после каждого ответа.
  • Сузьте по проекту условием, чтобы тестовый репозиторий вообще не присылал уведомлений.

Claude Code удалённо или в CI

Тот же подход работает в облачных и удалённых средах, потому что хук — это просто исходящий HTTPS-запрос. Ничего не должно быть доступно из интернета. Задайте две переменные окружения в секретах среды вместо профиля shell, и уведомление дойдёт до телефона, где бы ни работала сессия.

Устранение неполадок

Ничего не приходит, ручная проверка тоже не работает. Проверьте, что переменная с URL задана в shell, из которого запускается Claude Code: echo "$ECHOBELL_CLAUDE_BLOCKED_URL". Пустая переменная заставляет curl молча завершаться с ошибкой.

Ручная проверка работает, а хук не срабатывает. Проверьте matcher: permission_prompt и idle_prompt — разные значения, а matcher, который ничему не соответствует, просто никогда не запускается. Выполните /hooks и убедитесь, что JSON валиден — лишняя запятая в конце отключает хуки всего файла настроек.

Тело уведомления пустое. Фильтр jq обратился к полю, которого нет у этого события. message есть во входных данных Notification; last_assistant_message — во входных данных Stop. Используйте //, чтобы задать значение по умолчанию, как в конфиге выше.

Срабатывает слишком часто. См. раздел выше — перейдите с Stop на idle_prompt или добавьте условие.

Частые вопросы

Как получать уведомление, когда Claude Code нужно разрешение?

Добавьте хук Notification с matcher permission_prompt, который отправляет вебхук в канал. Echobell превратит этот запрос в пуш или оповещение в формате звонка на вашем телефоне.

Как узнать, что Claude Code закончил задачу?

Добавьте хук Stop. Он срабатывает, когда Claude заканчивает отвечать, а его входные данные включают last_assistant_message, который можно использовать как тело уведомления.

Может ли уведомление пробить режим «Не беспокоить»?

Да, если принимающий канал — Calling. Он ведёт себя как входящий звонок, который режим фокусирования iOS пропускает. Обычный пуш любого приложения — нет.

Работает ли это в Claude Code в вебе или в удалённых сессиях?

Да. Хук лишь делает исходящий HTTPS-запрос, поэтому работает везде, где у сессии есть доступ в интернет. Передайте URL каналов через секреты среды.

Безопасно ли хранить URL вебхука в settings.json?

Лучше использовать переменную окружения, как показано выше, чтобы токен не попал в репозиторий. Если он утёк, создайте новый канал и удалите старый.

Итоги

Два канала, два хука и конвейер jq | curl: канал Calling или Time Sensitive для permission_prompt и канал Normal для Stop. После этого можно запустить долгую задачу агента, выйти из комнаты и вернуться только тогда, когда агент действительно в вас нуждается.

Скачайте Echobell для iPhone или установите из Google Play, а затем выполните ручную проверку выше, прежде чем доверять ему долгую задачу.

Читайте также