Линтеры и форматтеры для кода с активным использованием ИИ, которые держат стиль в порядке
Линтеры и форматтеры для кода с активным использованием ИИ помогают командам прекратить стильовые дрейфы, сохранять читаемость pull request-ов и облегчать проверку вывода ИИ.

Почему код, написанный ИИ, уходит вразнос
Инструменты ИИ копируют стиль, который рядом. Если в одном файле используют одинарные кавычки, в другом — двойные, а в третьем смешивают оба варианта, модель посчитает, что все это нормально. Она обычно повторяет паттерн, ближайший к тому коду, который меняет.
Это кажется малозначительным. На самом деле — нет. Два корректных ответа могут отличаться пробелами, порядком импортов, переносом строк и расположением функций. Когда такие различия появляются в каждом предложении, кодовая база начинает «шевелиться».
Ревьюеры чувствуют это первыми. Небольшой pull request превращается в просмотр изменений кавычек, сдвинутых пустых строк и перетасованых импортов без видимой причины. Ревью должно сосредоточиться на логике, крайних случаях и безопасности. Шум от стиля крадёт это время.
Косметические правки также мешают заметить логические изменения. Исправление бага может быть трёхстрочным, но если файл одновременно переформатировали и переставили блоки, ревьюеру придётся просмотреть сорок строк изменений, чтобы быть уверенным.
Проблема усиливается, когда команда использует ИИ постоянно. Один человек принимает завершающие запятые, другой — нет. Один prompt переписывает хелпер, потому что рядом лежит файл с другим паттерном. К пятнице спор уже не о поведении, а о вкусе.
Поэтому форматирование и линтинг важны с самого начала. Без фиксированного стиля каждый prompt становится маленьким голосованием за то, как должен выглядеть код. Небольшой набор жестких правил делает код предсказуемым, и ревьюеры могут сосредоточиться на том, что действительно может сломать продакшен.
Что должен делать небольшой набор обязательных правил
Хороший набор правил предотвращает повторяющиеся споры в каждом PR. Если люди всё ещё спорят о кавычках, порядке импортов или переносах строк вручную, правила слишком расплывчаты. Инструменты должны решать эти детали автоматически.
Держите правила короткими. Новый участник команды должен прочитать их за несколько минут и понять, зачем каждое правило нужно. Если правило требует длинных оправданий, скорее всего ему не место в принудительных настройках.
Разделите обязанности форматтера и линтера. Форматтер отвечает за внешний вид: пробелы, отступы, ширину строки, завершающие запятые и похожие выборы. Линтер должен ловить код, который сломан, рискован или может ввести в заблуждение — неиспользуемые переменные, затенённые имена, небезопасные async-паттерны или оставленный debug-вывод. Когда обязанности смешиваются, команда получает шум вместо ясности.
Обычно работает простая настройка:
- Поместите выборы стиля в форматтер.
- Оставьте правила линтера для багов, рискованных паттернов и пары общих привычек.
- Автофиксите то, что можно, до ревью.
- Блокируйте только те правила, которые команда готова соблюдать каждый раз.
Запишите исключения до развёртывания. Большинство команд уже знают, где дефолты мешают: тесты, генерируемый код и скрипты миграций. Если ждать первого заблокированного PR, правила покажутся случайными и раздражающими.
С ИИ в цепочке узкая цель помогает. Модели быстро копируют последовательность, но и быстро копируют несогласованность. Короткий набор правил сокращает шум в диффах, косметические комментарии и повторяющиеся споры о стиле. Если настройка работает, о ней никто почти не говорит после первой недели.
Выберите один форматтер и придерживайтесь его
Когда каждый человек и каждый ИИ-инструмент форматируют код чуть по-разному, pull request-ы заполняются шумом. Один форматтер во всём репозитории быстро это сокращает.
Выберите форматтер, подходящий для вашего основного стека, и прекратите споры о стиле. Пусть он решает пробелы, кавычки, завершающие запятые и переносы строк. Эти выборы не требуют человеческого ревью.
Это особенно важно при помощи ИИ. Ассистент часто копирует то, что видел в последнем файле, даже если тот файл использует устаревшие паттерны. Форматтер возвращает вывод к единому виду до ревью.
Практичный форматтер должен покрывать большинство файлов, которые команда редактирует, запускаться из командной строки, работать в редакторах с минимальной настройкой и давать одинаковый результат в CI.
Последовательность важнее, чем поиск идеального инструмента. Если ваша JavaScript-команда использует Prettier, применяйте его везде, где это имеет смысл. Если Go-код форматируют с помощью gofmt, не навязывайте личные предпочтения поверх него. Лучший форматтер тот, о котором никто не думает после первой недели.
Запускайте его одинаково на всех машинах. Зафиксируйте версию, добавьте одну команду проекта и используйте её же в CI. Это убирает классическую проблему, когда код выглядит нормально локально, но меняется после пуша.
Не добавляйте ручных правил стиля, которые конкурируют с форматтером. Если он переносит длинную строку, ревьюерам не стоит просить её «развернуть». Если он предпочитает двойные кавычки, никто не должен вручную просить одинарные. Такие комментарии тратят время и дают ИИ смешанные сигналы.
Оставьте ручное ревью для того, что форматтер не может оценить: запутанные имена, рискованная логика, мёртвый код и отсутствующие тесты. Форматтер отвечает за визуальную согласованность. Люди — за качество кода.
Добавьте правила линтера, которые ловят реальные проблемы
Код, написанный ИИ, часто компилируется, но всё равно оставляет мелкие ошибки. Видны устаревшие импорты, неиспользуемые хелперы, переименованные функции, которые потеряли ссылку, и переменные, с которыми ничего не происходит. Линтер должен ловить это ещё до того, как ревьюер будет тратить время на правки вручную.
Начните с правил, которые окупаются каждую неделю. Хорошие первые выборы: неразрешённые импорты, неиспользуемые импорты, неиспользуемые переменные, затенённые имена, простые async-ошибки и базовые синтаксические или типовые ошибки, которые может обнаружить ваш язык. Эти проверки просты и практичны. Они останавливают баги и редко порождают долгие споры.
Короткий список обычно выглядит так:
- Сломанные или неразрешённые импорты
- Неиспользуемые импорты и переменные
- Дублирующиеся или затенённые имена
- Простые синтаксические, async- или логические ошибки, которые способен определить ваш язык
Избегайте правил, которые в основном отражают вкусы. Если правило вновь и вновь вызывает споры в PR, не включайте его в первую версию. Форматтер уже покрывает большую часть стилевых вопросов. Линтер должен фокусироваться на том, что сломано, рискованно или явно мёртво.
Небольшой пример показывает, почему это важно. Ассистент переписывает fetchUser() в getUser(), обновляет половину файла и забывает старый импорт сверху. Код может выглядеть нормально на беглый взгляд. Линтер за секунды найдёт неиспользуемый импорт и пропавшую ссылку. Это экономит ревьюеру время поиска по файлу.
Не делайте каждое новое правило «ошибкой» с первого дня. Начните с предупреждений на неделю и посмотрите на реальные PR. Если правило постоянно ловит настоящие ошибки, оставьте и ужесточите. Если люди ставят disable-комментарии или получают ложные срабатывания, уберите правило. Сгенерированный код часто попадает в странные краевые случаи, поэтому спокойный набор правил лучше умного, но шумного.
Внедряйте изменения поэтапно
Внедрения рушатся, когда команды меняют слишком многое сразу. Чтобы настройка прижилась, сделайте первый шаг скучным и строгим.
Начните с файлов, которые ИИ пишет чаще всего. Для большинства команд это обработчики API, React-компоненты, тесты, скрипты и небольшие утилиты. Не беритесь за весь репозиторий сразу. Начните там, где PR меняют код каждый день.
Чистый rollout обычно выглядит так:
- Согласуйте, что новый код в самых нагруженных папках следует форматтеру и правилам линтера.
- Выполните форматирование всего репозитория одним коммитом.
- Включите небольшой набор правил линтера.
- Исправьте текущие ошибки до того, как CI начнёт блокировать новые нарушения.
Один коммит с форматированием по всему репозиторию важнее, чем кажется. Если пропустить его, каждое последующее изменение смешает реальную работу со странностями по пробелам, кавычкам и переносам строк. Ревьюеры быстро устают, и история blame становится грязной.
Держите набор правил намеренно коротким. Огромный пресет вызывает споры, локальные переопределения и случайные исключения. Короткий список запомнить проще, и ИИ-инструменты быстрее к нему адаптируются.
Небольшая команда может сделать это за неделю. В первый день — отформатировать репозиторий. Во второй — убрать ошибки линтера в самых активных папках. После этого — дать CI проверять изменённый код, пока остальное не подтянется.
Если в команде есть fractional CTO или инженерный лидер, доверьте одному человеку коммит с очисткой и переключение CI. Комитеты затягивают процесс, и стиль снова уйдёт вразнос, пока люди спорят о табах, кавычках и запятых.
Как это выглядит в небольшой команде
Команда из трёх человек быстро выпустила простой API. Один писал хендлеры, другой — тесты, а основатель использовал ИИ для черновиков, когда очередь была длинной. Они двигались быстро, но каждый PR выглядел немного по-разному.
Код обычно работал. Проблема была в деталях. Один черновик группировал импорты по имени пакета, другой смешивал локальные и внешние импорты, третий оставлял неиспользуемые импорты. В одних хендлерах использовался userId, в других — user_id, имена тестов прыгали от коротких ярлыков до полных предложений. Всё это не ломало продакшен, но замедляло ревью.
Через две недели команда изменила одну привычку. Они выбрали один форматтер и запускали его при каждом коммите. Это прекратило споры о кавычках, отступах, запятых и переносах одной командой. Затем добавили шесть правил линтера и оставили их достаточно узкими, чтобы запомнить.
Их правила покрывали порядок импортов, неиспользуемые импорты, единый стиль именования переменных и функций, затенённые имена, забытые промисы и debug-логи в PR. Этот небольшой набор решил большую часть проблем. Они не пытались поймать всё возможное.
Следующая волна PR ощутимо изменилась. ИИ всё ещё писал черновики, но вывод приходил в одинаковом виде. Комментарии ревью перестали крутиться вокруг стиля. Люди начали обсуждать, вернул ли хендлер правильный статус код, покрывает ли тест краевой случай и понятна ли ошибка.
В этом и смысл. Эти инструменты не делают код умнее. Они делают его достаточно последовательным, чтобы люди могли сосредоточиться на логике.
Команда заметила изменения быстро:
- PR стали короче, потому что исчезли чисто форматирующие правки.
- Время ревью уменьшилось примерно с 25 до 10 минут.
- Новички стали копировать паттерны с минимальным наставничеством.
- Тесты стало легче просматривать при отладке багов.
Небольшой набор правил не замедлил их. Он сократил пространство для дрейфа ИИ и вернул внимание команды к важным вещам.
Ошибки, которые создают ещё больше шума
Самый быстрый способ сделать настройку непопулярной — превратить её в проект по очистке вместо защитного барьера. Когда каждый PR переписывает половину файла, люди перестают доверять инструментам и начинают их игнорировать.
Обычная ошибка — подключить огромный пресет в первый же день. Большие пресеты кажутся безопасными, но обычно несут мнения, с которыми команда не согласилась. Тогда ИИ добавляет код в одном стиле, пресет требует другой, и каждый ревью превращается в спор о вкусе.
Смешение двух форматтеров в одном репозитории ещё хуже. Один инструмент меняет кавычки, другой — переносы строк, и оба трогают одни и те же файлы. Сохранил файл, закоммитил, и следующая проверка снова его меняет. Этот цикл тратит время и учит людей игнорировать шум форматирования.
Сломанные билды вызывают ту же проблему. Если CI внезапно падает из-за 700 старых предупреждений, никто не увидит реальную проблему. Новый баг окажется среди стены старых жалоб, и команда либо добавит массовые игнор-правила, либо отключит проверку совсем.
Лучший rollout — скучный по замыслу. Начните с одного форматтера и короткого набора линтера для реальных проблем: неразрешённые импорты, случайное затенение, очевидный мёртвый код, простые async-ошибки и unsafe any, если команда за это переживает. Исправляйте старые файлы пакетами или включайте правило только для изменённых строк и новых файлов.
Плохие правила также живут слишком долго. Если одно и то же правило выключают в каждом третьем PR, оно не помогает. Уберите его, сузьте или измените порог.
Небольшой пример показывает проблему. Команда подключила популярный ESLint-пакет, Prettier и ещё один форматтер, потому что одному разработчику нравится его вывод. Следующий AI-помощник затронул 18 файлов, но реально логики поменялись только в двух. Ревьюеры тратили 20 минут на сортировку форматирования и работы. Через неделю разработчики стали вставлять disable-комментарии, чтобы пройти проверку.
Такой шум — самосозданный. Держите набор правил коротким, один форматтер — главным, и делайте CI строгим только там, где команда реально может следовать правилам.
Короткий чеклист для слияния
Pull request должен рассказывать простую историю. Ревьюеры должны сначала заметить изменение поведения, а не тратить время на пробелы, кавычки или порядок импортов.
Держите проверку мерджа достаточно короткой, чтобы её реально использовали:
- Форматтер уже запустился локально или в CI. Никто не должен исправлять пробелы, переносы или запятые вручную прямо перед мержем.
- Дифф в основном показывает изменения поведения. Если половина PR — стиль, вынесите форматирование в отдельный коммит или перезапустите форматтер на меньшей области.
- Линтер не показывает неиспользуемых импортов, мёртвых переменных или очевидных ошибок.
- Каждое обязательное правило имеет объяснение на простом языке. Если участник не может объяснить правило в одном предложении, ему, вероятно, не место в наборе по умолчанию.
Второй пункт важнее, чем многие думают. Ассистенты ИИ часто переписывают соседние строки, трогая одну функцию. Код может продолжать работать, но ревью замедляется, потому что людям приходится сканировать шумный дифф, чтобы найти реальное изменение.
Четвёртый пункт помогает поддерживать здоровье набора правил. Малые команды попадают в беду, добавляя правила после каждого раздражающего PR. Через месяц никто уже не помнит, зачем правило нужно, и люди начинают ставить ignore-комментарии, чтобы получить зелёную галочку.
Хорошая привычка для мёрджа — скучна специально. Форматтер запустился. Линтер молчит. Дифф достаточно мал, чтобы его можно было прочитать за один проход. Тогда ревьюер может сосредоточиться на именовании, крайних случаях и том, нужен ли вообще этот код.
Если в вашей команде снова и снова виден стильовой шум в PR, не добавляйте ещё пять правил. Урежьте список, применяйте базовое, и сделайте диффы снова читабельными.
Что делать дальше
Начните с сокращения правил, а не с их добавления. Большинство команд уже имеют достаточно проверок, чтобы держать код читаемым. Больший беспорядок обычно создают старые правила, которые порождают шум, споры о вкусе или заставляют править мелочи в каждом PR.
Откройте текущую конфигурацию и пройдитесь по ней строчку за строчкой. Задайте простой вопрос к каждому правилу: предотвращает ли это баги или порождает споры о стиле? Если правило в основном вызывает комментарии о пробелах, переносах или вкусе имен, уберите его. Когда ИИ трогает много файлов сразу, короткий набор линта часто лучше длинного.
Для большинства команд эта настройка должна быть скучной. Она автоматически исправляет стиль, ловит реальные ошибки и не мешает в остальное время.
Проверьте её на одном активном проекте, прежде чем распространять шире. Выберите репозиторий с регулярными PR, а не побочный проект, за которым никто не следит. Через неделю или две посмотрите на изменения: стало ли меньше комментариев о стиле, меньше перезапусков CI и меньше споров перед мержем.
Напишите короткую заметку для команды о привычках при работе с ИИ. Одной страницы достаточно, если она отвечает на четыре вопроса: какой форматтер запускается автоматически, какие правила линтера блокируют мерж, когда AI-сгенерированный код требует ручной доработки и что ревьюерам можно не замечать, потому что это уже покрывает tooling.
Эта заметка важнее, чем кажется. ИИ-инструменты быстро копируют локальные паттерны. Если ваш репозиторий, CI и привычки ревью говорят одно и то же, стильовой шум быстро падает.
Если нужен внешний обзор, Oleg Sotnikov at oleg.is работает со стартапами и малыми командами над рабочими процессами разработки с ИИ, CI/CD и поддержкой Fractional CTO. Быстрый просмотр ваших инструментов и процесса ревью часто достаточно, чтобы сократить раздутый набор правил до того, что команда действительно будет соблюдать.
Держите первый проход коротким. Удалите шум, протестируйте на одном проекте, напишите заметку для команды и посмотрите, что всё ещё создаёт трение. Когда мусор убран, оставшиеся проблемы обычно легко увидеть.
Часто задаваемые вопросы
Почему ИИ постоянно меняет кавычки, импорты и пробелы?
Потому что модель подражает коду вокруг неё. Если рядом файлы смешивают кавычки, группы импортов или стили именования, инструмент считает все это допустимым и копирует то, что видел последним.
Нужны ли и форматтер, и линтер?
Да. Форматтер отвечает за внешний вид (отступы, ширина строки, запятые и т. п.), а линтер — за ошибки и рискованные паттерны. Такое разделение сохраняет фокус ревью на логике, а не на стиле.
Сколько правил стоит взять вначале?
Начинайте с малого. Выберите только те правила, которые команда действительно будет соблюдать всегда. Для многих команд достаточно форматтера и пары проверок линтера на неиспользуемые импорты, неиспользуемые переменные, затенение имён, сломанные импорты и простые ошибки с async.
Что должно первым блокировать pull request?
Блокируйте проверки, которые предотвращают реальные баги или явный шум. Хорошие первые кандидаты: неразрешённые импорты, неиспользуемые импорты, мёртвые переменные, затенённые имена, оставшиеся debug-логи и простые ошибки с промисами.
Нужно ли форматировать весь репозиторий перед включением правил?
Да. Сначала выполните один коммит с форматированием всего репозитория, а уже затем включайте строгие проверки. Это уберёт будущие смешанные изменения стиля в пулл-реквестах.
Что делать со старыми файлами, которые уже падают по линту?
Не пытайтесь всё исправить за неделю. Сначала почистите самые активные папки, затем дайте CI проверять изменённые файлы или новый код, пока остальное не подтянется.
Можно ли использовать больше одного форматтера в одном репозитории?
Нет. Один форматтер должен владеть репозиторием или, по крайней мере, каждым языковым участком с чёткой границей. Два инструмента, переписывающие одни и те же файлы, будут конфликтовать и создавать шум в диффах.
Как сделать AI-сгенерированные pull request-ы компактными и удобными для чтения?
Зафиксируйте версию форматтера, выполняйте одну и ту же команду локально и в CI, и просите участников форматировать перед ревью. Если дифф всё ещё шумный, вынесите косметические правки в отдельный коммит.
Какие файлы стоит считать исключениями?
Обычно исключают генерируемый код, некоторые скрипты миграций и отдельные шаблоны тестов. Зафиксируйте эти исключения заранее, чтобы никто не удивлялся заблокированному мерджу.
Когда маленькой команде стоит обратиться за внешней помощью по этой настройке?
Когда ревью затягиваются, CI тонет в шуме или команда постоянно спорит о стиле — пора привлекать помощь. Fractional CTO или инженерный лидер может сократить набор правил, упорядочить rollout и вернуть проверкам эффективную роль.