Background task queue for AI CLIs — schedule prompts, retry on rate limits, manage everything via Web UI or Telegram bot.
Works with Claude Code, OpenAI Codex, Qwen Code, Cursor Agent, or any CLI that accepts a prompt argument.
Универсальный планировщик промптов для AI CLI — очередь, планирование и автоматический retry.
Работает с любым AI CLI: Claude Code, Codex, Qwen Code и другими.
Одна очередь для разовых задач, расписаний и автономных workflow.
- Мульти-провайдер — Claude, Codex, Qwen, Cursor Agent, или любой свой CLI
- Очередь задач с приоритетами (1 — высший, 10 — низший)
- Планирование — запуск промптов в заданное время
- Выбор модели — для Claude Code провайдеров (sonnet/opus/haiku) и любых провайдеров с явным списком
models(Web UI + бот) - Rate limit detection — автоматическое определение лимитов API; перегрузка провайдера (529 overloaded) отличается от исчерпанной квоты и так и называется в уведомлении
- Exponential backoff — retry с нарастающей задержкой (60s → 1h)
- Crash recovery — при перезапуске воркера зависшие задачи возвращаются в очередь
- CLI + Web UI — два интерфейса на выбор
- Telegram бот — управление задачами через Telegram с авторизацией по номеру телефона
- Пароль на создание задач в боте — опциональная защита через
PP_TASK_PASSWORD - Автономный режим — флаг на задачу для запуска Claude или Codex без интерактивных подтверждений
- Уведомления — Telegram бот присылает сообщение как только задача завершилась (с результатом или ошибкой)
- Интеграция с herdr — задачи выполняются в живых терминальных сессиях: permission-диалог не роняет задачу, а ждёт подтверждения (с уведомлением в Telegram); режим
keep_paneоставляет сессию открытой для продолжения - herdr → Telegram мост — уведомления о заблокированных/завершённых агентах herdr с кнопками «Подтвердить / Экран / Ответить»
- Опциональная авторизация Web UI/API — токен через
PP_API_TOKEN - Скилы Claude Code — запуск
/skill-nameчерез Web UI и бота (для всех Claude Code провайдеров) - Продолжение сессии — кнопка 💬 в боте после завершённой задачи для диалога в той же сессии
- Пауза воркера — кнопка ⏸ в Web UI и боте, чтобы временно остановить обработку без потери задач
- Автоперезапуск worker'а — при обновлении кода пакета worker сам перезапускается между задачами
- Повторяющиеся задачи — поле Recur:
6h,30m,daily@09:00— новая задача создаётся автоматически, в том числе после неудачного прогона - Экран расписания — кнопка 🗓 в Web UI: все повторяющиеся задачи как серии — период, следующий запуск, исход прошлого и пометка «оборвана»
- Диагностика внешних конвейеров — локальные профили показывают backlog, возраст, churn, ETA и проектные health-check без запуска LLM и расхода токенов
- Правка задачи в очереди — провайдер, модель, эффорт, повтор и приоритет меняются прямо в карточке, без пересоздания задачи
- Фоновый запуск (detached) — запустить процесс в фоне и сразу завершить задачу (для серверов, ботов, polling-скриптов)
- Per-task таймаут — индивидуальный лимит времени задачи в Web UI (переопределяет глобальный
PP_TASK_TIMEOUT) - Свой git worktree на задачу — галка «🌿 свой worktree»: агент работает в отдельном чекауте на ветке
pp/t<id>, твоё рабочее дерево не трогается, результат виден как diff - Срыв среды ≠ провал задачи — отказ доступа (401/403/5xx) или обрыв ответа возвращает задачу в очередь вместо
failed - Сторож запретов — PreToolUse-хук режет катастрофические команды у задач с
--dangerously-skip-permissions: диалога там нет, значит запрет должен держать не он - Параллельные задачи —
PP_CONCURRENCY=N: worker выполняет несколько задач одновременно, но никогда две в одном рабочем дереве - Отмена running-задач — из Web UI, бота или API: worker убивает процесс задачи (группу процессов) в течение пары секунд
- Уведомления об обновлениях — баннер в Web UI когда выходит новая версия
- Дашборд стоимости — статистика расходов за сегодня / неделю / всего по провайдерам
- Дописать решателю — приписка к задаче: пара фраз, которые уйдут в следующий прогон (в том числе в повтор после rate limit)
- Итог задачи —
PP_VERDICT=1: агент заканчивает строкойИТОГ: ГОТОВО | НУЖЕН ЧЕЛОВЕК | НЕ СМОГ | …, и уведомление сразу говорит, надо ли идти смотреть; тихий итогПУСТО(«делать нечего») в Telegram не шлётся — для повторяющихся дежурных задач - Расход за окно лимита —
pp usage: сколько сожжено за последние 5 ч по ВСЕМ сессиям Claude Code, включая herdr-задачи и живую переписку - Tray-приложение — двойной клик на
pp.exe, иконка в трее, всё управление мышью - Standalone .exe — сборка без зависимостей через PyInstaller
- SQLite — данные хранятся локально в
~/.promptpilot/ - Workflow Orchestrator (W3) — planner разбивает большую задачу на утверждаемые этапы, затем автономный цикл «исполнитель → deterministic gate → независимый аудитор» ведёт каждый этап до PASS; есть crash recovery, лимиты, provenance и JSON/Markdown-экспорт для последующего анализа
Архитектура автономного цикла описана в
docs/WORKFLOW_ORCHESTRATOR_SPEC.md.
W0–W3 реализованы: можно импортировать прежние раунды, поручить сильному planner
разбиение новой задачи, отредактировать и один раз утвердить план, после чего
PromptPilot автоматически передаёт ход между executor, gate и reviewer и
сохраняет непрерывный журнал. Настройка описана в
docs/WORKFLOW_AUTOMATION_GUIDE.md.
В Web UI кнопка Workflows → Новый workflow открывает четырёхшаговый мастер:
задача, команда агентов, правила автоматизации и preflight. Перед созданием он
без выполнения проектного кода проверяет Git-путь, имя ветки, доступность
providers и синтаксис gate-команд. Есть рекомендуемый, экономный и усиленный
профили, а повторяющиеся настройки можно сохранить как локальный шаблон.
Экран сразу показывает, у кого «мяч» и какой переход произойдёт дальше.
Минимальный ручной пилот:
pp workflow create workflow.json
pp workflow import-history <id-or-slug> history.json
pp workflow start <id-or-slug> --base-sha <sha>
pp workflow dispatch <id-or-slug> executor --file executor-prompt.md
pp workflow sync <id-or-slug>
pp workflow gate <id-or-slug> PASS --gate-id tests
pp workflow dispatch <id-or-slug> reviewer --file reviewer-prompt.md
pp workflow sync <id-or-slug>
pp workflow review <id-or-slug> PASS --summary "Принято"
pp workflow list
pp workflow show <id-or-slug>
pp workflow rounds <id-or-slug>
pp workflow events <id-or-slug> --json
pp workflow findings <id-or-slug>Формат переноса старых итераций и правила отделения проверенных фактов от
ручных воспоминаний описаны в
docs/HISTORY_IMPORT_GUIDE.md.
- Скачай последний релиз: github.com/ivanarama/PromptPilot/releases
- Распакуй архив
PromptPilot-vX.X.X-windows.zipв любую папку - Заполни
.env(шаблон уже в архиве) - Запусти
start.ps1илиpp.exe tray
git clone https://github.com/ivanarama/PromptPilot.git
cd PromptPilot
pip install -e .Или установка из pip-пакета (из релиза):
pip install promptpilot-X.X.X-py3-none-any.whlТребования: Python 3.10+, хотя бы один AI CLI в PATH (claude, codex, qwen и т.д.).
git clone https://github.com/ivanarama/PromptPilot.git
cd PromptPilot
docker compose up -d --build
# Web UI: http://localhost:8420 (по умолчанию только loopback)docker compose поднимает два сервиса — server и worker — с общей SQLite БД
на volume promptpilot-data (данные переживают пересборку). Образ уже включает
Node.js и @anthropic-ai/claude-code и работает под non-root пользователем.
- Аутентификация Claude в контейнере: проще всего через LiteLLM-прокси —
задайте
ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKENв.envрядом сdocker-compose.yml. Альтернатива для обычной подписки — примонтировать свой логин: добавьте в сервисыvolumes: - ~/.claude:/home/pp/.claude. - Рабочие репозитории: чтобы задачи работали по вашим проектам, примонтируйте
их в контейнер
worker(пример вdocker-compose.yml) и задайтеPP_PROJECTS_ROOT. - Безопасность: порт публикуется только на
127.0.0.1:8420. Чтобы открыть в сеть — поменяйте на"8420:8420"и задайтеPP_API_TOKEN(тогда/api/*требуютAuthorization: Bearer <token>), либо ставьте за reverse-proxy. - Telegram-бот выключен по умолчанию: раскомментируйте сервис
botвdocker-compose.ymlи задайтеPP_TG_TOKEN(при необходимостиPP_TG_PROXY). - Ограничение: Docker-вариант локальный и одномашинный — herdr и раздача задач по ssh на другие машины из контейнера не работают.
./build.sh # → dist/pp
./dist/pp serverИспользует тот же кроссплатформенный pp.spec, что и Windows. Tray-зависимости
(pystray/Pillow) в Linux-сборку не входят — pp tray там просто сообщит об
этом и предложит pp worker/pp server/pp bot.
# Добавить задачу
pp add "Объясни что такое рекурсия"
# Запустить воркер (выполняет задачи)
pp worker
# В другом терминале — запустить веб-интерфейс
pp server
# UI доступен на http://127.0.0.1:8420 (браузер не открывается автоматически)Важно:
pp workerиpp server— два отдельных процесса, которым нужно работать одновременно. Пока воркер не запущен, задачи просто висят вpending.
Двойной клик на pp.exe — иконка появляется в системном трее, worker и server стартуют автоматически.
Правый клик на иконке:
▶ Worker ← кликнуть = остановить
▶ Server ← кликнуть = остановить
■ Bot ← кликнуть = запустить (нужен PP_TG_TOKEN в .env)
─────────────────
Запустить все
Остановить все
─────────────────
Открыть Web UI ← открывает браузер на http://127.0.0.1:8420
─────────────────
Выход ← останавливает все сервисы и закрывает трей
Цвет иконки показывает состояние: 🟢 все работают / 🟠 частично / ⚫ остановлено.
Или явно через команду:
pp traypp worker # запустить воркер
pp server # запустить веб-UI
pp bot # запустить Telegram бот
pp add "промпт" # добавить задачу
pp list # список задач
# и т.д.Оба режима работают с одной и той же БД и настройками.
Все настройки — токен бота, путь к claude.exe, разрешённые номера — хранятся в .env файле.
Скопируй шаблон и заполни:
copy .env.example .env
notepad .env.env рядом с pp.exe (или рядом со скриптом):
PP_TG_TOKEN=7123456789:AAF...
PP_TG_ALLOWED_PHONES=+79001234567,+79007654321
PP_CLAUDE_EXE=C:\Users\YourName\.local\bin\claude.exe
PP_GH_EXE=C:\Program Files\GitHub CLI\gh.exe
PP_GO_EXE=C:\Program Files\Go\bin\go.exe
PP_DEFAULT_CLI=claudeАвторизация Claude: PromptPilot запускает
claude.exeкак обычный процесс — он наследует окружение текущего пользователя. Достаточно один раз выполнитьclaude auth loginна этой машине, больше ничего настраивать не нужно.
Порядок поиска .env:
- Рядом с
pp.exe— для дистрибуции - Текущая рабочая директория — для разработки
~/.promptpilot/.env— постоянный пользовательский конфиг
Значения из .env применяются только если переменная не задана в окружении — то есть $env:PP_TG_TOKEN всегда перекрывает .env.
Запустить воркер + сервер в фоне:
.\start.ps1Запустить всё включая Telegram бота:
$env:PP_TG_TOKEN = "ваш-токен"
$env:PP_TG_ALLOWED_PHONES = "+79001234567"
.\start.ps1 -BotЛоги пишутся в .\logs\. Остановить:
.\stop.ps1Скрипт автоматически использует dist\pp.exe если он собран, иначе pp из PATH.
Сборка standalone-бинаря (не требует Python на целевой машине):
.\build.ps1На выходе: dist\pp.exe. Использование аналогично:
.\dist\pp.exe worker
.\dist\pp.exe server
.\dist\pp.exe bot
.\dist\pp.exe add "промпт"Примечание: при первом запуске
pp.exeможет занять несколько секунд — PyInstaller распаковывает бандл во временную папку.
Кириллица и любые не-ASCII промпты безопасны: при не-UTF-8 локали CLI перезапускается в UTF-8 Mode, а битую вставку из терминала (
привет)pp addдетектирует и чинит автоматически.
pp add "промпт" # добавить задачу (дефолтный провайдер)
pp add "промпт" -c codex # через Codex
pp add "промпт" -c qwen # через Qwen
pp add "промпт" -c claude-z # через кастомный алиас
pp add "промпт" -p 1 # с приоритетом (1 = высший)
pp add "промпт" -a "2026-03-25T03:00" # запланировать на время
pp add -f prompts.txt # добавить из файла (по строке)
pp add "промпт" -d /path/to/project # задать рабочую директорию
pp add "промпт" -d /repo -w # в своём git worktree (ветка pp/t<id>)
pp list # задачи (по умолчанию последние 20; -n N — больше)
pp list -s pending # фильтр по статусу
pp status 1 # детали задачи #1
pp cancel 1 # отменить задачу
pp delete 1 # удалить задачу
pp stats # статистика
pp purge --days 7 # удалить старые завершённые задачи
pp note 42 "перечитай комментарий" # дописать решателю к задаче #42
pp note 42 --clear # убрать приписку
pp usage # расход за окно лимита (5 ч)
pp usage --hours 24 --json # то же машинно, за сутки
pp guard --rules # правила сторожа запретов
pp guard "git push origin main" # что сторож сделает с командой
pp worker # запустить воркер
pp server # запустить веб-UI
pp server -p 9000 # на другом порту
pp bot # запустить Telegram бот
- Создай бота через @BotFather, получи токен.
- Задай переменные окружения:
$env:PP_TG_TOKEN = "токен-от-botfather"
$env:PP_TG_ALLOWED_PHONES = "+79001234567,+79007654321"- Запусти:
pp botПри первом открытии бота пользователь видит кнопку «Поделиться контактом». Бот получает номер телефона и сверяет с PP_TG_ALLOWED_PHONES. При совпадении — доступ открыт.
Авторизованные пользователи сохраняются в ~/.promptpilot/tg_users.json. Повторная авторизация при перезапуске не нужна.
Альтернатива env-переменной — файл ~/.promptpilot/tg_config.json:
{
"allowed_phones": ["+79001234567", "+79007654321"]
}| Функция | Описание |
|---|---|
| 📋 Задачи | Список задач с пагинацией и статусами |
🖥 Окна (/windows) |
Живые herdr-сессии по всем машинам: статус, проект, хвост экрана; в карточке — 💬 промпт прямо в панель и клавиши permission-диалога |
| ➕ Добавить задачу | Промпт → провайдер → модель (если у провайдера есть список) → приоритет → skip-permissions → оставить herdr-сессию? (для herdr) → директория → расписание → повтор → режим запуска |
| 📊 Статистика | Сводка по статусам |
| 🔌 Провайдеры | Список провайдеров с деталями: команда, модели, env-переменные (ключи маскированы), источник настройки |
| Детали задачи | Промпт, результат, ошибка; кнопки: отмена (работает и для running — процесс будет убит), сброс, удаление |
| 💬 Ответить | Продолжить диалог с моделью в той же сессии |
⚡ Скилы (/skills) |
Список Claude Code скилов; выбор запускает пошаговое создание задачи |
| 🔔 Уведомления | Автоматически присылает результат или ошибку после завершения задачи |
| 📎 Вложения | Скриншот или файл прямо в мастере: подпись к фото становится текстом задачи |
Файл можно приложить и в боте, и в веб-интерфейсе — агент получит абсолютный путь к нему приписанным к промпту («Приложенные файлы (читай по этим путям)») и прочитает файл сам.
В боте — на шаге ввода промпта или на карточке подтверждения: пришли фото (подпись к нему станет текстом задачи) либо документ. Файлы принимаются и на остальных шагах мастера — альбом из нескольких скриншотов Telegram отправляет отдельными сообщениями, они долетают уже после того, как мастер шагнул дальше. Ограничение Telegram: боту не отдают файлы больше 20 МБ.
В вебе — кнопка 📎, перетаскивание в поле промпта или просто Ctrl+V
скриншота из буфера.
Где лежат файлы: ~/.promptpilot/attachments/<uuid>/<имя> (бот) и
~/.promptpilot/uploads/ (веб). Наружу каталоги не раздаются. Файлы
недосозданной задачи бот удаляет сам, а вложения созданных задач остаются на
диске — автоочистки по возрасту пока нет.
Ограничение: вложения работают только для задач на локальной машине. Файл лежит на этом хосте, и агент на другой машине его не увидит — бот и веб в этом случае не дадут запустить задачу и скажут, почему.
После завершения задачи в деталях появляется кнопка 💬 Ответить — если модель спросила что-то или ты хочешь продолжить диалог:
- Открой детали завершённой задачи → нажми 💬 Ответить
- Введи ответ или следующий вопрос
- Бот создаст новую задачу с флагом
--resume <session_id>— Claude продолжит разговор в том же контексте
Цепочка не ограничена: каждый «ответ» тоже получает кнопку 💬. Новая задача наследует провайдера, рабочую директорию и флаги оригинальной.
При создании задачи через бота последний шаг — выбор режима запуска:
Как запустить?
[▶ Обычно (ждать результата)] [🔁 Фоново (сервер/бот)]
Обычно — воркер ждёт завершения команды и сохраняет результат. Подходит для разовых задач.
Фоново — процесс запускается отдельно и сразу отвязывается. Задача помечается completed (PID XXXX), воркер переходит к следующей задаче. Процесс живёт независимо до ручной остановки.
Когда использовать «Фоново»:
- Запустить другой бот / сервер
- Скрипт с бесконечным polling-циклом
- Любой процесс, который никогда не завершится самостоятельно
Примечание: в режиме «Фоново» воркер не перехватывает вывод и не знает об ошибках после старта. Если процесс упал сразу — в задаче это не отобразится.
Кнопка 🔌 Провайдеры показывает inline-кнопки со списком провайдеров. При нажатии — карточка с деталями:
- Команда запуска (или «Исполнитель: herdr» для herdr-провайдеров)
- Список моделей (или «по умолчанию»)
- Env-переменные (API-ключи маскированы:
sk-...xyz) - Источник настройки (
builtin,providers.json, или оба) и путь к файлу
Если задана переменная PP_TASK_PASSWORD, бот запрашивает пароль перед созданием задачи. При неверном вводе создание отменяется; введённое сообщение автоматически удаляется из чата.
PP_TASK_PASSWORD=mysecretpasswordПросмотр задач и статистика паролем не защищены — только создание.
Встроенные провайдеры:
| Имя | Описание | Скилы | Выбор модели |
|---|---|---|---|
claude |
Claude Code (Anthropic) — дефолт | ✅ | ✅ sonnet / opus / haiku |
claude-z |
Claude Code с альтернативным API (GLM, z.ai и др.) | ✅ | ✅ sonnet / opus / haiku |
codex |
OpenAI Codex | — | — |
qwen |
Qwen Code | — | — |
cursor |
Cursor Agent | — | — |
opencode |
OpenCode AI (GPT-4o/5, o1/o3 и др.) | — | ✅ из списка моделей |
Любой провайдер с
supports_skills=Trueсчитается Claude Code-совместимым и получает выбор модели автоматически.
Команды управления:
pp provider # список всех (+пометки hidden / not installed)
pp provider add <name> ... # добавить
pp provider hide <name> # убрать из списков Web UI и бота (unhide — вернуть)
pp provider remove <name> # удалитьКастомные провайдеры сохраняются в ~/.promptpilot/providers.json. Провайдеры,
чей исполняемый файл не найден на машине, автоматически не показываются в
списках Web UI и бота; ненужные (например claude-z без ключа z.ai) можно
скрыть вручную: pp provider hide claude-z.
Дефолтный провайдер: переменная PP_DEFAULT_CLI (по умолчанию claude).
Путь к claude ищется в PATH автоматически (claude на Linux/macOS,
claude.exe на Windows), переопределяется через PP_CLAUDE_EXE. opencode
ищется в PATH, затем в ~/.opencode/bin (официальный установщик) и npm-биндирах.
pp provider add myai \
--cmd "myai run {prompt}" \
--desc "My AI Tool"С переменными окружения и поддержкой скилов:
pp provider add claude-z `
--cmd "C:\Users\<username>\.local\bin\claude.exe -p --verbose --output-format stream-json {prompt}" `
--desc "Claude Code (GLM via z.ai)" `
--env "ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic" `
--env "ANTHROPIC_AUTH_TOKEN=your-token-here" `
--env "ANTHROPIC_DEFAULT_SONNET_MODEL=glm-4.7" `
--env "ANTHROPIC_DEFAULT_OPUS_MODEL=glm-4.7"Windows:
subprocessне видит PowerShell-функции и алиасы — нужен полный путь к исполняемому файлу..cmd/.bat-обёртки (npm-инструменты вродеqwen,codex) находятся автоматически черезshutil.which.
herdr — терминальный мультиплексор для
AI-агентов. PromptPilot умеет выполнять задачи не headless-процессом, а в
живой herdr-сессии: агент виден, к нему можно подключиться и вмешаться,
а главное — задача, упёршаяся в permission-диалог, не падает и не требует
--dangerously-skip-permissions: агент переходит в состояние blocked,
в Telegram приходит уведомление, вы подтверждаете действие — задача
продолжается.
Провайдер с исполнителем herdr описывается так (~/.promptpilot/providers.json):
"claude-herdr": {
"executor": "herdr",
"kind": "claude",
"description": "Claude Code в herdr-сессии",
"supports_skills": true
}Добавить можно тремя способами:
Web UI — кнопка ⚙ Providers → форма «Добавить провайдер» → тип «herdr-сессия» → указать имя, агента (kind) и, при желании, список моделей через запятую — тогда при создании задачи появится выпадашка выбора модели.
CLI:
pp provider add claude-herdr --executor herdr --kind claude --desc "Claude в herdr"
pp provider add opencode-herdr --executor herdr --kind opencode \
--desc "OpenCode в herdr" \
--models "opencode/big-pickle,opencode/mimo-v2.5-free,opencode/deepseek-v4-flash-free"providers.json — вручную, поле "models": [...] опционально.
kind — любой агент, который поддерживает herdr: claude, codex, gemini,
cursor, opencode, grok, copilot, droid, amp, kilo и другие
(полный список: herdr agent start --help). Список доступных моделей opencode:
opencode models. Выбранная модель передаётся агенту флагом --model при
старте сессии.
Режимы завершения:
- «🖥 оставить сессию открытой» — галочка при создании задачи (Web UI;
в боте — отдельный шаг для herdr-провайдеров), по умолчанию включена:
результат сохраняется в базу, но сессия остаётся — приходите, читаете
транскрипт и продолжаете диалог в той же панели. Снятая галочка — панель
закрывается после задачи. (Провайдерный флаг
"keep_pane": trueтоже поддерживается и форсирует режим.) - detached (галочка «Фоновый запуск» в боте) — промпт отправлен, задача сразу completed, агент работает в открытой панели.
Ограничения: интерактивная сессия не отдаёт stream-json, поэтому cost/session_id для herdr-задач не считаются (дашборд стоимости и кнопка 💬 неактивны).
Встроенный провайдер herdr-session отправляет промпт в уже открытую
панель herdr — оставленную задачей (pp-kept-N) или запущенную вручную:
- Web UI: выберите провайдера
herdr-session— появится выпадашка живых сессий (панель · агент · статус · имя); в боте — те же кнопки. - Работает вся механика задач: очередь, расписание («в 09:00 подведи итоги»), recurrence, blocked-уведомления, отмена, результат в базу.
- Чужая панель никогда не закрывается и не переименовывается; если панель закрыли до запуска — задача падает с понятной ошибкой (и уведомлением).
- Так удобно строить цепочки продолжений в одну сессию — аналог «💬 Ответить» для herdr-задач.
Обратная сторона моста: не ждать уведомления, а самому зайти и посмотреть, чем
заняты агенты. Список живых панелей собирается по всем машинам с herdr
(agent list), в карточке — статус, проект, хвост экрана и действия:
- 💬 Ответить — промпт уходит прямо в панель (
agent prompt), мимо очереди задач: быстро, но без записи в задачи и без учёта стоимости. - Enter / 2 / 3 / Esc — ответ на permission-диалог, когда агент
blocked. - Панели задач PromptPilot помечены номером задачи (
#42).
Отправленные так промпты журналируются в таблицу prompt_log — время, проект
(cwd панели), машина, панель и текст; сами транскрипты не дублируются, их
хранит агент (~/.claude/projects/…). Выключается через PP_LOG_PROMPTS=0.
У запущенной herdr-задачи раскрытая карточка показывает блок Экран агента: хвост панели (обновляется раз в 4 секунды, пока карточка раскрыта), статус агента и кнопки Enter / 2 / 3 / Esc — тот же ответ на permission-диалог, что в боте, но с десктопа. Раньше заблокированная задача выглядела в вебе как бесконечный «running now», и разблокировать её можно было только из Telegram или из самого herdr.
Эндпоинты сознательно узкие: GET /api/tasks/{id}/screen и
POST /api/tasks/{id}/keys работают только через id задачи (не через
произвольный pane_id), а список клавиш — ровно enter, 2, 3, esc.
Произвольного ввода в чужой терминал через веб нет.
Web UI: ⚙ Providers → «Изменить» у нужного провайдера — форма заполнится текущими значениями; сохранение с тем же именем перезаписывает. У встроенных провайдеров так создаётся переопределение (сбрасывается кнопкой «Сбросить к встроенному»). Замаскированные env-секреты при редактировании нужно ввести заново.
Повторяющаяся задача хранится как постоянная серия, а каждый запуск — отдельное вхождение этой серии. Кнопка 🗓 Расписание в Web UI показывает период, параметры (провайдер, модель, эффорт, машина), следующий запуск, результат прошлого прогона и статистику здоровья. Кнопка «Изменить» правит всю серию: основной интервал, effort, приоритет и таймаут сохраняются для будущих запусков, даже если текущий уже работает.
Для временного разбора накопившейся очереди есть «ускорение»: например,
основной интервал 4h, временный 1h. PromptPilot автоматически вернёт 4h
по указанной дате или после N последовательных итогов ПУСТО. Серия также
ставится на паузу, возобновляется, запускается немедленно или окончательно
завершается из Web UI и Telegram (/schedule). При сокращении интервала уже
созданный будущий запуск переносится ближе сразу; ждать старого четырёхчасового
scheduled_at больше не нужно. Более длинный интервал, наоборот, не откладывает
запуск, который уже должен состояться раньше. Если единственное вхождение было
отменено, «Запустить сейчас» создаёт для активной серии новое и тем самым
восстанавливает её без пересоздания расписания.
В общей очереди карточка повторяющейся задачи показывает короткое имя серии, а
полный служебный промпт остаётся внутри раскрытой карточки. Если серия поставлена
на паузу, будущий запуск явно помечается PAUSED и не выглядит как готовый к
исполнению queued. Остальные ожидающие задачи также различаются явно:
SCHEDULED означает будущий запуск по времени, а QUEUED — уже готовый запуск,
который ждёт свободного worker.
Отдельная кнопка «📈 Конвейеры» в главной панели и команда бота /pipeline
показывают любой настроенный pipeline-профиль. Аналитика считает внешний backlog
через GitHub CLI, сопоставляет его с ёмкостью одного прогона и сохраняет локальные
снимки по profile_id. Узкое место — этап с максимальным ETA: учитываются
backlog / capacity, интервал серии и средняя длительность её выполнения.
PromptPilot не поставляет профили конкретных проектов. Метки, запросы и лимиты
задаются пользователем в ~/.promptpilot/pipeline_profiles.json (или файле из
PP_PIPELINE_PROFILES), поэтому чужие репозитории не появляются в новой установке.
Если в профиле включён priority_control, дашборд показывает элементы очередей
и позволяет поставить P0…P3 либо вернуть автоматическую оценку. Кнопка
«⚡ Следующим» ставит P0 и переносит будущий запуск соответствующей серии на
ближайшее время; поставленная на паузу серия при этом остаётся на паузе.
Одинаковые диагностические сигналы в окне конвейера сворачиваются в одну строку
со списком и количеством PR; владелец single-flight барьера всегда показывается
первым, чтобы было видно, какой PR сейчас должен пройти REVIEW → MERGE. В основной
карточке служебные коды и сырая health-сводка заменяются понятными формулировками:
какой PR следующий, выполняется ли REVIEW прямо сейчас, сколько решений ждут
человека и сколько PR ещё переходят со старого формата протокола.
Снимки активных профилей собираются фоново каждые пять минут
(PP_PIPELINE_SNAPSHOT_INTERVAL, 0 отключает). Дашборд показывает Δ backlog,
вход/выход, переходы между очередями, churn, возраст элементов и смысловые итоги
прогонов за 5 и 24 часа. Это обычные GitHub API, SQLite и арифметика — LLM не
вызывается и токены не расходуются. После первого запуска историческим карточкам
нужно накопить соответствующее окно; до этого интерфейс честно показывает покрытие.
В таблице каждого этапа видны номер, время и итог последнего завершённого запуска;
отдельная карточка показывает время последнего REVIEW. Для Codex PromptPilot
использует JSONL-режим CLI и сохраняет точные input/output tokens. Старые
текстовые запуски остаются с пометкой «нет данных»: их расход не оценивается по
длительности и не выдумывается задним числом. «ГОТОВО без действий» учитывается
отдельно от продуктивных прогонов. Исторические НЕ СМОГ и технические падения
остаются в статистике окна, но красное здоровье учитывает только ещё не
восстановленные инциденты: последующий штатный итог той же серии помечает старый
сбой как восстановленный.
Локальным агентам PromptPilot добавляет в PATH каталоги из PP_GH_EXE и
PP_GO_EXE. На Windows также автоматически обнаруживаются стандартные установки
GitHub CLI и Go в C:\Program Files. Поэтому tray/служба не зависит от того,
успело ли приложение получить обновлённый пользовательский PATH.
Идентификатор JSONL-сессии сохраняется сразу после события thread.started, а
не только в финале. Если worker или процесс Codex оборвался после создания
ветки/worktree, retry запускает codex exec resume для той же сессии. Благодаря
этому продолжение знает о собственных незавершённых изменениях и не объявляет их
«чужой работой» после повторного запуска.
stop.ps1 не полагается только на .pp-pids.json: после hot-reload PID worker
меняется. Скрипт получает актуальный worker PID из heartbeat API, server PID —
из слушателя PP_PORT, проверяет командную строку процесса и лишь затем
останавливает дерево. Поэтому штатный stop не оставляет скрытый worker, который
продолжает расходовать токены после «остановки» старого launcher PID.
Рекомендация считается прозрачно: backlog / capacity даёт число необходимых
прогонов, а один цикл равен интервал + средняя длительность прогона — повтор
назначается после завершения предыдущего запуска. Поэтому серия 15m со средним
выполнением 30 минут даёт примерно один результат за 45 минут, а не четыре в час.
Профиль задаёт желаемое время очистки (target_clear_hours, обычно 8 часов),
интервал выбирается из практичных пресетов. Если одна длительность прогонов уже
не позволяет уложиться в цель, дашборд предлагает увеличить ёмкость или
параллелизм. ETA — нижняя оценка: она не учитывает новые входящие задачи и
ожидание более приоритетных серий в общей очереди worker; для этапа с
manual_gate: true ускорение не предлагается, потому что его ограничивает
решение человека.
Worker публикует heartbeat в общей SQLite БД. Активный профиль немедленно
становится красным, если heartbeat отсутствует или устарел; running, который
пережил настроенный task_timeout, отдельно показывается как зависший запуск.
Это позволяет отличить медленную очередь от остановившегося исполнителя без
ожидания пятичасового окна статистики. Завершившийся итогом НЕ СМОГ или
технически упавший прогон тоже сразу делает профиль красным: жёлтая проектная
диагностика больше не маскирует потраченные токены без результата.
Каждая строка расписания — самостоятельная серия со своим working_dir.
Аналитический профиль объединяет нужные серии в одну логическую цепочку по
series_contains. Несколько проектов — это несколько профилей; раздел
«Конвейеры» покажет их в выпадающем списке и не смешивает снимки. Пользовательский файл по умолчанию:
~/.promptpilot/pipeline_profiles.json:
{
"profiles": {
"my-project": {
"title": "MyProject: сопровождение",
"repository": "owner/my-project",
"target_clear_hours": 8,
"priority_control": {
"trusted_account": "YOUR_GITHUB_LOGIN",
"default_level": "p2",
"aging_hours": 168,
"max_items": 12
},
"queues": [
{
"id": "plan",
"title": "Планы",
"query": "is:issue is:open label:plan-needed label:approved -label:hold -label:manual -label:plan-in-review",
"capacity": 1,
"series_contains": "MyProject - PLAN",
"backlog_diagnostic_field": "plan_candidates",
"wake_when": {"field": "plan_candidates"},
"dispatch_gate": {
"skip_when_empty": true
}
},
{
"id": "fix",
"title": "Исправления",
"queries": [
"is:issue is:open label:ready-fix -label:in-work -label:needs-decision -label:plan-needed -label:plan-in-review -label:hold -label:manual",
"is:issue is:open label:approved -label:in-work -label:plan-needed -label:plan-in-review -label:hold -label:manual"
],
"capacity": 1,
"series_contains": "MyProject - FIX",
"backlog_diagnostic_field": "fix_candidates",
"wake_when": {"field": "fix_candidates"},
"dispatch_gate": {
"skip_when_empty": true
}
},
{
"id": "review",
"title": "Ревью",
"query": "is:pr is:open -label:changes-requested -label:needs-decision -label:hold",
"capacity": 2,
"series_contains": "MyProject - REVIEW",
"backlog_diagnostic_field": "review_backlog",
"wake_when": {"field": "review_candidates"}
},
{
"id": "merge",
"title": "Слияние",
"query": "is:pr is:open label:ship",
"capacity": 1,
"series_contains": "MyProject - MERGE",
"backlog_diagnostic_field": "merge_candidates",
"wake_when": {"field": "merge_executable"},
"dispatch_gate": {
"skip_when_empty": true,
"defer_when_diagnostics_match": [{
"field": "review_candidates",
"key": "stage",
"values": ["integration-review", "legacy-integration-review"]
}],
"defer_for": "10m"
}
}
],
"health_check": {
"command": ["/absolute/path/to/project-health", "-json"],
"working_dir": "/absolute/path/to/project",
"timeout_seconds": 180
}
}
}
}priority_control необязателен. Он использует GitHub-метки queue:p0…
queue:p3 для ручного решения и queue:auto:p0…queue:auto:p3 для оценки,
перенесённой с issue на PR. Ручная метка старше автоматической; без обеих
critical/security получает P0, bug — P1, enhancement/documentation/default —
P2, question — P3. Каждые aging_hours ожидания эффективный уровень повышается
на один до P1, поэтому низкий приоритет не означает вечное ожидание, а P0
остаётся полосой для действительно срочной работы. Если
проектный исполнитель сортирует кандидатов сам, он должен применять те же
правила: PromptPilot управляет метками и показывает порядок, но не подменяет
безопасный выбор внутри репозитория. Проверка trusted_account не даёт случайно
менять приоритет под другой учётной записью GitHub CLI.
Если выбранное решение требует сначала архитектурного плана, FIX должен
передать issue меткой plan-needed, сохранив человеческий approved. Отдельная
серия PLAN создаёт PR только с плановым документом и переводит issue в
plan-in-review; такой PR проходит обычные REVIEW, человеческий ship и MERGE.
Ручная queue:p0…queue:p3 при этом копируется с issue на plan-PR, поэтому
ускорение действует на весь маршрут, а не теряется перед REVIEW плана.
После merge проектный handoff снимает plan-in-review и возвращает issue в FIX.
Так «сначала план» является исполняемым этапом, а не тупиком needs-decision.
В workflow со sticky-разрешением метка ship означает «слить этот точный HEAD,
когда его REVIEW успешно завершится». Она не исключает PR из первой review-
очереди и может быть поставлена до финального служебного completion: HEAD epoch,
последний trusted label-transition и последующий каноничный review proof вместе
защищают решение от переноса на другой код. Поэтому человеку не приходится
снимать и повторно ставить ship из-за гонки между UI и завершением REVIEW.
health_check необязателен. Это проектная команда без shell, которая должна
вернуть JSON со state: green|yellow|red, summary и массивом findings.
PromptPilot запускает её при каждом снимке и показывает результат сразу, поэтому
нарушение текущих инвариантов видно без ожидания 5- или 24-часовой истории. Команда
не должна вызывать LLM; для GitHub-проверок путь из PP_GH_EXE передаётся ей как
GH_EXE. Таймаут по умолчанию — 180 секунд; для больших репозиториев его можно
увеличить до 900. Ошибка или timeout самой команды отображается как
«диагностика не выполнена», а не как доказанное нарушение инварианта.
dispatch_gate тоже необязателен и настраивается у конкретного этапа. Перед
запуском провайдера PromptPilot получает свежий снимок профиля. При
skip_when_empty пустой запуск завершается как ПУСТО, не запуская LLM. Поле
defer_when_diagnostics_nonempty задаёт простую зависимость от непустого массива
в JSON health_check. Когда один массив содержит несколько состояний, используйте
defer_when_diagnostics_match: в примере MERGE возвращается в pending только для
элементов со stage integration-review/legacy-integration-review, но проходит
для integration-merge-ready. Это даёт автоматический порядок REVIEW → MERGE
даже при более высоком приоритете MERGE и не расходует токены на ожидание. Если
профиль или checker сломан, gate fail-open: задача запускается обычным способом,
чтобы ошибка наблюдаемости не остановила полезную работу.
wake_when необязателен. Он указывает поле диагностики, которое означает, что
этапу уже есть что делать. После полезного (ГОТОВО) запуска и при фоновом
обновлении профиля PromptPilot переводит ближайший pending-запуск серии на
«сейчас». Один и тот же неизменившийся снимок будит серию только один раз:
НУЖЕН ЧЕЛОВЕК, НЕ СМОГ или другой результат не создаёт бесконечный цикл и не
тратит токены повторно. Новое состояние диагностики снова разрешает автозапуск;
ручной «Запустить сейчас» всегда остаётся доступен. Можно добавить key и
values, если готовность определяется только некоторыми состояниями элементов.
При ПУСТО, паузе серии или пустом поле пробуждения нет.
backlog_diagnostic_field заменяет приблизительный размер GitHub Search точным
массивом из health_check. Это особенно важно для REVIEW: поисковый запрос
намеренно не исключает stale-метку reviewed, а checker уже различает новый
HEAD, актуально проверенный HEAD и интеграционный handoff. Для REVIEW используйте
review_backlog (вся ожидающая работа), а wake_when оставьте на
review_candidates (только исполняемая сейчас работа). Для MERGE аналогично:
merge_candidates показывает весь backlog, а merge_executable содержит только
PR, который разрешено сливать прямо сейчас с учётом single-flight barrier.
Не исключайте reviewed из поискового запроса REVIEW: метка относится к старому
HEAD и после нового push может остаться. Канонический health_check отличает
актуальное ревью (reviewed_waiting_ship) от устаревшей метки и возвращает новый
HEAD в review_candidates. Для двухполосной схемы он также публикует
content_review_candidates, integration_owner, merge_candidates и
merge_executable: single-flight сериализует интеграцию, но не останавливает
содержательные ревью. Уже взятый содержательный REVIEW остаётся валиден, если
параллельно появился или сменил состояние несвязанный integration_owner;
завершение всё равно проверяет собственные HEAD и timeline lease этого PR.
Для REVIEW/MERGE повторяемые GitHub-проверки можно вынести из промпта в проектный CLI. PromptPilot не привязан ни к Claude, ни к Codex: он сам выполняет безопасный preflight до запуска провайдера и только затем решает, нужна ли модель. В очередь профиля добавляется:
"execution": {
"mode": "auto",
"stage": "review",
"command": [
"{python}", "-m", "promptpilot.project_pipeline",
"--config", "pipelinectl.json", "next", "{stage}"
],
"required_paths": ["pipelinectl.json"],
"probe_command": [
"{python}", "-m", "promptpilot.project_pipeline",
"--config", "pipelinectl.json", "capabilities"
]
}{python} заменяется интерпретатором запущенного PromptPilot, {stage} — id
этапа. Команда и относительные пути проверяются в working_dir серии без
вызова LLM, после чего command выполняется с таймаутом timeout_seconds
(по умолчанию 180 секунд). Режимы:
| Режим | Поведение |
|---|---|
auto |
empty/wait завершается без модели; audit/merge/cleanup получает короткий prompt с готовым lease; fallback или недоступный CLI использует исходный prompt/скилл |
tool |
CLI обязателен; при отсутствии, ошибке или fallback запуск завершается НУЖЕН ЧЕЛОВЕК без токенов |
skill |
всегда используется исходный prompt, как до появления pipelinectl |
Эффективный маршрут (auto → tool, auto → skill или blocked) виден в
дашборде и боте для каждого этапа. Это позволяет заметить незапланированный
fallback сразу, а не по суточному расходу токенов. Пустой REVIEW/MERGE
закрывается самим preflight с явной записью «провайдер не запускался».
Встроенный promptpilot.project_pipeline реализует общий protocol v1. Проект
задаёт repository, доверенный аккаунт, health-команду, base branch и required
checks в pipelinectl.json. Обычный REVIEW получает ровно один кандидат и
opaque lease; complete review повторно проверяет HEAD и два одинаковых полных
GraphQL snapshot, затем сам выполняет review → claim → label → completion.
Обычный CLEAN MERGE аналогично повторяет proof/labels/CI и использует merge с
точным SHA. Base-sync, carry, legacy re-ship, конфликт, recovery и третий круг
намеренно возвращают action=fallback: их продолжает полная проектная
процедура. Таким образом быстрый путь не ослабляет сложные гейты.
До необратимого merge быстрый путь публикует в PR неизменяемый
pp:merge-cleanup-intent: точный HEAD, hash review-proof и тела PR, а также
same-repository closing issues. Только после него повторяются proof/labels/CI и
отправляется compare-and-merge. Если процесс оборвался до ответа GitHub, новый
запуск по серверному MergedEvent различает открытый PR и уже выполненный merge.
Для влитого PR он продолжает action=cleanup: снимает in-work только с
закрытых связанных issues, идемпотентно завершает PLAN-handoff, снимает ship и
последним публикует pp:merge-cleanup-done. Поэтому crash после успешного merge
не вызывает второй merge и не оставляет промежуточные метки навсегда.
Новые protocol-комментарии больше не выглядят пустыми в GitHub: над скрытой
неизменяемой строкой есть короткая видимая подпись PromptPilot service marker.
Старые HTML-only markers продолжают распознаваться, поэтому их не нужно
редактировать и уже созданные review-proof не обесцениваются.
Claude и Codex получают одну и ту же команду и JSON. Различаются только тонкие
файлы обнаружения навыка (.claude/skills и .agents/skills); логика CLI и
lease от модели не зависят.
Статус в Web UI и боте читается так:
| Статус | Значение |
|---|---|
green — «работает штатно» |
Инварианты соблюдены, активных ожиданий нет |
yellow — «есть ожидания» |
Выполняется восстанавливаемая транзакция или нужен ход человека; это не поломка |
red — ошибка |
Worker не работает, запуск превысил timeout, серия оборвана либо нарушен проектный инвариант |
Причина и конкретные findings выводятся рядом со статусом. Поэтому жёлтый
индикатор сам по себе не требует останавливать очередь: сначала нужно прочитать,
какое именно ожидание он показывает.
Жёлтый статус означает ожидаемый handoff или ход человека; подробная причина видна в той же карточке.
У двух цепочек могут быть одинаковые этапы: добавьте проект в первую строку
промпта (MyProject - REVIEW, OtherProject - REVIEW) и используйте такое же
уникальное значение в series_contains. Профиль влияет только на аналитику;
интервалы, effort, пауза и временное ускорение принадлежат самим сериям.
Сейчас профиль и серии связываются по названию. Отдельного мастера «Создать всю цепочку из шаблона» пока нет: этапы создаются как повторяющиеся задачи, а потом собираются профилем. Это важное отличие от Workflow-оркестратора: workflow ведёт конечную разработку «исполнитель → аудитор → исправление», а расписание обслуживает бесконечные дежурные очереди TRIAGE/PLAN/FIX/REVIEW/MERGE.
Серия без запланированного вхождения помечается «оборвана» — она сама не
продолжится. Раньше в это состояние приводило любое падение: следующее
вхождение создавалось только после успешного прогона, поэтому один rate limit
тихо убивал дежурную задачу насовсем. Теперь расписание продлевается и после
failed, а в Telegram уходит «🔁 задача упала, но расписание продолжено —
следующий запуск в …». Отменённая серия не продлевается: отмена — это решение
человека, а не сбой.
Одно вхождение в очереди (pending/rate_limited) по-прежнему можно править
в карточке. Для постоянного изменения расписания используйте экран серии.
-
Claude Code и Codex — уровень
low|medium|high|xhigh|maxзадаётся полем и работает на двух уровнях:- у провайдера — «Эффорт рассуждений» в форме провайдера (⚙ Providers)
или
pp provider add ... --effort max. Это дефолт: с ним живут все задачи провайдера, в том числе этапы конвейеров; - у задачи — селект «Effort» рядом с «Model» в веб-мастере и кнопка «Эффорт» в разделе «Дополнительно» бота. Перекрывает провайдера на один прогон и наследуется следующими вхождениями повторяющейся задачи.
Пустое значение = «по умолчанию»: PromptPilot не передаёт override и уровень выбирает сам CLI. Для Claude используется
--effort, для Codex — одноразовый-c model_reasoning_effort=...; глобальная конфигурация агента не меняется. Если настройка уже вписана руками в шаблон команды или аргументы провайдера, выигрывает написанное руками. Остальным агентам effort не передаётся. - у провайдера — «Эффорт рассуждений» в форме провайдера (⚙ Providers)
или
-
OpenCode — два пути:
-
headless: флаг
--variant high|max|minimalвcmd-шаблоне (opencode run --variant max {prompt}); -
herdr-сессия: у TUI флага запуска нет, но variant задаётся через агент-профиль в
~/.config/opencode/opencode.jsonc:{ "agent": { "max": { "mode": "primary", "variant": "max" } } }и доп. аргументы провайдера
--agent max.
-
Заводить отдельных провайдеров под каждый уровень (claude-herdr и
claude-herdr-max) больше не нужно — но если такие уже есть, они продолжают
работать: эффорт провайдера просто становится их дефолтом.
Побочно: cmd-провайдер, собранный вокруг самого claude (клон встроенного
через «Изменить»), теперь отмечается как Claude-провайдер автоматически — ему
достаются скилы, выбор модели, --resume и эффорт. Раньше такой клон выглядел
«неизвестным CLI» и молча ронял всё перечисленное.
Минимальный плагин для herdr 0.7.5+ лежит в herdr-plugin/. Установка:
herdr plugin install ivanarama/PromptPilot/herdr-plugin # из GitHub
herdr plugin link /path/to/PromptPilot/herdr-plugin # локальная копияПлагин — тонкая обёртка над pp: сам PromptPilot он не ставит и без него не
работает. Если pp на машине нет (не в PATH, не в ~/.local/bin, модуль
promptpilot не импортируется), плагин не пытается запустить что-то наугад —
он показывает уведомление herdr со ссылкой на установку и пишет то же самое в
~/.promptpilot/startup.log.
Что даёт:
- автозапуск worker'а — при старте herdr-сервера плагин поднимает
pp worker, если тот ещё не запущен (уже работающий не трогается); - постановка задачи из панели — action «PromptPilot: поставить задачу»
(палитра действий,
herdr plugin action invoke enqueue --plugin promptpilotили клавишаctrl+alt+e) открывает popup: ввёл текст — задача ушла в очередь с рабочей директорией текущей панели.
После правок манифеста нужен herdr plugin unlink promptpilot + повторный
link.
По умолчанию агент работает прямо в указанной директории — то есть в том же
рабочем дереве, где сидишь ты. Галка 🌿 свой worktree (Web UI, шаг мастера
в боте, pp add -w, поле worktree: true в API) меняет это: задача получает
собственный чекаут репозитория на ветке pp/t<id>.
Что это даёт:
- твоё рабочее дерево остаётся нетронутым — незакоммиченные правки в безопасности, ветка не переключается;
- результат — ветка, а не грязный
git status: смотришь diff, вливаешь или выбрасываешь целиком; - retry после rate-limit возвращается на ту же ветку и в тот же чекаут, а не наслаивается на полуизменённое дерево;
- две задачи по одному репозиторию могут идти параллельно (см.
PP_CONCURRENCY).
Куда попадает чекаут:
| Исполнитель | Расположение |
|---|---|
| herdr-провайдеры | herdr создаёт worktree-workspace сам (herdr worktree create) — его видно в UI herdr, там же можно закрыть или удалить. Работает и на удалённой машине |
| обычные (headless) | <родитель репозитория>/.pp-worktrees/<repo>-t<id>, либо PP_WORKTREES_ROOT/<repo>/t<id> |
Путь и ветка сохраняются в задаче и показываются в Web UI, боте и pp status <id>
— вместе с короткой сводкой «коммитов: N, незакоммиченных файлов: M».
Нюансы:
- Директория обязана быть git-репозиторием. Не репозиторий — галка в Web UI недоступна, шага в боте нет, а задача, созданная через API, честно падает с ошибкой вместо тихого запуска в общем дереве.
- Игнорируемые файлы не переезжают. Свежий чекаут — без
.env,node_modules,venv. PromptPilot копирует в него то, что перечислено вPP_WORKTREE_COPY(по умолчанию.env) — и только те файлы, которые git действительно игнорирует. Остальное — сборка, установка зависимостей — на совести самой задачи. - Чекаут не удаляется после задачи — в нём результат. Исключение: если
агент не оставил ни коммитов, ни изменений, herdr-исполнитель убирает пустой
чекаут за собой. Ветка
pp/t<id>остаётся всегда. - На удалённых машинах worktree поддерживают только herdr-провайдеры: headless-команда по ssh выполняется в домашней директории и в чекаут просто не зайдёт — такая задача падает с явным сообщением.
PP_CONCURRENCY=1 (по умолчанию) — worker берёт задачи строго по одной, как
раньше. Больше единицы — задачи идут в пуле потоков, и очередь при этом
обходит всё, что столкнулось бы с уже работающей задачей:
- две задачи с одной рабочей директорией (на одной машине) одновременно не запустятся — второй агент подождёт, пока первый закончит;
- задачи со своим worktree не блокируют никого и ничего: у каждой свой чекаут — именно в этом сочетании параллелизм и раскрывается;
- задачи в одну и ту же открытую herdr-сессию (
herdr-session) сериализуются по сессии.
Захват задачи атомарный (BEGIN IMMEDIATE + условный UPDATE), так что гонки
за одну задачу нет. Предположение остаётся прежним: worker'ов — один
процесс; второй при старте вернёт running-задачи первого в очередь
(recover_running). Нужно больше параллелизма — поднимай PP_CONCURRENCY, а
не второй worker.
Раньше любой ненулевой код возврата означал failed. Но отказ в доступе
(API Error: 401/403/5xx, Failed to authenticate) и обрыв ответа на полуслове
(Connection closed mid-response, terminal_reason=api_error, ECONNRESET,
EAI_AGAIN) — это не вина задачи. Причём обрыв почти всегда приходится на конец
прогона: работа сделана и закоммичена, не доехало только последнее слово.
Теперь такая задача возвращается в очередь со статусом rate_limited и
обычным экспоненциальным backoff'ом, а в error пишется, что именно случилось.
Считается это против max_retries, так что навсегда сломанная среда всё-таки
доводит задачу до failed, а не крутит её вечно.
Что НЕ считается срывом среды: API Error: 400, падения тестов, отсутствующие
модули, ошибки компиляции — всё это провал задачи и честный failed. Коды
сокетов (ENOTFOUND и прочие) сверяются с учётом регистра: иначе
ModuleNotFoundError читался бы как обрыв связи.
PP_MIN_FREE_MB (по умолчанию 0 — проверки нет): если свободной памяти меньше,
worker не берёт новую задачу и говорит об этом один раз, а не каждый опрос.
Слоты PP_CONCURRENCY сами по себе ничего не знают о том, потянет ли машина ещё
один прогон — а на деле она уходит в своп, и следом API начинает отказывать. На
Linux читается MemAvailable, на Windows — GlobalMemoryStatusEx; там, где
померить нельзя, очередь не останавливается.
Прогон идёт, а видно, что копает не туда — не перечитал свежий комментарий, работает по старому описанию. Приписка к задаче добавляет пару фраз, которые пойдут в следующий прогон отдельным блоком после промпта, с прямым указанием, что это написано последним и главнее всего выше.
pp note 42 "перечитай комментарий, идёшь не туда"
pp note 42 # показать
pp note 42 --clear # убратьВ Web UI — поле «Дописать решателю» в развёрнутой карточке задачи; в списке у
такой задачи стоит пометка ✎ приписка.
Живёт при задаче, а не при прогоне — и это главное:
- идущий прогон её уже не увидит — она уйдёт в следующий прогон (после rate limit или срыва среды); если нужно применить прямо сейчас, проще пересоздать задачу с уже вписанной припиской;
- одноразовая: задача дошла до вердикта — приписка снимается, чтобы не лезть во все следующие прогоны;
- но срыв по вине среды или rate limit её сохраняет — та попытка приписку так и не увидела;
- в повторяющиеся копии задачи она не попадает: следующая копия создаётся из сохранённого промпта, а не из того, что получил конкретный прогон.
PP_VERDICT=1 дописывает к промпту просьбу закончить одной строкой:
ИТОГ: ГОТОВО | УЖЕ СДЕЛАНО | НУЖЕН ЧЕЛОВЕК | НЕ СМОГ | ПУСТО
Итог парсится и хранится у задачи, показывается в Web UI, боте и pp status.
Разница практическая: код возврата говорит только «процесс завершился», а
🟡 НУЖЕН ЧЕЛОВЕК в уведомлении сразу говорит, надо ли идти смотреть.
ПУСТО — тихий итог для повторяющихся задач: «проснулся по расписанию, делать
нечего». Такая задача завершается как обычно (итог в базе, виден в списках),
но уведомление в Telegram не отправляется — иначе дежурный робот,
просыпающийся каждые два часа, превращает бота в будильник. Ошибки (failed)
шлются всегда, независимо от итога.
Парсится он всегда, даже когда мы не просили — если агент сам закончил такой строкой, итог подхватится. Побеждает последнее совпадение: формат могли процитировать по дороге, а вердикт — это закрывающая строка.
Каждый прогон помечен в своём окружении переменной PP_TASK_ID, и метку
наследует процесс агента. Поэтому живой прогон опознаётся по процессу, а не
по нашим же записям — и переживает смерть worker'а.
При старте recover_running() возвращает в очередь зависшие running-задачи, но
теперь обходит те, чей агент всё ещё работает: раньше перезапуск worker'а
выдёргивал очередь из-под живых агентов, а второй процесс worker'а на старте
отбирал задачи у первого. Поиск идёт по /proc (Linux); там, где так нельзя,
поведение прежнее.
Дашборд стоимости считает деньги по результатам задач — а herdr-задачи стоимости не дают вообще: интерактивная сессия не отдаёт stream-json. Чем больше работы уходит в herdr, тем слепее был дашборд.
pp usage (и строка «Окно 5ч» в Web UI) закрывает дыру, разбирая транскрипты,
которые Claude Code пишет в ~/.claude/projects/**/*.jsonl — в том числе для
herdr-панелей:
За последние 5 ч — оценка по прайсу API:
всего: $18.40 26.1 млн токенов сессий: 4
задачи: $12.05
прочее: $6.35 (живая переписка ест то же окно лимита)
Почему именно так:
- Считаем по сообщениям, а не по кускам. В транскрипте каждое сообщение
записано целиком и с полным
usage— суммировать можно. В потоковом журнале headless-прогона наоборот: сообщение разбито на куски с частичным usage, и суммирование занижает выход в сотню раз. Поэтому для headless-задач по-прежнему берётся готовый итог из событияresult. - Лимит общий на человека, поэтому в счёт идут и твои собственные сессии — иначе на вопрос «сколько осталось» ответить нельзя.
- Задача узнаётся по
session_id, а если его нет — по своему worktree. Обычныйworking_dirв признаки не годится: его задача делит с человеком, и живая переписка засчитывалась бы задаче (проверено — так и было). - Кэш считается отдельно: чтение ×0.1 от входа, запись ×1.25. Без этого счёт мимо на порядок — кэш-чтений на порядок больше обычного входа.
- Деньги — оценка по прайсу API, а не счёт. На подписке они не списываются; полезны как мера того, куда уходит окно.
Окно скользящее — «последние 5 часов», а не доля выбранной нормы: точку сброса API называет только событием лимита, которого в транскриптах нет.
Задача с --dangerously-skip-permissions не спрашивает человека ни о чём —
значит, и остановить её диалогом нельзя. Останавливает PreToolUse-хук: он
видит команду до запуска и срабатывает независимо от режима разрешений.
Заблокированное — код 2 и причина в stderr, её читает модель; всё
заблокированное пишется в ~/.promptpilot/guard.log.
По умолчанию (PP_GUARD=auto) сторож включается ровно там, где больше некому
спросить: у задач с skip_permissions, и только для Claude Code провайдеров —
формат хука их. PP_GUARD=1 — всегда, PP_GUARD=0 — никогда.
Что запрещено «из коробки»: удаление корня и домашнего каталога, удаление
.git, форс-пуш и удаление веток на сервере, пуш в main/master (в том
числе git push origin HEAD из main — ветка проверяется отдельно, регулярка не
видит, что именно пушат), git worktree remove|prune (в чужих worktree идёт
работа других задач), sudo, запись на устройства, выключение машины.
Правила намеренно узкие: срабатывать они должны на катастрофе, а не на слове
sudo внутри сообщения коммита — поэтому команды опознаются по позиции в
строке, а main-fix не считается веткой main. Посмотреть и проверить:
pp guard --rules # какие правила действуют
pp guard "git push origin main" # что будет с этой командой (ничего не запускается)Дополнить или заменить — ~/.promptpilot/guard.json:
{"extend": [{"pattern": "npm\\s+publish", "reason": "Публикация — только руками"}]}{"replace": [...]} вместо extend отключает встроенные правила целиком.
Сломанный или нечитаемый файл оставляет встроенные правила в силе — сторож,
который сам себя разоружает из-за лишней запятой, хуже отсутствующего.
Ограничение: на удалённых машинах сторож не ставится — файл настроек с хуком лежит здесь, а путь к нему там ничего не значит.
Машина — отдельное измерение задачи: регистрируете машины, а те же самые провайдеры работают на любой из них.
Web UI: ⚙ Providers → «🖥 Машины» → имя + user@host → «Добавить и
проверить» — PromptPilot сам определяет по ssh, какие CLI есть на машине
(login-shell PATH). После этого в форме задачи появляется поле Машина
(💻 локально / vm2 / ...), и список провайдеров фильтруется по возможностям
выбранной машины. В боте — тот же шаг «Где выполнить задачу?».
Как выполняется: ssh host bash -lc '<команда провайдера>' — исполняемый
файл ищется в PATH удалённой машины, env-блок провайдера (например,
claude-z с GLM) пробрасывается, stream-json проходит насквозь — стоимость,
session_id и rate-limit-детекция работают как локально.
Требования: ssh по ключу (BatchMode), нужные CLI на машинах (и их PATH в
~/.profile). Ограничение: detached-задачи (фоновый запуск headless-процесса)
— только локально; headless-команда выполняется в домашней директории
удалённой машины.
Низкоуровневая альтернатива — обёртка scripts/pp-ssh-run <host> <cmd...> {prompt} как cmd-шаблон провайдера (полный контроль над командой и путями).
herdr-провайдеры (включая herdr-session) работают на машинах так же, как
локально: PromptPilot вызывает herdr CLI удалённой машины по ssh, а панель с
агентом живёт там — подключиться к ней можно командой
herdr --remote <host> (она есть в уведомлениях и в мета-строке результата).
- Проба машины сама находит herdr-провайдеров: нужен
herdrв login-shell PATH машины и CLI соответствующегоkind(claude,opencode, ...). Если агент установлен не в системный PATH (например, opencode в~/.opencode/bin), допишите путь в~/.profileмашины и нажмите «Перепроверить» — иначе провайдер в списке машины не появится. - herdr server на машине поднимается автоматически (
herdr serverв фоне), если он там ещё не запущен. - Работают все режимы: blocked-ожидание с уведомлением и кнопками, keep-pane,
detached,
herdr-session(выпадашка живых сессий показывает сессии выбранной машины). - Рабочая директория задачи должна существовать на целевой машине. Если её там нет (или поле пустое), herdr молча откроет панель в домашней директории машины — задача выполнится не там, где вы ждали.
- Уже зарегистрированные машины нужно один раз «Перепроверить» — старая запись
в
machines.jsonне знает про herdr-провайдеров.
Дальше A — главная машина: на ней PromptPilot (worker, Web UI, бот) и общая очередь; B — вторая машина, на которую уезжают задачи. На B не нужны ни Python, ни PromptPilot — только herdr и сам агент.
1. На B поставить herdr и агента. Тем же способом, что и на A; обновление —
herdr update. Версии herdr на A и B лучше держать одинаковыми: подключение
herdr --remote требует совместимого протокола.
2. Проверить PATH login-шелла на B. PromptPilot ходит на машину как
ssh B bash -lc '...', то есть видит PATH из ~/.profile/~/.bash_profile, а
не из ~/.bashrc (он читается только интерактивными шеллами). С машины A:
ssh B "bash -lc 'command -v herdr; command -v claude'"Обе строки должны напечататься. Если пусто — на B в ~/.profile:
export PATH="$HOME/.local/bin:$PATH" # herdr, claude
export PATH="$HOME/.opencode/bin:$PATH" # если нужен opencode3. Настроить ssh по ключу (с A на B).
ssh-keygen -t ed25519 # если ключа ещё нет
ssh-copy-id user@B
ssh -o BatchMode=yes user@B true && echo OKBatchMode обязателен: PromptPilot никогда не отвечает на запрос пароля. Если
ключ с парольной фразой — держите ssh-agent и следите, чтобы воркер видел
SSH_AUTH_SOCK.
4. Зарегистрировать машину. Web UI: ⚙ Providers → 🖥 Машины → имя vm2
user@B→ «Добавить и проверить». Или через API:
curl -s -X POST localhost:8420/api/machines \
-H 'Content-Type: application/json' -d '{"name":"vm2","host":"user@B"}'В ответе — список найденных провайдеров; там должны быть claude-herdr и
herdr-session. Если их нет — вернитесь к шагу 2 (herdr или агент не видны
login-шеллу) и нажмите «Перепроверить» (POST /api/machines/vm2/probe).
5. Поставить задачу. В форме задачи: Машина — vm2, провайдер —
claude-herdr, рабочая директория — путь, который существует на B. В боте
это шаг «Где выполнить задачу?». Дальше PromptPilot сам поднимет herdr server на
B (если не запущен), создаст вкладку pp-t<id>-*, стартует агента и отправит
промпт; упёрся в permission-диалог — задача останется running, а в Telegram
придёт уведомление с кнопками.
6. Подключиться к живой сессии на B. С машины A — herdr --remote user@B,
на самой B — просто herdr. Эта же команда приходит в уведомлении и в
мета-строке результата. Оставленные задачами сессии называются pp-kept-<id>;
отправить в такую сессию следующий промпт можно провайдером herdr-session
(выпадашка показывает сессии выбранной машины).
herdr есть и под Windows — нативный herdr.exe из preview-канала:
powershell -ExecutionPolicy Bypass -c "irm https://herdr.dev/install.ps1 | iex"WSL не нужен. PromptPilot определяет, на каком языке разговаривать с машиной,
сам — при добавлении/перепроверке машины и хранит это в machines.json полем
"shell": "posix" | "powershell" (в списке машин видно значком 🐧/🪟):
- posix — команда уходит как
ssh host bash -lc '<...>'; - powershell — как
ssh host powershell -EncodedCommand <base64/UTF-16LE>. Кодирование не украшательство: виндовый sshd сначала отдаёт командную строкуcmd.exe, и никакие кавычки через него живыми не проходят. В base64 нет символов, которые cmd трактует по-своему, поэтому скрипт доезжает байт в байт. Перед скриптом выставляется[Console]::OutputEncoding = UTF8— иначе JSON herdr'а и любая кириллица возвращаются кракозябрами.
Что нужно на Windows-машине:
herdr.exeи агент (claude) — в PATH пользователя, под которым ходит ssh (проверка:ssh winbox powershell -NoProfile -c "Get-Command herdr, claude").- OpenSSH Server (Параметры → Приложения → Дополнительные компоненты) с
входом по ключу; публичный ключ для админской учётки кладётся не в
~/.ssh/authorized_keys, а вC:\ProgramData\ssh\administrators_authorized_keys. - Шелл по умолчанию менять не надо — PowerShell вызывается явно; работает и
дефолтный
cmd.exe. - Порт, отличный от 22, задавайте алиасом в
~/.ssh/configна машине A — в поле «хост» можно писать имя алиаса.
Дальше всё как обычно: «Добавить и проверить» → в списке claude-herdr,
herdr-session → задача с этой машиной → подключение herdr --remote winbox.
Рабочая директория задачи — в виндовой записи (C:\work\proj).
Если на Windows-машине настроен Git Bash как shell для sshd, проба определит её
как posix — это не ошибка: такой машиной можно рулить обычным bash -lc.
Если что-то не так
| Симптом | Причина / что сделать |
|---|---|
| В списке машины нет herdr-провайдеров | ssh B "bash -lc 'command -v herdr'" пуст → PATH в ~/.profile (шаг 2), затем «Перепроверить» |
| «herdr server на машине … не запущен и не удалось его поднять» | зайдите на B и запустите herdr server руками; проверьте ssh B "bash -lc 'herdr status server --json'" |
| ssh спрашивает пароль | ключи не разложены или agent недоступен (шаг 3); на Windows-машине для админской учётки ключ кладётся в administrators_authorized_keys |
| Windows-машина определилась как posix и падает | на ней sshd отдаёт bash (Git Bash/WSL), но herdr стоит нативный — либо уберите bash из DefaultShell и перепроверьте машину, либо держите herdr там же, где bash |
| Задача отработала «не в том каталоге» | указанной рабочей директории нет на B — herdr молча ушёл в $HOME |
Задача висит в running |
агент в blocked ждёт человека: подключитесь (herdr --remote B) или подтвердите кнопкой в Telegram |
Бот (если запущен) наблюдает за всеми агентами herdr — не только за
задачами PromptPilot — на этой машине и на каждой зарегистрированной машине
с herdr-провайдерами — и присылает уведомление, когда агент заблокирован
диалогом или закончил работу незамеченным. В тексте уведомления видно, на
какой машине агент. Кнопки под уведомлением:
✅ Подтвердить (Enter) · 📺 Экран · ✍️ Ответить — работают и для
удалённых панелей, так что разблокировать агента на любой машине можно прямо
с телефона. Отключение: PP_HERDR_WATCH=0.
npm install -g @nothumanwork/cursor-agents-sdk
winget install BurntSushi.ripgrep.MSVCДобавь в .env:
CURSOR_API_KEY=crsr_your_key_here
Ключ: cursor.com/settings → API Keys. Первый запуск занимает ~60 секунд.
Скилы — команды (/skill-name) из ~/.claude/commands/, ~/.claude/skills/ и плагинов Claude Code. Доступны для всех провайдеров с supports_skills=True.
При выборе Claude-провайдера под полем промпта появляется кнопка ⚡ Skills. Нажми — откроется список скилов с описаниями. Выбор подставляет /skill-name в промпт.
Кнопка ⚡ Скилы в главном меню или команда /skills. Поддерживает глобальные скилы и скилы конкретного проекта (📁 Скилы проекта...).
GET /api/skills — все доступные скилы
GET /api/skills?provider=claude — только если провайдер поддерживает скилы
GET /api/skills?provider=claude&workdir=/path — + локальные скилы проекта
Минималистичный dark-theme UI на http://127.0.0.1:8420:
- Выбор провайдера и модели (дропдаун модели появляется автоматически для Claude Code провайдеров)
- Добавление задач с приоритетом и расписанием (Ctrl+Enter для отправки)
- Чекбокс
--dangerously-skip-permissions - ⚡ Skills — раскрывает список доступных скилов
- Фильтры по статусу, раскрытие деталей задачи
- Отмена (в т.ч. running-задач — процесс будет убит) и удаление задач
- Recur, per-task таймаут, галочка «🖥 оставить сессию открытой» (herdr)
- Кнопка ⏸ Pause воркера и панель стоимости по провайдерам
- ⚙ Providers — управление провайдерами: список с пометками (встроенный/кастомный, «не установлен», «скрыт»), добавление (команда-шаблон или herdr-сессия: агент, доп. аргументы, модели, env), «Изменить», «Скрыть/Показать», «Удалить» / «Сбросить к встроенному»
- В выпадашке провайдеров у формы задачи — только установленные и не скрытые
- Автообновление каждые 5 секунд
Доступ с другой машины — через SSH-туннель:
ssh -L 8420:127.0.0.1:8420 user@server # затем открой http://localhost:8420По умолчанию API открыт только на 127.0.0.1 и без авторизации. Если сервер
нужно открыть наружу (PP_HOST=0.0.0.0), задайте токен:
PP_API_TOKEN=длинный-случайный-токен
Браузер покажет стандартное окно логина (имя любое, пароль — токен); скрипты
ходят с заголовком Authorization: Bearer <токен> или curl -u x:<токен>.
Без токена запросы получают 401.
GET /api/tasks — список задач (?status=pending&limit=50)
POST /api/tasks — создать задачу (все поля TaskCreate, вкл. keep_pane, worktree)
GET /api/tasks/{id} — детали задачи
PATCH /api/tasks/{id} — отменить (для running — worker убьёт процесс) / сменить приоритет
DELETE /api/tasks/{id} — удалить
POST /api/tasks/{id}/reset — сбросить зависшую задачу в pending
GET /api/stats — статистика по статусам
GET /api/stats/costs — стоимость: today / week / total / by_provider
GET /api/stats/usage — расход за окно лимита по всем сессиям (?hours=5)
POST /api/tasks/{id}/note — дописать решателю ({"text": "..."}; пустой текст убирает)
GET /api/worker/status — paused + state/heartbeat_at/age_seconds/pid
POST /api/worker/pause|resume — пауза/возобновление воркера
GET /api/version — проверка обновлений (кэш 24 ч)
GET /api/providers — провайдеры (description, supports_skills, models, available, hidden, executor)
GET /api/providers/manage — полная информация для настроек (env-секреты маскированы)
POST /api/providers — создать/изменить провайдера
DELETE /api/providers/{name} — удалить кастомного провайдера
POST /api/providers/{name}/hide|unhide — скрыть/показать в списках
GET /api/skills — скилы (?provider=claude&workdir=/path)
GET /api/projects — проекты из PP_PROJECTS_ROOT ({name, path, git})
POST /api/workflows — создать draft workflow
POST /api/workflows/validate-setup — read-only preflight мастера создания
GET /api/workflows — список workflow (?status=draft&limit=50)
GET /api/workflows/{id} — детали workflow
PATCH /api/workflows/{id} — обновить draft-метаданные с expected_version
POST /api/workflows/{id}/start — создать первый новый раунд
POST /api/workflows/{id}/dispatch — поставить executor/reviewer task в очередь
POST /api/workflows/{id}/gate — записать результат ручного W1-гейта
POST /api/workflows/{id}/review — записать структурированный verdict аудитора
POST /api/workflows/{id}/human-input — решение человека/возобновление
POST /api/workflows/{id}/cancel — отменить workflow и связанные задачи
POST /api/workflows/{id}/sync — восстановить проекцию из состояния tasks
POST /api/workflows/{id}/history/import — импортировать старые раунды и факты
GET /api/workflows/{id}/rounds — раунды
GET /api/workflows/{id}/rounds/{round_id}/runs — запуски ролей
GET /api/workflows/{id}/events — append-only история (?after_seq=0)
GET /api/workflows/{id}/findings — текущие findings
GET /api/workflows/{id}/artifacts — зарегистрированные артефакты
| Переменная | По умолчанию | Описание |
|---|---|---|
PP_DATA_DIR |
~/.promptpilot |
Директория для БД |
PP_POLL_INTERVAL |
5 |
Интервал опроса очереди (сек) |
PP_TASK_TIMEOUT |
0 (без лимита) |
Глобальный таймаут задачи, сек; у задачи переопределяется индивидуально |
PP_BASE_DELAY |
60 |
Начальная задержка retry (сек) |
PP_MAX_DELAY |
3600 |
Максимальная задержка retry (сек) |
PP_MAX_RETRIES |
5 |
Макс. кол-во retry по умолчанию |
PP_CONCURRENCY |
1 |
Сколько задач worker выполняет одновременно |
PP_PIPELINE_SNAPSHOT_INTERVAL |
300 |
Интервал фоновых снимков активных pipeline-профилей, сек; 0 отключает |
PP_MIN_FREE_MB |
0 (без проверки) |
Не начинать новую задачу, если свободно меньше памяти |
PP_VERDICT |
0 |
Просить агента заканчивать строкой ИТОГ: ... (дописывается к промпту) |
PP_GUARD |
auto |
Сторож запретов: auto — при skip_permissions, 1 — всегда, 0 — выключен |
PP_WORKTREE_PREFIX |
pp/ |
Префикс ветки задачи с worktree (pp/t42) |
PP_WORKTREES_ROOT |
— | Куда класть чекауты; пусто = .pp-worktrees рядом с репозиторием |
PP_WORKTREE_COPY |
.env |
Игнорируемые git'ом файлы, которые копировать в новый чекаут (через запятую; пусто — не копировать) |
PP_DEFAULT_CLI |
claude |
Провайдер по умолчанию |
PP_HOST |
127.0.0.1 |
Хост веб-сервера |
PP_PORT |
8420 |
Порт веб-сервера |
PP_API_TOKEN |
— | Токен авторизации Web UI/API (пусто = без авторизации) |
PP_TG_TOKEN |
— | Токен Telegram бота |
PP_TG_ALLOWED_PHONES |
— | Разрешённые номера (через запятую) |
PP_TASK_PASSWORD |
— | Пароль для создания задач через бота |
PP_PROJECTS_ROOT |
— | Корневая папка проектов для быстрого выбора директории |
PP_CLAUDE_EXE |
из PATH | Путь к claude / claude.exe |
PP_GH_EXE |
стандартный путь/PATH | Путь к GitHub CLI; его каталог добавляется в окружение локальных агентов |
PP_GO_EXE |
стандартный путь/PATH | Путь к Go; его каталог добавляется в окружение локальных агентов |
PP_HERDR_BIN |
herdr |
Путь к herdr CLI |
PP_HERDR_KEEP_PANE |
0 |
Форсировать «оставить сессию» независимо от галочки задачи |
PP_HERDR_READ_LINES |
300 |
Сколько строк транскрипта читать как результат |
PP_HERDR_START_TIMEOUT_MS |
60000 |
Таймаут готовности агента при старте сессии |
PP_HERDR_WATCH |
1 |
herdr→Telegram мост (уведомления о blocked/done) |
PP_HERDR_WATCH_INTERVAL |
10 |
Интервал опроса агентов herdr (сек) |
PP_HERDR_RENOTIFY_COOLDOWN |
600 |
Антидубль blocked-уведомлений: повтор с тем же экраном в течение этого срока молчит (сек) |
| Статус | Описание |
|---|---|
pending |
В очереди |
running |
Выполняется |
completed |
Успешно завершена |
failed |
Завершена с ошибкой |
rate_limited |
Ожидает retry: rate limit или срыв по вине среды (см. ниже) |
cancelled |
Отменена |
promptpilot/
├── config.py — настройки, провайдеры, скилы, build_cmd
├── models.py — Pydantic-модели
├── db.py — SQLite (очередь, CRUD, планирование)
├── worker.py — воркер (subprocess → любой AI CLI)
├── cli.py — CLI (Click)
├── api.py — REST API (FastAPI)
├── bot.py — Telegram бот (python-telegram-bot)
├── tg_auth.py — авторизация по номеру телефона
└── static/
└── index.html — веб-интерфейс
start.ps1 — запустить все сервисы
stop.ps1 — остановить все сервисы
build.ps1 — собрать dist\pp.exe
pp.spec — конфиг PyInstaller
Воркер и сервер — два отдельных процесса, работающих с одной SQLite БД. По
умолчанию воркер выполняет задачи по одной; PP_CONCURRENCY>1 включает
параллельное выполнение (см. раздел «Параллельные задачи»).
MIT — см. LICENSE.



