Когда проект растёт, вопрос «сколько у нас кода» возникает снова и снова: для оценки объёма, сравнения модулей, отчёта или проверки, что в репозиторий не попал сгенерированный каталог. tokei считает файлы, строки, код, комментарии и пустые строки по языкам, делает это очень быстро и умеет отдавать JSON. Ниже — практическая работа с ним, включая места, где цифры обманывают.
Установка
В Fedora, Arch и openSUSE пакет есть в репозитории; в Debian и Ubuntu сначала проверьте наличие через apt-cache policy. Если готового пакета нет или нужна свежая версия, ставьте через Cargo.
apt-cache policy tokei
cargo install tokei
sudo dnf install tokei
sudo pacman -S tokei
Сборка из исходников требует Rust и нескольких минут компиляции. JSON поддерживается в обычной сборке; флаг --features all добавляет только CBOR и YAML.
Первый запуск
Запустите утилиту в корне проекта. По умолчанию она обходит текущий каталог рекурсивно и печатает таблицу: язык, число файлов, всего строк, код, комментарии, пустые строки. Внизу — итоговая строка.
cd ~/projects/example
tokei
tokei src tests
tokei --sort code
Столбец Code — это строки с кодом, а не все строки файла. Comments учитывает и строчные, и блочные комментарии, включая вложенные; строки с кодом и комментарием одновременно считаются кодом. Blanks — пустые строки. Сумма трёх столбцов даёт Lines.
Вложенные языки показываются с отступом: например, блоки кода внутри Markdown считаются отдельно, а строка (Total) показывает сумму без двойного счёта. Это важно для документации: иначе Markdown с примерами раздувал бы статистику. Для сравнения модулей запускайте утилиту от корня репозитория, чтобы относительные пути в отчёте были одинаковыми.
Исключения
tokei уважает .gitignore, .ignore и собственный .tokeignore. Каталоги target, node_modules и vendor обычно перечислены в .gitignore и потому не попадают в отчёт. Дополнительные шаблоны задаются флагом --exclude, синтаксис совпадает с gitignore.
tokei . --exclude vendor --exclude '*.min.js'
printf 'vendor/\n*.min.js\n' > .tokeignore
tokei . --exclude 'package-lock.json' --exclude '*.d'
tokei .
Кавычки обязательны: без них оболочка раскроет *.min.js по текущему каталогу. Если нужно посчитать зависимости или скрытые файлы, используйте --no-ignore и --hidden, но помните, что цифры тогда перестанут отражать собственный код проекта.
Фильтры и сортировка
Флаг --types (короткий -t) оставляет только указанные языки, --sort сортирует по столбцу, а --files показывает статистику по каждому файлу. Список поддерживаемых языков и расширений выводит --languages.
tokei --types Rust,Python
tokei --files --sort code | head -20
tokei --hidden
tokei --languages | head -30
Сортировка по code быстро показывает самые крупные модули, а по lines — самые длинные файлы. Для ревью полезнее смотреть на файлы с большим числом строк: именно там обычно концентрируется сложность.
JSON и автоматизация
Для CI и отчётов используйте JSON. Он содержит статистику по языкам, список файлов и вложенные языки; формат может меняться между версиями. Сохраняйте результат как артефакт и сравнивайте с предыдущей сборкой, а не с абсолютным порогом, который быстро устаревает.
tokei --output json > tokei.json
jq -r 'to_entries[] | "\(.key)\t\(.value.code)"' tokei.json | sort -k2 -nr | head
jq -e '.Rust.code >= 50000' tokei.json
wc -c tokei.json
Пример выше печатает код по языкам и завершает проверку с ошибкой, если Rust стал меньше заданного порога. Такой порог — грубый, но полезный способ заметить случайное удаление каталога или неудачный merge. В реальном CI сравнивайте два отчёта и падайте только на резком падении.
Конфигурация
Файл tokei.toml или .tokeirc ищется в текущем каталоге, домашнем каталоге и каталоге конфигурации. В нём задаются ширина вывода, сортировка, список языков и трактовка docstring как комментариев.
columns = 100
sort = "code"
types = ["Rust", "Toml", "Markdown"]
treat_doc_strings_as_comments = true
Локальный конфиг может неожиданно повлиять на вывод в другом проекте, если вы запускаете утилиту из домашнего каталога. Для CI задавайте параметры явно через флаги или храните конфиг в корне репозитория. Переменная NO_COLOR=1 отключает цвета в логах.
Что может исказить цифры
- Сгенерированный код и миграции: они существуют, но не отражают ручной труд.
- Минифицированные файлы: одна строка может содержать целую библиотеку.
- Lock-файлы
package-lock.jsonиCargo.lock: JSON и TOML считаются как код. - Каталоги зависимостей, если вы отключили ignore-файлы.
- Файлы
.d, которые tokei принимает за язык D. - Docstring: по умолчанию они могут считаться кодом, а не комментариями.
- Неизвестные расширения: строки просто не попадут в отчёт.
tokei . -v 2>&1 | head -20
tokei . --files --sort lines | head -20
tokei . --no-ignore --exclude '*.json'
Флаг -v показывает неизвестные расширения, а --files помогает найти файл-гигант. Если проект использует нестандартные расширения, добавьте их в конфигурацию или переименуйте файлы: tokei не обязан угадывать.
tokei, cloc и scc
cloc — зрелый инструмент на Perl с огромной базой языков, но медленнее на больших репозиториях. scc написан на Go, тоже быстрый и добавляет оценки сложности. Определения комментариев и строк у них различаются, поэтому абсолютные числа между инструментами не совпадают.
Выберите один инструмент и следите за динамикой. Для быстрого локального взгляда хватит tokei; для отчёта, где нужна оценка сложности, посмотрите scc; для экзотических языков проверьте cloc. Сравнивать «мой проект больше, чем ваш» по разным утилитам бессмысленно.
Чек-лист
- Утилита установлена и версия известна.
- Каталоги зависимостей и сборки исключены.
- Lock-файлы и минифицированный код не учитываются.
- Вложенные языки проверены, двойного счёта нет.
- JSON-вывод работает и сохраняется в CI.
- Конфиг лежит в репозитории, а не только в домашнем каталоге.
Итог
tokei решает узкую задачу — быстро и аккуратно посчитать код по языкам. Он не измеряет качество, сложность или производительность команды, и относиться к его цифрам как к KPI не стоит. Зато для оценки размера проекта, поиска раздутых файлов и автоматической проверки репозитория инструмент удобен, предсказуем и почти не требует настройки.