Как понять, что Claude Code, Codex или OpenCode ждёт вас
Claude Code сообщает, что ждёт вас, через три хука: PreToolUse на AskUserQuestion, Notification типа permission_prompt и Stop, последнее сообщение которого заканчивается вопросом. idle_prompt игнорируйте: он приходит после любого ответа, на который никто не отреагировал. Вот карта, по которой Foxl Code следит за удалёнными терминалами Claude Code, Codex, OpenCode и Hermes, чего каждый CLI сообщить не может и как написать хук, который почти ничего не стоит агенту и никогда случайно не обращается к модели.

На этой странице
Хуки Claude Code запускают настроенную вами команду, когда происходит определённое событие, и три из них сообщают, что агент ждёт вас. Хук PreToolUse на инструменте AskUserQuestion срабатывает, когда открывается диалог с вопросом. Хук Notification типа permission_prompt срабатывает, когда диалог разрешения открыт уже несколько секунд. Хук Stop срабатывает в конце каждого ответа и передаёт текст ответа в last_assistant_message, так что можно проверить, не закончился ли он вопросом. idle_prompt игнорируйте: он приходит примерно через минуту после любого ответа, после которого никто ничего не набрал, а не только после вопроса.
Foxl Code, который запускает агентов для программирования в удалённых терминалах, именно по этим трём хукам помечает удалённый терминал Claude Code как ожидающий своего пользователя. Начиная с v0.9.3-beta.5 та же команда отчёта читает и Codex, OpenCode и Hermes через их собственные хуки и плагины. Ниже карта для каждого CLI, ловушки каждого из них и то, как написать хук, чтобы он как можно меньше стоил агенту и никогда не подмешивал текст в контекст модели. Ни один настоящий облачный терминал пока не сообщил о вопросе; в последнем разделе сказано, что ещё не проверено.
Почему не видно, что агент в терминале ждёт?
Человек, который запускает агентов в удалённых терминалах, может держать открытыми несколько сразу и не смотреть ни в один. 21 октября 2026 года удалённый терминал Claude Code задал вопрос с ответом да или нет и остался стоять на своём приглашении, а собственный API Foxl при этом говорил, что ни одна задача никого не ждёт. Боковое меню Foxl Code, его список задач, ожидающих человека, «Требует вашего внимания», и приложение для телефона молчали. До этого изменения в Foxl Code ничто не отслеживало такой момент.
Читать экран кажется решением, но оно легко ломается. Для стороннего наблюдателя экраны «думаю», «закончил» и «спрашиваю» отличаются несколькими символами собственной отрисовки CLI, и любой выпуск может перерисовать их по-другому. Когда мы однажды обновили версии CLI, которые поставляем, новые сборки рисовали другой первый экран, не тот, которого ждала наша проверка ввода, и удалённые терминалы Codex и OpenCode десять дней молча не принимали ввод. Хук же - это собственное заявление CLI о том, что только что произошло, с задокументированными данными, поэтому слушаем мы именно его.
Какие хуки Claude Code означают «я жду вас»?
В наших облачных образах закреплена версия Claude Code 2.1.296. Там, где деталь ниже помечена как прочитанная из пакета, она взята из npm-пакета этой версии, а не из работающего терминала.
| хук | что он означает | как мы его считаем |
|---|---|---|
PreToolUse, matcher AskUserQuestion | сейчас откроется диалог с вопросом; в tool_input вопросы и варианты ответа | вопрос с вариантами |
Notification, matcher permission_prompt | диалог разрешения открыт около шести секунд без единого нажатия клавиши (прочитано из пакета) | запрос разрешения |
Stop | ответ закончен; last_assistant_message - его текст | вопрос, если текст заканчивается на ?, иначе конец хода |
UserPromptSubmit, PostToolUse, PostToolUseFailure, SessionEnd | человек что-то набрал, одобренный инструмент выполнился или упал, CLI завершился | ответ получен |
Notification, тип idle_prompt | «Claude finished responding about 60 seconds ago and you haven't typed since» | игнорируется |
Именно на строке idle_prompt ошибается большинство настроек. Её сообщение звучит как раз как то, что нужно, но оно приходит после любого ответа, после которого никто ничего не набрал, поэтому если считать его вопросом, оповещение будет почти после каждого хода (в случае Foxl это запись в «Требует вашего внимания» и уведомление на телефон). Мы регистрируем хук Notification только с matcher permission_prompt, а скрипт ещё раз проверяет тип. Для проверки Stop мы сначала отбрасываем пробелы в конце, выделение Markdown, обратные кавычки, закрывающие скобки и кавычки и принимаем полноширинный ?, который печатают методы ввода для китайского, японского и корейского.
В текущей документации Claude Code есть ещё отдельное событие PermissionRequest и больше типов уведомлений, чем здесь. Мы не проверяли, есть ли это новое событие в 2.1.296. permission_prompt по-прежнему есть в текущем списке, а его шестисекундное ожидание отсеивает диалог, на который человек отвечает прямо у экрана. Добавьте хуки в пользовательский файл настроек Claude Code, после хуков, уже настроенных для того же события, чтобы существующие хуки продолжали работать:
{
"hooks": {
"PreToolUse": [{ "matcher": "AskUserQuestion",
"hooks": [{ "type": "command", "command": "report-prompt", "timeout": 10 }] }],
"Notification": [{ "matcher": "permission_prompt",
"hooks": [{ "type": "command", "command": "report-prompt", "timeout": 10 }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "report-prompt", "timeout": 10 }] }]
}
}Все они вызывают один небольшой скрипт, команду отчёта (report-prompt выше), которая читает учётные данные задачи из своего окружения. События, означающие, что человек ответил, UserPromptSubmit и остальные (события закрытия), регистрируются так же, за проверкой, о которой ниже.
Как написать хук, который как можно меньше стоит агенту?
Хук отчёта работает внутри собственного цикла агента, поэтому любая ошибка в нём становится проблемой агента. В итоге у нас получилось пять правил, каждое взято из документации или из пакета 2.1.296:
- Ничего не печатайте в stdout. Для большинства событий Claude Code только записывает stdout хука в журнал, но для
UserPromptSubmitи ещё нескольких «Claude Code adds plain-text stdout as context that Claude can see and act on», то есть добавляет обычный текст из stdout в контекст, который Claude видит и учитывает. Строка состояния из скрипта отчёта стала бы частью промпта. - Всегда завершайтесь с кодом 0. Код 2 блокирует действие на событиях, которые умеют блокировать, а любой другой ненулевой код показывает уведомление об ошибке. В нашем скрипте сбой сети стоит одной строки в stderr, и больше ничего.
- Работайте синхронно, с коротким тайм-аутом. Хуки можно запускать с
"async": true, но закреплённая сборка печатает строку в терминале каждый раз, когда завершается асинхронный хук, а когда хуки срабатывают после каждого вызова инструмента, это превращается в шум. Наши хуки синхронные, сtimeout: 10, а скрипт даёт своему запросу три секунды и чуть позже сам завершается. В Claude Code реальная цена - один запуск Node.js и один запрос в конце каждого ответа, не больше примерно трёх секунд, когда сервер Foxl недоступен. - Отсекайте частые события ещё в оболочке.
PostToolUseсрабатывает на каждый вызов инструмента. Команда отчёта создаёт файл-маркер, когда сообщает об открытом вопросе. Хуки закрытия запускают Node.js, только если этот файл существует, а иначе вычитывают stdin, чтобы CLI никогда не увидел разорванный канал:
Пока ничего не открыто, это одинif [ -e /tmp/foxl-agent-prompt/open ]; then exec report-prompt; else cat >/dev/null; fitest -eна вызов инструмента. - Не пускайте учётные данные в командную строку. Хук наследует окружение CLI, поэтому токен читается из переменной окружения и никогда не появляется в
ps.
Как об этом сообщают Codex, OpenCode и Hermes?
У каждого CLI своя точка расширения; каждую мы прочитали в том выпуске, который закреплён в наших образах. У Codex есть движок хуков, который принимает формат хуков Claude Code. OpenCode и Hermes (CLI-агент от Nous Research) в своём терминальном интерфейсе не запускают хуки оболочки; они загружают плагины, и наши плагины передают той же команде отчёта нормализованное событие. У Kiro, CLI для программирования от AWS, нет события, которое можно было бы слушать.
| CLI (версия) | спрашивает | ответ получен | не сообщается |
|---|---|---|---|
Codex 0.162.1, системный hooks.json | PermissionRequest; Stop, у которого last_assistant_message заканчивается на ? | UserPromptSubmit, PostToolUse, Interrupt, SessionEnd | диалог с вопросом в режиме Plan |
| OpenCode 1.19.0, серверный плагин | question.asked, permission.asked; session.status idle с ответом, который заканчивается на ? | question.replied или rejected, permission.replied, session.status busy | - |
| Hermes 0.19.0, плагин на Python | pre_tool_call для clarify, pre_approval_request, post_llm_call, который заканчивается на ? | post_tool_call для clarify, post_approval_response, pre_llm_call, прерванный on_session_end | - |
| Kiro 2.29.1 | ничего | - | всё: нет события вопроса или одобрения, а его Stop не несёт текста ответа |
Codex. Codex проверяет хуки из вашей собственной конфигурации, прежде чем их запускать: новые или изменённые хуки «are marked for review and skipped until trusted», то есть помечаются для проверки и пропускаются, пока им не начнут доверять. Управляемый хук, заданный в системной конфигурации, считается доверенным по политике, поэтому мы устанавливаем свои именно так. Сама команда отчёта устанавливается только в терминалах, где Foxl Code запросил отчёты о вопросах. По замерам на 0.162.1 неинтерактивный codex exec тоже запускает управляемые хуки и печатает о них по две строки на каждый вызов инструмента в свой вывод, поэтому для запусков, которые Foxl Code начинает через codex exec, мы хуки отключаем. Как видно из исходников 0.162.1, терминальный интерфейс Codex показывает любой хук, который работает дольше 300 мс, поэтому команда отчёта решает, есть ли вопрос, записывает свой файл-маркер и передаёт сетевой запрос отсоединённой копии самой себя.
О диалоге с вопросом в режиме Plan у Codex мы намеренно не сообщаем, потому что его хук PreToolUse срабатывает до того, как Codex решит, разрешён ли вопрос, а вне режима Plan Codex его отклоняет. По замерам на 0.162.1 хук сработал с вопросом, а затем Codex ответил «request_user_input is unavailable in Default mode». Терминалы Foxl Code запускаются в режиме Default, поэтому сообщение об этом хуке отправило бы на телефон вопрос, который никому так и не задали. Цена такого решения: у терминала Codex в режиме Plan диалог с вопросом не попадает в «Требует вашего внимания».
OpenCode. Наш плагин слушает шину событий OpenCode. Событий вопросов нет в списке событий в документации по плагинам OpenCode; они есть в исходниках схемы v1.19.0, их мы и читали. Статус idle завершает ход, и ход считается вопросом, если его последний ответ заканчивается на ?. Пока открыт диалог с вопросом или разрешением, смена статуса игнорируется, поэтому переходы агента в busy или idle вокруг диалога его не закрывают. События из сеанса субагента пропускаются.
Hermes. Несмотря на название, on_session_end у Hermes на 0.19.0 срабатывает в конце каждого хода, сразу после ответа. Когда наш плагин считал его закрытием, он отзывал вопрос, который ход только что задал: 7 из 12 вопросов закрылись сразу, а в 1 из 12 вопрос дошёл до сервера уже после собственного закрытия и так и остался открытым, потому что закрыть его было уже нечему. Теперь закрытием считается только прерванное завершение сеанса, а отчёты уходят по одному в том порядке, в котором их поднял Hermes.
Kiro не поддерживается, потому что у его хуков нет события вопроса или одобрения, а данные его остановки не содержат текста ответа. Хук не смог бы ни открыть вопрос, ни отличить вопрос от ответа. Единственный сигнал - внутренний файл сеанса в неопубликованном формате, и мы решили его не разбирать.
Что происходит, когда Foxl узнаёт?
Каждый отчёт уходит на одну конечную точку сервера Foxl Code, с проверкой по собственным учётным данным задачи, и открывает или закрывает запись в том же списке «Требует вашего внимания», где лежат и другие вопросы агентов. Задача помечается как ожидающая вашего ответа, как на рисунке.

На вопрос в конце ответа можно ответить из «Требует вашего внимания» или с телефона. Foxl вводит ответ в терминал этой задачи одной строкой, а через секунду отдельно отправляет клавишу Enter, потому что один фрагмент вместе с Enter воспринимается как вставка и так и не отправляется. Для диалога с вопросом или разрешением Foxl никогда не угадывает нажатия клавиш, которых ждёт терминальный интерфейс. Вместо этого его карточка в «Требует вашего внимания» перечисляет варианты, говорит ответить в терминале и содержит кнопку, которая открывает терминал. Ответ в терминале закрывает карточку через те же хуки.
Телефон получает уведомления только о вопросах, которые могут остаться незамеченными. Диалог с вопросом или разрешением, который всё ещё открыт через 15 секунд после того, как Foxl о нём узнал, вызывает уведомление, ведь человек, который смотрит в терминал, отвечает за секунды. О диалоге разрешения Claude Code сообщается примерно через шесть секунд после его открытия, поэтому уведомление о нём приходит примерно на 21-й секунде. Ответ, который заканчивается вопросом, показывается в «Требует вашего внимания», но не объявляется, ведь вопросом заканчиваются многие ответы. Вопрос 21 октября был именно таким, так что теперь он появился бы в «Требует вашего внимания» и на задаче, но телефон всё равно не зазвонил бы.

Что ещё не проверено?
В наших тестах настоящая команда отчёта работала на данных каждого закреплённого CLI, плагины работали под Node.js и Python на закреплённых форматах событий, а конечная точка сервера работала в локальной копии среды выполнения Cloudflare. Чего ещё не было:
- Настоящего вопроса из реального облачного терминала. На 23 октября 2026 года в рабочей таблице нет ни одного вопроса оттуда, так что сквозная проверка на живом терминале ещё впереди.
- Claude Code, который запускает эти хуки. Детали Claude Code, включая шестисекундную задержку и строку асинхронного хука, прочитаны из пакета 2.1.296, а не увидены в работающем терминале. У нас есть тест, который запускает эту сборку с этими хуками; его ещё не запускали.
- Терминалов других CLI. Несколько деталей Codex, OpenCode и Hermes прочитаны из исходников, в том числе то, что OpenCode доставляет события вопросов именно под этими именами; запускали только
codex exec.
Если вы запускаете агентов в собственных терминалах, копировать стоит таблицу хуков Claude Code. Подключите три хука к тому, что до вас дотянется, игнорируйте idle_prompt, ничего не печатайте, завершайтесь с кодом 0 и подождите несколько секунд, прежде чем отправлять оповещение. О терминальной стороне Foxl Code, то есть о том, как ввод вообще доходит до удалённого агента, рассказывает наша статья о том, почему каждое нажатие клавиши однажды уходило не на ту машину (на английском).
Источники и дополнительное чтение
- Claude Code: справочник по хукамДокументация
- Codex: хукиДокументация
- OpenCode: плагиныДокументация
- Hermes Agent (Nous Research)Справка
- Выпуск Foxl v0.9.3-beta.5Выпуск