turnbell даёт знать в тот момент, когда CLI-агент кодинга завершает ход или замирает в ожидании вашего ввода. Запустите длинный прогон Claude Code, Codex или Gemini CLI, переключитесь на что-то другое и перестаньте караулить терминал: turnbell читает ответ вслух, показывает уведомление на рабочем столе, проигрывает звук или пингует вебхук в тот самый момент, когда агенту нужны вы, не минутой раньше, не десятью минутами позже.

Что я сделал
- 8 интеграций первого класса: Claude Code, Codex, Gemini CLI, Copilot CLI, Cursor, opencode, Antigravity и Amp, каждый адаптер подключён к тому сигналу done/blocked/read-aloud, который собственная система хуков этого агента реально предоставляет, плюс универсальная обёртка
turnbell runдля любой другой команды. - Записи конфигурации с журналом изменений: каждый хук, который turnbell добавляет в файл настроек агента, фиксируется в атомарном, дописываемом журнале с построчным диффом, поэтому
turnbell uninstallможет хирургически удалить именно то, что добавил turnbell, и ничего больше, сохраняя правки, сделанные позже. - Режим озвучивания "speakable mode": опциональная подсказка, добавляемая в собственный файл памяти агента (
CLAUDE.md,AGENTS.md,GEMINI.md), которая просит его сохранять ответы пригодными для озвучивания и направлять код или плотные детали во временный файл вместо того, чтобы их проговаривать, обратимо, с автоочисткой через 24 часа. - Определение завершения с учётом фоновой работы: оповещение
doneв Claude Code задерживается, пока субагенты, воркфлоу или тиммейты ещё сообщают о работе в процессе, так что вас пингуют один раз в реальном конце хода, а не посреди делегирования. - Локальный приёмник вебхуков: один сериализатор отправляет ровно шесть полей метаданных (время, агент, событие, проект, краткое описание) в ntfy, Pushover, Slack или произвольный эндпоинт, никогда рабочую директорию, код или сам ответ агента.
Почему это было важно
Раньше любой длинный прогон агента означал либо караулить терминал, либо пропустить момент, когда он замер на запросе разрешения. turnbell закрывает этот разрыв без фонового демона, SDK или какой-либо телеметрии: он подключается к собственным хукам каждого агента, и каждое такое подключение можно отследить и отменить.
Зачем это существует
Длинные прогоны Claude Code и Codex не проваливаются громко: они тихо замирают на запросе разрешения или завершаются, пока я на три вкладки в стороне занят чем-то не связанным. Решение не в терминале побольше, а в том, чтобы узнать в момент, когда ход реально требует меня. Я единственный контрибьютор, проект активно поддерживается, построен сначала, чтобы решить мою собственную проблему, и лишь затем выпущен как публичный npm-пакет. Раньше он назывался hollr; переименование в turnbell достаточно осознанное решение, чтобы пакет всё ещё поставлял совместимый bin-алиас и автоматическую миграцию конфигурации для тех, кто остался на старом имени.
Ограничение: никакого SDK, никакого демона, ничего инвазивного
Каждая интеграция агента в turnbell подчиняется одному правилу: она редактирует собственную конфигурацию хуков агента, чтобы вызвать turnbell emit, и ничего больше. Никакого фонового процесса, никакого SDK, который агенту пришлось бы импортировать, никакого polling. Именно это ограничение и потребовало по-настоящему решить историю с удалением, а не задокументировать её как известное ограничение.
Записи с журналом вместо удаления "по мере возможности"
Очевидный способ построить turnbell init, дописывать записи хуков в тот конфигурационный файл, который использует агент, и считать дело сделанным. Очевидный способ построить поверх этого turnbell uninstall, искать по grep собственные маркеры turnbell и надеяться, что в файле больше ничего не столкнётся. Именно так выглядит удаление "по мере возможности", и этого недостаточно, когда редактируемый файл: это общая конфигурация, от которой зависят собственные инструменты пользователя.
src/adapters/diffwire.ts использует другой подход: каждая запись выражается как WireOp над JSON- или текстовым файлом, применяется через атомарную запись (временный файл + переименование, никогда частичная запись при сбое) и добавляется в журнал (listWiredKeys, appendLedgerEntry), который фиксирует, какие именно ключи или маркеры затронул turnbell и каким было предыдущее значение. turnbell init показывает предпросмотр каждого изменения в виде построчного диффа перед тем, как что-либо записать. turnbell uninstall воспроизводит журнал вместо того, чтобы заново выводить намерение из текущего состояния файла, и именно это превращает фразу "хирургически удаляет только то, что добавил turnbell, правки, сделанные позже, сохраняются" в реальную гарантию, а не в утверждение "по мере возможности" из README.
Особый случай Codex
Codex допускает только одну команду notify верхнего уровня в конфиге, а не список хуков. Если у пользователя уже была подключена команда notify для чего-то другого, наивная перезапись молча сломала бы существующую настройку. Адаптер архивирует исходное значение notify перед заменой, а turnbell uninstall восстанавливает его из архива вместо того, чтобы просто удалить ключ. Единственный случай, который нельзя восстановить, это если сам config.toml удалён между установкой и удалением, тогда восстанавливать уже не из чего, и это задокументировано как реальная граница, а не скрыто.
Не пинговать вас посреди делегирования
Собственный хук done в Claude Code срабатывает на каждый ход верхнего уровня, но ход может породить субагентов, воркфлоу или тиммейтов, которые продолжают работать после того, как родительский ход сообщил о завершении. Ранняя версия turnbell отправляла оповещение прямо там, что означало возврат к терминалу, пока фоновая работа всё ещё шла. Решение задерживает объявление done, пока Claude Code не сообщит, что делегированной работы в процессе больше нет, при этом явно игнорируя долгоживущие задачи shell/watcher и monitor, поскольку считать их "в процессе" заглушило бы любое оповещение в любой сессии, где просто есть фоновый процесс.
Полезная нагрузка: только метаданные, по конструкции
turnbell работает локально: голос, уведомления и звук никогда не покидают машину. Единственное, что может уйти по сети, это вебхук, который пользователь явно настраивает, и этот путь проходит через единственный сериализатор, отправляющий ровно шесть полей и ничего больше: время, агент, событие, базовое имя проекта и короткую строку описания. В кодовой базе нет второго пути, который мог бы случайно раскрыть рабочую директорию или реальный ответ агента, потому что сериализатор: единственное место во всём коде с доступом к сети. turnbell test --show-payload печатает точную полезную нагрузку, ничего не отправляя, так что это утверждение можно проверить, а не просто принять на веру.
Стек
TypeScript, tsup для сборки, Vitest с порогом покрытия 80%, нативные примитивы ОС для голоса/уведомлений/звука на каждой платформе (macOS стабильна, Linux и Windows в бете), а также форматы хуков/конфигов для каждого агента (Claude Code, Codex, Gemini CLI, Copilot CLI, Cursor, opencode, Antigravity, Amp) без единого общего SDK между ними. Лицензия MIT.