RunnerMonitor -- легковесное TUI- и CLI-приложение для мониторинга и управления self-hosted CI runner'ами. Оно сделано для рабочей станции, где одновременно есть несколько GitHub Actions runner'ов на Windows и WSL/Linux, с перспективой переезда runner'ов на отдельную машину в локальной сети.
Приложение объединяет локальное состояние runner'а, статус GitHub, очередь workflow, принадлежность к проекту и безопасные команды управления.
- Автоматически находит GitHub Actions runner'ы в настроенных Windows, WSL и Linux каталогах.
- Показывает проект/репозиторий, к которому относится runner.
- Объединяет локальное состояние службы/процесса со статусом GitHub через
gh api. - Показывает busy-статус, количество queued workflow и stale queued workflow.
- Позволяет запускать, останавливать, перезапускать, чистить, удалять и перенастраивать runner'ы.
- Защищает опасные операции dry-run режимом, проверкой busy-состояния и явным подтверждением.
- Дает project-scoped команды, которые может запускать Codex или оператор перед push/ожиданием CI.
- Поддерживает сохраненные SSH-профили удаленной runner-машины.
- Оставляет OneDev как будущий provider-oriented этап.
- Go 1.26+
- Charmbracelet Bubble Tea для TUI
- Charmbracelet Bubbles для таблицы и поля ввода
- Charmbracelet Lip Gloss для оформления терминала
- GitHub CLI (
gh) для данных GitHub Actions - Windows PowerShell для Windows Services
- WSL и Linux systemd для Linux runner'ов
- SSH для доступа к удаленной runner-машине
-
Go 1.26+
-
Авторизованный GitHub CLI с доступом к нужным репозиториям:
gh auth status
-
Windows PowerShell для локальных Windows runner'ов.
-
WSL для Linux runner'ов на текущей машине.
-
gitдля определения текущего GitHub-проекта.
Скачайте готовый Windows-пакет из GitHub Releases:
RunnerMonitor-v0.1.0-windows-x64.zip
Распакуйте ZIP и запустите TUI:
powershell -NoProfile -ExecutionPolicy Bypass -File .\runner-monitor.ps1Или соберите из исходников локально:
Собрать exe и создать локальный config рядом с exe:
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\build.ps1
.\runner-monitor.ps1 --show-configОткрыть TUI:
.\runner-monitor.ps1Один раз вывести inventory:
.\runner-monitor.ps1 --onceПровести аудит runner'ов:
.\runner-monitor.ps1 --auditЗапустить runner'ы для текущего GitHub-проекта:
.\runner-monitor.ps1 --start-currentRunnerMonitor читает настройки из runner-monitor.json, который лежит рядом с
исполняемым файлом. Для локальной сборки по умолчанию это:
C:\Repos\RunnerMonitor\bin\runner-monitor.json
Создать или посмотреть config:
.\runner-monitor.ps1 --init-config
.\runner-monitor.ps1 --show-config--show-config маскирует wslSudoPassword как <set> или <empty> и никогда
не печатает реальное значение.
Пример config:
{
"projectsRoot": "C:\\Repos",
"windowsRunnerRoots": [
"C:\\Runners"
],
"wslRunnerRoots": [
"/home/gsv777/Runners"
],
"linuxRunnerRoots": [
"/opt/Runners",
"/srv/Runners"
],
"wslSudoPassword": ""
}Поля:
| Поле | Назначение |
|---|---|
projectsRoot |
Корень проектов для --project, например C:\Repos. |
windowsRunnerRoots |
Windows-каталоги runner'ов для поиска и безопасного удаления папок. |
wslRunnerRoots |
WSL-каталоги runner'ов для поиска. |
linuxRunnerRoots |
Linux-каталоги runner'ов для отдельной Linux runner-машины. |
wslSudoPassword |
Значение sudo-пароля для WSL fallback. Хранить только в app-local config. |
Для тестов или особых запусков можно переопределить путь:
$env:RUNNER_MONITOR_CONFIG = "D:\Temp\runner-monitor.json"Не коммитьте настоящий runner-monitor.json и sudo-пароли.
Команды внутри TUI:
| Команда | Описание |
|---|---|
refresh |
Обновить локальное и GitHub-состояние runner'ов. |
| Стрелки | Выбрать строку runner'а. |
start [N] |
Запустить runner N или выбранную строку без номера. |
stop [N] |
Остановить runner N или выбранную строку без номера. |
restart [N] |
Перезапустить runner N или выбранную строку без номера. |
force-stop [N] |
Остановить даже если GitHub показывает busy. Использовать осторожно. |
force-restart [N] |
Перезапустить даже если GitHub показывает busy. Использовать осторожно. |
clear [N] |
Безопасно очистить idle runner N или выбранную строку. |
clear idle |
Очистить все idle runner'ы. Busy runner'ы пропускаются. |
auto-clear on |
Включить safe cleanup после refresh. |
auto-clear off |
Выключить auto cleanup. |
remove [N] |
Dry-run отвязки runner'а от GitHub. |
remove [N] confirm |
Выполнить отвязку runner'а после подтверждения. |
delete [N] confirm |
Отвязать runner и удалить безопасную папку runner'а. |
logs [N] |
Открыть логи runner'а. |
connect remote NAME |
Открыть удаленный RunnerMonitor TUI по SSH. |
q, quit, exit, Esc, Ctrl+C |
Выйти из TUI. |
Таблица адаптируется к размеру терминала. На узком окне скрываются низкоприоритетные колонки, а ключевые поля project/runner/status/busy/queue остаются выровненными.
Inventory и аудит:
.\runner-monitor.ps1 --once
.\runner-monitor.ps1 --auditУправление runner'ами по репозиторию:
.\runner-monitor.ps1 --start-repo SGribanov/DeltaG
.\runner-monitor.ps1 --stop-repo SGribanov/DeltaG
.\runner-monitor.ps1 --restart-repo SGribanov/DeltaGУправление runner'ами для текущего Git-проекта:
.\runner-monitor.ps1 --start-current
.\runner-monitor.ps1 --stop-current
.\runner-monitor.ps1 --restart-currentБезопасная очистка:
.\runner-monitor.ps1 --clear-repo SGribanov/DeltaG
.\runner-monitor.ps1 --clear-current
.\runner-monitor.ps1 --clear-idle
.\runner-monitor.ps1 --clear-runner ideabox-runnerОтключение автозапуска:
.\runner-monitor.ps1 --disable-autostartConfig:
.\runner-monitor.ps1 --init-config
.\runner-monitor.ps1 --init-config --overwrite-config
.\runner-monitor.ps1 --show-configУдаленная машина:
.\runner-monitor.ps1 --configure-remote runnerbox
.\runner-monitor.ps1 --connect-remote runnerboxУдаление runner'а по умолчанию работает как dry-run:
.\runner-monitor.ps1 --remove-runner ideabox-runner --repo SGribanov/IdeaBox
.\runner-monitor.ps1 --remove-runner ideabox-runner --repo SGribanov/IdeaBox --confirm
.\runner-monitor.ps1 --remove-runner ideabox-runner --repo SGribanov/IdeaBox --confirm --delete-folderДобавление runner'а настраивает существующую подготовленную папку runner
distribution. --project -- это имя папки проекта внутри projectsRoot.
.\runner-monitor.ps1 --add-runner runner-monitor-win --project RunnerMonitor --runner-folder C:\Runners\SGribanov-RunnerMonitor\runner-monitor-win --labels "self-hosted,Windows,X64"
.\runner-monitor.ps1 --add-runner runner-monitor-win --project RunnerMonitor --runner-folder C:\Runners\SGribanov-RunnerMonitor\runner-monitor-win --labels "self-hosted,Windows,X64" --confirm --replaceС установкой и запуском службы после настройки:
.\runner-monitor.ps1 --add-runner runner-monitor-win --project RunnerMonitor --runner-folder C:\Runners\SGribanov-RunnerMonitor\runner-monitor-win --labels "self-hosted,Windows,X64" --confirm --replace --serviceПосле переезда runner'ов на отдельную машину RunnerMonitor запускается на этой машине, а локально к нему можно подключаться по SSH.
Настроить или обновить профиль:
.\runner-monitor.ps1 --configure-remote runnerboxПромпт спросит:
- имя remote-профиля;
- SSH host/alias;
- OS хоста:
windowsилиlinux; - путь к RunnerMonitor на удаленной машине;
- путь проекта по умолчанию.
Открыть сохраненный remote TUI:
.\runner-monitor.ps1 --connect-remote runnerboxЭквивалентная Windows SSH-команда:
ssh -t runnerbox "powershell -NoProfile -ExecutionPolicy Bypass -File C:/Repos/RunnerMonitor/runner-monitor.ps1"Запустить runner'ы на удаленной машине перед push/ожиданием CI:
ssh runnerbox "cd C:/Repos/DeltaG; powershell -NoProfile -ExecutionPolicy Bypass -File C:/Repos/RunnerMonitor/runner-monitor.ps1 --start-current"Linux host пример:
ssh -t runnerbox "cd /opt/RunnerMonitor && ./runner-monitor"
ssh runnerbox "cd /srv/DeltaG && /opt/RunnerMonitor/runner-monitor --start-current"Remote-профили хранятся отдельно от app-local runner config в пользовательском
каталоге config как RunnerMonitor\remote-hosts.json.
Предпочтительная текущая структура:
C:\Runners\<owner>-<repo>\<runner-name>
/home/gsv777/Runners/<owner>-<repo>/<runner-name>
Для будущего выделенного Linux host:
/opt/Runners/<owner>-<repo>/<runner-name>
/srv/Runners/<owner>-<repo>/<runner-name>
Миграция папок runner'ов ведется отдельно и только по одному runner'у за раз. Не перемещайте и не удаляйте busy runner без явного подтверждения.
- Busy runner'ы защищены по умолчанию.
- Удаление и reprovisioning по умолчанию dry-run.
- Удаление папки требует
--delete-folderи разрешено только внутри настроенных safe runner roots. - Cleanup удаляет безопасные generated файлы вроде содержимого
_workи installer archives, но сохраняет регистрацию и бинарники runner'а. --show-configникогда не печатает реальный WSL sudo password.- Локальные config-файлы и секреты нельзя коммитить.
Тесты:
go test ./...Сборка:
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\build.ps1Перегенерировать иконки:
uv run --with pillow python .\scripts\generate-icon-assets.py
go run github.com/akavel/rsrc@v0.10.2 -arch amd64 -ico .\assets\runner-monitor-hourglass.ico -o .\cmd\runner-monitor\runner-monitor_windows_amd64.sysocmd/runner-monitor/ Точка входа приложения
internal/app/ Discovery, GitHub integration, lifecycle, TUI, cleanup
scripts/ Build, migration, cleanup и automation helpers
assets/ Иконки песочных часов
reports/ Runner audit reports
research/ Долгоживущие project insights
tasks/ Планы и статусы по GitHub issues
См. CONTRIBUTING.md. Любые изменения должны сохранять модель безопасности: никаких незащищенных destructive runner operations, никаких секретов в git и никаких silent-изменений runner registration. Также соблюдайте Code of Conduct.
См. SECURITY.md. Не публикуйте в issues секреты, runner tokens, sudo passwords и приватные hostnames.
RunnerMonitor распространяется по MIT License.