Перейти к основному содержанию

Claude Opus 4.6 vs Codex GPT-5.4: сравнение AI-кодеров на Go-задачах

Последние месяцы я использую два AI-инструмента для повседневной разработки: Claude Code (Anthropic, текущая модель Opus 4.6) и Codex CLI (OpenAI, текущая модель GPT-5.4). Оба работают в терминале, оба умеют читать файлы, запускать тесты и писать код. Но ведут себя по-разному.

На реальной задаче в рабочем проекте я заметил, что Codex на medium effort быстрее находит root cause бага и предлагает более короткий фикс, чем Claude на high effort с контекстом в миллион токенов. Это показалось неожиданным — и я решил проверить наблюдение на контролируемых задачах.

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

Методология

Обе модели получают одинаковый промпт с описанием задачи. Работают в изолированных директориях, параллельно. Замеряю wall time, количество tool calls, размер финального кода и прохождение тестов.

ПараметрClaudeCodex
Модельclaude-opus-4-6 (1M context)gpt-5.4
Efforthigh (subagent)medium
РежимClaude Code Agent (feature-implementer)codex exec (full-auto)

Задачи взяты из Exercism Go track — готовые тесты, чёткая спецификация, самодостаточность.

Задача 1: Tournament (средняя сложность)

Реализовать функцию Tally(io.Reader, io.Writer) error — парсинг результатов футбольного турнира, подсчёт статистики, вывод форматированной таблицы. Обработка комментариев, пустых строк, невалидного ввода.

Результаты

МетрикаClaudeCodex
Время~38 сек~60 сек
Тесты17/1717/17
Размер кода111 строк113 строк
С первой попыткиДаДа

Оба решения используют один и тот же подход: bufio.Scanner + map[string]*struct + sort.Slice. Различия косметические:

  • Codex выделил helper-функции (recordWin, recordDraw, standingsFor), использовал switch вместо if/else if, обернул ошибки через %w
  • Claude добавил явную валидацию спецсимволов в именах команд

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

Задача 2: React (высокая сложность)

Реализовать reactive system: input cells с изменяемым значением, compute cells с зависимостями от других ячеек, автоматическое распространение изменений по графу зависимостей, callbacks с возможностью отмены. Включая diamond dependency problem — callback должен сработать один раз, даже если ячейка зависит от изменённого input через несколько путей.

Это уже архитектурная задача: нужно спроектировать граф зависимостей, topological sort для пропагации, механизм callbacks.

Результаты

МетрикаClaudeCodex
Время~148 сек~84 сек
Тесты14/1414/14
Размер кода221 строка165 строк (-26%)
Tool calls30~12
Токены68K23K

Оба решения корректны — все 14 тестов проходят с -race. Но архитектура принципиально отличается.

Как решил Claude (221 строка)

Четыре типа: reactor, cell (базовый), inputCell (embedding), computeCell (расширенный). Отдельные baseDependencies и computeDependencies. Две функции вычисления: compute1 и compute2. Пропагация — итеративная: собрать все зависимые ячейки, затем в цикле обновлять те, чьи зависимости уже обновлены, пока не останется необновлённых. В худшем случае O(n^2).

Helper getBaseCell() с type switch извлекает базовый *cell из inputCell или computeCell. Canceler использует self-referencing pointer trick — хранит указатель на себя как ключ map.

Как решил Codex (165 строк)

Три типа: reactor, cell (единый для input и compute), canceler. Input от compute отличается наличием compute func() int — closure, которая захватывает зависимости при создании. Никаких compute1/compute2, никакого getBaseCell.

Пропагация — DFS для сбора достижимых ячеек, затем сортировка по ID создания. Поскольку зависимости всегда создаются раньше зависимых ячеек, сортировка по ID гарантирует правильный порядок — элегантная замена полноценного topological sort. O(n log n).

Callbacks откладываются: сначала полная пропагация всех значений, потом вызов callbacks. Это гарантирует, что callback видит стабильное состояние системы.

Canceler — простой nil-check: Cancel() обнуляет ссылку на cell, повторный вызов безопасен.

Ключевые различия

АспектClaudeCodex
Типы4 (cell, inputCell, computeCell, canceler)3 (reactor, cell, canceler)
Compute functionОтдельные compute1/compute2Единая closure func() int
Topological sortИтеративная convergence O(n^2)Sort by creation ID O(n log n)
CallbacksВо время пропагацииПосле полной пропагации
Type assertionsgetBaseCell() type switchПрямой dep.(*cell)

Решение Codex проще, короче и алгоритмически лучше. Трюк с сортировкой по ID создания — красивое решение, которое Claude не нашёл, выбрав более “академический” подход с итеративной convergence.

Что я думаю

Два бенчмарка — недостаточно для выводов. Это exploratory эксперимент, не научное исследование. Нужны задачи на диагностику багов, работу с большими кодовыми базами, рефакторинг, iterative refinement. Возможно, на других типах задач расклад будет обратным.

Тем не менее, наблюдения совпадают с моим опытом на реальных проектах:

Codex на medium effort тратит меньше токенов на compliance и больше — на задачу. У моей конфигурации Claude Code загружено ~900 строк правил и чеклистов. Это полезно для production-кода, но на бенчмарке означает, что модель тратит ресурсы на соблюдение TDD-цикла, pattern-first алгоритма, pre-commit чеклиста — вместо того чтобы просто писать код. Codex получает минимальный системный промпт и тратит все токены на решение.

Codex склонен к более простым архитектурным решениям. Единый тип вместо иерархии, closure вместо отдельных полей, sort by ID вместо iterative convergence. Это может быть свойством модели, а может — следствием medium effort: меньше “думает”, меньше over-engineers.

Claude более “defensive” и формальный. Отдельные типы для input и compute, explicit type safety, больше комментариев. Для большого проекта с командой это может быть преимуществом. Для решения задачи — overhead.

После этого эксперимента я упростил свои rule-файлы для Claude Code (с 777 до 436 строк) и добавил “Fast Path” в workflow — для багфиксов и задач с понятной реализацией модель пропускает обязательный TDD-цикл и code review loop. Посмотрим, как это повлияет на скорость.

Воспроизведение

Задачи из Exercism Go track : Tournament , React .

Запуск Claude Code:

# Через Agent (feature-implementer subagent)
# Промпт с описанием задачи + "run go test -v -race ./..."

Запуск Codex:

codex exec -m gpt-5.4 \
  --dangerously-bypass-approvals-and-sandbox \
  -C /path/to/exercise \
  "описание задачи"