Claude Code или Codex: одна правка и разные тесты

7 минут чтения

Claude Code и Codex исправили подписи в учебном шаблоне Telegram-бота: обе правки прошли 14 проверок в браузере. Codex закончил за 3 мин 31 с, Claude Code за 4 мин 32 с. При этом тесты, которые написали агенты, отклоняли часть правильных вариантов кода.

Прогон 8 октября 2026 года: одна задача, по одной попытке. Общего победителя он не определяет. В исходники шаблона я взял правку Codex: она короче и обходится без дополнительной ветки для теста.

Задача: «1 входящих, 1 ответов»

В бесплатном шаблоне Telegram Mini App, который лежит у нас готовым материалом, список клиентов в панели бота подписан без склонения, например «2 входящих, 1 ответов». Архив для скачивания пока со старой подписью.

Подпись собирает одна строка кода, но ошибиться легко: числа от 11 до 14 и 111 склоняются иначе, чем 1, 21 и 101, а заметка клиента должна заменять счётчики. На глаз такое не проверишь, нужен тест.

Список клиентов в панели бота: до правки «1 входящих, 1 ответов», после «1 входящее, 1 ответ»
Экран панели до и после правки Codex.

В каких условиях сравнивали агентов

Если один агент может ходить в сеть и писать куда угодно, а второй сидит в закрытой папке, вы сравниваете настройки. Поэтому условия записали до запуска и уравняли всё, что смогли.

Claude Code
Codex

Версия, модель, уровень рассуждения

Claude Code

2.1.280, Opus 5.5, xhigh

Codex

0.162.0-alpha.2, GPT-6.1 Sol, xhigh

Запуск без диалога

Claude Code

claude -p, бинарник из расширения VS Code

Codex

codex exec, бинарник из своего расширения

Проект

Claude Code

копия шаблона и окружения Python из одного коммита

Codex

такая же копия

Файлы правил

Claude Code

нет; личные настройки и MCP отключены

Codex

нет; личный AGENTS.md пустой

Песочница

Claude Code

запись только в свою папку и временный каталог, сеть закрыта

Codex

то же, режим workspace-write

Вмешательство человека

Claude Code

ни одной реплики

Codex

ни одной реплики

Три различия убрать не удалось: уровень xhigh у двух компаний совпадает только по названию, Codex мог подтянуть общие для аккаунта заметки памяти, а у Claude Code поверх песочницы работает свой слой разрешений. Задание у обоих одно, текст ниже.

Сам прогон готовили с помощью Claude Code. Поэтому результат принимал отдельный скрипт, который не знает устройства кода. Он открывал панель из каждой копии в браузере, подставлял 13 клиентов с парами чисел и одного с заметкой и сверял подписи. На исходной версии он нашёл 8 ошибок из 14.

Что показала проверка двух агентов

Обе правки прошли приёмку с первого раза, без ручных правок.

Claude Code
Codex

Время до ответа

Claude Code

4 мин 32 с

Codex

3 мин 31 с

Приёмка, 14 случаев

Claude Code

14 из 14

Codex

14 из 14

Общий прогон вне песочницы

Claude Code

83 теста: 82 прежних и запуск Node-теста

Codex

82 теста; Node-тест отдельно

Что изменил

Claude Code

app.js (+26 −2), README, два файла тестов

Codex

app.js (+14 −1), один файл теста

Свои тесты

Claude Code

9 тестов: функции из app.js и старт панели

Codex

2 теста: 324 пары чисел и заметка

Проверка своих тестов

Claude Code

6 раз нарочно ломал правку, тест падал

Codex

тест упал на исходной версии

Отказы разрешений

Claude Code

5 отказов при самопроверке; от первого до рабочего запуска 50 с

Codex

нет

Оба написали, чего не смогли проверить: в песочнице 26 серверных тестов не открыли локальный порт. Claude Code ещё и сверил, что до правки они падали так же. Вне песочницы весь набор прошёл.

Расход: почему цену задачи не посчитать

Оба агента работали по подписке, дополнительных списаний не было. Сумма 1,42 доллара в журнале Claude Code рассчитана по прайсу API. Долю квоты на задачу выделить нельзя: аккаунт Claude использовали другие сессии, а журнал codex exec её не показывает. Как читать свой журнал, разобрано в замерах расхода Claude Code.

Почему тесты отвергли правильные правки

Мы поменяли тесты агентов местами. Этой проверки в протоколе не было, её добавили после итогов. Тест Codex проходит на правке Claude Code и ловит поломку в обеих, если убрать исключение для чисел от 11 до 14. Тест Claude Code на правке Codex падает: ждёт экспорт, которого там нет.

Терминал: приёмка 6, 14 и 14 из 14; тест Codex проходит на чужой правке, тест Claude Code падает
Вывод проверок 8 октября.

Через неделю, при проверке статьи, сделали ещё две правильные правки: подпись через innerText вместо textContent и блок подписи через createElement, как в соседнем экране. Обе прошли приёмку в браузере 14 из 14, а тест Codex упал на обеих: его подставная страница не знает innerText и не умеет insertBefore. На четырёх правильных правках приёмка прошла 4 раза, тест Codex 2, тест Claude Code 1.

Claude Code вынес склонение в отдельные функции и в конце app.js добавил ветку: если файл запущен под Node, экспортировать их и не запускать панель. Его тест проверяет эти функции. Ещё он подключил тест к общему набору и дописал README: без этого новый тест легко забыть.

Конец app.js в правке Claude Code
  // Под Node (tests/webapp.test.js) файл отдаёт чистые функции и страницу не
  // трогает. В браузере module не определён, и панель стартует как обычно.
  if (typeof module === 'object' && module.exports) {
    module.exports = { plural: plural, contactSummary: contactSummary };
    return;
  }

  start();
})();

Codex код панели не перестраивал. Склонение у него одна функция рядом с отрисовкой списка. Тест исполняет весь app.js на самодельной подставной странице, открывает вкладку «Клиенты» и читает подписи из поля textContent.

Подставная страница из теста Codex
function element() {
  const fields = new Map();
  return {
    value: '',
    textContent: '',
    children: [],
    listeners: {},
    classList: { add() {}, remove() {} },
    set innerHTML(html) {
      this.children.length = 0;
      fields.clear();
    },
    querySelector(selector) {
      if (!fields.has(selector)) fields.set(selector, element());
      return fields.get(selector);
    },
    addEventListener(type, callback) { this.listeners[type] = callback; },
    appendChild(child) { this.children.push(child); }
  };
}

Как проверить агентов на своей задаче

  1. Возьмите две-три проверяемые задачи и повторите каждую дважды для обоих агентов.
  2. До запуска запишите критерии и подготовьте отдельную проверку результата.
  3. Для каждой попытки сделайте две копии проекта из одного коммита, с одинаковым окружением.
  4. Уравняйте доступ к сети, файлам и командам. Дайте обоим общий AGENTS.md. Различия разрешений и уровней рассуждения запишите отдельно.
  5. Не отвечайте агентам по ходу. Любое вмешательство запишите.
  6. Проверьте результат отдельно. Тесты агентов запустите на чужой правке, на другой реализации, прошедшей приёмку, и на правке с намеренно внесённой ошибкой. Для каждого падения выясните причину.
  7. Запишите время, изменения и расход каждого инструмента отдельно.

На 22 октября 2026 года Беларуси и России нет в официальных списках стран ни у Anthropic, ни у OpenAI. Если Anthropic поддерживает вашу страну, откройте инструкцию по установке Claude Code.

Ниже задание и команды запуска. Приёмка показана фрагментом: подготовка данных и сравнение подписей в него не входят.

task.md: одно задание для обоих агентов (тире заменены двоеточиями)
Ты работаешь в каталоге шаблона Telegram-бота с панелью управления (mini app): Python-сервер в app/, панель без сборки в webapp/, тесты в tests/.

Задача. В списке клиентов панели (вкладка «Клиенты») подпись под именем собирается без склонения: «1 входящих, 1 ответов», «2 входящих, 1 ответов». Код: webapp/app.js, функция renderContacts. Сделай так, чтобы подпись читалась по-русски.

Критерии приёмки (после твоей работы их проверят независимо):
1. Подпись имеет вид «<N> <слово>, <M> <слово>», слова согласованы с числом:
   - входящие: 1, 21, 101: «входящее»; 0, 2, 4, 5, 11, 12, 22, 111: «входящих»;
   - ответы: 1, 21, 101: «ответ»; 2, 4, 22: «ответа»; 0, 5, 11, 12, 14, 111, 112: «ответов».
2. Если у клиента есть заметка, она по-прежнему показывается вместо подписи.
3. Склонение покрыто автотестом, который запускается одной командой без установки новых зависимостей. Назови эту команду в итоговом сообщении.
4. Существующие тесты проходят: `.venv/bin/python -m unittest discover -s tests` (сейчас 82 теста, все зелёные).
5. Меняются только файлы в webapp/ и tests/ (README: по желанию). Серверную часть, зависимости и структуру проекта не трогай. Панель остаётся без сборки: обычный JavaScript в духе этого файла.

Работай сам до конца и вопросов не задавай: отвечать на них некому. Сети нет. В конце коротко: что изменил, как проверил, какой командой запускается тест.
Запуск обоих агентов, как в прогоне 8 октября
# task.md: задание. claude и codex: бинарники из расширений VS Code, их папки в PATH.
# Обе копии: git-репозитории с исходным коммитом, так потом виден дифф,
# а codex exec вне git-репозитория не запускается.
# В этом режиме слой разрешений claude -p у нас отклонил 4 команды и запись файла
# во временный каталог, агент их переписал.
cd /tmp/exp/claude
claude -p "$(cat ../task.md)" --model claude-opus-5-5 --effort xhigh \
  --setting-sources project,local --strict-mcp-config \
  --settings '{"sandbox":{"enabled":true,"autoAllowBashIfSandboxed":true,"allowUnsandboxedCommands":false}}' \
  --permission-mode acceptEdits --disallowedTools "WebFetch WebSearch Agent Skill" \
  --no-session-persistence --output-format stream-json --verbose > ../claude-run.jsonl

cd /tmp/exp/codex
codex exec -m gpt-6.1-sol -c model_reasoning_effort='"xhigh"' -s workspace-write \
  -C /tmp/exp/codex --ephemeral --json -o ../codex-last.txt "$(cat ../task.md)" > ../codex-run.jsonl
Фрагмент приёмки
await page.route('**/*', async (route) => {
  const url = new URL(route.request().url());
  if (url.hostname === 'telegram.org') return route.fulfill({ contentType: 'application/javascript', body: SHIM });
  if (url.pathname === '/') return route.fulfill({ contentType: 'text/html', body: readFileSync(join(dir, 'webapp/index.html')) });
  if (url.pathname.startsWith('/static/')) {
    const file = url.pathname.replace('/static/', '');
    const type = file.endsWith('.css') ? 'text/css' : 'application/javascript';
    return route.fulfill({ contentType: type, body: readFileSync(join(dir, 'webapp', file)) });
  }
  if (api[url.pathname]) return route.fulfill({ contentType: 'application/json', body: JSON.stringify(api[url.pathname]) });
  return route.fulfill({ status: 404, body: '' });
});
await page.goto('http://acceptance.test/');
await page.waitForFunction(() => document.querySelectorAll('#contacts .item__text').length > 0, null, { timeout: 10000 }).catch(() => {});
const actual = await page.$$eval('#contacts .item__text', (els) => els.map((e) => e.textContent));

Так что лучше: Claude Code или Codex

На этой правке ничья по приёмке: оба прошли 14 из 14. Codex справился быстрее и меньшей правкой. Claude Code проверил тест шестью нарочными поломками и дописал README, но добавил в код ветку ради теста. Тесты обоих привязаны к устройству кода: падение чужого теста не доказывает ошибку, правильность здесь подтвердила только приёмка в браузере. Большие переделки требуют своих прогонов.

В работе у меня оба: Claude Code пишет код и тексты, Codex вычитывает статьи до публикации, эту тоже. Настроить такую связку под свой репозиторий можно на менторинге по вайб-кодингу.

Что дальше

Новые посты на почту

Без спама. Отписка в один клик в любом письме.