CLI с набором самостоятельных команд для рутинных задач разработки — чистит код от мусора, чинит битые пути в package.json, проверяет примеры в доках на актуальность.

Четырнадцать самостоятельных команд редко вызываются по одной — вот четыре момента в работе над пакетом, где сразу несколько из них решают одну и ту же задачу.
Закомментированный код, забытый console.log, catch-блок без обработки и заметка «TODO: доделать» — обычный набор к моменту коммита, который жалко вычищать руками. strip-comments, console-strip, empty-catch и todo-report находят всё это за один прогон, не трогая то, что должно остаться.
Перед npm publish хочется быть уверенным в структуре пакета: ни одного мёртвого экспорта, ни одной забытой или фантомной зависимости, ни одного цикла импортов, ни одного пути в package.json, который ведёт в никуда. dead-exports, unused-deps, circular-imports и exports-doctor проверяют это за один проход.
Пример в README, скопированный когда-то из рабочего кода, и npm run-команда, упомянутая в CI-конфиге, легко расходятся с реальностью, пока пакет меняется, — и это первым замечает читатель или красная сборка, а не вы. readme-check типчекает примеры против настоящей сборки, scripts-check сверяет упомянутые скрипты с тем, что реально объявлено в package.json.
Три момента, где код был верным в момент написания и незаметно перестал быть таким: импорт с чуть другим регистром работает на Windows и падает на Linux в CI, тест остаётся зелёным, хотя source давно переименовали, а // @ts-ignore продолжает молчать, хотя ошибка под ним уже другая. case-check, orphan-tests и stale-ts-ignore ловят именно такой дрейф.

strip-comments вычищает //, /* */, /** */ и <!-- --> — включая .vue-файлы, где <script> разбирается тем же парсером, а <!-- --> внутри <template> — построчным сканом. --keep-jsdoc оставляет /** */ прямо над экспортируемым объявлением, чтобы не терять подсказки в IDE.

console-strip убирает console.log/console.debug/debugger, оставленные по ошибке — console.warn/console.error по умолчанию не трогаются, это часто легитимное логирование, а не отладочный мусор. Удаляется только вызов, который является отдельным выражением целиком — часть более сложного выражения просто перечисляется отдельно.

dead-exports находит именованные экспорты, которые нигде в проекте не импортируются, при этом понимает разницу между «неиспользуемый внутри репозитория» и «неиспользуемый вообще» — точки входа пакета исключены по умолчанию, а --strict при необходимости проверяет и их.

case-check находит импорты, регистр которых не совпадает с реальным именем файла на диске — то, что Windows и macOS прощают, а Linux в CI — нет. Проверяется каждый сегмент пути, включая алиасы из tsconfig.json; --fix переписывает специфайер на реальный регистр.

exports-doctor резолвит каждый путь, заявленный в package.json (main/module/types/bin/exports), против того, что реально лежит на диске — включая случай, когда рантайм резолвится штатно, а типы для того же пути нигде не объявлены.

readme-check вытаскивает ts-блоки кода из README/доков и реально прогоняет их через TypeScript Compiler API против собственной сборки пакета — включая self-reference импорт по опубликованному имени. Ничего не выполняется, только компилируется.

unused-deps находит зависимости в package.json, на которые нет ни одного импорта, и зеркально — «фантомные» зависимости, которые реально используются, но нигде не объявлены. Знает про обычные способы использования без прямого импорта: вызов из scripts, упоминание в конфиг-файле.

circular-imports находит циклы импортов в собственном коде — то, что в ESM иногда молча даёт undefined в рантайме. Показывает каждый цикл полной цепочкой, а цикл из одних только import type скрыт по умолчанию — это не рантайм-баг.

empty-catch находит catch-блоки, которые ничего не делают с ошибкой или делают настолько мало, что она по факту проглатывается — например, тело только из console.* без throw и без записи в переменную. Комментарий внутри блока освобождает находку от отчёта.

todo-report собирает TODO/FIXME/HACK-комментарии со всего проекта в один список — file:line плюс сам текст заметки, даже если она обёрнута на несколько строк. --max <n> поднимает планку с «падать на любой находке» до заданного числа, чтобы уже накопленные заметки не блокировали сборку.

scripts-check сверяет scripts из package.json с README и .github/workflows — упомянутый, но не объявленный скрипт — это реально сломанная ссылка, а объявленный, но нигде не упомянутый — более слабый сигнал. Зарезервированные npm-скрипты жизненного цикла исключены.

orphan-tests находит тестовые файлы, у которых пропал исходник — переименовали или удалили source, а тест остался зелёным и ничего реального больше не проверяет. Надёжна при простом соглашении об именовании: X.test.ts рядом с X.ts или в соседней __tests__.

stale-ts-ignore находит // @ts-ignore, который больше ничего не подавляет — код починили, а комментарий остался и молча прячет уже другую ошибку. Прогоняет тайпчек всего проекта дважды и сравнивает, появилась ли на месте директивы новая диагностика.

devtoolz ui запускает локальный веб-интерфейс: формы, таблицы и превью вместо флагов, файловый браузер для выбора папок, находки рядом с кодом, граф циклов импортов. Изменения файлов подтверждаются по одному, с резервной копией и отменой. Сервер слушает только 127.0.0.1 под одноразовым токеном.