Я снова и снова запускал длинные прогоны агента, а потом зависал над терминалом, будто он был мне что-то должен. Мёртвые минуты накапливались. Так что я написал маленький инструмент, который следит за терминалом вместо меня.

Вот в чём неловкость. Я давал своему AI-агенту настоящую задачу, отрефакторить модуль авторизации, перенести роут, прогнать весь набор тестов, а потом просто… смотрел. Шесть минут крутящегося индикатора прогресса, и я, уставившийся на него так, будто он сбежит, если отвести взгляд.
Альтернатива была ещё хуже. Переключиться в Slack, увязнуть там в чём-то, и вернуться спустя десять минут, когда агент уже давно закончил и остыл. К тому моменту я уже терял нить того, что вообще просил.
Так что прогон занимал шесть минут, но стоил мне пятнадцати. Каждый раз. Этот разрыв, между запустил и готово, тихо съедал мой день.
🔔 Сигнал уже существовал
Раздражает то, что момент, о котором я хотел узнать, уже существует. Каждый агент точно знает, когда он завершает ход или останавливается, чтобы что-то у вас спросить. Claude Code вызывает хук Stop. У Codex есть команда notify. У Gemini есть событие AfterAgent. У Copilot есть agentStop.
Событие уже сидело внутри каждого инструмента. Просто никто не превращал его в простое «эй, вернись».
Именно эта формулировка заставила меня перестать жаловаться и начать писать код. Мне не нужно было ничего опрашивать или парсить лог. Нужно было лишь поймать сигнал, который агент и так рассылал, и превратить его в голос, уведомление, звук: толчок, который достанет меня где бы я ни отвлёкся. Именно это делает turnbell.

🧱 Первым решением стало ограничение, а не функция
Прежде чем написать хоть строку, я решил, чего этому инструменту делать нельзя.
Никакого фонового демона, гудящего в списке процессов. Никакого SDK, который нужно импортировать в каждый проект. Ничего, из-за чего я бы нервничал по поводу того, к чему это прикасается. Он просто прописывает в конфиге хуков каждого агента вызов одной команды, и это весь его след.
Из этого вышло два правила:
- Каждое изменение обратимо, побайтово. turnbell (также на npm) применяет правку конфига атомарно, затем показывает вам точный диф того, что только что записал, и даёт оставить это или откатить на месте. Нетронутый файл восстанавливается до тех же самых байтов, что были до правки; а файл, в который был лишь вставлен блок (скажем, файл инструкций агента), лишается ровно этого блока, так что всё, что вы отредактировали вокруг него позже, сохраняется.
- Удаление должно быть честным. Оно откатывает ровно то, что было добавлено, и ничего больше, по тем же двум правилам выше, так что инструмент никогда не заявляет об обратимости, а потом тихо её нарушает.
Основная часть реальной инженерной работы ушла именно сюда, в негламурное обещание, что эта штука оставит вашу машину точно такой же, какой её нашла. Инструмент, который правит ваш глобальный конфиг, должен заслужить этот доступ.
🔒 Единственное, что покидает вашу машину
Мне хотелось уведомлений на телефон, а значит, что-то должно было уйти по сети. Из-за этого я стал осторожнее, а не наоборот.
Голос, уведомления на рабочем столе и звук никогда не покидают машину, они локальны по определению. Единственный исходящий путь, это необязательный вебхук, и у него один сериализатор, который выдаёт ровно шесть полей: версию, метку времени, имя агента, событие, имя папки проекта и короткую строку статуса.
Никакого кода. Никакой рабочей директории. Никакого ответа агента. И вы можете распечатать точные байты, прежде чем вообще этому довериться: один флаг показывает payload и ничего не отправляет.
Приватность не была маркетинговой строчкой, приделанной под конец. Это было структурное решение: дать сети ровно одну дверь и сделать эту дверь крошечной.
🧩 Восемь агентов, один контракт
Дальше пошла грязная середина, а именно там обычно и прячется интересная работа.
Каждый агент выставляет разный набор хуков с разными возможностями. Claude Code умеет всё: завершение, блокировку, зачитывание вслух, слэш-команду. Cursor может лишь объявить, что закончил. opencode не может отдать наружу свою транскрипцию, так что зачитывание ответа вслух для него отпадает.
Соблазн, замазать это и заявить об одинаковой поддержке везде. Я поступил наоборот. Я написал по одному адаптеру на агента поверх единого контракта wire/unwire, а таблица возможностей говорит прямую правду о том, что каждый из них реально может дать.
Потому что самый быстрый способ потерять чьё-то доверие, это пообещать функцию, которую конфигурация человека не способна выполнить. Честные ограничения лучше красивой таблицы, которая врёт.
🎯 Чему я на самом деле научился
Самой интересной частью никогда не был говорящий терминал. Ей было всё, что вокруг него.
Настоящая задача была в том, чтобы построить нечто, что залезает в ваш глобальный конфиг, ваших агентов, вашу машину, и заслуживает там находиться. Применять атомарно, делать обратимым, дать сети одну маленькую дверь, вслух говорить, чего не умеешь.
Я постоянно возвращался к одному тесту: строй так, будто человек, который это удаляет, наблюдает за тобой. Именно эта одна линза решила больше архитектурных вопросов, чем смог бы решить любой запрос на новую функцию.
Сейчас я запускаю длинный прогон и правда ухожу. Через несколько минут ноутбук зачитывает ответ вслух, или телефон вибрирует, потому что агент застрял и ему нужно решение. Мёртвые минуты исчезли. Меня просто зовут обратно ровно в тот момент, когда это важно, ни минутой раньше, ни десятью позже.
Если обратимые правки конфига и сетевая политика с одной дверью кажутся вам полезными: turnbell с открытым исходным кодом: GitHub · npm.
Какой инструмент, редактирующий конфиг, вы бы мгновенно перестали ценить, если бы он оказался необратимым?
Мне любопытно, случалось ли это уже с вами, какой-нибудь CLI, переписавший dotfile и не оставивший пути назад, и изменило ли это то, насколько внимательно вы с тех пор читаете обещания установщиков.


