Claude CodeとCodexは、Node.jsのスクリプト1つで自動的に議論させ、その様子をDiscordに流すことができます。
この記事の結論
- APIキーは不要Claude(Pro/Max)とChatGPTのサブスクのまま動きます。
- 追加のライブラリも不要Node.js標準の
fetchだけで投稿できます。 - 準備は約30分、実行はコマンド1行応用としてDiscord Botにすると、書き込むだけで2人が返事・議論します。
こんにちは、Yoraku(yoraku.art)のよざです。Web制作やブランディングをしている、いわゆる非エンジニアのクリエイターです。この記事は、私が実際にこの仕組みを作ったときの手順と、つまずいたポイントをそのまままとめたものです。
なぜAI同士を議論させるのか

これまで私は、ChatGPTの回答をコピーしてClaudeに貼り、「これどう思う?」と聞く……という人間バケツリレーをしていました。2つのAIに意見を出させると、1つのAIだけでは気づかない抜け漏れが見つかるからです。
ただ、手作業のコピペは面倒で、往復が増えるほど大変になります。そこで、次のように自動化しました。
| これまで | この仕組み | |
|---|---|---|
| やること | AIの回答を手でコピペして往復 | コマンドを1回打つだけ |
| 役割分担 | 自分で指示し直す | Codex=提案役、Claude Code=レビュー役で自動進行 |
| 結果の見え方 | 画面がバラバラ | Discordに会議の議事録のように並ぶ |
仕組みの全体像
登場するのは次の4つです。
- 司会役(discuss.mjs)Node.jsで書いた小さなプログラム。2人に順番に話を振ります。
- Codex CLI
codex exec "質問"で一発回答を返すモード(非対話モード)を使います。 - Claude Code CLI
claude -p "質問"で同じく一発回答を返します。 - Discord Webhook外部からメッセージを投げ込むための専用URL。「投稿専用のポスト」のようなものです。
流れはシンプルです。司会役がCodexにテーマを渡して案を出させ、それをDiscordに投稿します。次に、その案を含めた議論の経緯をClaude Codeに渡してレビューさせ、また投稿します。これを指定した往復数だけ繰り返します。
必要なもの

- Mac(この記事はmacOSのターミナルで解説します)
- Node.js v20.6以上(
.envファイルを読む--env-fileオプションを使うため) - Claudeの有料プラン(Claude Codeを使うため)
- ChatGPTのアカウント(Codexを使うため)
- Discordのアカウントと、自分専用のサーバー
ターミナルが何か分からない場合は先にこちら → ターミナルとは? パソコンに文字で命令する窓のこと
手順1〜7:作って動かす

手順1:DiscordでWebhookを作る
- Discordで自分専用のサーバーを作ります(左端の「+」→「オリジナルの作成」)。
- 投稿先のチャンネル(
#一般など)の歯車アイコン →「連携サービス」→「ウェブフックを作成」を押します。 - 作成したウェブフックを開き、「ウェブフックURLをコピー」を押します。
URLを知っている人は誰でもそのチャンネルに投稿できます。私は作業中のスクリーンショットにURLが写り込んでしまい、ウェブフックを削除して作り直しました。画面共有やスクショのときは特に気をつけてください。
手順2:Node.jsをインストールする
nodejs.org から LTS版 のインストーラーをダウンロードして実行します。ターミナルで次のコマンドを実行し、バージョンが表示されればOKです。
node -v
手順をまとめてコピーしたら、# から始まる説明文まで貼り付けてしまい、command not found が連発しました。コマンドは1行ずつ貼り付けて実行するのが確実です。
手順3:Claude Codeをインストールしてログインする
curl -fsSL https://claude.ai/install.sh | bash
インストール後に claude と打つと、初期設定とログインが始まります。
インストール完了画面に ~/.local/bin is not in your PATH と表示された場合は、画面に出ている次のコマンドを実行します。PATHとは「コマンドを探しに行く場所のリスト」のことです。
> echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
>
初回起動時に「このフォルダを信頼しますか?」と聞かれます。ホームフォルダ全体は信頼せず、作業用フォルダだけを信頼するのが安全です。
手順4:Codexをインストールしてログインする
npm install -g @openai/codex
codex と打つと起動し、ChatGPTアカウントでログインできます。
Macでは権限エラーになることがあります。その場合は先頭に sudo を付けて再実行し、Macのログインパスワードを入力します。入力中は文字が表示されませんが、正常です。
手順5:作業フォルダと司会プログラムを用意する
mkdir ~/ai-discuss && cd ~/ai-discuss
次に、司会プログラム discuss.mjs を作ります。以下は実際に動かしているコードです。
// discuss.mjs — Codex と Claude Code を交互に議論させ、Discord に流す司会役
// 使い方: node --env-file=.env discuss.mjs "テーマ" [往復数(省略時2)]
import { spawn } from "node:child_process";
import { readFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
const WEBHOOK = process.env.DISCORD_WEBHOOK_URL;
const topic = process.argv[2];
const rounds = Number(process.argv[3] ?? 2);
const TIMEOUT_MS = 5 * 60 * 1000;
if (!WEBHOOK || !topic) {
console.error('使い方: node --env-file=.env discuss.mjs "テーマ" [往復数]');
process.exit(1);
}
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
function run(cmd, args) {
return new Promise((resolve, reject) => {
const p = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
let out = "", err = "";
const timer = setTimeout(() => { p.kill(); reject(new Error(`${cmd} がタイムアウトしました`)); }, TIMEOUT_MS);
p.stdout.on("data", (d) => (out += d));
p.stderr.on("data", (d) => (err += d));
p.on("error", (e) => { clearTimeout(timer); reject(e); });
p.on("close", (code) => {
clearTimeout(timer);
code === 0 ? resolve(out.trim()) : reject(new Error(`${cmd} 終了コード ${code}\n${err.slice(-500)}`));
});
});
}
async function askCodex(prompt) {
const file = join(tmpdir(), `codex-${Date.now()}.txt`);
await run("codex", ["exec", "--skip-git-repo-check", "--output-last-message", file, prompt]);
const text = (await readFile(file, "utf8")).trim();
await rm(file, { force: true });
return text;
}
const askClaude = (prompt) => run("claude", ["-p", prompt]);
async function post(username, content) {
const chunks = content.match(/[\s\S]{1,1900}/g) ?? ["(空の返答)"];
for (const chunk of chunks) {
for (let attempt = 0; attempt < 3; attempt++) {
const res = await fetch(WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, content: chunk, allowed_mentions: { parse: [] } }),
});
if (res.ok) break;
if (res.status === 429) { const { retry_after = 1 } = await res.json(); await sleep(retry_after * 1000); continue; }
throw new Error(`Discord投稿失敗: ${res.status} ${await res.text()}`);
}
}
}
const speakers = [
{ name: "Codex", ask: askCodex, role: "提案役。案を出し、相手の指摘を受けて改善する" },
{ name: "Claude Code", ask: askClaude, role: "レビュー役。相手の案を批判的に検討し、具体的な改善点を示す" },
];
const log = [];
function buildPrompt(sp) {
const history = log.map((m) => `【${m.name}】\n${m.text}`).join("\n\n");
return [
`あなたは「${sp.name}」として議論に参加しています。役割: ${sp.role}。`,
`テーマ: ${topic}`,
history ? `これまでの議論:\n${history}` : "あなたが最初の発言者です。",
"次のあなたの発言だけを、日本語で800字以内で書いてください。",
"ファイルの作成・編集やコマンドの実行はしないでください。",
].join("\n\n");
}
try {
await post("司会", `🎤 テーマ: ${topic}(${rounds}往復)`);
for (let r = 1; r <= rounds; r++) {
for (const sp of speakers) {
console.log(`[${r}/${rounds}] ${sp.name} 考え中...`);
const text = await sp.ask(buildPrompt(sp));
log.push({ name: sp.name, text });
await post(sp.name, text);
}
}
await post("司会", "✅ 議論終了");
console.log("完了");
} catch (e) {
console.error(e);
await post("司会", `⚠️ エラーで停止: ${e.message.slice(0, 1500)}`).catch(() => {});
process.exit(1);
}
コードのポイントは3つです。
- Codexの最終回答だけを取り出す
codex execは途中経過も出力するため、--output-last-messageで最終回答だけをファイルに書き出して読んでいます。 - 議論の経緯を毎回渡すCLIの非対話モードは1回ごとに記憶がリセットされるので、これまでの発言をすべてプロンプトに含めています。
- Discordの2000字制限に対応長い発言は1900字ごとに分割して投稿します。
ファイルをうまく保存できなかったときは、ターミナルに直接ファイルを作る方法が確実でした。cat > discuss.mjs << 'EOF' と入力してからコードを貼り付け、最後に EOF と入力します。作成後は node --check discuss.mjs で文法チェックができます。
手順6:Webhook URLを.envファイルに保存する
URLをコードに直接書かず、.env という別ファイルに分けておきます。Discordで「ウェブフックURLをコピー」を押した直後に、次のコマンドを手で入力します。
echo "DISCORD_WEBHOOK_URL=$(pbpaste)" > .env
pbpaste は、Macのクリップボードの中身を取り出すコマンドです。コマンド自体をコピペするとクリップボードが上書きされてしまうので、手入力するのがコツです。確認は、URL全体を画面に出さないよう先頭だけ表示します。
cut -c1-50 .env
テキストエディットで .env を編集したつもりが保存されておらず、このエラーが出ました。上の pbpaste を使う方法に切り替えて解決しました。
手順7:実行する
node --env-file=.env discuss.mjs "個人事業のWebサイトで信頼感を出す方法" 2
最後の数字は往復数です。2 なら「Codex → Claude Code → Codex → Claude Code」の4発言になります。Discordを開いて待っていると、発言が順番に流れてきます。1人あたり数十秒〜数分かかります。
テーマは具体的に書くほど、議論が濃くなります。
- 良い例:「個人事業のWebサイトで、実績が少なくても信頼感を出す方法」
- 悪い例:「Webサイトについて」
応用:書き込むだけで返事するBotにする

Webhookは投稿専用(一方通行)なので、上の仕組みではDiscordに書き込んでも2人は反応しません。Discordの書き込みに反応させるには、Discord Botを作ります。
| Webhook版 | Bot版 | |
|---|---|---|
| 起動方法 | ターミナルでテーマを指定して実行 | Discordに書き込むだけ |
| 書き込みを読む | できない | できる |
| 必要なもの | Webhook URL | Webhook URL+Botトークン+チャンネルID |
| 動かし方 | 議論が終わると終了 | ターミナルで起動し続ける |
私のBot版は、書き方で2つのモードを切り替えるようにしました。
- ふつうに書き込む会話モード:Codex → Claude Code の順に返事が来ます。直近15件の会話を読むので、話を続けられます。
!議論 テーマと書き込む議論モード:2人が往復で議論します。!議論3 テーマのように数字を付けると往復数を変えられます。- .mdや.txtを添付するファイルの中身を読んだうえで返事・議論します。
Bot作成の流れは次のとおりです。
- Discord Developer Portal で「New Application」を作成します。
- 「Bot」ページで Message Content Intent をオンにします。オフのままだと、Botが書き込みの内容を読めません。
- 「公開Bot」をオフにします。
- 「トークンをリセット」でトークンを取得し、
.envに追記します。トークンはWebhook URL以上に大事な鍵です。 - 「OAuth2」→「URLジェネレーター」で、スコープ「bot」と、権限「チャンネルを表示」「メッセージを送る」「メッセージ履歴を読む」を選び、生成されたURLから自分のサーバーに追加します。
- チャンネルIDを
.envに追記します。ブラウザ版Discordなら、URLの最後の数字がチャンネルIDです。 npm install discord.jsをしてから、node --env-file=.env bot.mjsで起動します。
「プライベートアプリにはデフォルトの認可リンクを設定できません」というエラーが出ました。「インストール」ページで「インストールリンク」を「なし」にしてから保存すると解決しました。
モデルの選び方

この記事を書いた2026年9月時点で、私はClaude Codeを Opus 5.5、Codexを GPT-6-Sol(推論:high) で使っています。スクリプトはそれぞれのCLIの初期設定に従うので、モデルを変えたいときは次のようにします。
- Codex
codexを起動して/modelと入力し、モデルと推論の深さを選びます。設定は保存され、スクリプトにも反映されます。 - Claude Code
claude -pに--model sonnetなどを付けると、議論用のモデルを固定できます。回数を多く回したいときは、軽めのモデルにすると利用枠を節約できます。
よくある質問
Q. APIキーは必要ですか?
必要ありません。Claude CodeとCodexのCLIにサブスクのアカウントでログインしていれば、そのまま動きます。
Q. 料金はかかりますか?
追加料金はかかりませんが、それぞれのサブスクの利用枠を消費します。往復数が多いほど、また過去の議論が長いほど、消費量が増えます。まずは1〜2往復で試すのがおすすめです。
Q. ターミナルを閉じると議論は止まりますか?
止まります。Macのスリープでも止まります。閉じても続けたい場合は、次のように起動します。
nohup caffeinate -i node --env-file=.env discuss.mjs "テーマ" 2 > log.txt 2>&1 &
nohup はターミナルを閉じても処理を続けるため、caffeinate -i は議論中にMacをスリープさせないためのコマンドです。
Q. 議論中にClaude CodeやCodexのアプリを使っても大丈夫ですか?
基本的には影響しません。ただし、利用枠はアプリと共有なので、上限に達するとスクリプトはエラーで止まります。また、モデルなどの設定がアプリとCLIで共有されている場合があり、アプリ側で設定を変えると次の議論にも反映されることがあります。
Q. 発言者のアイコンは変えられますか?
変えられます。Webhookに送るデータに avatar_url を追加し、httpsで公開されている画像URLを指定します。Discordにアップロードした画像のリンクは時間が経つと期限切れになるので、自分のサイトなどに置いた画像を使うのがおすすめです。
Q. 自分の好みや前提知識をAIに覚えさせられますか?
作業フォルダにメモファイルを置くと、毎回自動で読み込まれます。Claude Codeは CLAUDE.md、Codexは AGENTS.md を読むので、AGENTS.md に内容を書き、CLAUDE.md には @AGENTS.md と1行だけ書いておくと、1つのファイルで両方に共有できます。
まとめ

- Claude CodeとCodexは、CLIの非対話モード(
claude -pとcodex exec)を使えば、スクリプトから自動で議論させられます。 - 結果をDiscordのWebhookに投稿すれば、議論がチャット形式の議事録として残ります。
- さらにDiscord Bot化すると、書き込むだけで返事・議論・資料の読み込みまでできるAI会議室になります。
2つのAIに意見をぶつけ合わせると、1つのAIに聞くよりも、案の弱点や別の視点が見つかりやすくなります。人間バケツリレーに疲れている方は、ぜひ試してみてください。
AIに道具を持たせる話 → AIエージェントとは? 道具を使って自分で動くAIの話
