技術 約9分で読めます

tmuxでClaude CodeとCodexを連携させて一晩放置でゲームを作らせる(実践編)

前回のおさらい

準備編では、Claude CodeとCodexを連携させるアイデアと基本スクリプトを書いた。

Claude Code(実装)
    ↓ コード出力
Codex(レビュー)
    ↓ レビュー結果
Claude Code(修正)
    ↓ 繰り返し...

今回は実際にこの仕組みを動かしてみた。


使ったスクリプト

実際に使ったスクリプトは4つ。

start-tmux.sh(起動スクリプト)

tmuxセッションを左右分割で起動して、それぞれにワーカーを配置する。

#!/bin/bash
# tmuxセッション起動スクリプト
# 左: Claude Code(実装) / 右: Codex(レビュー)

PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
SESSION_NAME="my-dev"  # 好きな名前に変更
MAX_ROUNDS=${1:-10}

# 既存セッションチェック
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
    echo "セッション '$SESSION_NAME' は既に存在します"
    echo "接続: tmux attach -t $SESSION_NAME"
    echo "削除: tmux kill-session -t $SESSION_NAME"
    exit 1
fi

# ログディレクトリ作成・シグナルファイルクリア
mkdir -p "$PROJECT_DIR/logs"
rm -f "$PROJECT_DIR/logs/.commit_done" "$PROJECT_DIR/logs/.review_done"

# 実行権限付与
chmod +x "$PROJECT_DIR/scripts/claude-worker.sh"
chmod +x "$PROJECT_DIR/scripts/codex-worker.sh"

# tmuxセッション作成
tmux new-session -d -s "$SESSION_NAME" -c "$PROJECT_DIR"

# 左ペイン: Claude Code ワーカー
tmux send-keys -t "$SESSION_NAME" "./scripts/claude-worker.sh $MAX_ROUNDS" C-m

# 右ペイン: Codex ワーカー
tmux split-window -h -t "$SESSION_NAME" -c "$PROJECT_DIR"
tmux send-keys -t "$SESSION_NAME" "./scripts/codex-worker.sh" C-m

# セッションにアタッチ
echo "tmuxセッション '$SESSION_NAME' を起動します..."
echo "左: Claude Code(実装) / 右: Codex(レビュー)"
tmux attach -t "$SESSION_NAME"

claude-worker.sh(左ペイン)

Claude Codeで実装を進める。1ラウンド1タスクで、コミットしたらCodexを待つ。

#!/bin/bash
# Claude Code ワーカー(左ペイン)
# 実装 → コミット → レビュー待ち → 修正のループ

set -e

PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
LOG_DIR="$PROJECT_DIR/logs"
CLAUDE_LOG="$LOG_DIR/claude.log"
REVIEW_FILE="$LOG_DIR/review.md"
COMMIT_SIGNAL="$LOG_DIR/.commit_done"
REVIEW_SIGNAL="$LOG_DIR/.review_done"
MAX_ROUNDS=${1:-10}

mkdir -p "$LOG_DIR"

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'

cd "$PROJECT_DIR"

# シグナルファイル初期化
rm -f "$COMMIT_SIGNAL" "$REVIEW_SIGNAL"

echo -e "${GREEN}=== Claude Code ワーカー開始 ===${NC}"

for ((round=1; round<=MAX_ROUNDS; round++)); do
    echo -e "${YELLOW}=== ラウンド $round/$MAX_ROUNDS ===${NC}"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ラウンド $round 開始" >> "$CLAUDE_LOG"

    # Step 1: 実装
    echo -e "${CYAN}[実装中...]${NC}"
    claude --dangerously-skip-permissions -p "
あなたは○○の開発を担当しています。(ここに何を作っているか書く)

## 指示
1. docs/todo.md を確認して未完了タスクを把握
2. 次の未完了タスクを1つ選んで実装
3. 実装完了後、docs/progress.md に記録
4. 変更をgit commitする(メッセージは日本語で簡潔に)
5. git pushする
6. docs/todo.md の該当項目を完了にマーク

## 制約
- 質問せず自分で判断して進める
- エラーが出たら自力で修正
- 1ラウンド1タスクに集中

実装を開始してください。
" 2>&1 | tee -a "$CLAUDE_LOG"

    # コミット完了シグナル
    touch "$COMMIT_SIGNAL"
    echo -e "${GREEN}[コミット完了 - Codexレビュー待ち...]${NC}"

    # レビュー完了待ち
    while [ ! -f "$REVIEW_SIGNAL" ]; do
        sleep 2
    done
    rm -f "$REVIEW_SIGNAL"

    # Step 2: レビュー結果確認・修正
    if [ -f "$REVIEW_FILE" ] && ! grep -qi "LGTM" "$REVIEW_FILE"; then
        echo -e "${CYAN}[レビュー指摘あり - 修正中...]${NC}"
        claude --dangerously-skip-permissions -p "
Codexから以下のレビューコメントを受けました。
指摘に従って修正し、再度コミットしてpushしてください。

$(cat "$REVIEW_FILE")
" 2>&1 | tee -a "$CLAUDE_LOG"
    else
        echo -e "${GREEN}[LGTM - 修正不要]${NC}"
    fi

    # Step 3: Code Simplifier
    echo -e "${CYAN}[Code Simplifier 実行中...]${NC}"
    claude --dangerously-skip-permissions -p "
/plugin run code-simplifier

最近変更したコードを整理・簡素化してください。
機能は変えずに、可読性と保守性を向上させてください。
変更があればコミットしてpushしてください。
" 2>&1 | tee -a "$CLAUDE_LOG"

    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ラウンド $round 完了" >> "$CLAUDE_LOG"

    # 全タスク完了チェック
    if ! grep -q "\- \[ \]" "$PROJECT_DIR/docs/todo.md" 2>/dev/null; then
        echo -e "${GREEN}全タスク完了!${NC}"
        break
    fi

    sleep 2
done

echo -e "${GREEN}=== Claude Code ワーカー終了 ===${NC}"

codex-worker.sh(右ペイン)

コミットを検知してCodexでレビューする。

#!/bin/bash
# Codex ワーカー(右ペイン)
# コミット検知 → レビュー実行のループ

set -e

PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
LOG_DIR="$PROJECT_DIR/logs"
CODEX_LOG="$LOG_DIR/codex.log"
REVIEW_FILE="$LOG_DIR/review.md"
COMMIT_SIGNAL="$LOG_DIR/.commit_done"
REVIEW_SIGNAL="$LOG_DIR/.review_done"

mkdir -p "$LOG_DIR"

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'

cd "$PROJECT_DIR"

echo -e "${GREEN}=== Codex ワーカー開始 ===${NC}"
echo "コミット待機中..."

while true; do
    # コミット完了シグナル待ち
    if [ -f "$COMMIT_SIGNAL" ]; then
        rm -f "$COMMIT_SIGNAL"

        echo -e "${YELLOW}=== 新規コミット検知 ===${NC}"
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] レビュー開始" >> "$CODEX_LOG"

        echo -e "${CYAN}[レビュー中...]${NC}"
        codex review --commit HEAD 2>&1 | tee "$REVIEW_FILE" | tee -a "$CODEX_LOG"

        echo "[$(date '+%Y-%m-%d %H:%M:%S')] レビュー完了" >> "$CODEX_LOG"

        # レビュー完了シグナル
        touch "$REVIEW_SIGNAL"
        echo -e "${GREEN}[レビュー完了]${NC}"
        echo ""
        echo "コミット待機中..."
    fi

    sleep 2
done

ai-loop.sh(シンプル版)

tmuxを使わないシンプル版。直列で実行する。

#!/bin/bash
# AI自動開発ループスクリプト
# Claude Code 実装 → Codex レビュー → Claude Code 修正

set -e

# 設定
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
LOG_DIR="$PROJECT_DIR/logs"
CLAUDE_LOG="$LOG_DIR/claude.log"
CODEX_LOG="$LOG_DIR/codex.log"
REVIEW_FILE="$LOG_DIR/review.md"
MAX_ROUNDS=${1:-10}

# ログディレクトリ作成
mkdir -p "$LOG_DIR"

# 色付き出力
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'

echo -e "${GREEN}=== AI自動開発ループ開始 ===${NC}"
echo "プロジェクト: $PROJECT_DIR"
echo "最大ラウンド: $MAX_ROUNDS"
echo ""

cd "$PROJECT_DIR"

for ((round=1; round<=MAX_ROUNDS; round++)); do
    echo -e "${YELLOW}=== ラウンド $round/$MAX_ROUNDS ===${NC}"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ラウンド $round 開始" >> "$CLAUDE_LOG"

    # Step 1: Claude Code 実装
    echo -e "${CYAN}[Step 1] Claude Code 実装中...${NC}"
    claude --dangerously-skip-permissions -p "
あなたは○○の開発を担当しています。(ここに何を作っているか書く)

## 指示
1. docs/todo.md を確認して未完了タスクを把握
2. 次の未完了タスクを1つ選んで実装
3. 実装完了後、docs/progress.md に記録
4. 変更をgit commitする(メッセージは日本語で簡潔に)
5. git pushする
6. docs/todo.md の該当項目を完了にマーク

## 制約
- 質問せず自分で判断して進める
- エラーが出たら自力で修正
- 1ラウンド1タスクに集中

実装を開始してください。
" 2>&1 | tee -a "$CLAUDE_LOG"

    # Step 2: Codex レビュー
    echo -e "${CYAN}[Step 2] Codex レビュー中...${NC}"
    codex review --commit HEAD 2>&1 | tee "$REVIEW_FILE" | tee -a "$CODEX_LOG"

    # Step 3: レビュー結果を確認し、修正が必要なら対応
    if ! grep -qi "LGTM" "$REVIEW_FILE"; then
        echo -e "${CYAN}[Step 3] Claude Code 修正中...${NC}"
        claude --dangerously-skip-permissions -p "
Codexから以下のレビューコメントを受けました。
指摘に従って修正し、再度コミットしてpushしてください。

$(cat "$REVIEW_FILE")
" 2>&1 | tee -a "$CLAUDE_LOG"
    else
        echo -e "${GREEN}[Step 3] レビューOK - 修正不要${NC}"
    fi

    # Step 4: Code Simplifier でコード整理
    echo -e "${CYAN}[Step 4] Code Simplifier 実行中...${NC}"
    claude --dangerously-skip-permissions -p "
/plugin run code-simplifier

最近変更したコードを整理・簡素化してください。
機能は変えずに、可読性と保守性を向上させてください。
変更があればコミットしてpushしてください。
" 2>&1 | tee -a "$CLAUDE_LOG"

    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ラウンド $round 完了" >> "$CLAUDE_LOG"
    echo ""

    # 全タスク完了チェック
    if ! grep -q "\- \[ \]" "$PROJECT_DIR/docs/todo.md" 2>/dev/null; then
        echo -e "${GREEN}全タスク完了!${NC}"
        break
    fi

    # インターバル
    sleep 3
done

echo -e "${GREEN}=== ループ終了 ===${NC}"

コピペして使う場合には

claude plugin install code-simplifier

してから使う。なくても動くけど。


動作の様子

tmuxで左右分割して動かしている様子。

tmux左右分割でAIループ動作中

左ペインでClaudeが実装してコミット、右ペインでCodexがレビューしてフィードバックを返している。

Codexのレビュー結果

Codexが「LGTM」を出すとClaudeは修正せず次のタスクに進む。指摘があれば修正してから次へ。


結果

投入した仕様

そば食いゲーム仕様書を投入した。2ゲージ制、座席システム、敵システムなどを含む仕様。

生成されたコード

  • 1134行のTypeScript
  • Viteプロジェクトとして動作
  • ブラウザで遊べる状態

完了したタスク

docs/progress.mdに記録された履歴の一部:

### 基本HTML構造
- [x] ゲーム画面レイアウト実装
- [x] 2ゲージUI(満腹・そば満足)
- [x] タイマー表示
- [x] NEXT表示エリア
- [x] 座席指定表示エリア

### プレイヤー移動
- [x] プレイヤー状態インターフェース定義
- [x] キーボード入力処理(矢印キー・WASD)
- [x] 8方向移動対応

### 食べ物システム
- [x] 食べ物パラメータ設定(そば並/大盛/特盛、うどん、ラーメン、ナポリタン)
- [x] ステージ別出現確率
- [x] カウンターへの配置・取得

### 座席システム
- [x] ステージ別テーブル選択ルール
- [x] テーブル指定システム
- [x] 喫食システム

### 敵システム
- [x] ステージ別敵パラメータ
- [x] プレイヤーと敵の衝突判定
- [x] 運搬中に衝突で食べ物落下

うまくいった点

ファイルベースの履歴管理

CLAUDE.mdで「進捗は docs/progress.md に記録しろ」と指示しておいたのが効いた。Claudeのコンテキストがコンパクトされても、ファイルを読み直せば過去の経緯を把握できる。

作業単位の制御

プロンプトで「1ラウンド1タスクに集中」と指示しているが、Claudeがフェーズと作業単位を1対1にしてる時もあれば、複数タスクをまとめてやる時もある。どういう気分かはわからない。

Codexのバグ検出

Codexが「食べ物落下時に座席が解放されていない」というバグを検出して、Claudeが修正した。これはprogress.mdにも記録されていた:

### バグ修正
- [x] 食べ物落下時の座席解放漏れ修正
  - dropCarriedFood()でassignedTableIdに対応する座席のstateを'available'にリセット
  - Codexレビュー指摘(P1)への対応

Tips

仕様書の足りない部分は適当に実装される。これを回避するには仕様書をかなり作りこむ必要がある。別窓でAskUserQuestionToolを使って徹底的に質問させて、何も疑問がないようにさせるといい。

このスクリプトだと上限10回なので、回数を変えるときは適宜自己責任で。

各コミット後に都度pushするようにした。理由:

  1. 進捗の可視化: 離れていても何をしているか把握できる
  2. 外部からの介入手段: --dangerously-skip-permissionsでフル権限を渡しているため、エージェントが予期しない動作(外部接続など)をする可能性がある。そのとき外出先からCLAUDE.mdやTODO.mdを修正してGitHubにpushしておけば、エージェントがpushしようとしたときにコンフリクトする。コンフリクト解消のためにpullすると、修正されたCLAUDE.mdを読み込む。1ラウンドごとに新しいClaudeが起動するので、次のラウンドでは必ず最新の指示が反映される

実際、SFTPで外部接続しようとしていたのをこの方法で止めた。


まとめ

Claude Code + Codexの自動ループは動く。仕様書とタスクリストをしっかり用意しておけば自走してくれる。放置しようとしたら1時間弱で終わった。