
Claude Code и Codex исправили подписи в учебном шаблоне Telegram-бота: обе правки прошли 14 проверок в браузере. Codex закончил за 3 мин 31 с, Claude Code за 4 мин 32 с. При этом тесты, которые написали агенты, отклоняли часть правильных вариантов кода.
Прогон 8 октября 2026 года: одна задача, по одной попытке. Общего победителя он не определяет. В исходники шаблона я взял правку Codex: она короче и обходится без дополнительной ветки для теста.
В бесплатном шаблоне Telegram Mini App, который лежит у нас готовым материалом, список клиентов в панели бота подписан без склонения, например «2 входящих, 1 ответов». Архив для скачивания пока со старой подписью.
Подпись собирает одна строка кода, но ошибиться легко: числа от 11 до 14 и 111 склоняются иначе, чем 1, 21 и 101, а заметка клиента должна заменять счётчики. На глаз такое не проверишь, нужен тест.

Если один агент может ходить в сеть и писать куда угодно, а второй сидит в закрытой папке, вы сравниваете настройки. Поэтому условия записали до запуска и уравняли всё, что смогли.
Версия, модель, уровень рассуждения
2.1.280, Opus 5.5, xhigh
0.162.0-alpha.2, GPT-6.1 Sol, xhigh
Запуск без диалога
claude -p, бинарник из расширения VS Code
codex exec, бинарник из своего расширения
Проект
копия шаблона и окружения Python из одного коммита
такая же копия
Файлы правил
нет; личные настройки и MCP отключены
нет; личный AGENTS.md пустой
Песочница
запись только в свою папку и временный каталог, сеть закрыта
то же, режим workspace-write
Вмешательство человека
ни одной реплики
ни одной реплики
Три различия убрать не удалось: уровень xhigh у двух компаний совпадает только по названию, Codex мог подтянуть общие для аккаунта заметки памяти, а у Claude Code поверх песочницы работает свой слой разрешений. Задание у обоих одно, текст ниже.
Сам прогон готовили с помощью Claude Code. Поэтому результат принимал отдельный скрипт, который не знает устройства кода. Он открывал панель из каждой копии в браузере, подставлял 13 клиентов с парами чисел и одного с заметкой и сверял подписи. На исходной версии он нашёл 8 ошибок из 14.
Обе правки прошли приёмку с первого раза, без ручных правок.
Время до ответа
4 мин 32 с
3 мин 31 с
Приёмка, 14 случаев
14 из 14
14 из 14
Общий прогон вне песочницы
83 теста: 82 прежних и запуск Node-теста
82 теста; Node-тест отдельно
Что изменил
app.js (+26 −2), README, два файла тестов
app.js (+14 −1), один файл теста
Свои тесты
9 тестов: функции из app.js и старт панели
2 теста: 324 пары чисел и заметка
Проверка своих тестов
6 раз нарочно ломал правку, тест падал
тест упал на исходной версии
Отказы разрешений
5 отказов при самопроверке; от первого до рабочего запуска 50 с
нет
Оба написали, чего не смогли проверить: в песочнице 26 серверных тестов не открыли локальный порт. Claude Code ещё и сверил, что до правки они падали так же. Вне песочницы весь набор прошёл.
Оба агента работали по подписке, дополнительных списаний не было. Сумма 1,42 доллара в журнале Claude Code рассчитана по прайсу API. Долю квоты на задачу выделить нельзя: аккаунт Claude использовали другие сессии, а журнал codex exec её не показывает. Как читать свой журнал, разобрано в замерах расхода Claude Code.
Мы поменяли тесты агентов местами. Этой проверки в протоколе не было, её добавили после итогов. Тест Codex проходит на правке Claude Code и ловит поломку в обеих, если убрать исключение для чисел от 11 до 14. Тест Claude Code на правке Codex падает: ждёт экспорт, которого там нет.

Через неделю, при проверке статьи, сделали ещё две правильные правки: подпись через innerText вместо textContent и блок подписи через createElement, как в соседнем экране. Обе прошли приёмку в браузере 14 из 14, а тест Codex упал на обеих: его подставная страница не знает innerText и не умеет insertBefore. На четырёх правильных правках приёмка прошла 4 раза, тест Codex 2, тест Claude Code 1.
Claude Code вынес склонение в отдельные функции и в конце app.js добавил ветку: если файл запущен под Node, экспортировать их и не запускать панель. Его тест проверяет эти функции. Ещё он подключил тест к общему набору и дописал README: без этого новый тест легко забыть.
// Под Node (tests/webapp.test.js) файл отдаёт чистые функции и страницу не
// трогает. В браузере module не определён, и панель стартует как обычно.
if (typeof module === 'object' && module.exports) {
module.exports = { plural: plural, contactSummary: contactSummary };
return;
}
start();
})();Codex код панели не перестраивал. Склонение у него одна функция рядом с отрисовкой списка. Тест исполняет весь app.js на самодельной подставной странице, открывает вкладку «Клиенты» и читает подписи из поля textContent.
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); }
};
}На 22 октября 2026 года Беларуси и России нет в официальных списках стран ни у Anthropic, ни у OpenAI. Если Anthropic поддерживает вашу страну, откройте инструкцию по установке Claude Code.
Ниже задание и команды запуска. Приёмка показана фрагментом: подготовка данных и сравнение подписей в него не входят.
Ты работаешь в каталоге шаблона 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 в духе этого файла. Работай сам до конца и вопросов не задавай: отвечать на них некому. Сети нет. В конце коротко: что изменил, как проверил, какой командой запускается тест.
# 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.jsonlawait 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));На этой правке ничья по приёмке: оба прошли 14 из 14. Codex справился быстрее и меньшей правкой. Claude Code проверил тест шестью нарочными поломками и дописал README, но добавил в код ветку ради теста. Тесты обоих привязаны к устройству кода: падение чужого теста не доказывает ошибку, правильность здесь подтвердила только приёмка в браузере. Большие переделки требуют своих прогонов.
В работе у меня оба: Claude Code пишет код и тексты, Codex вычитывает статьи до публикации, эту тоже. Настроить такую связку под свой репозиторий можно на менторинге по вайб-кодингу.
Что такое ИИ-агент и чем он отличается от чат-бота
ИИ-агент простыми словами: чем он отличается от чат-бота и ассистента. Проверили на Claude: без инструментов модель отчиталась о правке, которой не было.
AGENTS.md: что это и пример для Codex и Claude
Что такое файл AGENTS.md и кто из агентов его читает: пример, проверенный в Codex и Claude Code, и строка, без которой Claude Code может его не увидеть.
Промпт-инъекция: что это и как угоняют ИИ-агента
Что значит термин, как письмо или README подсовывают агенту чужую команду (проверили на Claude Code) и что поменять в своих настройках.