Решение проблем
Частые сбои и как их исправить. Если сомневаешься, запусти:
aipager doctor
Он по порядку выполняет все проверки ниже и для каждого сбоя выводит рекомендуемое решение. Исходник: aipager/doctor.py.
«Another aipager daemon already owns the socket»#
Два aipager не могут делить один управляющий сокет. Эта ошибка значит, что aipager всё ещё работает и отвечает на нём (сокет это $XDG_RUNTIME_DIR/aipager.sock или /tmp/aipager.sock, если $XDG_RUNTIME_DIR не задан). Файл сокета, оставшийся от упавшего aipager, не проблема: следующий запуск удаляет его и создаёт новый. Сначала останови работающий aipager:
aipager service stop # если он работает как служба
pkill -f 'aipager start' # иначе
Если проверка сокета его не заметит, aipager start всё равно откажется с aipager is already running (pid=N) и назовёт свой файл блокировки (~/.local/share/aipager/daemon.lock): останови этот процесс так же.
Бот в Telegram не отвечает#
aipager status: если в строке aipager написаноnot running, запусти его.aipager doctor: проверкиtoken_validиchat_reachableобращаются к API Telegram от начала до конца и показывают точную ошибку.- Не тот чат: запусти
aipager configи выбери Test bot reachability. Чтобы исправить неправильный личный чат, добавь правильный через Add a DM scope (см. как найти ID), потом убери неправильный в Edit a scope. - Боту ни разу не отправляли
/start: открой бота в Telegram и один раз нажми «Запустить» (Start).
Рабочие карточки стали медленнее#
Telegram разрешает примерно одно сообщение в секунду в один чат (и 20 в минуту в группу). Считается каждое сообщение и каждая правка. aipager даёт каждому чату свой бюджет примерно в 1 вызов в секунду с небольшим запасом на всплески, и рабочие карточки этого чата его делят. Индикатор «печатает…» тоже входит в этот бюджет, как самое неважное, что отправляет чат (см. «Пузырь набора» ниже).
Доля пузыря откладывается первой (один вызов каждые 4,5 секунды, пока самой старой работающей задаче чата меньше десяти минут, реже, когда она стареет, см. «Пузырь набора»), а карточки делят остальное. Поэтому одна карточка в личном чате обновляется примерно каждые 4,8 секунды; при двух сессиях, работающих в одном чате, каждая карточка примерно каждые 9,7 секунды; при трёх примерно каждые 14,5. Медленная карточка это бюджет за работой, а не баг. Ответы, сообщения в ответ и реакции на кнопки никогда не замедляются ради карточки: у них есть зарезервированный жетон, а правка карточки, которой не хватает на вызов, просто пропускается и повторяется на следующем проходе, а не встаёт в очередь перед твоим ответом.
В группе лимит 20 вызовов в минуту, сколько бы там ни было сессий, и один пузырь съел бы две трети этого. Карточки группы вместе сохраняют одно обновление каждые 10 секунд (11 с для одной карточки), а пузырь берёт остальное: поэтому в группе он может время от времени пропадать на секунду-другую.
Чтобы ускорить карточки: держи меньше одновременных сессий в одном чате или дай самым активным собственный чат (aipager config). Можно также настроить STREAM_EDIT_INTERVAL (по умолчанию 1.2, темп, пока карточка выводит текст) и BUSY_EDIT_INTERVAL (по умолчанию 3.0, когда она затихла) как переменные окружения aipager (см. настройки окружения). Поставить любую из них ниже нижней границы для чата безопасно и ничего не меняет: побеждает граница, и именно это держит чат под лимитом Telegram, какое бы значение ни стояло в настройках.
Карточка долгой задачи обновляется реже#
Темп выше действует первые две минуты задачи. Потом карточка замедляется по мере того, как задача стареет, а с 10 минут её часы идут шагами по 30 с, в такт обновлениям, чтобы она никогда не выглядела зависшей:
| возраст задачи | карточка обновляется не чаще, чем раз в | часы показывают |
|---|---|---|
| 0–2 мин | как выше (около 4,8 с для одной карточки в личном чате) | 0:45 |
| 2–10 мин | 10 с | 4:10 |
| 10–60 мин | 30 с | 23:00, 23:30 |
| больше 60 мин | 30 с | 1:23:00, 1:23:30 |
Часы округляются вниз до своего шага в 30 с, а обновления идут не чаще, чем через 30 с, иногда чуть реже. Поэтому карточка время от времени пропускает шаг: обновление на 23 мин 29 с показывает 23:00, а если следующее придёт на 24 мин 1 с, оно покажет 24:00, и 23:30 будет пропущено.
Новая строка инструмента или новое предложение ждут следующего обновления; смена состояния (сессия переходит из работы в ожидание фонового агента и обратно) показывается сразу, не чаще раза в 10 секунд. Живые строки агентов и строка ожидания идут теми же шагами. Законченная карточка показывает длительность задачи в настоящих секундах (23:17).
Именно это не даёт четырёхчасовой задаче править одно сообщение тысячи раз: 2026-09-23 одна карточка так и сделала, и чат заблокировали на семь часов. Чтобы сохранить быстрый темп на всю задачу, выключи /settings → ⏱ Обновление карточки в долгих задачах (для чата или для одной сессии из Mini App или из 👤 Настройки каждой сессии).
Пузырь набора#
Пузырь «печатает…» отправляет один цикл на чат, сколько бы сессий там ни работало (во всех клиентах Telegram пузырь один на чат), каждые TYPING_INDICATOR_INTERVAL секунд (по умолчанию 4,5: Telegram убирает статус набора через 5; 0 выключает пузырь). В бюджете чата он считается самым неважным, что отправляет чат:
- он замедляется по мере того, как задача стареет, по возрасту самой старой работающей задачи чата: каждые 4,5 с в первые десять минут (пузырь горит постоянно), потом каждые 15 с; Telegram показывает его 5 с, поэтому пузырь старой задачи мигает, а не горит. На 4,5 с он один давал бы 800 вызовов в час, и часовой лимит (ниже) выключал бы его надолго; выключение ⏱ Обновление карточки в долгих задачах держит его на 4,5 с;
- он появляется с самого начала каждой задачи; молодая карточка обновляется чуть медленнее, чтобы освободить ему место: доля пузыря откладывается до того, как карточки делят остальное (выше), поэтому вместе они никогда не превышают лимиты чата;
- он никогда не берёт жетон, нужный правке карточки: пузырь, который должен уйти сразу после правки карточки, ждёт полсекунды (
TYPING_RETRY_WAKE) и пробует снова, так что он опаздывает максимум на секунду-другую, но никогда не пропадает; - его первым выбрасывают, когда часовой объём чата становится большим (ниже);
- 429 на сам пузырь блокирует только пузырь, на столько, сколько попросил Telegram (карточки продолжают работать), но запускает шестичасовой режим предупреждения чата (темп ограничен 0,5 вызова/с, поэтому карточки тоже замедляются);
- блокировка на пузырь (
retry_afterвыше границы ниже) отключает отправку в чат ровно так же, как блокировка на любой другой вызов: в него больше ничего не уходит, а ответ задачи придерживается и доставляется, когда блокировка снимется.
Раньше он был бесплатным (один цикл на каждую работающую сессию, вне любого бюджета), пока 2026-09-23 две сессии в одном личном чате не отправили его около 5 400 раз за три часа и Telegram не ограничил сам пузырь.
Бот замедлился: лимит запросов (429)#
Если Telegram всё же ограничивает чат, он отвечает на один вызов 429 и retry_after в несколько секунд. aipager перестаёт обращаться к этому чату ровно на это время, потом повторяет одну отложенную отправку и удваивает интервал карточек этого чата (до ×8). Каждая спокойная минута уменьшает его вдвое обратно до нормы.
Что ты видишь:
aipager status(и строкаaipager daemonвaipager doctor) показываетTelegram flood backoff ×4 (chat …), last 429 12 s ago.- Ровно одна строка в
aipager logs, без трассировки:flood: chat … 429 retry_after=5s → cadence ×2. - Ничего не отключено, и ни один ответ не теряется: он откладывается, а не выбрасывается.
- Заработанная скорость отправки чата падает вдвое, и чат входит в шестичасовой режим предупреждения (
FLOOD_WARNING_HOURS): его скорость не может подняться выше 0,5 вызова/с (FLOOD_WARNED_CEILING) и растёт обратно медленно.aipager statusэто показывает:Telegram chat 123: rate 0.25/s (ceiling 0.50/s), 212/1200 calls in the last hour (as of 18s ago), 7/30 in the last minute - warning regime, 5h 52m left.
Ничего делать не нужно. Это проходит само. Строка о притормаживании пропадает, когда чат минуту-другую спокоен; скорость растёт на 0,1 вызова/с за каждое спокойное окно (обычно минута, в режиме предупреждения 36 минут), а полный потолок возвращается, когда режим заканчивается. aipager doctor всё это время держит строку aipager зелёной: чат, который притормаживает, это нормальная работа. (Раньше 429 забывался примерно через пять минут. Единственное предупреждение Telegram перед блокировкой 2026-09-23 пришло за 3 ч 23 мин до неё, а чат вернулся на полную скорость через несколько минут после него.)
Часовой бюджет#
У каждого чата есть ещё скользящий час: не больше FLOOD_HOURLY_MAX (1200) вызовов за любые 60 минут, пузыри набора, правки карточек и ответы вместе; исключены только реакции. Последние 120 (FLOOD_HOURLY_ESSENTIAL_RESERVE) оставлены для ответов, сообщений в ответ и запросов:
- на 810 вызовах в час пузырь набора ставится на паузу (он возвращается ниже 648);
- на 1080 чат входит в минимальный режим (ниже), пока час не опустится до 864;
- ответы часовой бюджет никогда не отклоняет; если они когда-нибудь перейдут 1200, лог скажет об этом раз в час.
aipager status показывает вызовы чата за последний час относительно его бюджета. Число берётся из файла состояния, который aipager перезаписывает не чаще раза в минуту, пока идут вызовы, поэтому рядом с ним указан его возраст. Две активные сессии, часами пишущие в один личный чат, остаются заметно ниже бюджета (инцидент 2026-09-23, воспроизведённый заново: около 900 вызовов в самый загруженный час против примерно 3 400 по модели для той же работы без бюджета).
Заработанная скорость и почему твои карточки могут быть медленнее, чем раньше#
С версии 0.7.13 устойчивая скорость отправки каждого чата узнаётся, а не предполагается. Telegram не публикует лимит, который на самом деле действует для твоего бота (он зависит от недавней истории твоего аккаунта), поэтому aipager начинает каждый чат с 0,5 вызова/с, добавляет 0,1 за каждую спокойную минуту до потолка 1/с, уменьшает вдвое при 429 и опускает до 0,05 после блокировки. Бот, которого только что блокировали, идёт гораздо осторожнее, чем тот, которого не блокировали, и зарабатывает скорость обратно за следующие часы.
Если скорость чата падает ниже 0,2 вызова/с или доля его часового бюджета на карточки и пузыри исчерпана, он входит в минимальный режим: рабочие карточки перестают анимироваться и показывают одну неподвижную строку ⏳ x1 · работает (карточка пока не обновляется), пузырь набора останавливается, а закреплённое сообщение со статусом показывает ⏸ карточки пока не обновляются (часовой лимит Telegram) (или (лимит Telegram), когда туда чат привела скорость) и в остальном не меняется, пока это не пройдёт. Ответы, сообщения в ответ и запросы разрешения продолжают идти: в этом весь смысл. Карточка это около 95 % того, что отправляет этот бот, а ответ около 5 %, поэтому под давлением он жертвует пикселями, а не работой. aipager doctor показывает минимальный режим как предупреждение, чтобы карточку на паузе никогда не приняли за сломанную; он снимается сам, когда скорость восстанавливается.
Бот замолчал: блокировка Telegram (flood control)#
retry_after больше TELEGRAM_MAX_RETRY_AFTER (по умолчанию 90 с) это не лимит запросов, а блокировка, и она может длиться часами. Из чата это выглядит так, будто бот умер: сообщения по-прежнему доходят до Claude, сессии продолжают работать, но ответы не приходят.
Что ты видишь:
aipager status(и строкаaipager daemonвaipager doctor) показываетTelegram flood-muted until HH:MM (chat …).- Одна строка в
aipager logs:Telegram flood control — chat … muted for Ns (until HH:MM) …, потом тишина по этому чату. Позже одна строкаflood mute on chat … lifted. aipager statusещё и показывает полное состояние чата:Telegram chat 123: rate 0.05/s (ceiling 0.50/s), 431/600 calls in the last hour (as of 12s ago) - MINIMAL MODE, card updates paused - flood-muted until 09:41 - warning regime, 5h 59m left (1 ban(s) in the last 7 days).
aipager отключает отправку в чат ровно на то время, которое попросил Telegram, и не делает к нему ни одного вызова любого вида: ни ответов, ни правок рабочей карточки, ни вложений, ни реакций, ни индикаторов набора, ни коротких уведомлений после нажатия кнопок, ни ответов, которые дали бы твои команды. Каждый из них стал бы новым нарушением, которое продлевает блокировку; именно запрос посреди активной блокировки 2026-09-15 превратил блокировку на 21 минуту в блокировку на 9,5 часа. Поэтому команда, набранная во время отключения, не получает вообще никакого ответа, и нажатие кнопки тоже не подтверждается: до 0.7.12 короткое уведомление всё равно уходило, в расчёте на то, что Telegram считает его отдельно. Для темпа это так; для блокировок нет. Другие чаты это не затрагивает.
Писать боту во время блокировки безопасно, и ничего не теряется. Ничто из того, что ты делаешь в чате, не заставляет бота обращаться к Telegram, пока отправка в чат отключена, поэтому блокировку это продлить не может:
- Сообщение, которое ты отправляешь (текст, голосовое, файл, быстрый шаблон), всё равно доходит до Claude, и сессия над ним работает. Его рабочая карточка придерживается, а не выбрасывается: если задача ещё идёт, когда блокировка снимется, карточка появится тогда. После блокировки чат ещё какое-то время остаётся в минимальном режиме, поэтому карточка может появиться на несколько минут позже конца блокировки. Если задача закончилась во время блокировки, ты получишь её ответ и никакой карточки.
- 🔄 Повторить во время блокировки ничего не делает. Сообщение не отправляется снова, а кнопка остаётся, так что её можно нажать ещё раз после блокировки. До 0.7.14 включительно сообщение уходило к Claude, а сообщение об ошибке с кнопкой оставалось, так что второе нажатие отправляло его ещё раз.
- Основная клавиатура тоже придерживается, включая ту, что отправляет перезапуск (до 0.7.14 включительно она терялась, пока что-нибудь другое её не обновляло). Она отправляется после блокировки.
После снятия блокировки всё приходит в таком порядке: придержанные ответы, потом карточки задач, которые ещё идут, потом клавиатура. Карточка, которой приходится ждать конца минимального режима, приходит после клавиатуры.
Ответы не теряются. Ответ, получившийся, пока отправка в чат отключена, придерживается и доставляется после снятия блокировки за пару секунд, с первой строкой ⏳ пришло с опозданием: задержано на 42 минуты из-за лимита Telegram. Спрашивать заново не нужно, а если спросишь, придут оба ответа, сначала старый: блокировка на несколько часов охватывает несколько задач, и ответ каждой нужен тебе. (Придержанные ответы живут в памяти: если перезапустить aipager, пока какие-то ждут, они теряются; лог выключения говорит сколько. Чат придерживает не больше 20 и ничего старше 24 часов; всё, что выброшено по любой из этих причин, отмечается в логе предупреждением с указанием, что это было.)
Блокировка делает чат потом медленнее, а не быстрее. Как только блокировка начинается, заработанная скорость чата падает до минимума, а блокировка засчитывается; часы отключения ничего не возвращают, рост начинается заново с момента снятия блокировки, и семь дней (FLOOD_BAN_MEMORY_DAYS) потолок скорости чата и его часовой бюджет делятся на единицу плюс число блокировок за эту неделю: одна блокировка делит оба вдвое, две на три. aipager status показывает всё это. (Раньше эта память длилась 24 часа и делила только потолок; чат, заблокированный 2026-09-19, вернулся на полную скорость и был заблокирован на семь часов 2026-09-23.) Пять и больше блокировок за неделю держат чат в минимальном режиме, пока они не устареют: ответы идут, карточки остаются на паузе.
Чего НЕ делать:
- Не перезапускай aipager, чтобы «починить». Отключение снимется само в показанное время. С версии 0.7.13 перезапуск больше не забывает блокировку (срок, заработанная скорость чата и история его блокировок сохраняются в
~/.claude/aipager-flood-state.jsonи восстанавливаются при запуске, как и последний час вызовов чата и его режим предупреждения), поэтому перезапуск её больше и не продлевает. Но он выбросит все ещё придержанные ответы и ничего не починит. - Не опускай
TELEGRAM_MAX_RETRY_AFTERниже стандартных 90 с в надежде повторить раньше: всё выше этого порога это блокировка, а не лимит запросов.
Как этого избежать: держи меньше одновременных сессий в одном чате или дай самым активным собственный чат (aipager config).
Сессия пропала из закреплённого сообщения (она GONE)#
Процесс dtach этой сессии завершился (перезагрузка компьютера, pkill claude, кто-то набрал exit в подключённой сессии dtach). Создай её заново: в её папке ~/.claude/projects/... переписка осталась.
Проще всего /resume <label> в Telegram (или просто /resume для списка): это перезапускает сессию и продолжает переписку. Из командной строки:
aipager resume <label> # то же самое из терминала
aipager session <label> # или новая сессия, без истории
aipager session <label> --continue # новый dtach, последняя переписка этой папки
Запрос разрешения без новостей 5 минут#
Если сессия ждёт запрос разрешения или вопрос, а Claude Code 5 минут ничего не сообщает, aipager читает сохранённую переписку сессии. Считаются только новости от самого Claude и от агента, который спросил: фоновый агент, который продолжает работать, не мешает этой проверке. Только если она показывает, что запрос закончен (на него ответили в терминале, а весть об этом потерялась), aipager перестаёт его ждать и снова считает сессию работающей. Иначе запрос остаётся открытым сколько угодно: карточка и закреплённое сообщение по-прежнему говорят, что сессии нужен твой ответ, заметка «всё ещё работает» не приходит, а твои сообщения задерживаются, пока ты не ответишь (см. текст). Claude Code, закрывшийся с открытым запросом, завершает сессию. Кнопки запроса по-прежнему отвечают в диалоге, если он ещё открыт (см. ответы).
Изменить ожидание:
AIPAGER_INTERACTIVE_TIMEOUT=300 aipager start # в секундах
Поддержка голосовых не ставится через Telegram#
Кнопка [📦 Установить голосовые] запускает установщик и правит своё сообщение каждые несколько секунд, пока он работает (всё ещё идёт… (25 с)). Если установка не удалась, сообщение показывает код выхода и последние 500 символов вывода установщика. Частые причины:
- Сеть: pip не может достучаться до PyPI. Проверь соединение с компьютера, где работает aipager.
- Диск:
~/.cache/huggingface/нужно около 74 МБ на модель и кешу wheels от pip ещё около 250 МБ. Сначала освободи место. - Permission denied: venv только для чтения. Перейди на
uv tool install, который всегда использует venv, принадлежащий твоему пользователю.
Если бот потерял связь посреди установки, сама установка на компьютере обычно завершилась: перезапусти aipager и попробуй голосовое ещё раз.
При открытии приложения видно «Открой эту страницу из приложения Telegram, чтобы войти.»#
Страница загрузилась, а скрипт Mini App SDK от Telegram (тот, что даёт initData) нет, поэтому странице не с чем входить, и она не делает ни одного вызова API. Сообщение звучит так, будто виноват ты; на самом деле причина в сети.
Новые версии aipager сами скачивают этот скрипт и отдают его со своего источника страницы (/telegram-web-app.js), так что телефону нужно достучаться только до сервера, который отдал страницу, а не ещё и до telegram.org. Если видишь это на старой версии, обновись.
Затем по порядку:
- Посмотри исходник страницы. Если её тег
<script>указывает наhttps://telegram.org/js/telegram-web-app.js, aipager ещё не смог скачать скрипт, и страница грузит его из Telegram, а именно это и не работает на телефоне, который не может достучаться доtelegram.org. aipager скачивает его при запуске сервера Mini App и повторяет не чаще раза в день, поэтому перезапуск aipager повторяет сразу;journalctl --user -u aipager | grep "webapp sdk"говорит, что пошло не так (обычно заблокированный или фильтруемыйtelegram.org). - Если тег указывает на
/telegram-web-app.js, проверь, что aipager его отдаёт:curl -sI http://127.0.0.1:8765/telegram-web-app.jsна компьютере aipager (поправь порт, если он менялся) должен ответить200сContent-Type: application/javascript. Копия лежит в~/.local/share/aipager/webapp-sdk/. - URL открыт в обычном браузере, а не через кнопку
/appили кнопку меню бота: тогда это ожидаемое сообщение. SDK даётinitDataтолько внутри Telegram. - Страница была открыта больше пяти минут:
initDataистекает, и страница просит открыть её заново. Нажми/appещё раз. - Mini App открыта кнопкой
📱 Appна клавиатуре от более старой версии aipager. Telegram не даётinitDataMini App, открытой кнопкой клавиатуры, поэтому на клавиатуре aipager этой кнопки больше нет. Отправь/start, чтобы получить текущую клавиатуру, и открывай приложение кнопкой меню или командой/app.
pyexpat _XML_SetAllocTrackerActivationThreshold при установке через brew#
Пакет python@3.12 из Homebrew собран с более новой libexpat, чем есть в твоей системе, почти всегда потому, что Xcode и Command Line Tools устарели на macOS Tahoe (26.x). Вывод brew обычно сам об этом говорит. Два решения:
- Используй вместо этого
uv tool install aipager. uv приносит свой python и полностью обходит проблему. Это рекомендуемый путь на macOS; см. README. - Обнови Xcode и Command Line Tools:
Или открой Xcode в App Store и обнови до последней версии.
sudo rm -rf /Library/Developer/CommandLineTools sudo xcode-select --install
«ModuleNotFoundError: aipager»#
Программа aipager ссылается на Python, в котором aipager больше не установлен (часто после удаления venv). Переустанови:
uv tool install --reinstall aipager
# или тем установщиком, с которого начинали: pipx, brew, pip
Список сессий потерян или повреждён#
aipager хранит свои сессии в ~/.claude/aipager-sessions.json и перезаписывает его атомарно (новый файл, потом переименование), так что прерванная запись оставляет старый файл целым. Если файла всё же нет, он не читается или это не валидный JSON, aipager пишет в лог, что начинает заново (предупреждение, если файл был, но не прочитался), и начинает с пустым списком; он не останавливается. Резервных копий этого файла нет. Ничего важного не теряется:
- работающие сессии находятся снова на первом проходе монитора, по их сокетам dtach (
/tmp/claude-dtach-*.sock); - каждая переписка по-прежнему лежит в собственной папке Claude Code
~/.claude/projects/..., так чтоaipager session <name> --continueв папке этой сессии её продолжит (--resumeпозволяет выбрать); - теряется список завершённых сессий (
/resume), карточки, которые были открыты, и остальное, что aipager помнил о каждой сессии.
Если aipager продолжает падать при запуске, aipager logs (или journalctl --user -u aipager) скажет почему; отодвинь файл в сторону (mv ~/.claude/aipager-sessions.json ~/aipager-sessions.json.old), чтобы исключить его.
Сессия не запускается#
Запуск, от которого отказался dtach, показывает в чате причину в одну строку (сокет уже существует, shell не исполняемый, нет псевдотерминала, имя слишком длинное, доступ запрещён, нет папки); собственное сообщение dtach, с путями, есть в aipager logs.
Список проверок aipager doctor#
Порядок важен: каждая следующая проверка предполагает, что предыдущие прошли. Проверка, которая падает в неожиданном окружении, показывается одной строкой ⚠ с названием проверки и ошибкой; остальные проверки всё равно выполняются.
Проверка (ключ --json) | Что проверяет | Как исправить |
|---|---|---|
config_parses | aipager.yaml и policy.yaml читаются; идёт первой, потому что все следующие проверки читают конфигурацию | ошибка называет файл и строку |
config | ~/.config/aipager/aipager.yaml существует, и в нём есть токен и чат | aipager config |
token_valid | Токен работает с getMe в Telegram | снова запустить aipager config |
chat_reachable | Telegram знает настроенный чат (getChat; ничего не отправляется) | открыть бота, нажать «Запустить» |
team | Чаты и участники (или старый team.yaml): говорит, личный это режим или командный, и отмечает повреждённый или не совпадающий старый team.yaml | aipager config |
role_shell_access | Один раз предупреждает о каждой роли участника, которая может запускать Bash (её правила безопасности работают в меру возможного, это не граница; см. группы) | не давать этой роли Bash в policy.yaml или смириться |
peer_messages | Сообщения между сессиями Claude: где хранятся их квитанции и закрыта ли эта папка, может ли эта система проверить время запуска отправителя, и предупреждение о каждой роли, которой правило разрешает SendMessage (см. безопасность) | убрать общую папку квитанций (aipager создаст её заново) или не давать этой роли SendMessage |
claude | Находит программу claude так же, как каждый запуск (claude_path в aipager.yaml или $AIPAGER_CLAUDE_BIN побеждают сразу; иначе самая новая из ~/.local/bin, PATH и Homebrew), и перечисляет каждую ДРУГУЮ найденную установку | установить Claude Code или задать claude_path / AIPAGER_CLAUDE_BIN |
claude_auth | Пробует claude auth status в том же окружении, что получает настоящая сессия. Никогда не проваливается: «не выполнен вход» и «сама проба не удалась» показываются по-разному, и ни то ни другое не мешает запуску сессии | claude auth login или задать ключ API / CLAUDE_CODE_OAUTH_TOKEN |
dtach | Программа dtach найдена (собственный dtach-bin aipager или та, что в PATH) | uv tool install --reinstall aipager |
hook_scripts | aipager-hook и aipager-statusline есть в PATH | uv tool install --reinstall aipager |
settings_json | В ~/.claude/settings.json подключены hooks aipager | aipager config |
daemon | aipager работает и его сокет отвечает; показывает и состояние лимитов Telegram (см. выше) | aipager start |
service_installed | По желанию: файл службы на месте | aipager service install |
service_unit_path | Только Linux: Environment=PATH= установленной службы действительно содержит папку найденной программы claude, прочитанный как текст, потому что doctor не видит PATH systemd из твоего интерактивного shell | aipager service install --yes |
miniapp | Может ли запуститься Mini App, когда она включена. Никогда не проваливается: Mini App необязательна | исправление, которое она называет |
aipager doctor --json выводит те же проверки в этом порядке с этими ключами (см. команды).
Запусти aipager doctor --fix, чтобы интерактивно найти учётные данные Claude и скопировать их в daemon.env (и тогда, когда файл есть, но в нём их нет) или закрепить claude_path, когда найдено больше одной установки. Он действует только после вопроса. Для службы, в PATH которой нет папки claude, запусти aipager service install --yes.
aipager не находит claude или выбирает не ту установку#
Раньше шесть мест искали claude каждое по-своему и могли не совпадать. Теперь все идут через одну функцию поиска (aipager/claude_resolve.py). claude_path в aipager.yaml, затем $AIPAGER_CLAUDE_BIN, побеждают сразу, если работают. Иначе проверяется каждый claude, найденный в ~/.local/bin, в $PATH и в префиксах Homebrew, и побеждает самая новая версия (так что смена порядка в $PATH не меняет выбор, если другая установка новее). Запусти aipager doctor, чтобы увидеть, какую именно он выбрал и что ещё нашёл; если побеждает не та, закрепи нужную:
aipager doctor --fix # интерактивный выбор среди найденных установок
# или вручную:
echo 'claude_path: /home/you/.local/bin/claude' >> ~/.config/aipager/aipager.yaml
Сессии не могут войти под службой systemd, хотя claude в терминале работает#
Службы systemctl --user никогда не читают ~/.bashrc или ~/.profile, поэтому строка export CLAUDE_CODE_OAUTH_TOKEN=… оттуда никогда не доходит до aipager. Вместо этого служба использует LoadCredential= из systemd и читает ~/.config/aipager/daemon.env: простой файл KEY=VALUE с правами 0600, который создаётся автоматически при первом запуске aipager service install (переносится из старого config.env, если там был токен, иначе один раз находится в твоём shell входа, иначе остаётся пустым с предупреждением). Если он всё ещё пустой, aipager doctor --fix снова ищет в тех же местах, если ответить «да», и добавляет найденную строку, сохраняя остальные строки файла; токен он никогда не выводит. Или добавь строку вручную:
cat ~/.config/aipager/daemon.env # посмотреть, что там есть (или нет)
echo 'CLAUDE_CODE_OAUTH_TOKEN=sk-...' >> ~/.config/aipager/daemon.env
chmod 600 ~/.config/aipager/daemon.env
aipager service stop && aipager service start
См. Модель безопасности: учётные данные Claude о том, от чего этот файл защищает и от чего нет.
Управляющий сокет aipager переехал#
aipager doctor / aipager status раньше всегда смотрели в /tmp/aipager.sock. Под службой systemd управляющий сокет теперь лежит в $XDG_RUNTIME_DIR/aipager.sock (с запасным /tmp, только когда $XDG_RUNTIME_DIR не задан: контейнеры, WSL1, минимальные дистрибутивы). Переехал только этот один сокет; сокеты dtach каждой сессии (/tmp/claude-dtach-*.sock) не затронуты. Задай AIPAGER_SOCKET_PATH, если нужно конкретное место.
/update говорит, что перезапуск завершит сессии (KillMode)#
В файлах служб, записанных до этой версии, нет строки KillMode=, поэтому systemd использует control-group: остановка или перезапуск aipager.service завершает каждую сессию Claude, которую запустил aipager. Поэтому /update ставит новую версию, но aipager не перезапускает и перечисляет сессии, которые уронил бы перезапуск. Исправь это один раз:
aipager service install
Это перезаписывает службу с KillMode=process, перезагружает systemd и перезапускает aipager, и этот перезапуск уже идёт с новой настройкой. Проверь через systemctl --user show -p KillMode aipager.service (KillMode=process). С этой настройкой systemd при каждом перезапуске пишет для твоих сессий строки «left-over process»; это нормально.
aipager update не находит uv или pipx#
aipager update ищет установщик по абсолютному пути в твоём PATH, а также в ~/.local/bin, ~/.cargo/bin, префиксах Homebrew, /usr/bin и /bin. Если он всё равно говорит, что не нашёл pipx, установщика, который создал этот aipager, больше нет или он лежит в другом месте; переустанови тем инструментом, который есть (pipx install --force aipager, uv tool install --reinstall aipager).
Обновление отклонено: editable или чужая установка#
/update и aipager update обновляют только установку, которая принадлежит твоему пользователю и доступна ему на запись, через установщик, который её создал. Они отказывают и называют причину для:
- рабочей копии в режиме editable (для разработки): обнови её через
git pull; - установки через Nix, Snap, Docker или системный пакет: используй обновление этой системы;
- установки, которая принадлежит другому пользователю (например, venv root в
/opt): обнови её от имени этого пользователя; - установки из локальной папки (
pipx install /path/to/aipager):отсюда не обновить: it was installed from a local folder; update it from that folder. Получи новую версию в эту папку и переустанови из неё или перейди на PyPI черезpipx install --force aipager; - установки, для которой непонятно, какой установщик её сделал (
could not tell which installer owns this aipager): переустанови её черезuv tool install aipagerилиpipx install aipager.
Обновление не удалось: unexpected argument '--refresh'#
aipager 1.0.0 и старше запускали uv tool upgrade aipager --refresh, а этот флаг не принимает ни одна версия uv, поэтому каждое обновление установки через uv останавливалось с error: unexpected argument '--refresh' found и ничего не перезапускало. Новые версии запускают uv tool upgrade aipager. Чтобы один раз пройти это место, обнови из терминала на этом компьютере (aipager update на этих версиях страдает тем же):
uv tool upgrade aipager
systemctl --user restart aipager.service
Без службы (или на macOS) перезапусти aipager тем способом, которым он был запущен.
Обновление Claude Code: установлен через npm в папку, куда нельзя писать#
Claude Code, установленный через sudo npm install -g, лежит в папке, которую может менять только root (вроде /usr/lib/node_modules), поэтому claude update от твоего пользователя падает с global folder isn't writable. /update и Mini App показывают более новую версию с отсюда не обновить: installed with npm into a folder your user can't write to и без кнопки для неё. Один раз запусти claude install от того пользователя, под которым работает aipager: это переводит на собственный установщик Claude Code в твоей домашней папке, который обновляется без sudo. Потом перезапусти aipager (systemctl --user restart aipager.service или тем способом, которым он был запущен): работающий aipager держит тот Claude Code, который нашёл при запуске, а после перезапуска берёт самый новый из найденных. Если claude_path в aipager.yaml (aipager doctor --fix может его задать) или AIPAGER_CLAUDE_BIN указывает на версию из npm, направь его на ~/.local/bin/claude или сначала убери, потому что они всегда побеждают.
Обновилось, но версия не изменилась#
Установка pipx из git URL обновляется из этого источника git, а не из PyPI. Когда в источнике нет ничего новее, /update пишет ✅ У aipager уже версия A: эта установка через pipx обновляется из своего git-репозитория, а там нет ничего новее.. Отправь или выбери новую версию там или перейди на PyPI через pipx install --force aipager.
Без службы aipager, который не перезапускает никакой менеджер служб (aipager start в терминале или tmux, Docker, launchd), устанавливает обновление, но продолжает работать на старом коде, пока не перезапустится. Тогда /update пишет aipager B установлен и ждёт перезапуска (сейчас работает A)., а hooks Claude Code, которые запускаются заново на каждое событие, возможно, уже работают на B: владелец получает одно уведомление, что обновление сделано только наполовину (через две минуты после того, как hooks впервые запустили B, так что перезапуск сразу после установки его никогда не показывает, и когда в личном чате владельца не идёт ни одна задача). Когда aipager уже работает на B, это уведомление превращается в ✅ Обновление aipager завершено: aipager теперь работает на B., без кнопки. Нажми 🔄 Перезапустить сейчас (в сообщении об обновлении, в уведомлении или в Настройки → Обновления в Mini App). aipager ждёт, пока не останется ни одной идущей задачи, аккуратно останавливается и запускает новую версию на месте: тот же процесс в том же терминале, окне tmux или контейнере, с той же командой и тем же окружением.
Если запуск на месте не удался, отдельная копия запускает aipager, когда старый процесс уже завершился. Её вывод тогда идёт в лог самоперезапуска (aipager.log в папке экземпляра или /tmp/aipager.log), а не в твой терминал, а лог aipager называет команду, которую нужно выполнить, если эта копия не вернётся. Если пропал сам интерпретатор (его окружение удалили) или ничего не удалось запустить, aipager завершается с кодом 1, лог aipager заканчивается строкой restart.failed: с командой, которую нужно выполнить, а следующий запуск сообщает об обновлении.
Когда кнопки Перезапустить сейчас нет, сообщение даёт шаги для твоей установки: в терминале или tmux нажми Ctrl+C и выполни aipager start; на macOS: launchctl kickstart -k gui/<uid>/com.aipager.daemon; в Docker: docker restart <container> на компьютере, где работает Docker. Пересоздание контейнера Docker (docker compose up после down или снова docker run) запускает его из образа, а это возвращает версию aipager из этого образа: чтобы оставить более новый aipager, используй более новый образ.
aipager не вернулся после обновления#
Обновление проверяет, что новая версия загружается, прежде чем что-то перезапускать, но если новый aipager всё равно не запускается, systemd повторяет попытку каждые 5 с. Посмотри почему:
journalctl --user -u aipager.service -n 50
Переустанови предыдущую версию тем же установщиком, потом перезапусти:
pipx install --force aipager==<previous> # или:
uv tool install --force aipager==<previous> # или:
<venv>/bin/python -m pip install aipager==<previous>
systemctl --user restart aipager.service
Установка pipx из локального пути: pipx install --force /path/to/aipager на старом коммите. Если ждёт устаревшее объявление, убери его через rm -f ~/.local/share/aipager/update-restart.json (через 24 ч его всё равно игнорируют); ~/.local/share/aipager/update.lock это всего лишь файл блокировки, и его безопасно удалить, когда никакое обновление не идёт.
«Обновление прервалось, когда aipager выключался»#
aipager остановился (или был перезапущен), пока /update устанавливал, и установщик остановился вместе с ним, так что установка может быть записана наполовину. Если aipager или Claude Code ведут себя странно, почини: для aipager запусти команду переустановки из сообщения (например, pipx install --force aipager) и потом systemctl --user restart aipager.service; для Claude Code снова запусти claude update.
Если «Перезапустить сейчас» не смог снова запустить aipager (без службы), в логе aipager остаётся restart.failed: с командой, которую нужно выполнить; выполни её, и новый aipager сообщит об обновлении.
Чат не на том языке#
Язык aipager берётся из того, что выбрано для чата, а не из сообщений в нём. Открой /language в этом чате и выбери нужный язык: этот выбор важнее всего остального. В личном чате Автоматически следует языку твоего приложения Telegram (Настройки → Язык в Telegram); язык, которого у aipager нет, показывается по-английски. Личный чат, который существовал до появления языков, остаётся на английском, пока ты не выберешь язык. Группа остаётся на английском, пока админ не выберет ей язык. Язык меняет только тексты самого aipager: Claude отвечает на том языке, на котором ты ему пишешь, что бы ни показывал aipager. См. Языки.
Описание бота не то, что было написано в BotFather#
aipager ставит описание и короткое описание бота на каждом языке, на котором он говорит, для людей, у которых приложение Telegram на этом языке, и Telegram показывает им этот текст вместо того, что написан в BotFather. aipager делает так, только пока у тебя нет своего описания, поэтому описание, написанное до установки этой версии, видят все. Если оно было написано после того, как aipager поставил своё, люди на этих языках по-прежнему видят описание aipager. Чтобы показать им твоё, сотри текст aipager для каждого языка через Bot API (setMyDescription и setMyShortDescription с пустым текстом и этим language_code); aipager никогда не поставит его снова, пока есть твой.
aipager пишет, что languages.json использовать не удалось#
aipager хранит то, что узнал о языках (кто был здесь до появления языков, последний язык Telegram, который он видел у каждого человека, и ушли ли разовое предложение и строка первого контакта), в ~/.local/state/aipager/languages.json. Если этот файл не читается, aipager отодвигает его в сторону как languages.json.bad-<time> в той же папке, пишет в лог предупреждение (снова при каждом запуске, пока не будет принято решение) и держит все чаты на английском без предложения языка, пока не будет принято решение: верни старый файл, если можешь его починить, или удали languages.json и перезапусти, и aipager снова будет считать каждого известного ему человека уже бывшим здесь (английский, пока человек не выберет). Язык, который кто-то выбрал, в этом файле не хранится и никогда не теряется.
Текст справа налево выглядит неправильно#
На персидском и арабском aipager ставит в свои тексты невидимые метки направления, чтобы каждая строка читалась справа налево, а имена сессий, команды и код оставались слева направо. Если строка всё равно выглядит перемешанной, чаще всего дело в клиенте Telegram, который по-своему рисует текст со смешанным направлением: проверь в другом клиенте (телефон против Desktop или Web), прежде чем сообщать. Собственные ответы Claude показываются так, как Claude их написал, без добавленных меток.
Переведённое слово клавиатуры ничего не делает в другом чате#
Клавиатура каждого чата на языке этого чата. Слова основной клавиатуры (status, stop, new, kill и остальные) понимаются в каждом чате на любом языке, а английские слова работают всегда. Слово кнопки шаблона или команды другое дело: набранное в чате с другим языком, это сообщение для Claude, а не кнопка, поэтому русское «Очистить переписку» никогда не запустит /clear в персидском или английском чате. Используй саму кнопку или английскую команду (/clear). Если клавиатура выглядит устаревшей после смены языка чата, отправь /start, чтобы получить текущую. Слово, которое ещё и имя одной из твоих сессий, обращается к этой сессии. /mode всегда читает ask, auto и full как режим, а переведённое слово режима как сессию только тогда, когда у работающей сессии ровно такое имя.
Не получается?#
Отправь отчёт о проблеме: нажми Сообщить о проблеме под /help в своём личном чате с ботом или запусти aipager report в терминале. Ты видишь весь отчёт до того, как что-то будет отправлено, и в нём нет чатов, сообщений, имён, путей или токенов (см. Отчёты о проблемах). После отправки ты получишь номер вроде ap1-7c41d09e2b3a.
Потом, если хочешь это обсудить, открой issue на github.com/dev-aly3n/aipager/issues и укажи этот номер. Пожалуйста, не вставляй в issue вывод aipager doctor или aipager logs: в них есть ID твоего чата, пути твоей домашней папки, имена сессий и начало твоих сообщений. Если нужна строка лога, тот, кто поддерживает aipager, попросит именно эту одну строку, и ты сможешь сначала убрать из неё всё личное.
См. также#
- Архитектура: что делает каждая часть.
- Модель безопасности: что aipager трогает и чего не трогает.