# Как в Anthropic мигрируют миллионы строк кода с помощью Claude

Канонический URL: https://zero2claude.ru/blog/claude-code-large-migrations
Дата: 2026-07-16
Теги: claude-code, агенты, автоматизация, enterprise

История о том, как Anthropic перевела Bun с Zig на Rust за две недели и Python-проект на 165 тысяч строк TypeScript за выходные — и какой процесс из шести шагов за этим стоит.

Ещё пару лет назад миграция крупного проекта с одного языка программирования на другой — это история на годы. Команда замораживает роадмап, держит две параллельные кодовые базы, а в итоге получает 90% паритета и вдвое больше головной боли, чем было в начале. Именно поэтому такие проекты обычно откладывали до последнего — пока не становилось совсем невыносимо.

<Cover src="/blog/claude-code-large-migrations.jpg" alt="Символ миграции кода: река, разделяющаяся на два параллельных потока" />

За последний месяц разработчики в Anthropic мигрировали десять кодовых пакетов размером от десятков до сотен тысяч строк, используя Claude Fable 5, Claude Opus 4.8 и гибкие рабочие процессы с агентами. В этом посте — два самых показательных примера и шесть шагов процесса, который за ними стоит.

## Два примера, которые меняют представление о возможном

Джарред Самнер, сооснователь Bun и сотрудник Anthropic, перевёл Bun с языка Zig на Rust с помощью Claude Code. Миллион строк кода был написан за меньше чем две недели, при этом 100% существующего набора тестов Bun проходили в CI ещё до слияния. После мерджа обнаружилось 19 регрессий — все они уже исправлены. Rust-версия Bun встроена в Claude Code с июня.

Майк Крегер, соруководитель Anthropic Labs, перевёл внутренний Python-проект на 165 000 строк TypeScript за одни выходные. В процессе участвовали сотни агентов, восемь фазовых «шлюзов» (gate), три раунда адверсариального ревью и финальная проверка паритета — построчное сравнение вывода каждой команды между Python-оригиналом и новым TypeScript-кодом.

![Иллюстрация к статье про миграцию кода](/blog/claude-code-large-migrations-1.jpg)

Оба случая объединяет один принцип: команды не пытались «поправить» существующий код руками. Они выстроили процесс — цикл перевода, проверки и исправления, — который сам довёл проект до готового результата. Это и есть ключевая мысль всей статьи: ты не чинишь код, ты чинишь процесс (цикл), который этот код производит.

## Когда миграция действительно оправдана

Команды берутся за миграцию, когда меняется ландшафт: известный компромисс, на который пошли когда-то, стал слишком дорогим, появился лучший подход, или экосистема исходного языка усыхает. Джарред изначально выбрал Zig для Bun, потому что он давал производительность уровня C при радикальной простоте — идеально для соло-основателя, писавшего Bun «за год в тесной квартире в Окленде, ещё до эры LLM». У этой простоты были известные издержки, и ещё квартал назад их одних не хватило бы, чтобы оправдать заморозку роадмапа на несколько кварталов.

Сегодня CLI Bun скачивают больше 10 миллионов раз в месяц, и он активно используется внутри самого Claude Code. Но бизнес-кейс всё равно нужен: миллионнострочные миграции больше не стоят 3–4 миллиона долларов инженерных ресурсов и четыре года времени, но они всё ещё обходятся в десятки-сотни тысяч долларов. Миграция Bun потребовала 5,9 миллиарда входных токенов (без кеша) и 690 миллионов выходных — это около 165 000 долларов по ценам API. Основная часть проекта Майка обошлась в 27 миллионов токенов.

Для Майка триггером стал этап компиляции. Внутренний инструмент его команды собирался в единый бинарник для пользователей, и сборка на Python-тулчейне занимала около восьми минут на платформу — суммарно до 30 минут ожидания на весь набор платформ при каждом релизе. После переноса на TypeScript та же сборка занимает около двух секунд, бинарник запускается в 6 раз быстрее, а отдельный пайплайн деплоя команда просто отключила.

<Callout type="tip">
Хороший повод для миграции больше не обязан быть «экзистенциальным». Год патчей одной и той же проблемы с памятью в чейнджлоге или один хронический узкий узел — уже достаточное основание попробовать.
</Callout>

## Почему ИИ меняет саму математику миграций

Claude Fable 5 — самая мощная общедоступная модель Anthropic, и вместе с Opus 4.8 они особенно хороши в делегировании и проверке параллельной работы через сабагентов. Крупные миграции кода оказались почти идеальным сценарием для таких моделей — вот почему:

| Свойство миграций | Почему это подходит агентам |
|---|---|
| Работа параллельна | Тысячи независимых файлов и модулей — агенты работают одновременно, а не по очереди |
| Контекст полный и понятный | Старый код сам служит спецификацией и опорой для правил перевода |
| Есть встроенный «судья» | Тестовый набор объективно проверяет результат — модель может биться за истину сутками без арбитра-человека |
| Очередь задач формируется сама | Провал компилятора или теста автоматически становится следующей задачей для агента |
| Нужна строгая консистентность | Ревьюеры ссылаются на конкретное правило при каждой находке — нарушение становится задачей в очереди, а не тихим расхождением |

И Майк, и Джарред использовали Fable на ключевых этапах миграции — в частности, в «консультативном» режиме, когда более мощная модель формирует правила, а более лёгкие модели массово применяют их, экономя токены. Кстати, если тебе интересно, как в принципе делегировать сложную работу моделям через агентные сценарии, посмотри бесплатный курс zero2claude — там разбирается именно эта логика, только на простых примерах для новичков.

## Обязательное условие: сильный «судья»

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

Чтобы построить такого судью, нужно сделать три вещи: классифицировать существующие тесты (какие можно выразить через внешние вызовы, а какие завязаны на внутренние детали, которые не переживут перенос), переписать переносимые тесты в вид ассертов, работающих против обоих вариантов кода (и проверить адверсариальными агентами, что переписанные тесты не стали слабее оригинальных), и наконец — валидировать самого судью: прогнать его на исходном коде (должен пройти) и на заведомо сломанном (должен упасть). Судья, который не ловит поломку, — не судья.

У Джарреда был большой тестовый набор, написанный на третьем языке (TypeScript), но так бывает не у всех. Для своего Python-в-TypeScript проекта Майк создал контрольный набор из семи реальных сценариев и считал любое изменение поведения багом, который нужно исправить.

![Схема шести шагов процесса миграции с ревью и шлюзами на каждом этапе](/blog/claude-code-large-migrations-2.jpg)

## Шаг 1 — Свод правил, карта зависимостей и инвентарь пробелов

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

Форма свода правил зависит от главного архитектурного решения: сохранит ли новый код ту же структуру, или его перепишут заново. В первом случае (путь Джарреда) правила — это, по сути, таблицы соответствия типов и идиом между языками со ссылками на инвентарь пробелов для сложных мест. Во втором случае (путь Майка) — это скорее проектный документ. Джарред формировал свои правила в диалоге с Claude, вырабатывая политику для каждой зоны неопределённости, а также использовал восемь специализированных сабагентов — каждый ревьюил свою категорию типичных ошибок на основе его собственной инженерной интуиции.

Карту зависимостей файлов нужно построить, чтобы правильно разбить работу на параллельные потоки: какие файлы переводить первыми, а какие объединять в одну партию. Для многих легаси-кодовых баз и языков вроде C/C++ и Python таких явных манифестов зависимостей нет — их приходится вычислять отдельно, и Claude Code умеет разворачивать агентов для написания и прогона детерминированного скрипта, строящего эту карту через цикл проверки и исправления.

Инвентарь пробелов фиксирует то, что новый язык требует иначе, чем старый. При переходе с Zig на Rust ключевым различием стало ручное управление памятью: в Zig компилятор пропустит функцию, которая возвращает буфер и «забывает» упомянуть в комментарии, что вызывающий код обязан его освободить — утечка проявится только во время выполнения. В Rust владение буфером явно переходит вызывающей стороне, память освобождается автоматически, а попытка использовать её после перемещения или освободить дважды просто не скомпилируется.

При переходе с Python на TypeScript пробелом стали интерфейсы и контракты. В Python функция может принять любой объект с нужными методами — какие объекты реально передаются, можно узнать только вычитав всю кодовую базу. В TypeScript контракт (интерфейс с сигнатурами методов) должен быть явно описан, прежде чем код скомпилируется. И Джарред, и Майк создавали отдельные файлы-инвентари для фиксации этого неявного знания — только Джарред делал это заранее, а Майк сначала перевёл код и уже потом собрал инвентарь через аудит постфактум.

## Шаг 2 — Стресс-тест правил на малой выборке

Второй шаг — это своего рода «пробный рейс» перед полномасштабной миграцией. Джарред запустил три параллельных агента: один переводил три файла строго по своду правил, второй переводил те же файлы «как опытный Rust-инженер» без жёсткой привязки к правилам, а третий сравнивал два результата и на основе разницы формулировал новые правила перевода.

На этом этапе Джарред поймал два критических изъяна в правилах, которые иначе размножились бы по всем 1 448 файлам проекта Bun и создали массу проблем при полном развороте миграции. Такой стресс-тест построчного сравнения работает только для миграций, сохраняющих структуру кода, — когда два перевода одного файла можно честно сопоставить строку к строке. Если свод правил предполагает архитектурное переосмысление (как у Майка), приходится проверять правила иначе — например, через сквозные прогоны на небольшом реальном сценарии с последующим ревью расхождений.

![Иллюстрация процесса ревью и исправления при миграции кода](/blog/claude-code-large-migrations-3.jpg)

## Дальше — циклы, шлюзы и финальная сверка

После стресс-теста процесс масштабируется по тому же принципу: агенты параллельно переводят батчи файлов по проверенным правилам, а любой провал компилятора или теста автоматически становится следующей задачей в очереди — без человека-арбитра. У Майка это выглядело как восемь фазовых шлюзов и три раунда адверсариального ревью, где отдельные агенты специально искали расхождения в поведении между версиями. Финальным условием прохождения служила построчная сверка вывода каждой команды между Python-оригиналом и TypeScript-портом — любое отличие считалось багом, который нужно закрыть, а не «допустимой погрешностью».

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

<Callout type="warning">
Стресс-тест на малой выборке — не формальность. Именно на этом шаге Джарред поймал баги, которые при масштабировании на 1 448 файлов превратились бы в системную проблему всего проекта.
</Callout>

## Что это значит для тебя

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

Если тебе интересно, как агенты вообще делегируют друг другу сложную работу и проверяют результат друг за другом, стоит почитать про [Claude Fable 5 в Claude Cowork](/blog/claude-fable-5-claude-cowork) — там показан похожий принцип на менее масштабных задачах.

## Частые вопросы

<Faq>
<FaqItem q="Сколько стоит такая миграция на практике?">

Судя по примеру Bun, перевод около миллиона строк кода потребовал 5,9 миллиарда входных токенов (без кеша) и 690 миллионов выходных — примерно 165 000 долларов по ценам API. Проект Майка Крегера обошёлся в 27 миллионов токенов на основную часть работы. Это заметно дешевле классической многолетней миграции силами инженерной команды, но всё ещё требует реального бюджета.

</FaqItem>
<FaqItem q="Подходит ли этот подход для любого языка и любой кодовой базы?">

Стресс-тест построчного сравнения из шага 2 работает только для миграций, сохраняющих структуру кода (как Zig в Rust у Джарреда). Если новый код переосмысливается архитектурно (как Python в TypeScript у Майка), правила проверяют по-другому — через сквозные прогоны и последующий аудит расхождений, а не построчное сравнение.

</FaqItem>
<FaqItem q="Что самое важное нужно подготовить до старта миграции?">

Надёжного «судью» — способ объективно проверить, что новый код ведёт себя так же, как старый. Без него нет измеримого условия успеха. Это может быть переписанный тестовый набор или контрольный набор реальных сценариев, как у Майка Крегера, — и его обязательно нужно проверить на заведомо сломанном коде, чтобы убедиться, что он реально ловит поломки.

</FaqItem>
</Faq>

Если хочешь попробовать всё это руками — начни с бесплатного курса [«Claude Code и терминал: с 0»](/learn/code-terminal).

<Callout type="note" title="Источник">
По мотивам статьи Anthropic «How Anthropic runs large-scale code migrations with Claude Code». Пересказали по-русски для новичков.
</Callout>
