Я Go-разработчик, но у меня есть собственный проект - и это значит, что Go только часть работы. В обычную неделю я переключаюсь между Go-бэкендом, SQL, React и TypeScript, дизайном API, архитектурой, Docker, CI/CD, инфраструктурой, тестами и UX.

Проблема не в том, что я чего-то из этого «не знаю». Невозможно держать все эти области в голове одновременно и при этом в одиночку делать продукт целиком. Контекст-свитчинг стоит дорого сам по себе.

AI помогает. И примерно здесь у всех начинается один и тот же спор: Claude или Codex? Кто лучше пишет код, за какую подписку платить.

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

задача → нейросеть сама придумала → сама написала → сама себя проверила → сказала, что всё готово

Один исполнитель, который одновременно заказчик, архитектор, разработчик и ревьюер. В командной разработке так не работает, и с моделями тоже.

Поэтому я перестал выбирать и развёл роли: Claude принимает решения. Codex реализует. Claude независимо проверяет результат.

Это дало три вещи, а не одну:

  1. Модели проверяют друг друга. Codex до реализации разносит план Claude, Claude после реализации читает diff Codex. Ни одна не подписывает собственную работу.

  2. Токены тратятся осмысленнее. Дорогое рассуждение - на требования, архитектуру и ревью; чтение кода, boilerplate и тесты - на более экономичного исполнителя.

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

Дальше - как это устроено, как повторить, полный skill и честный список того, что подход не решает.

Почему не «одна модель на всё»

Когда сравнивают Claude и Codex, их обычно ставят на одну и ту же роль: кто напишет функцию лучше. Ответ всегда получается «зависит от задачи», и он бесполезен.

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

Если отдать всё это одной модели, я получаю не «лучшую модель на трёх ролях», а одну модель без внешнего контроля. Что при этом ломается на практике:

  • Модель защищает своё решение. Выбранный на первом шаге подход достраивается дальше, даже когда видно, что он неудачный.

  • «Тесты проходят» становится доказательством корректности. Хотя тесты писала та же модель из тех же предположений: неверное предположение тест не поймает, а закрепит.

  • Отчёт о выполнении не равен выполнению. «Реализовано, всё работает» встречается и там, где часть требований потерялась по дороге.

  • Контекст размывается. К концу длинной сессии требования уже переформулированы самой моделью, и не в лучшую сторону.

Это не про плохие модели, это про отсутствие процесса. Тот же результат даст человек, который пишет требования, код, тесты и сам себя ревьюит за пять минут до релиза.

Разделение ролей

Блок-схема взаимодействия AI-агентов
Блок-схема взаимодействия AI-агентов

Claude - tech lead. Разбирает задачу, лезет в репозиторий, формулирует требования и ограничения, принимает архитектурные решения, пишет PLAN.md с проверяемыми критериями приёмки, потом сам читает diff и решает, принята работа или нет.

Codex - исполнитель. Реализует утверждённый план, пишет и правит тесты, делает необходимый рефакторинг в рамках задачи, исправляет найденное на ревью.

Ключевое правило: Claude не делегирует Codex архитектурные решения и приёмку, Codex не переопределяет план по ходу дела.

Проверка при этом двусторонняя. Codex проверяет Claude до реализации: читает PLAN.md в read-only и пытается его сломать - это дёшево, кода ещё нет. Claude проверяет Codex после: читает diff и сверяет с критериями. Каждая модель попадает под независимый взгляд там, где её ошибка стоит дороже всего: у Claude это неверно понятое требование, у Codex - реализация, разошедшаяся с планом.

И PLAN.md здесь - письменный контракт, который нельзя незаметно переформулировать в середине разговора.

Это не «две модели спорят и договариваются». Codex - советник и исполнитель, а не вторая инстанция. Финальное решение за Claude, ответственность за архитектуру - за мной.

Стек и модели

Работаю на macOS, основной редактор - VS Code. Локально стоят Claude Code, Codex CLI, расширения Claude и Codex для VS Code и официальный OpenAI-плагин codex-plugin-cc для Claude Code - именно он позволяет Claude делегировать работу локальному Codex без кастомной настройки MCP. (К Codex, кстати, можно подключиться и по MCP прямо локально - такая возможность есть.)

VS Code удобен тем, что оба агента видят один репозиторий, изменения сразу в редакторе, git diff и терминал рядом, и не надо копировать куски проекта в браузерные чаты. Но схема его не требует - всё работает из обычного терминала. Это просто мой рабочий интерфейс, настроенный за годы под себя.

Рабочая конфигурация:

  • Claude: Opus / high - решения, план, ревью, приёмка

  • Codex: GPT-5.6 Terra / high - реализация, тесты, фиксы

Opus / high отвечает там, где ошибка дороже всего: понимание задачи, границы изменений, архитектурный выбор, критерии приёмки, проверка diff. Здесь важно удерживать связи между частями системы и различать «работает» и «корректно».

Terra / high отвечает за объём: прочитать много кода, вписаться в конвенции, написать реализацию и тесты, прогнать проверки. Это большая механическая работа с уже готовой спецификацией.

Terra / xhigh поднимаю для действительно сложного: concurrency, распределённые системы, нетривиальная работа с БД, миграции, сложный root-cause debugging, крупный взаимосвязанный рефакторинг. Sol - только escalation, когда Terra реально не справляется или цена ошибки особенно высока. Держать максимум везде смысла нет: дороже и медленнее, а на типовой реализации по готовому плану качество заметно не растёт.

Sonnet использую, когда хочется и есть возможность сэкономить, но минимум - Sonnet / high. Начиная с medium он критично пропускает контекст кода и смысла; выяснил на личном тестировании, особенно заметно в большом репозитории, где изменение затрагивает несколько слоёв. Экономия оказывается ложной: дальше идут дополнительные итерации и правки того, что было упущено.

Отсюда главный практический вывод: high - минимально комфортный reasoning для разработки на экономичных моделях. На пониженных режимах я стабильно получал пропущенные связи между файлами, игнорирование конвенций репозитория, поверхностные тесты на happy path и необходимость объяснять одно и то же по второму кругу. Каждая такая итерация - ещё один полный проход по контексту плюс моё время.

Это не касается Sol и Fable: они нормально отрабатывают и на medium, но для постоянной работы требуют дорогих тарифов. А зачем платить больше, если можно платить меньше? =)

Установка

Claude Code:

npm install -g @anthropic-ai/claude-code
claude --version

или плагин для IDE.

Codex CLI:

Cтавится отдельно и должен быть доступен как codex в PATH (codex --version). Актуальные команды установки обоих инструментов лучше сверить с официальной документацией - они меняются.

Плагин codex-plugin-cc - внутри claude:

/plugin marketplace add openai/codex-plugin-cc
/plugin install codex@openai-codex
/reload-plugins
/codex:setup

актуальную информацию лучше смотреть тут->

Появятся команды /codex:review, /codex:adversarial-review, /codex:rescue, /codex:status, /codex:result. Ими можно пользоваться вручную, но смысл skill ниже ровно в том, чтобы не оркестрировать это руками при каждой задаче.

Дефолтный worker - в ~/.codex/config.toml:

model = "gpt-5.6-terra"
model_reasoning_effort = "high"

Стоит по-умолчанию в нынешнем релизе codex

Более сильные конфигурации в дефолт не прописываются, а задаются точечно на конкретной задаче.

Skill cdx

Skill описывает весь процесс: кто за что отвечает, как исследовать репозиторий, как писать PLAN.md, как запускать adversarial review, как вести builder-thread, как ревьюить diff и принимать работу.

Я назвал /cdx, просто потому что мне так удобно. Это локанично, удобно писать каждый раз, не перекликается с другими скиллами, логически понятно. Вы можете назвать как вам угодно.

Создаём папку скилла для claude:

mkdir ~/.claude/skills/cdx

Потом в нём добавляем сам файл со скиллом, который будет использовать claude:

Дальше создать в папке ~/.claude/skills/cdx/ файл SKILL.md и положить туда следующее целиком:

Скрытый текст
---
name: cdx
description: Claude leads the task while Codex implements it. Use for non-trivial software development where Claude should own requirements, architecture, review, and acceptance.
disable-model-invocation: true
effort: high
---

# Cdx

Claude is the lead engineer.

Codex is the implementation worker.

## Ownership

Claude owns:

- requirements
- architecture
- technical decisions
- planning
- acceptance criteria
- review
- final approval

Codex owns:

- implementation
- tests
- refactoring required by the task
- fixes requested during review

Do not let Codex make final architectural or acceptance decisions.

Do not write substantial implementation code yourself while this
workflow is active.

## Codex background tasks — always report to the user

Steps 3, 4, and 6 invoke `codex:codex-rescue`, which typically runs as a
background task. Whenever anything comes back from it — a
task-notification, a resumed-agent reply, or a direct
`codex-companion.mjs status`/`result` check — relay it to the user in
that same turn, close to verbatim. Never sit on a Codex response and
only reveal it after deciding unilaterally what to do next.

- If it's a genuine finished result (review findings, build report),
  present it per `codex:codex-result-handling` and stop for user
  direction before acting on it.
- If it's not actually finished — Codex stalled on its own internal
  skill-picker, asked a clarifying question, hit an auth prompt, or
  exited with an error — that is an incomplete run per
  `codex:codex-result-handling`. Report the stall/failure explicitly,
  including the raw message, before deciding whether to resume or
  retry. Do not silently resend a new prompt or guess at a fix without
  telling the user what actually happened first.
- If the user asks for a status update and the subagent hasn't
  reported one, check directly and read-only with
  `node <path-to-codex-companion.mjs> status <task-id>` (and `result`
  if completed) rather than leaving them without an answer.
- `codex-rescue`'s own task-notification fires as soon as it hands the
  prompt off to Codex (it is a pure forwarder that calls `task` once
  and does not poll), not when Codex actually finishes. Treat that
  notification as "dispatched", not "done". After dispatching or
  resuming a task, proactively poll
  `node <path-to-codex-companion.mjs> status <task-id>` yourself at a
  reasonable cadence (e.g. every 30-60s, via `ScheduleWakeup` or a
  short sleep loop) until it reaches a real terminal state, then
  report the outcome — do not wait for the user to ask "как там?".

## 1. Investigate

Before asking the user questions, inspect the repository.

Read relevant:

- CLAUDE.md
- AGENTS.md
- README
- manifests and build configuration
- existing implementation
- tests
- git status and current diff

Use Claude Code's read-only Explore agent for broad repository search
when useful.

Do not ask questions that can be answered from the repository.

Ask the user only when ambiguity materially affects:

- behavior
- architecture
- public API
- data model
- security
- compatibility
- destructive actions
- task scope

For small reversible implementation details, make a reasonable
assumption instead of interrupting the user.

## 2. Plan

For non-trivial tasks create PLAN.md.

Keep it short.

Use:

# Goal

# Requirements

# Non-goals

# Constraints

# Acceptance criteria

# Implementation plan

# Verification

Acceptance criteria must be observable and testable.

## 3. Challenge the plan

For a non-trivial change, run one independent Codex planning review
before implementation.

Invoke the installed `codex:codex-rescue` subagent.

Start a fresh Codex task.

Explicitly request READ-ONLY behavior.

Prompt it approximately:

"Read PLAN.md and inspect the relevant repository code.

READ ONLY. Do not modify files.

Critique the plan adversarially.

Look for:
- misunderstood requirements
- unnecessary complexity
- missing edge cases
- architectural conflicts
- compatibility problems
- security problems
- concurrency problems
- data-integrity risks
- missing tests
- simpler solutions

Return only meaningful findings classified as:

BLOCKER
MAJOR
MINOR

Finish with:

VERDICT: APPROVE

or:

VERDICT: REVISE"

Evaluate the findings yourself.

Codex is an advisor here, not the authority.

Update PLAN.md only for valid findings.

Do not perform a fixed number of review rounds.

One planning review is normally enough.

## 4. Build

Start a NEW fresh Codex task through the installed
`codex:codex-rescue` subagent.

This becomes the persistent builder thread.

Tell Codex:

"Implement the approved PLAN.md.

PLAN.md is the contract.

Rules:

- inspect repository conventions before editing
- preserve existing user changes
- stay inside scope
- prefer the smallest coherent implementation
- add or update tests where appropriate
- run relevant tests, builds and linters
- do not commit
- do not push
- do not deploy
- do not modify secrets
- do not weaken tests merely to make them pass

When finished report:

1. changed files
2. implementation summary
3. verification performed
4. failures or limitations
5. assumptions"

Default Codex configuration comes from `.codex/config.toml`.

Expected default:

gpt-5.6-terra / high.

## 5. Review

Never trust Codex's completion report by itself.

Claude must independently inspect:

- git status
- complete relevant diff
- changed files
- tests
- verification output

Compare the implementation with PLAN.md.

Check:

- all requirements
- every acceptance criterion
- correctness
- edge cases
- error handling
- security
- authorization
- compatibility
- concurrency
- data integrity
- unnecessary complexity
- unrelated modifications
- test quality

Claude is the quality gate.

## 6. Fix

If problems are found, continue the SAME Codex builder task.

Do not start a new builder.

Resume the previous builder and send only verified findings.

Prompt approximately:

"Continue the existing implementation.

Fix only these review findings:

...

For every finding:

- identify the root cause
- make the smallest correct fix
- add a regression test when appropriate
- rerun relevant verification

Do not expand scope."

Then Claude reviews the new diff again.

Repeat until acceptance criteria pass.

## 7. Escalation

Default:

gpt-5.6-terra / high

Use Terra xhigh for genuinely difficult:

- concurrency
- distributed systems
- subtle database correctness
- risky migrations
- difficult root-cause debugging
- large interacting refactors

Escalate to gpt-5.6-sol only when:

- Terra repeatedly fails
- correctness is unusually critical
- stronger reasoning is clearly justified

Do not use max reasoning by default.

## 8. Finish

Approve only when acceptance criteria are satisfied.

Return briefly:

- what was built
- important problems found
- verification performed
- remaining risks

Final status:

APPROVED

or

APPROVED WITH CAVEATS

or

NOT APPROVED

Добавил polling кодекс клаудом. Без этого надо у claude спрашивать "ну как там дела?".

Скилл должен быть на английском, чтобы агент тратил на него меньше токенов. Он работает с английским текстом и с другого языка он будет тратить токены на перевод.

Три решения внутри, которые я считаю принципиальными:

  1. disable-model-invocation: true - skill запускается только явной командой /cdx, а не когда модель сама решит, что пора звать Codex.

  2. Один persistent builder thread - исправления по ревью идут в ту же Codex-задачу. Новый thread теряет контекст реализации и чинит симптом вместо причины.

  3. Число итераций не фиксировано. Ни «ровно три раунда ревью», ни «ровно два adversarial-прохода»: модель, которую попросили что-то найти, обязательно что-нибудь найдёт. Плюс стоп-правило: если один дефект пережил две осмысленные попытки починки - возвращаться к причине и к PLAN.md, а не повторять инструкцию третий раз.

Запуск и пример

claude

Внутри: /model opus или sonnet, /effort high, затем /cdx и постановка задачи на уровне требования, а не техзадания:

/cdx

Добавь в кабинет пользователя историю фоновых задач.
Backend API уже существует.

Нужно показывать: активные задачи, завершённые, прогресс, ошибку выполнения.
Активные задачи должны обновляться автоматически.

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

Дальше - как проходит один цикл. Стек в примере: Go на бэкенде, React + TypeScript на фронте. Эндпоинты, имена и findings ниже иллюстративные - они показывают форму процесса, а не мой реальный код.

1. Claude читает репозиторий, а не задаёт вопросы: существующий API задач, типы, routing, похожие страницы, принятый подход к загрузке данных, тесты. Вопрос ко мне остаётся один - за какой период показывать историю (это влияет на API и UX, из кода не выводится).

2. Claude пишет PLAN.md:

# Goal
Страница «Фоновые задачи»: активные и завершённые задачи с прогрессом и причиной ошибки.

# Requirements
- активные задачи с индикатором прогресса
- завершённые (успех/ошибка) за 30 дней, для упавших — текст ошибки
- обновление активных без перезагрузки страницы
- состояния загрузки, пустого списка и недоступности бэкенда

# Non-goals
- отмена и перезапуск задач, пагинация, изменения backend API

# Constraints
- существующий API: GET /api/tasks, GET /api/tasks/stream (SSE)
- React + TypeScript, существующий api-client, новых зависимостей не добавлять

# Acceptance criteria
1. Роут /account/tasks доступен из меню кабинета.
2. Прогресс активных задач берётся из потока обновлений.
3. Упавшая задача показывает текст ошибки из API.
4. При обрыве потока UI переходит в состояние «обновления недоступны» и переподключается.
5. Одновременно открыто не более одного потока обновлений.
6. Пустой список — пустое состояние, а не бесконечная загрузка.
7. Тесты: рендер списков, состояние ошибки, обрыв потока.

# Implementation plan
типы → api-client → хук подписки → компоненты → страница и роут → тесты

# Verification
unit-тесты, typecheck, линтер, ручная проверка на активной и упавшей задаче

3. Codex делает read-only adversarial review плана:

MAJOR: не определено поведение при разрыве SSE-соединения.
План описывает получение обновлений, но не реакцию UI на разрыв,
стратегию переподключения и предотвращение дублей.

VERDICT: REVISE

Это резюме аудита, оно не носит характер требования - Claude оценивает каждое замечание сам. Здесь я согласен: обрыв SSE в проде случается регулярно, а в разработке не воспроизводится. Из этого замечания и появились критерии 4 и 5 выше.

4. Terra реализует в новой Codex-задаче с правами на запись - это и есть persistent builder thread. PLAN.md передаётся как контракт.

5. Opus читает diff, а не отчёт Codex. Пример находки:

MAJOR: логика переподключения может открыть два SSE-соединения.
Обработчик onerror инициирует переподключение, предыдущее соединение
явно не закрывается, очистка срабатывает только при размонтировании.
При кратковременной сетевой ошибке получаем два активных подписчика.

Нарушен acceptance criterion 5.

Это ровно та категория дефектов, которую не поймают ни тесты (они не эмулируют флап сети), ни отчёт исполнителя (с его точки зрения всё реализовано).

6-7. Замечание уходит в тот же thread, Terra чинит корневую причину и добавляет регрессионный тест, который эмулирует ошибку соединения и проверяет, что подписка ровно одна.

8. Opus проверяет критерии явно, по списку:

1. Роут и пункт меню                   PASS
2. Прогресс активных задач             PASS
3. Текст ошибки упавшей задачи         PASS
4. Явное состояние при обрыве потока   PASS
5. Не более одного потока              PASS (regression test добавлен)
6. Пустое состояние                    PASS
7. Тесты                               PASS

RESULT: APPROVED

Remaining risks: переподключение проверено только в тестах,
поведение при длительной недоступности бэкенда вручную не проверялось

Раздел «Remaining risks» считаю обязательным: APPROVED без списка непроверенного - это APPROVED, которому не стоит верить. Дальше diff смотрю уже я.

Экономика

Я не утверждаю, что это дешевле в каждом отдельном запросе - запросов тут больше, чем в обычном диалоге. Экономия появляется на распределении:

  • Opus: требования, архитектура, решения, review.

  • Terra: чтение кода, реализация, boilerplate, tests, fixes.

Основной объём токенов в разработке - это не «придумать», а прочитать половину репозитория, написать десять файлов, обновить тесты и починить то, что не собралось. Этот объём уходит исполнителю, у которого уже есть спецификация. Дорогая модель не пишет каждую функцию и каждый React-компонент, а делает то, где её преимущество реально проявляется.

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

Чего я не делаю

Оркестрацию можно переусложнить не хуже микросервисов. Я сознательно не использую десяток subagents, пять моделей-ревьюеров, фиксированные пять итераций, максимальный reasoning везде, отдельный MCP-слой поверх уже установленного плагина и автоматический бесконечный Claude ↔ Codex loop.

Каждый лишний участник - это ещё одна передача контекста, на которой что-то теряется. Обязательный третий раунд ревью без замечаний порождает выдуманные замечания. А бесконечный автоматический loop без человека, который скажет «здесь достаточно», не сходится - два агента способны долго улучшать друг друга, уходя от исходной задачи.

Плагин Superpowers

Отдельно про плагин Superpowers: он у меня установлен, но частью cdx не является. Понятная инженерная задача → /cdx. Сырая идея, где сначала надо понять, что вообще строить → brainstorming, и уже его результат становится входом для /cdx. Есть похожий скилл grill-me, но с Claude, как мне показалось, работает лучше Superpowers: brainstorming. На задачах, например, маркетинга или написания сценария для контента, мне понравился больше grill-me, но и специфика чуть-чуть иная.
За поиском новых идей лучше вообще идти в скилл llm-council.

Что это не решает

  • AI регулярно пишет ерунду - и Claude, и Codex. Разделение ролей повышает шанс, что её заметят до попадания в репозиторий, но не гарантирует.

  • PLAN.md не гарантирует хороший код. Плохой план даёт аккуратно реализованное плохое решение.

  • Второй агент тоже ошибается. Adversarial review возвращает и ложные findings - принимать их не думая значит ухудшить план.

  • Без понимания архитектуры вы быстрее получите плохую систему. Скорость реализации растёт, скорость принятия неверных решений тоже.

  • Ревью человеком остаётся обязательным. APPROVED от Claude - фильтр, а не подпись под релизом.

Разработчик из процесса никуда не исчезает - он перемещается с позиции «пишу каждую строку» на позицию «отвечаю за требования, архитектуру и приёмку». Это не более лёгкая позиция.

Итоги

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

Что это дало: несогласованность требований всплывает на этапе PLAN.md, а не на этапе diff; появился письменный контракт задачи; ревью перестало быть формальностью, потому что проверяющий не автор кода; проще переключаться между областями, потому что решения и объём работы разведены по разным шагам.

Чего не дало: волшебства. Мне по-прежнему нужно понимать, что происходит в системе, читать финальный diff и отвечать за результат.

AI хорошо масштабирует инженерную работу, но ответственность за архитектуру и результат остаётся у разработчика.