Первые две недели: всё работает, и это опасно

Первые дни с Cursor на реальном проекте ощущаются как читерство. Просишь сгенерировать REST-эндпоинт с валидацией, пагинацией и обработкой ошибок, получаешь рабочий код через 40 секунд. CRUD, который раньше занимал полдня вместе с тестами, закрывается до обеда. Скорость настолько неприличная, что начинаешь коситься на коллег: они ещё не пробовали или просто молчат?

Cursor здесь реально хорошо справляется. Он индексирует локальный репозиторий и держит контекст: если у тебя есть UserService с определёнными соглашениями по именованию и обработке исключений, новый OrderService получится в том же стиле. Не надо каждый раз объяснять структуру проекта с нуля. На небольших кодовых базах это работает хорошо, пока весь граф зависимостей помещается в контекстное окно с запасом.

И вот тут прячется проблема.

Код проходит ревью. Логика читается нормально, стиль соблюдён, тесты зелёные. Коллеги апрувят пулл-реквесты быстрее, чем обычно, потому что поверхностно код выглядит аккуратно. Но потом приходит SonarQube, и в отчёте появляются когнитивная сложность 24 там, где допустимо 15, дублирование логики валидации в трёх местах, которые AI честно скопировал из разных частей репозитория, и пара мест с потенциальными null-разыменованиями, которые статический анализ ловит, а глаз на ревью пропускает.

Это ранний сигнал того, что происходит на самом деле. AI оптимизирует на "выглядит правдоподобно и компилируется", а не на "хорошо укладывается в архитектуру". На маленьком проекте это незаметно, потому что цена каждого такого решения мала. Но решения накапливаются.

IDE с зелёными индикаторами и быстрой генерацией кода на маленьком проекте

На старте всё выглядит идеально: тесты зелёные, скорость генерации впечатляет, проект умещается в голове.

Что такое вайбкодинг и почему термин не просто мем

В феврале 2025 года Андрей Карпатий написал твит, где назвал свой подход к работе с кодом "vibe coding": ты описываешь задачу на естественном языке, смотришь на результат, принимаешь его и двигаешься дальше. Без глубокого разбора того, что именно сгенерировала модель. Термин прижился мгновенно, потому что назвал то, что уже делали тысячи людей, но без слова для этого.

Это не то же самое, что AI-assisted разработка в широком смысле. Когда ты используешь Copilot для автодополнения или просишь GPT объяснить чужой код, ты всё равно остаёшься в режиме ревью: читаешь, оцениваешь, переписываешь. Вайбкодинг снижает этот порог до минимума. Ты доверяешь выходу модели достаточно, чтобы не разбирать каждую строку. Карпатий буквально написал: "I mostly ignore the code" ("я в основном игнорирую код"). Вот граница.

Почему это работает, я видел сам: за выходные можно собрать работающий прототип, не думая об архитектуре. Нужен скрипт, который парсит CSV и строит график? Три промпта, пять минут. Нужна простая форма с отправкой на email? Аналогично. Скорость реальная.

Но продакшен это другая история. Там нет "вайба". Там есть баги в продакшен-логике, которые ты не увидел, потому что не читал код. Есть SQL-запрос без индексов, который ляжет под нагрузкой. Есть обработка ошибок, которую модель "забыла", потому что ты не уточнил в промпте. Прототип и продакшен решают разные задачи, и инструмент подхода должен меняться вместе с задачей.

Термин не мем именно потому, что он зафиксировал реальный сдвиг в том, как люди взаимодействуют с кодом. Не "помоги мне написать", а "напиши, я посмотрю, окей". Это новая позиция разработчика. И у неё есть цена.

Месяц второй: метрики начинают врать в вашу пользу

Velocity в джире растёт. PR-ы закрываются быстрее. Стендапы стали короче, потому что блокеров меньше. Все довольны, и именно в этот момент надо насторожиться.

SonarQube не врёт, но его показания легко проигнорировать, когда остальные цифры зелёные. По опыту команд, обсуждавших это на Habr в начале 2026 года, число static analysis warnings при активном вайбкодинге растёт быстро. Команды это видели, но списывали на "технический шум" и обещали разобраться в следующем спринте.

Главный маркер деградации в этот период: duplicate lines.

Cursor (и большинство других LLM-инструментов) решает задачу самым буквальным способом. Видит паттерн, который работает в одном месте, копирует его туда, где нужно решить похожую задачу. Не создаёт абстракцию. Не думает о переиспользовании. Просто копирует. Через шесть недель ты обнаруживаешь, что одна и та же логика валидации разбросана по восьми местам с микроотличиями, которые никто не документировал.

Цикломатическая сложность растёт по-другому. Тихо, по одному пути за раз. Функция, которая в конце первого месяца имела три-четыре пути выполнения, к концу второго легко набирает двенадцать-пятнадцать. Не потому что логика усложнилась. А потому что каждый новый edge case LLM закрывал отдельным if, не рефакторя существующую структуру. Ты просишь "добавить обработку пустого массива" и получаешь ещё одну ветку поверх уже ветвистого дерева.

Исследование Janea Systems зафиксировало интересный эффект: LLM оптимизирует legacy-код так, что результат выглядит чище визуально, но часть таких изменений ломается на граничных случаях. Код становится более читаемым и менее надёжным одновременно. Ревьюер видит опрятный diff и апрувит. Баг прилетает через три недели с продакшна.

Когда считают ROI для команд, которые перешли на AI-ассистированную разработку, фиксируют одно и то же: прирост velocity реальный, его не надо преуменьшать. Но качественный долг накапливается параллельно и с сопоставимой скоростью. Это не значит, что инструмент плохой. Это значит, что velocity без метрик качества показывает только половину картины. Причём более приятную половину.

Проблема не в том, что команды не замечают сигналы. Они их видят. Просто решение "разобраться потом" в условиях высокого velocity кажется разумным. Спринт закрыт, менеджер доволен, следующий тикет уже ждёт. Технический долг пока не болит.

Пока.

Два графика: скорость растёт, но рядом параллельно накапливаются предупреждения о техдолге

Velocity ползёт вверх, а счётчик предупреждений растёт с той же скоростью, и команда пока не замечает второй кривой.

Архитектурный потолок: почему Cursor теряется на больших кодовых базах

Cursor хорошо себя чувствует в небольших файлах. До 500 строк в файле, до 20 тысяч строк активного кода в проекте, инструмент работает плавно, контекст актуален, подсказки точные. Но когда репозиторий начинает расти, вылезает системная проблема.

RAG-индексация, на которой держится понимание кодовой базы в Cursor, начинает подтягивать нерелевантные куски. AI не "видит" весь проект разом, он видит то, что попало в контекстное окно прямо сейчас. И если ты пишешь новый сервис, он не знает, что аналогичная логика уже живёт в трёх других модулях.

Вот реальный симптом, который я наблюдал в нескольких командах в 2026 году:

// Cursor сгенерировал это в user.service.ts
function validateUserEmail(email: string): boolean {
  const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return re.test(email);
}

// И это же — в auth.service.ts, неделей позже
function checkEmailFormat(email: string): boolean {
  const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return pattern.test(email);
}

// Два файла, два имени, одна логика. SonarQube поймал. Cursor не заметил.

Два разных разработчика, две разные сессии, одна и та же регулярка. Cursor сгенерировал оба варианта честно, без ошибок, просто не видел, что первый уже существует. Это не баг инструмента. Это его архитектурное ограничение.

Проблему усугубляет то, как люди обычно работают с Cursor: открыл файл, написал фичу, закрыл. Никакого глобального взгляда. AI следует структуре, которую уже видит в текущем контексте, и только ей. Архитектурные решения он не принимает. Он воспроизводит паттерны из того, что перед ним.

В бенчмарке начала 2026 года, где сравнивали Cursor и Claude Code на задачах с реальными репозиториями, картина получилась показательная: Claude Code лучше справлялся с multi-file рефакторингом, где надо было отследить цепочку зависимостей через 15-20 файлов. Cursor выигрывал в inline-скорости, в режиме "пишу прямо сейчас", в одном файле, с минимальным переключением контекста. Разные инструменты под разные задачи.

Для команд, которые строят что-то серьёзнее пет-проекта, это означает конкретное решение: либо жёстко поддерживать архитектурную документацию и явно подтягивать её в контекст перед каждой сессией, либо переключаться на инструменты с более глубоким пониманием графа зависимостей для рефакторинга. Cursor как IDE-помощник для скорости набора кода, отличный. Как архитектурный советник на 100k+ строках, нет.

Карта модулей с дублирующейся бизнес-логикой в разных частях большого проекта

Одна и та же валидация заказа живёт в четырёх местах: AI честно скопировал её каждый раз, когда она потребовалась.

Технический долг от AI: чем он отличается от обычного

Обычный техдолг у разработчика есть в голове. Ты написал быстрое решение, знаешь, где именно срезал угол, и в идеале оставил комментарий или тикет. Это осознанный кредит. AI-долг работает иначе: никто не знает, где срезано. Ни модель, ни разработчик, принявший PR.

Адам Торнхилл с коллегами из CodeScene в 2024 году описал феномен, который назвали "refuctoring". Это код, который выглядит как рефакторинг, ведёт себя формально чище, проходит линтеры и ревью, но при этом ухудшает поведенческие характеристики системы. Хуже связность, хуже сопровождаемость, хуже производительность под нагрузкой. Причина в том, что языковая модель оптимизирует под локальный сигнал качества: правильные имена переменных, отсутствие очевидных code smells. Но глобальный контекст модуля, история изменений, неявные контракты между компонентами, она не держит.

Если конкретно, AI-долг приходит в трёх основных формах.

Первая: дублирование без осознания. Модель не знает, что аналогичная утилита уже есть в другом модуле, и генерирует новую. Разработчик видит чистый код и мержит. Через полгода в кодовой базе три реализации одной логики с небольшими расхождениями в поведении.

Вторая: избыточная цикломатическая сложность. AI охотно добавляет guard clauses, early returns и вложенные условия, "чтобы было надёжно". Визуально читабельно. По метрикам цикломатическая сложность функции вырастает с 4 до 11, и теперь покрыть её тестами полноценно значительно дороже.

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

Red Hat несколько лет назад сформулировали мысль, которая здесь точная: рефакторинг это экономическое решение, а не техническое. Ты оцениваешь стоимость изменений сейчас против стоимости сопровождения потом. AI убирает экономический контекст из этого решения. Для модели нет понятия "завтра команда будет разбираться в этом коде", есть только текущий запрос.

Эффект накапливается быстро. Команды, которые использовали AI-инструменты на фичах без жёсткого ревью-процесса, со временем обнаруживают, что значительная часть спринта уходит не на новые задачи, а на разбор и исправление AI-кода. Это не всегда очевидно постепенно: просто в какой-то момент velocity падает, и только тогда начинают считать.

Сравнение: явный TODO-комментарий рядом с чистым AI-кодом, скрывающим ошибку

TODO хотя бы виден в поиске, а аккуратный AI-код без единого комментария прячет race condition до первого нагрузочного теста.

Точка перелома: как её распознать до того, как стало поздно

Есть момент, когда Cursor из инструмента превращается в костыль. Он наступает незаметно, и команды обычно осознают это постфактум, когда уже накопился долг, который не спишешь за спринт.

Вот четыре сигнала. Если хотя бы два совпадают, у вас проблема.

Время на ревью AI-кода превышает время написания руками. Я видел команды, где разработчик генерировал функцию за 40 секунд, а ревьювер тратил 25 минут, чтобы понять, что она вообще делает. Суммарно это дороже, чем написать код самому. Если у вас регулярно появляются PR-комментарии в духе "а зачем здесь вот этот промежуточный слой", это первый звоночек.

Разработчик не может объяснить на ревью свой выбор реализации. Не "я не помню детали", а именно "я не знаю, почему так". Cursor предложил, он принял. Это уже не code review, это лотерея: повезёт с логикой или нет.

Растут странные баги, которые сложно воспроизвести изолированно. AI-код часто технически корректен в вакууме, но строится на неявных предположениях о контексте. Баги вылезают на пересечении модулей, в конкретной последовательности вызовов. Воспроизвести отдельно нельзя. Это не случайность, это структурный признак кода, который никто в команде до конца не понимает.

Новый человек не может читать кодовую базу без AI-ассистента. Если онбординг теперь выглядит как "открой Cursor и спроси его о модуле X", архитектура перестала быть читаемой. Документация в голове у модели, не в команде.

Есть простой тест, который я рекомендую проводить раз в квартал. Попросите разработчика закрыть редактор и объяснить архитектуру любого модуля, над которым он работал последние две недели. Устно, на доске, в чате, как угодно. Если он открывает Cursor, чтобы вспомнить, не файлы посмотреть, а именно чтобы понять собственный код, инструмент уже работает против команды.

Это не про запрет AI. Это про то, что Cursor должен ускорять людей, которые понимают, что делают. Когда он начинает замещать понимание, скорость становится иллюзией.

Разработчик не может объяснить архитектуру модуля без открытой IDE

Когда архитектуру генерирует инструмент, а не голова, знание остаётся в файлах, не у человека.

Что реально работает: практики, которые удерживают Cursor в роли инструмента

Я потратил несколько месяцев на то, чтобы понять, где Cursor помогает, а где тихо ломает кодовую базу. Вот что осталось в моём рабочем процессе после всех экспериментов.

###.cursorrules: первая линия обороны

Без явных ограничений Cursor будет генерировать "разумный" код по своим стандартам. А его стандарты не совпадают с твоими. Файл .cursorrules в корне проекта решает это напрямую:

// .cursorrules (фрагмент)
// НЕ создавай новые utility-функции без проверки utils/
// НЕ дублируй валидацию — используй validators/index.ts
// Все сервисы инжектируются через DI-контейнер, не создаются напрямую
// Максимум 1 уровень вложенности в Promise-цепочках
// При цикломатической сложности > 8 — раздели функцию

Это не документация для людей. Это машинные инструкции. Пишу их как запреты, а не как рекомендации. "Не делай X" работает лучше, чем "старайся делать Y": жёсткие формулировки модель выдерживает заметно надёжнее мягких.

Агентный режим: только для изолированных задач

В 2026-м агентный режим Cursor стал достаточно стабильным, чтобы доверять ему целые функциональные куски. Но с одним условием: задача должна иметь чёткий интерфейс на входе и выходе.

Хорошо работает так: я пишу сигнатуру функции, JSDoc с контрактом, несколько примеров в тестах. Потом говорю агенту: "Заполни реализацию под этот контракт." Агент работает в пределах заданного периметра и редко вырывается за него.

Плохо работает, когда я даю агенту размытую задачу вроде "добавь авторизацию". В этом случае он начинает принимать архитектурные решения сам. И принимает их быстро, уверенно и часто неудачно.

Архитектура до кода, не вместе с кодом

Мой порядок работы сейчас выглядит так: сначала вручную описываю интерфейсы TypeScript и контракты между модулями. На это уходит 20-30 минут. Потом Cursor заполняет реализацию.

Это меняет характер ошибок. Вместо "AI сделал не ту архитектуру" получаю "AI сделал не ту реализацию". Второе исправляется за пять минут, первое иногда за несколько дней.

Метрика перед мержем: цифра, а не ощущение

SonarQube с проверкой цикломатической сложности прямо в CI. Порог: complexity > 10 блокирует мерж. Без исключений.

Почему 10, а не 8 из .cursorrules? Правило в файле конфигурации Cursor ловит проблему на этапе генерации. CI ловит то, что просочилось. Два разных уровня с небольшим перекрытием лучше одного строгого.

По моему опыту работы с такой конфигурацией CI регулярно разворачивает сгенерированный код. Каждый раз там оказывается либо вложенная цепочка условий, либо функция, которая делает три вещи сразу.

Правило 60 на 40

Не больше 60% времени на задачу уходит на AI-код. Оставшиеся 40% я читаю, что сгенерировано, и переписываю слабые места руками.

Это не паранойя. Cursor хорошо пишет "что делать", но часто плохо пишет "почему именно так". Код работает, но логика в нём неочевидная, именование вводит в заблуждение, обработка ошибок добавлена для вида. Переписанные руками куски остаются понятными через три месяца. Куски, которые я принял без правок, я открываю снова и трачу время на то, чтобы вспомнить, что там происходит.

Сорок процентов времени на понимание чужого кода, даже если этот "чужой" сгенерировала твоя же IDE, это не накладные расходы. Это и есть твоя работа.

Разделённый экран: интерфейсы написаны вручную слева, Cursor заполняет реализацию справа

Контракты пишет разработчик, детали дописывает Cursor, именно такое разделение труда оставляет архитектурное мышление у команды.

Cursor в 2026: $20 в месяц и реальная окупаемость

Pro-план стоит $20/месяц. Business, $40 на разработчика. Это меньше, чем час работы джуниора в большинстве команд, поэтому вопрос "окупается ли" кажется риторическим. Но есть нюанс: при интенсивной работе с агентом токены сгорают быстро, и реальная стоимость сессии выше, чем строчка в подписке.

Milestone отслеживает окупаемость через PR velocity и review time. Это правильный подход. Без этих метрик оценка превращается в ощущение, а ощущения у разных разработчиков расходятся в обе стороны.

Мои цифры такие: на задачах до 200 строк Cursor ускоряет написание кода на 30-50%. Это реально измеримо. CRUD-эндпоинт, покрытие тестами, типовой компонент с пропсами, здесь автодополнение и Tab-переходы работают как мышечная память. Но как только задача переходит в архитектуру, ситуация меняется. Cursor начинает генерировать код, который выглядит правдоподобно, но тянет в неправильном направлении. Приходится тормозить, перечитывать, откатывать. Чистый минус к скорости.

Сравнение с Claude Code по бенчмарку 2026 года: Claude Code точнее на multi-file задачах, где нужно удерживать контекст нескольких модулей и согласовывать изменения между ними. Cursor выигрывает в inline-автодополнении. Прямо в редакторе, без переключения окон, с предсказанием следующей строки, тут Cursor быстрее. Так что выбор зависит от того, чем ты занимаешься большую часть дня.

$20 окупаются. Но только если разработчик знает, когда отключить AI и работать руками. Это не метафора. Есть конкретные сигналы: задача требует понимания бизнес-контекста, который не лежит в репозитории; код затрагивает несколько сервисов с неочевидными зависимостями; нужно принять решение, а не реализовать уже принятое. В таких ситуациях агент создаёт иллюзию прогресса. Полчаса генерации, потом час разбора того, что он наделал.

Инструмент окупается у тех, кто его использует прицельно. У тех, кто включает его на весь рабочий день подряд, окупаемость под вопросом.

Три месяца спустя: что изменилось в процессе

Cursor никуда не делся. Но после трёх месяцев я понял, что использовал его неправильно.

Первые недели были эйфорией. Скорость написания кода росла, PR-ы закрывались быстро, и казалось, что мы нашли правильный режим работы. Потом пришёл момент, когда нужно было добавить фичу в один из модулей, которые активно генерировались с помощью AI. Я открыл файл и понял, что не могу с ходу объяснить, почему код написан именно так. Не "что делает функция", а почему именно такие абстракции, почему такая структура зависимостей.

Это был сигнал.

Мы потратили две недели на рефакторинг критических модулей. Один переписали с нуля: не потому что он не работал, а потому что его никто не мог уверенно поддерживать. Это съело заметную часть того прироста скорости, которого мы достигли за первые три месяца. Счёт не в пользу бездумного вайбкодинга.

Теперь у нас есть правило: любой AI-сгенерированный код на ревью должен быть объяснён автором устно или в комментарии к PR. Не "что делает", а почему именно так. Это режет скорость на первом круге, но убивает накопление непонятного кода в кодовой базе. Разработчик, который не может объяснить чужой AI-код, должен его переписать, а не смёрджить.

Роль Cursor в стеке переопределилась. Boilerplate, тесты, миграции, шаблонный CRUD. Всё это он генерирует быстро и предсказуемо. Архитектурные решения, нетривиальные абстракции, модули с высокой связностью, всё это я теперь пишу руками. Не из принципа, а потому что цена ошибки там другая.

Главное, что я вынес: Cursor ускоряет разработчика, который понимает код. Для того, кто доверяет AI, он создаёт иллюзию скорости. Коммиты идут быстро, а понимание не накапливается.

Одна метрика осталась в нашем процессе навсегда. Если review-time AI-кода растёт второй спринт подряд, это признак того, что команда генерирует больше, чем способна осмысленно проверить. И пора пересматривать, что именно мы отдаём на аутсорс модели.