Перейти к содержимому

AI-инструменты разработчика в 2026 году

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

В краткой версии ты видел обзор: Copilot дополняет, Cursor правит, Ollama держит приватный код дома. Здесь разберём глубже: как устроены инструменты внутри (контекстное окно, retrieval, агентные циклы), почему модель уверенно ошибается и как это ловить, как организовать агентный workflow «план — исполнение — проверка» и в какой момент фундаментальные знания из предыдущих двенадцати разделов становятся единственным фильтром, отличающим работающую систему от красиво оформленной ошибки.

Под оболочками — три разных архитектурных подхода к одной задаче: дать модели релевантный контекст и встроить её ответ в поток работы.

GitHub Copilot — автодополнение следующего токена с учётом открытых файлов. Модель получает «префикс» (код до курсора, соседние вкладки, недавно закрытые фрагменты) и предлагает продолжение. Это generative-подход: быстро, дёшево, работает в любой IDE. Ограничение — модель мыслит локально: она видит кусок файла, но не архитектуру проекта. Отсюда классика: функция идеальна сама по себе, но использует API, которого нет в проекте, или дублирует существующую утилиту в трёх директориях выше.

Cursor — форк VS Code, где контекст собирается осознанно: индекс репозитория (эмбеддинги всех файлов, разбитых на чанки), поиск по индексу при каждом запросе, режим Composer с правками в нескольких файлах, ручное добавление файлов в контекст через @. Режимы и приёмы работы с контекстом описаны в документации Cursor. Это retrieval-подход: модель отвечает не из «своих знаний об усреднённых проектах», а из найденного в твоём коде. Отсюда главное качество Cursor — правки, которые уважают существующие соглашения проекта.

Windsurf (Codeium) — тот же retrieval-подход с акцентом на «agentic» режим: модель сама планирует последовательность правок, выполняет их, запускает команды и продолжает по результату. Разница с Cursor — скорее в UX и цене, чем в принципе.

Галлюцинации — не баг, а устройство. LLM генерирует правдоподобное продолжение текста, а не истину. Самый опасный тип — плаузибельный баг: код выглядит идиоматично, использует знакомые паттерны, но неверно обрабатывает пограничный случай (off-by-one в пагинации, гонка в асинхронном коде, regex, пропускающий юникод). Тон ответа не сигнализирует об ошибке: уверенный неверный ответ выглядит как уверенный верный.

Что помогает ловить:

  • Проверка пограничных случаев руками, а не взглядом: null/пустые коллекции, границы диапазонов, конкурентные вызовы, кодировки.
  • Тесты как критерий приёмки: промпт, требующий тесты, не от гребущего перфекционизма — он превращает «выглядит ок» в проверяемое утверждение.
  • Ревью с чек-листом классов ошибок (гонки, ресурсы, async), а не общее «посмотри код» — см. ниже.

Приватность — второй жёсткий предел. Код, отправленный в облачный сервис, покидает твой периметр: условия провайдера, судьба обучающих данных, корпоративные политики. Коммерческий код под NDA, конфиги с адресами внутренних сетей, ключи — отправлять наружу нельзя. Здесь не помогает «не показывай секреты в промпте»: репозиторий целиком может быть под NDA. Решение — локальные модели, об этом ниже.

Промпт-инжиниринг для кода: четыре части хорошей задачи

Заголовок раздела «Промпт-инжиниринг для кода: четыре части хорошей задачи»

Плохой промпт — «напиши валидацию email». Модель угадывает стек, фреймворк, формат ответа и пишет что-то среднее по индустрии, что редко совпадает с твоим проектом. Хороший промпт имеет структуру: контекст → задача → ограничения → формат результата.

Контекст:
Node.js 20, Express 4, TypeScript strict, проект на ESM.
В проекте уже есть middleware-обработчик ошибок: next(err) → { error: string }.
Задача:
Middleware validateEmail для поля email в теле POST /register.
Ограничения:
- regex по упрощённому RFC 5322, максимум 254 символа, только ASCII
- ошибка — через next(new HttpError(400, "invalid_email")), НЕ res.status().json()
- без сторонних библиотек (zod не подключать)
- существующий стиль: именованные функции, без default export
Формат:
Один файл src/middleware/validate-email.ts
Плюс тесты на vitest: валидный email, без "@", 300 символов, юникод в домене.

Каждая часть закрывает класс галлюцинаций: контекст — от неправильного стека и API; ограничения — от несуществующих зависимостей и чужих паттернов; формат — от размазанного ответа, который приходится выковыривать.

Правила, которые стабильно работают:

  1. Контекст сначала. Стек, версии, соглашения — до задачи. Модель якорится на начале промпта.
  2. Малые задачи. Одна функция, один файл, один сценарий. «Перепиши модуль» даёт мусор, потому что модель теряет детали на длине.
  3. Критерий готовности. Тесты, типизация, линтер — то, чем проверить результат. Промпт без критерия — заказ без ТЗ.
  4. Образец сильнее описания. «Сделай как функция X ниже: <код>» передаёт стиль точнее любых прилагательных.

Ревью промптом строится иначе, чем генерация: не «оцени код», а проверка конкретных классов проблем. Общее «найди баги» модель проводит поверхностно; перечисленные классы — системно:

Ревью как senior-инженер. Ищи ТОЛЬКО:
1. Гонки данных: shared state между запросами, неатомарные check-then-act.
2. Утечки ресурсов: незакрытые соединения БД, таймеры без clearInterval, stream без destroy.
3. Необработанные rejections в async-функциях (вызывающий код получает unhandled?).
4. SQL-инъекции и непараметризованные запросы.
Не предлагай стилистику и переименования. Каждая находка: файл:строка, суть, сценарий воспроизведения.

Плохая и хорошая генерация: один пример целиком

Заголовок раздела «Плохая и хорошая генерация: один пример целиком»

Смотреть на промпт-инжиниринг без живого примера — как учить плавание по картинке. Возьмём задачу из pet-проекта: рейтлимитер для API.

Плохой запрос и типичный результат:

запрос: «напиши rate limiter для express»
проблемы: модель не знает проект — пишет middleware с хранением счётчиков
в Map внутри процесса (при двух инстансах за балансировщиком
лимит удваивается), без TTL (утечка памяти), с фиксированным окном
(edge case: 2× лимит на границе окна), без заголовков Retry-After.

Хороший запрос:

Контекст: Express 4, TypeScript, кластер из 2+ инстансов за ALB,
Redis уже есть (ioredis), ключ лимита — user id из req.user.
Задача: Sliding window rate limiter: 100 запросов/мин на пользователя.
Ограничения:
- счётчики ТОЛЬКО в Redis (переживает масштаб), Lua-скрипт для атомарности
- при отказе Redis — пропускать запрос (fail-open) + error log, НЕ 500
- ответ 429: { error: "rate_limited", retry_after: <сек> }
- заголовки: X-RateLimit-Remaining, X-RateLimit-Reset
Формат: src/middleware/rate-limit.ts + vitest-тест с ioredis-mock:
101-й запрос за минуту → 429; после сдвига окна → 200.
// Результат под такой промпт — уже близок к продакшену (сокращено)
import type { Request, Response, NextFunction } from "express";
import Redis from "ioredis";
const lua = `
local key = KEYS[1]
local now = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local limit = tonumber(ARGV[3])
redis.call('ZREMRANGEBYSCORE', key, 0, now - window)
local count = redis.call('ZCARD', key)
if count < limit then
redis.call('ZADD', key, now, now .. ':' .. math.random())
redis.call('PEXPIRE', key, window)
return {1, limit - count - 1, window}
end
return {0, 0, window}`;
export function rateLimit(redis: Redis, limit = 100, windowMs = 60_000) {
return async (req: Request, res: Response, next: NextFunction) => {
try {
const now = Date.now();
const [ok, remaining, reset] = await redis.eval(
lua, 1, `rl:${req.user.id}`, now, windowMs, limit,
) as [number, number, number];
res.setHeader("X-RateLimit-Remaining", remaining);
res.setHeader("X-RateLimit-Reset", Math.ceil((now + reset) / 1000));
if (!ok) {
return res.status(429).json({ error: "rate_limited", retry_after: Math.ceil(reset / 1000) });
}
next();
} catch (err) {
req.log.error({ err }, "redis down, rate limit skipped"); // fail-open
next();
}
};
}

Разница не в модели — в том, что промпт указал на: распределённое состояние, атомарность, поведение при отказе, формат ответа. Это те самые вопросы, которые ты задаёшь код-ревью, — теперь они заданы до генерации. И всё равно: тесты, гонка на границе окна, нагрузочная проверка — руками.

Агентные workflow: планирование — исполнение — проверка

Заголовок раздела «Агентные workflow: планирование — исполнение — проверка»

Следующий уровень после «модель пишет по запросу» — агент, который выполняет задачу циклом: план → действие → наблюдение → коррекция. Claude Code и аналоги (aider, Continue с агентом, OpenAI Codex CLI) работают так: читают репозиторий, правят файлы, запускают команды, смотрят вывод, идут дальше. Справка по Claude Code — в документации Anthropic.

Рабочий цикл выглядит так:

1. ПЛАНИРОВАНИЕ
Задача: «добавь экспорт отчёта в CSV».
Агент читает код, предлагает план: новый endpoint, сервис экспорта,
тесты. ТЫ утверждаешь план — до первой правки.
2. ИСПОЛНЕНИЕ
Агент правит файлы, пишет тесты, запускает их сам.
3. ПРОВЕРКА
Агент смотрит результат: тесты зелёные? типы сходятся? линтер?
Падает — цикл исполнение↔проверка повторяется (автономно,
в рамках лимита шагов).
4. ТВОЯ ПРОВЕРКА
git diff. Ревью глазами + прогон тестов локально. Коммит — только после.

Ключевые дисциплины, без которых агент вреднее помощника:

  • Git — обязательное условие. Каждая задача — отдельная ветка/коммит, чистое состояние перед стартом. Агент правит уверенно и нечаянно: откат — единственная защита. Никогда не давай агенту работать над несколькими задачами в одной рабочей копии.
  • План утверждает человек. «Сделай экспорт в CSV» агент может понять как «добавь кнопку во фронте, перепиши API, вынеси логику в новый микросервис». Десять секунд на чтение плана экономят час отката.
  • Проверочные команды — часть задачи. В промпт агенту включай: «запусти npm test, npm run typecheck; работа готова только когда оба зелёные». Без этого агент считает готовым «код написан».
Окно терминала
# Пример сессии с Claude Code — задача с критериями готовности
claude
> Задача: вынести retry-логику из src/http/client.ts в src/http/retry.ts,
не меняя поведение. Критерии готовности:
1. npm run typecheck без ошибок
2. npm test все зелёные (тесты на retry существуют)
3. git diff --stat показывает ровно 2 файла
Сначала предложи план, жди моего подтверждения.
> [план] ... ок, выполняй
> [правки, запуск тестов, исправление] готово
# теперь ТЫ: git diff, прогон тестов руками, коммит

Локальные модели: Ollama для приватного кода

Заголовок раздела «Локальные модели: Ollama для приватного кода»

Ollama — рантайм локальных LLM: скачал модель одной командой, получил API на localhost:11434, совместимый с OpenAI-клиентами. Код не покидает машину — приватность из коробки. Полный гайд по моделям и API — в документации Ollama.

Окно терминала
# Установка и запуск (Arch Linux)
sudo pacman -S ollama
systemctl enable --now ollama
# Модели для кода: качество/скорость на обычной машине
ollama pull qwen2.5-coder:7b # лучшая «кодовая» 7B на 2026, ~4.7 GB
ollama pull deepseek-coder-v2:16b # если RAM ≥ 16 GB, заметно умнее
ollama pull llama3.1:8b # универсальная: объяснения, документация
# OpenAI-совместимый endpoint — подключается к Continue, aider, своим скриптам
curl http://localhost:11434/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "qwen2.5-coder:7b",
"messages": [{"role": "user", "content": "Объясни, что делает этот скрипт: <код>"}]
}'

Честно о качестве: локальные модели 2026 года (7–16B, Q4-квантование) заметно слабее облачных флагманов. Они хороши для: объяснения кода, черновых комментариев и докстрингов, простых утилит по образцу, рефакторинга с чётким ТЗ. Они плохи для: архитектурных решений, хитрых пограничных случаев, кода, где ошибка дорога. Гибридная стратегия: приватный код и конфиги — локально; несекретные черновики и тесты — облачные флагманы. Критерий — тип данных, не удобство.

Cursor и Windsurf делают retrieval внутри себя; для своих инструментов принцип тот же и прост:

  1. Индекс: репозиторий разбивается на чанки (функции/классы по AST, а не по строкам), каждый чанк превращается в эмбеддинг — вектор смысла.
  2. Поиск: вопрос → эмбеддинг → ближайшие чанки по косинусной близости → они попадают в контекст модели.
  3. Ответ модель строит уже на реальном коде проекта, а не на догадках.

Инструменты для своего RAG: continue.dev (поддерживает локальные эмбеддеры через Ollama — и тогда даже эмбеддинги не уходят в облако), Sourcegraph Cody для больших монореп. Эффект тот же, что у Cursor, но под твоим контролем — важно для корпоративных репозиториев.

Три задачи, где агенты сегодня дают максимум пользы при минимуме риска:

  • Тесты. «Напиши тесты на эту функцию, покрывай пограничные случаи: пустые входы, границы диапазонов, ошибки зависимостей». Агент методичен там, где человеку скучно. Проверка твоя: тесты должны реально падать при сломанном коде (мутируй функцию — тесты должны зазеленить обратно).
  • Документация. Docstrings, README, ADR (architecture decision records) по diff’у. Черновик — агенту, точность — тебе.
  • Legacy-код. Классический первый шход перед рефакторингом: «прочитай модуль, объясни, что он делает, от чего зависит, где опасные места; НЕ предлагай правки». Карта незнакомого кода за минуты вместо дней чтения. Сверяй с реальным поведением — модель иногда домысливает намерения по коду, который их давно утратил.

Почему фундамент стал дороже, а не дешевле

Заголовок раздела «Почему фундамент стал дороже, а не дешевле»

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

  • Знаешь сети — увидишь, что сгенерированный Nginx-конфиг ломает WebSocket (нет Upgrade-заголовков) или что retry-шторм создаст, потому что понимаешь TCP.
  • Знаешь SQL и транзакции — заметишь, что запрос из LLM положит таблицу seqscan’ом, а «проверь, потом вставь» в идемпотентности — гонка.
  • Знаешь CAP и репликацию — поймёшь, почему «просто синхронизируем два дата-центра» из ответа модели — фантастика, и сформулируешь правильный вопрос (async-репликация и read-your-writes).
  • Знаешь экономику облака — рассчитаешь, что предложенная архитектура стоит $2000/мес там, где хватит $40, и спросишь модель заново с ограничением бюджета.
  • Знаешь безопасность — увидишь в сгенерированном коде SQL-инъекцию, секрет в env-примерке, открытый CORS.

AI — ускоритель, а не замена. Пилот без понимания аэродинамики не садит самолёт даже с автопилотом: он не знает, когда автопилот ошибается. Твоя ценность — ставить задачу, проверять результат и отвечать за систему. Этому и учили предыдущие разделы.

  1. Принятие вывода без запуска. «Код выглядит правильно» ≠ «код работает». Минимальный барьер: тесты и typecheck прогнаны. Максимальный: пограничные случаи проверены руками.
  2. Промпт без контекста проекта. «Напиши X» → модель выдумывает стек и соглашения. Следствие: код в чужом стиле с несуществующими зависимостями. Контекст — первый абзац, всегда.
  3. Агент без git-дисциплины. Работа в «грязной» рабочей копии: агент затронул не те файлы, откат невозможен. Правило: ветка на задачу, чистый diff, коммит до и после.
  4. Отправка приватного кода в облако. «Только один файлик» с внутренним доменом и структурой БД — утечка архитектуры. Решение принимается по типу данных до открытия чата, не по настроению.
  5. Доверие к уверенности модели. Тон ответа не коррелирует с правильностью. Ловушка особенно коварна у опытных: чем грамотнее сгенерированный код, тем меньше подозрений — а плаузибельные баги пишутся грамотно.
  6. Деградация навыка. Месяц «пусть AI напишет» без ручной работы — и скорость печати кода падает, и чувство пограничных случаев тупится. Используй AI как спарринг-партнёра: сначала сам, потом сравнить.
  1. Как устроен Cursor и чем отличается от Copilot? Copilot — автодополнение по префиксу (генерация), Cursor — чат с retrieval: индекс репозитория через эмбеддинги, контекст собирается поиском по нему, правки в нескольких файлах. Разница — локальная генерация против поиска по проекту.
  2. Что такое галлюцинация LLM и как с ней работать? Генерация правдоподобного, но неверного: несуществующие API, плаузибельные баги. Работа: критерии приёмки в промпте, проверка пограничных случаев руками, тесты, ревью по чек-листу классов ошибок.
  3. Структура хорошего промпта для кода? Контекст (стек, соглашения) → задача → ограничения (что нельзя, какие зависимости, поведение при ошибках) → формат результата (файлы, тесты).
  4. Как безопасно работать с AI-агентом в репозитории? Чистая ветка, утверждение плана до правок, проверочные команды как критерий готовности, git diff и прогон тестов человеком перед коммитом. Никогда без отката.
  5. Когда локальные модели через Ollama предпочтительнее облачных? Когда код, конфиги или данные не должны покидать периметр: NDA, коммерческие секреты, внутренние инфраструктурные детали. Цена — качество ниже флагманов; выбирают по типу данных.
  6. Почему фундаментальные знания важнее в эпоху AI? Без них невозможно отличить верный ответ LLM от плаузибельной ошибки: человек без базы принимает оба. Знания — фильтр, через который проходит каждый AI-вывод, и единственная основа для постановки задачи и проверки результата.
  1. Возьми одну реальную задачу pet-проекта. Сначала напиши решение сам. Затем сгенерируй тем же требованиям через хороший промпт (контекст → задача → ограничения → формат). Сравни: что предложила модель, чего не хватило твоему решению, какие пограничные случаи упустили оба.
  2. Составь промпт-чек-лист ревью (5–7 классов проблем: гонки, ресурсы, async, инъекции, секреты, обработка ошибок). Прогони им три последних коммита проекта. Запиши: что нашла модель, что пропустила, что нашёл ты и она нет.
  3. Подними Ollama с qwen2.5-coder:7b, подключи Continue.dev или aider к локальному endpoint. Реши одну несекретную задачу локально: черновик документации или утилита. Замерь скорость и качество против облачной модели на той же задаче.
  4. Делегируй агенту (Claude Code/aider) генерацию тестов на модуль с самой сложной логикой проекта. Мутируй код (сломай условие) и проверь: какие тесты ловят поломку, какие — нет. Доработай недостающие тесты вручную.
  5. Найди участок legacy-кода, который давно боишься трогать. Попроси агента объяснить его и построить карту зависимостей, без предложений правок. Сверь с реальным поведением: запусти, поставь логи, проверь один сценарий end-to-end.