Codex와 Claude Code를 상호 호출하는 하네스(Harness)를 구축했다
요약
Codex와 Claude Code를 동일한 리포지토리에서 병용할 때 발생하는 수동 작업의 번거로움을 해결하기 위해 상호 호출 하네스(Harness)를 구축하는 방법을 다룹니다. CLAUDE_CODE_HANDOFF.md를 공유 메모로 활용하여 작업 의뢰, 리뷰 결과, 검증 조건을 체계적으로 전달함으로써 AI 간의 작업 계약을 유지하는 메커니즘을 설명합니다.
핵심 포인트
- 단순한 AI 실행을 넘어 작업 계약(work contract)을 유지하는 것이 공동 개발의 핵심임
- CLAUDE_CODE_HANDOFF.md를 시계열 공유 메모로 활용하여 AI 간의 컨텍스트 단절을 방지함
- Codex에서 Claude Code를 호출하는 리뷰 프로세스와 Claude Code에서 Codex를 호출하는 구현 프로세스를 자동화함
- 의뢰 범위, 검증 조건, 회신처 등을 수동 작성할 때 발생하는 누락 문제를 하네스 구축으로 해결함
서론
이 기사는 Codex와 Claude Code라는 두 가지 AI 코딩 에이전트(AI coding agent)를 동일한 리포지토리(repository)에서 병용하면서, 매번 무엇을 어느 쪽에 전달할지 수동으로 작성하는 것이 번거롭다고 느끼는 개인 개발자를 위한 글입니다.
Codex와 Claude Code를 동일한 리포지토리에서 사용하는 운영 방식은 이전에 cross-agent-harness로 분리했습니다. 여기서 말하는 하네스(harness)란, 의뢰 방식이나 리뷰 관점, 공개 게이트(publish gate)를 대화 외부(리포지토리 내의 파일과 스크립트)에 고정하는 메커니즘을 의미합니다.
지난 기사에서는 공동 작업을 위해 CLAUDE_CODE_HANDOFF.md, 프로젝트 프로필(project profile), 스킬(skills), 리뷰 게이트(review gate)를 준비했다는 내용을 다루었습니다. CLAUDE_CODE_HANDOFF.md(이하 handoff)는 AI 간의 작업 의뢰, 리뷰 결과, 미확인 사항을 시계열로 남기는 공유 메모입니다.
하지만 실제로 사용해 보니 다음과 같은 과제가 남았습니다.
- Codex에서 작업한 후, Claude Code가 리뷰해주길 원함
- Claude Code에서 설계한 후, Codex에 구현을 넘기고 싶음
- 그때마다 의뢰문, 대상 범위, 검증(verify) 조건, 회신처를 수동으로 작성하는 것이 번거로움
- 한쪽의 대화 로그에만 결과가 남으면, 다음 작업에서 추적할 수 없음
그래서 cross-agent-harness에 상호 호출을 위한 동선을 추가했습니다.
이 기사에서는 Claude Code에서 Codex를 호출하는 /codex-dev와, Codex에서 Claude Code를 리뷰 전용으로 호출하는 invoke-claude-review.ps1을 왜 나누었는지에 대해 작성하겠습니다.
두 개의 AI를 여는 것만으로는 공동 개발이 되지 않는다
Codex와 Claude Code는 모두 터미널(terminal)에서 사용할 수 있습니다. 단순하게 생각하면 두 개의 터미널을 열기만 하면 공동 개발이 가능해 보입니다.
하지만 저의 운영 방식에서는 그것만으로는 부족했습니다.
예를 들어 Codex로 구현한 후, Claude Code에게 리뷰를 부탁하고 싶은 상황이 있습니다. 이때 Claude Code에게 무엇을 전달해야 할까요?
- 최신 handoff
- 프로젝트 고유의 프로필(profile)
git diff HEAD- 리뷰 관점
- 작업 가능한 범위
- publish / push 가능 여부
이것을 매번 프롬프트(prompt)에 수동으로 작성하면 누락이 발생합니다.
역방향도 마찬가지입니다. Claude Code에서 설계를 구체화한 후, Codex에 구현을 넘기고 싶은 상황이 있습니다. 이때도 완성 조건, 대상 파일, 검증(verify) 명령, 금지 사항이 모호하면 Codex가 너무 넓은 범위를 건드리게 됩니다.
즉, 필요했던 것은 '다른 AI를 실행하는 것'이 아니었습니다. 작업 계약(work contract)을 유지한 채로 상대방에게 넘기는 것이었습니다.
호출 단위를 handoff로 설정했다
가장 먼저 결정한 것은 상호 호출의 중심을 CLAUDE_CODE_HANDOFF.md에 두는 것이었습니다.
호출 시의 프롬프트에만 의뢰 내용을 작성하면, 그 결과는 호출한 쪽의 세션(session)에 갇히게 됩니다. 다음 작업자가 읽기에는 취약합니다.
그래서 handoff에는 다음과 같은 내용을 남기도록 했습니다.
## YYYY-MM-DD HH:mm 추가 (<주제> — <agent> 작성)
- 대상: <branch / worktree / path>
- 작성자: <Codex | Claude Code | user>
...
이 형식을 갖춰두면 Codex에서 Claude Code를 호출하든, Claude Code에서 Codex를 호출하든 의뢰와 결과의 회신처가 동일해집니다.
상호 호출을 도식화하면 다음과 같은 형태입니다.
포인트는 Codex와 Claude Code가 직접 자유롭게 주고받는 것이 아니라, handoff를 사이에 두는 것입니다.
Claude Code에서 Codex를 호출하기
Claude Code에서 Codex를 호출하는 동선은 codex-dev 스킬(skill)로 배치했습니다.
이는 Claude Code가 설계와 구현 계획을 세우고, Codex를 MCP 서버를 통해 호출하여 구현을 위임하는 흐름입니다.
cross-agent-harness에서는 프로젝트의 .mcp.json에 Codex MCP 서버를 등록하는 것을 전제로 합니다.
{
"mcpServers": {
"codex": {
...
codex-dev
에서는 Codex에 전달할 지시 사항을 다음과 같이 고정하고 있습니다.
<RULE_FILE>의 규칙에 따라, 구현 계획 <계획 파일 경로>를 체크박스 순서대로 구현해 주세요.
작업 범위는 계획 파일에 작성된 파일 및 책임으로 한정해 주세요.
구현 후 가능한 범위 내에서 verify를 실행하고, 결과를 보고해 주세요.
...
여기서 중요한 점은 Codex에게 갑자기 "적당히 잘 구현해 줘"라고 전달하지 않는 것입니다.
Claude Code 측에서 설계하고, 구현 계획을 수립하며, 사용자의 승인을 얻은 뒤에 Codex에게 전달합니다. Codex에는 작업 범위를 계획 파일로 한정하도록 합니다.
또한, Codex에게 commit / push를 시키지 않습니다. Codex는 커밋되지 않은 차분(uncommitted diff)으로서 구현 내용을 반환하고, Claude Code가 해당 차분과 verify 결과를 확인합니다.
이렇게 역할을 분담하면, Claude Code는 설계와 리뷰에, Codex는 구현과 검증에 역할을 집중할 수 있습니다.
Codex에서 Claude Code를 리뷰 전용으로 호출하기
역방향, 즉 Codex에서 Claude Code를 호출하는 경로도 만들었습니다.
이것은 scripts/invoke-claude-review.ps1입니다. 용도는 리뷰 전용으로 한정했습니다.
이 스크립트는 대상 프로젝트에서 다음 항목들을 수집합니다.
CLAUDE_CODE_HANDOFF.md
.claude/rules/project-collaboration-profile.md
git diff HEAD
그다음, Claude Code CLI를 --print 옵션으로 호출합니다.
$arguments = @(
"--print",
"--output-format", "text",
...
--tools ""를 전달하는 이유는 Claude Code가 파일을 편집하지 못하게 하기 위해서입니다. Codex에서 호출하는 Claude Code는 어디까지나 review-only(리뷰 전용) 상대로 설정합니다.
프롬프트 측에서도 역할을 리뷰로 한정하고 있습니다.
Task:
- Review the current handoff and diff only.
- Do not edit files.
...
리뷰 결과는 그대로 CLAUDE_CODE_HANDOFF.md에 추가합니다.
$appendLines = @(
"",
"---",
...
Codex가 구현한 차분을 Claude Code가 리뷰합니다. 결과는 handoff로 돌아갑니다. 다음 세션에서는 어떤 AI가 보더라도 동일한 위치에 리뷰 결과가 존재하게 됩니다.
이것이 제가 원했던 흐름이었습니다.
상호 호출을 구현했기에 역할을 나누었다
상호 호출을 만들면 모든 것을 자동으로 돌리고 싶어집니다.
하지만 동일한 worktree에서 두 AI가 구현을 시작하면 충돌이나 덮어쓰기 사고가 발생합니다. 그래서 호출 방향에 따라 역할을 나누었습니다.
| 방향 | 주요 용도 | 권한 |
|---|---|---|
| Claude Code → Codex | 제한적 구현, 테스트 추가, 기계적 수정 | Codex가 workspace를 편집함 |
| Codex → Claude Code | 리뷰, 리스크 확인, merge / publish 판단 근거 | Claude Code는 편집하지 않음 |
Claude Code에서 Codex를 호출할 때는 구현을 맡깁니다. 대신 계획 파일, 완성 조건, verify, 금지 사항을 전달합니다.
Codex에서 Claude Code를 호출할 때는 리뷰만 수행합니다. --tools ""로 편집 권한을 제거하고, handoff와 diff를 읽어 판단 결과만 돌려받습니다.
이 비대칭성이 중요했습니다.
"상호 호출"이라고 해서 양방향에서 똑같은 일을 시킬 필요는 없습니다. 오히려 똑같은 일을 시키지 않기 위해 하네스(Harness)가 필요했습니다.
merge와 publish는 자동화하지 않는다
상호 호출을 도입하더라도 merge / publish는 자동화하지 않습니다.
cross-agent-harness에서는 merge / publish 전에 다음 4가지 조건을 확인하는 방식을 취하고 있습니다.
1. 셀프 verify 완료
2. 반대편 리뷰 완료
3. 중대한 지적 사항 없음
...
AI끼리 구현과 리뷰를 순환시킬 수 있도록 하더라도, 마지막 판단은 인간에게 남겨둡니다.
특히 Zenn 기사에서는 published: true로 설정하면 공개 단계로 진행됩니다. 앱 개발이라면 push, release, migration, 파괴적 변경 (breaking changes) 또한 마찬가지입니다.
호출을 자동화할수록, 중단해야 하는 조건도 명시해 둘 필요가 있습니다.
요약
Codex와 Claude Code를 상호 호출하는 하네스 (Harness)를 구축함으로써, 두 AI를 단순히 병용하는 상태에서 작업 계약(work contract)을 맺고 서로 넘겨주는 상태에 가까워졌습니다.
수행한 작업은 크게 세 가지입니다.
- Claude Code → Codex:
codex-dev를 통해 설계된 태스크를 MCP를 경유하여 구현 위임 - Codex → Claude Code:
invoke-claude-review.ps1을 통해 review-only CLI 호출 수행 - 의뢰, 결과, 미확인 사항은
CLAUDE_CODE_HANDOFF.md에 기록
중요했던 점은 상호 호출을 완전 자동화된 개발 플로우로 만들지 않았다는 것입니다.
구현하는 측, 리뷰하는 측, 판단하는 사람을 분리합니다. AI끼리 연결할수록, 그 경계를 파일과 스크립트로 명확히 구현할 필요가 있었습니다.
참고 링크
- harness17/cross-agent-harness — 본 기사에서 다룬 공동 개발 하네스
- Codex와 Claude Code의 공동 작업을 cross-agent-harness로 분리 — 하네스 전체 도입 기사
- AI 2대 교차 리뷰로 기술 기사의 맹점 포착 — Zenn 기사 리뷰에서의 선행 운용
- harness17/zenn-articles — 기사 관리 리포지토리 (Repository)
AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기