npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

packer-commander

v0.4.1

Published

TUI-раннер npm-скриптов монорепозитория: живые статусы задач, логи, поиск и пайплайны GitLab

Readme

packer-commander

TUI-раннер npm-скриптов монорепозитория — в духе mc: две колонки, живые статусы задач, логи рядом со списком, поиск по логу и пайплайны GitLab.

┌ Задачи ──────────────────────┬ build • режим: Watch • /core • 15 ──────────┐
│ ▶ Команды                    │ apps/core/analytics (ssmm-core-analytics)   │
│   build                      │ apps/core/auth (ssmm-core-auth)             │
│   serve                      │ apps/core/payment (ssmm-core-payment)       │
│ ● Запущено (2)               │                                             │
│   ● apps/api build     0:12  │                                             │
│ ✓ Завершено (1)              │                                             │
│   ✗ libs/core test   exit 1  │                                             │
│ ⚙ Пайплайны master (2)       │                                             │
│   ● #5 running               │                                             │
└──────────────────────────────┴─────────────────────────────────────────────┘
 Запущено: 2  Готово: 0  Ошибок: 1 │ Tab/←→ колонки  Enter выбрать  ? помощь

Запуск

Без установки:

npx packer-commander

Глобально:

npm i -g packer-commander

Дальше packer-commander или короткое pc в любой папке репозитория.

Что делает

  • Находит корень проекта сам. Поднимается от текущей папки: монорепо с workspaces важнее ближайшего package.json, дальше .git не уходит. Запуск из apps/api видит весь репозиторий.
  • Папки воркспейсов берёт из workspacesapps/*apps. Нет workspaces — пробует apps, libs, packages, services; нет и их — работает с одиночным пакетом (запуск без --workspace).
  • Показывает статусы живыми. Таймеры и статусы обновляются сами, вывод не смешивается с интерфейсом.
  • Держит лог рядом. Курсор на команде — справа её сервисы, курсор на задаче — её лог, курсор на пайплайне — его джобы.
  • Ищет по логу/, дальше n и N по совпадениям, с подсветкой. Работает и по трассе джобы GitLab.
  • Никаких новых зависимостей, кроме blessed.

Клавиши

| Клавиша | Что делает | |---|---| | Tab, , | переключить колонку | | , | курсор в списке или скролл лога | | Enter | команда → её сервисы, сервис → запуск, задача → лог, пайплайн → джобы, джоба → трасса | | Пробел | режим запуска: Обычный → Watch → В терминале | | s, S | остановить выбранную задачу / все; на пайплайне — отменить его | | d | забыть завершённую задачу | | i | детали задачи | | t | показать или скрыть таймстемпы | | y | скопировать лог или трассу в буфер обмена (без разметки) | | z | лог на весь экран без рамок — чтобы выделять мышью только его | | / | поиск по логу, Escape — снять | | p | запустить пайплайн на текущей ветке (спросит подтверждение) | | r | пересканировать воркспейсы и обновить пайплайны | | Backspace | назад | | ? | все клавиши | | q, Ctrl+C | выход; при живых задачах спросит подтверждение |

Как скопировать часть лога

Терминал выделяет мышью прямоугольник поперёк всего экрана, поэтому в двух колонках в выделение неизбежно попадает левое меню. Два способа обойти:

  • z — лог разворачивается на весь экран без рамок и меню. Выделяется только текст лога. Повторное z возвращает две колонки, состояние прокрутки и поиска сохраняется.
  • y — весь лог (или трасса джобы) уходит в буфер обмена без разметки: сначала пробуется системная утилита (clip, pbcopy, xclip), затем OSC 52, который работает и через ssh. Если включены таймстемпы по t, они попадут в копию.

Полезно и то, что в обычном режиме между рамкой и текстом есть отступ — Ctrl+click по src/app.ts:12:5 в VS Code открывает файл, а не тащит внутрь ссылки.

Каталог проектов

Если в текущей папке лежат несколько проектов — как /opt на сервере, — слева появляется секция 📦 Проекты: первая строка сам корень, дальше подпапки, в которых есть compose-файл, makefile, *.sh или package.json со скриптами. Курсор на проекте — справа плоский список запускаемого, отсортированный по типу:

▸    контейнеры 12/14
make up
make down
sh   check.sh
sh   checkmig.sh
npm  build

Буквы фильтруют весь список сразу: che находит check.sh и checkmig.sh. Enter на строке контейнеров уводит в список контейнеров этого проекта, Esc возвращает. Enter на make, скрипте или npm открывает меню:

  • Запустить (задачей, с логом) — обычная задача: лог рядом, поиск по /, стоп по s с убийством дерева процессов.
  • Запустить в терминале — TUI сворачивается, команда получает настоящий терминал. Нужно для всего интерактивного: задачи идут со stdin: ignore, и скрипт с вопросом Continue? [y/N] в задаче просто повиснет.

Перед запуском показывается точная команда и рабочая папка, и спрашивается подтверждение — всегда, без списка «безопасных» имён: отличить check.sh от clear-docker.sh по имени нельзя.

Сканируется один уровень вниз: рекурсия по /opt уперлась бы в тома docker и логи. Цели make читаются из файла, make -qp не вызывается — он разбирает всё окружение. Скрипты запускаются как bash <файл>: бита +x может не быть, а sh не понимает bash-измов.

Состояние контейнеров опрашивается только для проекта под курсором — 35 проектов не превращаются в 35 вызовов docker compose ps. r пересканирует проекты и перечитает состояние.

Docker Compose

Если рядом с проектом есть docker-compose.yml, слева появляется секция 🐳 Compose со строкой проекта, а справа — его контейнеры: состояние, статус, пометка про откат. Буквы фильтруют список, Enter открывает меню действий:

  • Логиdocker compose logs -f --tail=200 <сервис> как обычная задача: поиск по /, копирование по y, режим на весь экран по z.
  • Обновитьpull и up -d одной задачей с одним логом. Ненулевой код на первом шаге отменяет второй, и в логе видно, где встало.
  • Образы и откат — список образов из локального кеша и текущий digest тега из реестра GitLab. Выбор → подтверждение → при необходимости pull нужного digest, локальный ретег и up -d --no-deps. Compose-файл не меняется.
  • Рестарт, Стоп — то же с подтверждением.

Первая строка списка — весь проект: обновление всего сразу и логи всех сервисов.

Всё, что меняет состояние docker, показывает точные команды и спрашивает подтверждение. Читаются ps, images, inspect и реестр — без спроса, раз в 5 секунд, пока курсор стоит на секции; r перечитывает немедленно.

Про откат честно. Compose ссылается на изменяемый тег, поэтому откат делается локальным ретегом: после него тег указывает не на то, что в реестре, и сервис помечается ⇤ локально переопределён. Следующее «Обновить» осознанно уедет вперёд на свежий образ, и пометка снимется. Постоянного закрепления digest в compose-файле нет.

Откуда берутся образы для отката. Из локального кеша docker: после нового пуша прежний образ остаётся лежать с тегом <none>, и именно он нужен для возврата. Реестр GitLab историю тега не хранит — он отдаёт только текущий digest, поэтому в списке он справочный. Практический вывод: docker image prune -a на проде стирает возможность откатиться.

Как работает стоп

Раннер запускает npm run ..., а npm запускает уже свой процесс — node, nest, vite, — и порт держит именно он. Поэтому убить один pid недостаточно: npm умрёт, а внук останется слушать порт, и следующий запуск упадёт с EADDRINUSE.

s снимает всё дерево:

  • POSIX — задача стартует лидером своей группы процессов (detached), стоп посылает SIGTERM всей группе по отрицательному pid, через 5 секунд — SIGKILL.
  • Windows — сигналов нет, поэтому taskkill /PID <pid> /T, а через 5 секунд то же с /F.

S останавливает все живые задачи, выход по q предлагает сделать это же. Если TUI умрёт аварийно (не через q), задачи на POSIX останутся жить как осиротевшие — они в своей группе процессов; ищи их по lsof -i :порт.

Пайплайны GitLab

Секция включается, если в окружении есть токен:

export GITLAB_TOKEN=glpat-...

Scope read_api хватает для просмотра пайплайнов, джоб и трасс. Для запуска (p) и отмены (s) нужен api. Хост и путь проекта берутся из git remote get-url origin, ветка — из текущего HEAD. Токен читается только из окружения, никуда не пишется и не логируется. Нет токена — секция объясняет, чего не хватает, остальное работает как обычно.

Опции

packer-commander [опции]

  --cwd <путь>     откуда искать корень проекта (по умолчанию текущая папка)
  --roots a,b      папки воркспейсов вручную вместо чтения "workspaces"
  --self-check     напечатать корень, папки и число пакетов, не поднимая TUI
  -v, --version    версия
  -h, --help       справка

--self-check удобен, когда непонятно, что раннер вообще нашёл:

$ npx packer-commander --self-check
root=/repo roots=apps,libs packages=43 commands=4

Требования

Node.js 20 и новее. Нужен интерактивный терминал не меньше 80×24 — под пайпом или в CI раннер честно откажется работать с кодом 1.

Публикация

Публикует GitHub Actions по тегу — вручную npm publish запускать не нужно:

npm version patch -m "chore: версия %s"
git push --follow-tags

Workflow .github/workflows/publish.yml прогоняет тесты, сверяет тег с версией в package.json и публикует через trusted publishing (OIDC): токен в секретах не хранится, пакет получает provenance-подпись.

Однократная настройка на стороне npm: в настройках пакета на npmjs.com → Trusted publishers → добавить GitHub Actions с владельцем Slowmoney, репозиторием packer-commander и файлом workflow publish.yml.

Если trusted publishing по каким-то причинам не подходит, альтернатива — granular automation token в секрете NPM_TOKEN и NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} на шаге npm publish; тогда id-token: write и npm install -g npm@latest не нужны.

Разработка

npm test

53 теста на node:test: ядро (индекс воркспейсов, сборка команд npm, конвертер ANSI → теги blessed, кольцевой буфер лога, автомат статусов задач, клиент GitLab) и CLI. Интерфейс проверяется дымовым прогоном на заглушке blessed.

Лицензия

MIT