カテゴリ: AI活用・開発 タグ案: Claude Code, Codex, GPT Image 2, 画像生成, 業務自動化, コンテンツ制作
Claude Codeで記事を書き、CodexのGPT Image 2で画像を作る。
この分業自体は、もう珍しい話ではありません。2026年6月以降、「CodexならAPIキーなしで画像が作れる」という記事はいくつも出ています。私もそれを読んで試した側です。
そして、実際に1枚作れました。
問題はその次でした。
記事1本に画像は3枚要ります。サイトを1つ作るなら30枚以上です。それを毎回、手でコマンドを打って作るなら、業務としては成立しません。「1枚作れた」と「30枚を毎回まわせる」の間には、はっきりした段差があります。
その段差を埋めようとして自動化した瞬間、私のスクリプトは10分間、無言で固まりました。エラーも出ず、生成も始まらず、ただ止まっていました。
この記事では、そのまま自分の環境に置いて動く形で全部出します。
- ブリッジのスクリプト全文(73行)
- 画像の指示書(JSON)の書き方
- Claude Codeに持たせるスキル定義の全文
これを置けば、あとは「画像作って」と言うだけで、Claude Codeが指示書を書き、Codexが絵を描き、プログラムが検品するところまで通ります。
数字はすべて自社での実測値です。
1. 何をどちらに任せるか

最初に決めたのは、技術ではなく境界でした。
| 担当 | 役割 | |—|—| | Claude Code | 記事構成、本文、SEO設定、CMS入稿、画像の指示書を書く | | Codex | 指示書を受け取って絵を描くだけ | | プログラム | 生成の繰り返し、サイズ検品、WebP変換 | | 人間 | 採用する画像の判断と、公開の可否 |
そして1つだけルールを足しました。Codexは本文を書き始めない。
細かい話に見えて、これがいちばん効きました。境界を決めずに両方へ「いい感じにやって」と頼むと、記事の構成が画像に引きずられたり、逆に画像が本文と噛み合わなくなったりします。片方は文章に、もう片方は絵に専念させたほうが、結果として両方の質が上がります。
受け渡しは会話ではなくファイルでやります。Claude Codeが `image-gen-jobs.json` を書き、Codexはそれを1件ずつ受け取る。これだけです。
2. なぜAPIキーが要らないのか

ここが最初につまずきやすいところです。
「AIで画像を生成する」と聞くと、多くの人はOpenAIのAPIキーを取得して、1枚あたりいくらの従量課金を払う姿を思い浮かべます。私も最初はそう思っていました。
実際には、Codex CLIをインストールすると公式の内蔵スキルが最初から入っています。そして画像生成の経路は2本あります。
| 経路 | 認証 | 課金 | |—|—|—| | 内蔵 `image_gen` ツール | ChatGPTのログイン情報 | なし | | `image_gen.py` のCLI経路 | `OPENAI_API_KEY` | 従量課金 |
内蔵スキルの説明文には、はっきりこう書かれています。
> 内蔵の `image_gen` ツール(既定・推奨)は `OPENAI_API_KEY` を必要としない
つまり、多くの人が「AI画像生成といえばこれ」と思って取りに行くAPIキーは、そもそも要らないということです。
自分の環境がどちらになっているかは、次の1行で確認できます。
python3 -c "import json;d=json.load(open('$HOME/.codex/auth.json'));print(d['auth_mode'], bool(d.get('OPENAI_API_KEY')))"
`chatgpt False` と返れば正常です。APIキーは存在しなくて構いません。
3. まず手で1回だけ試す

自動化の前に、1枚だけ手で作って通ることを確かめます。
codex exec --skip-git-repo-check -c 'sandbox_mode="workspace-write"' "image_gen ツールで 1600x900 の画像を1枚生成し、カレントディレクトリに test.png として保存してください。濃紺の背景に白抜きの太いゴシックで「検証」と大きく1語だけ。説明不要。生成と保存のみ。"
分解するとこうなります。
| 部分 | 意味 | |—|—| | `codex exec` | Codexを画面なしで1回だけ実行する。対話画面を開かない | | `–skip-git-repo-check` | 作業フォルダがGit管理下でなくても動かす | | `-c ‘sandbox_mode=”workspace-write”‘` | そのフォルダだけ書き込みを許可し、他は触らせない | | `”…”` | Codexへの指示文 |
指示文の中で `image_gen` を名指しすることが地味に重要です。書かないと、Codexが「これはSVGやHTML/CSSで描いたほうがいい」と判断して、画像ではなくコードを書いてしまうことがあります。
もう1つ、最後は「説明不要。生成と保存のみ。」で締めます。書かないと丁寧な解説文を返してくれるのですが、自動化の中では読む人がいないので、時間の無駄になります。
`test.png` ができたら、次へ進みます。
4. 自動化すると必ず止まる

ここからが、手で1回叩いている限り絶対に出会わない話です。
コマンドが通ったので、これをスクリプトから呼べば枚数分まわせるはずでした。Node.jsから2枚ぶんを呼び出して、実行しました。
10分経っても、何も起きませんでした。
エラーは出ません。生成も始まりません。画像も作られません。タイムアウトで打ち切られただけでした。
調べていくうちに、おかしなことに気づきました。Codex側にセッションの記録が1件も作られていなかったのです。つまり処理が失敗したのではなく、そもそも始まってすらいませんでした。
原因は、手で叩いたときの出力の1行目にありました。
Reading additional input from stdin...
`codex exec` は起動時に標準入力を読みにいきます。ターミナルから叩いたときは問題になりませんが、プログラムから呼ぶと入力が来るのを永久に待ち続けます。
直し方は1行です。子プロセスを起動した直後に、標準入力を閉じる。
const child = execFile('codex', args, opts, callback)
child.stdin?.end() // これが無いと永久にハングする
書いてしまえば当たり前の話です。ただ、手で1回叩いて満足していたら、一生出会わなかった問題でもあります。自動化に踏み込んだ人だけが踏むタイプの罠なので、先に知っておいてください。
5. ブリッジのスクリプト全文【2026年7月版】

ここが記事の本体です。これを `scripts/codex-image-gen.mjs` として保存すれば動きます。Node.jsの標準機能だけで書いてあるので、`npm install` は不要です。
#!/usr/bin/env node
// codex-image-gen.mjs — Claude Code から Codex の GPT Image 2 を呼ぶ最小ブリッジ
import fs from 'node:fs'
import path from 'node:path'
import { execFile, execFileSync } from 'node:child_process'
const manifestPath = process.argv[2]
if (!manifestPath) {
console.error('usage: node codex-image-gen.mjs <image-gen-jobs.json>')
process.exit(1)
}
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'))
const outDir = path.resolve(path.dirname(manifestPath))
const CONCURRENCY = 2
// Codex へ渡す指示文。image_gen を名指しし、保存名を明示し、最後に「説明不要」で締める。
function buildPrompt(job) {
return [
`image_gen ツールで ${job.size || '1600x900'} の画像を1枚生成し、`,
`カレントディレクトリに ${job.file} として保存してください。`,
'',
job.prompt.trim(),
'',
'正確な日本語のみ。ダミー文字禁止。偽ロゴ・ウォーターマーク禁止。',
'説明不要。生成と保存のみ。',
].join('\n')
}
function runCodex(prompt) {
return new Promise((resolve) => {
const child = execFile(
'codex',
['exec', '--skip-git-repo-check', '-c', 'sandbox_mode="workspace-write"', prompt],
{ cwd: outDir, timeout: 300000, maxBuffer: 32 * 1024 * 1024 },
() => resolve()
)
child.stdin?.end() // ← これが無いと入力待ちで永久にハングする
})
}
function pixelSize(file) {
const out = execFileSync('sips', ['-g', 'pixelWidth', '-g', 'pixelHeight', file], { encoding: 'utf8' })
const read = (key) => Number(out.match(new RegExp(key + ':\\s*(\\d+)'))?.[1])
return { width: read('pixelWidth'), height: read('pixelHeight') }
}
async function generate(job) {
const target = path.join(outDir, job.file)
if (fs.existsSync(target)) return `skip ${job.file}`
await runCodex(buildPrompt(job))
if (!fs.existsSync(target)) return `FAIL ${job.file} 生成されなかった`
const { width, height } = pixelSize(target)
const [w, h] = (job.size || '1600x900').split('x').map(Number)
if (width !== w || height !== h) {
fs.rmSync(target)
return `FAIL ${job.file} サイズ不一致 ${width}x${height}`
}
if (job.webp) {
execFileSync('cwebp', ['-q', '88', '-quiet', target, '-o', path.join(outDir, job.webp)])
}
return `ok ${job.file}`
}
const queue = [...manifest.jobs]
await Promise.all(
Array.from({ length: CONCURRENCY }, async () => {
while (queue.length > 0) console.log(await generate(queue.shift()))
})
)
73行のうち、意味のある処理は5つです。
1. 指示文を組む — `image_gen` の名指しと保存名、共通の禁止事項を毎回自動で付ける 2. `codex exec` を呼ぶ — `child.stdin?.end()` を忘れない 3. サイズを検品する — 指定と違えば消して、次のループで作り直させる 4. WebPに変換する — `cwebp` があれば 5. 2枚ずつ並列で流す — `CONCURRENCY` の数だけワーカーを立てて、キューから取り合う
既にファイルがあれば `skip` します。途中で失敗しても、同じコマンドをもう一度叩けば足りない分だけ作られます。再実行が安全なことが、業務で回すうえでは一番効きます。
macOSを前提にしています。`sips` はmacOS標準です。Windowsやサーバー上で動かす場合は、この2行を `ffprobe` や `identify` に差し替えてください。
6. 画像の指示書を書く
スクリプトが読むのは、こういうJSONです。これを `assets/<記事名>/image-gen-jobs.json` に置きます。
{
"jobs": [
{
"file": "thumbnail.png",
"webp": "thumbnail.webp",
"size": "1600x900",
"prompt": "濃紺(#0A1730)のサイバー背景。左上に黄色の角丸ラベルで「APIキーは不要」。中央に白の極太立体文字で「Claude Code × Codex」。右側にダッシュボードとターミナルのUIモックを密に配置。人物は描かない。"
},
{
"file": "slide-01.png",
"webp": "slide-01.webp",
"prompt": "クリーム色の紙質感背景。ネイビー×ティール基調、オレンジのアクセント。最上部に特大の見出し「役割を分ける」。中央に左右2カラムのカード。左は「Claude Code」で記事構成・本文・SEO設定、右は「Codex」でサムネイル・図解。最下部にオレンジの帯で「Codexは本文を書かない」。"
}
]
}
実行はこれだけです。
node scripts/codex-image-gen.mjs assets/my-article/image-gen-jobs.json
ok thumbnail.png
ok slide-01.png
プロンプトに必ず書く5つ
ここが品質の分かれ目です。「きれいに作って」だと毎回違うものが出てきます。次の5つを必ず書きます。
1. 背景と配色 — できればHEXで。「おしゃれな色」では再現できません 2. 画像内の文字を一言一句そのまま — 見出し、パネル内の文字、下部の帯まで全部 3. 構図 — 上部・中央・下部に何を置くか。何コマか。番号付きか 4. 同一シリーズなら「◯◯と同じ様式に揃える」 — この1文で揃います 5. 描いてほしくないもの — 人物、ロゴ、ウォーターマークなど
とくに2番が効きます。画像内の文字をAIに考えさせてはいけません。 こちらが決めて、そのまま書かせる。そうしないと本文とズレた見出しが入り、記事の説得力が落ちます。
7. Claude Codeのスキルにする

ここまでは「人がコマンドを打つ」形でした。最後に、Claude Codeが自分で判断して回せるようにします。
置くファイルは3つだけです。
.claude/skills/blog-image-gen/SKILL.md ← AIへの手順書
scripts/codex-image-gen.mjs ← 実行するプログラム
assets/<記事名>/image-gen-jobs.json ← 今回作る絵の一覧(AIが書く)
`SKILL.md` の中身を全部載せます。これをそのままコピーして置いてください。
---
name: blog-image-gen
description: 記事やサイトに必要な画像を、CodexのGPT Image 2で生成する。サムネイル、本文の図解、OGP画像が必要なときに使う。APIキーは使わない。
---
# 画像生成(Codex連携)
## しないこと
- 自分で画像を生成しない。生成はCodexに任せる
- `OPENAI_API_KEY` を要求しない、受け取らない、出力に書かない
- 画像生成用の `.env` を作らない
- 画像内の文字を勝手に考えない。本文から取るか、決まっていなければ確認する
## 手順
1. 記事本文またはサイト構成を読み、必要な画像を洗い出す
2. 画像ごとに次を決める
- ファイル名(版番号は付けない)
- サイズ(記事なら 1600x900)
- 画像内に入れる文字(一言一句そのまま)
- alt テキスト
3. `<assets-dir>/image-gen-jobs.json` を書く
4. 生成する
```bash
node scripts/codex-image-gen.mjs <assets-dir>/image-gen-jobs.json
```
5. 出力を確認する。`FAIL` があればプロンプトを1点だけ直して再実行する
6. 生成された画像を開いて目視確認する
## プロンプトの型
必ず5つを書く。抽象語だけでは毎回違うものが出る。
1. 背景と配色(HEXまたは具体語)
2. 画像内の文字(一言一句そのまま)
3. 構図(上部・中央・下部、何コマか)
4. 同一シリーズなら「◯◯と同じ様式に揃える」
5. 描いてほしくないもの
## 制約
- 背景透過は使えない。単色背景で生成して後から抜く
- ロゴに日本語を焼き込まない。シンボルだけ生成し、社名はCSSのテキストで載せる
- 1記事の中で使う本文画像は、同じ様式に統一する
## 完了条件チェックリスト
- [ ] 全画像が指定サイズで存在する
- [ ] WebPに変換されている
- [ ] 画像内の日本語が崩れていない
- [ ] 見出しと画像の内容がズレていない
- [ ] 記事内の画像同士でトーンが揃っている
- [ ] ファイル名と絵の主題が一致している
- [ ] APIキーを使っていない
これを置いたあとは、Claude Codeにこう言うだけです。
この記事に必要な画像を洗い出して、blog-image-gen で作って。
本文画像はすべて同じ様式に揃えて。人物は入れないで。
Claude Codeが本文を読んでH2ごとに必要な絵を判断し、指示書を書き、スクリプトを叩き、出力を確認します。人がやるのは出てきた絵を見て採否を決めることだけになります。
8. 30枚規模で足したこと

記事1本(3枚)なら、ここまでで足ります。サイト1つ(30枚以上)になると、実際に運用して足したものが4つありました。
並列数を上げる
1枚あたり100〜130秒かかります。30枚を順番に作ると1時間近い計算です。
同時に2枚走らせたときの実測値がこちらです。
| 項目 | 実測 | |—|—| | 1枚目 | 107秒 | | 2枚目 | 131秒 | | 実時間 | 2分14秒 |
順番なら約4分かかるところが2分14秒。30枚なら30分前後で終わります。`CONCURRENCY` を3以上にするともっと速くなりますが、上げすぎるとサブスクの利用制限に当たるので、2〜3が現実的でした。
WebPの効果を確認する
WordPressに入れるのはWebPだけと決めています。効果はかなり大きいです。
| 形式 | サイズ | |—|—| | PNG(1600×900) | 1,979,029バイト(約1.9MB) | | WebP(q88) | 138,374バイト(約135KB) |
約93%の削減です。1記事に6枚使うなら、ページ全体で10MB近い差になります。
失敗を1件ずつ記録する
30枚あると1〜2枚は失敗します。全体を止めずに、失敗した分だけ後から作り直せるように、結果をJSONで残すようにしました。掲載したスクリプトでは `console.log` にしていますが、実運用ではファイルに書いて、終了コードで品質ゲートに繋いでいます。
リトライを入れる
サイズ不一致は、同じプロンプトでもう一度投げれば直ることが多いです。掲載版は「消して次のループで作り直す」だけですが、実運用では同じジョブを1回だけ自動で再試行しています。
9. 踏んだ罠

きれいに動いた話だけ書くと嘘になるので、うまくいかなかったところも書いておきます。
背景透過は使えない
gpt-image-2は背景透過に対応していません。「背景透過PNGで作って」と指示しても透過にはなりません。
回避策は、単色の背景で生成してから、あとでその色を抜くことです。本当の透過が必要な場合は別のモデルを使うことになりますが、そちらはAPIキーが必要=課金経路に戻ってしまうので、基本は使いません。
ロゴに日本語を焼き込んではいけない
これは意外でした。図解の中の日本語は正確に出るのに、ロゴのワードマークだけは崩れます。
見出しも、番号付きパネルの文字も、下部の帯も、全部きちんと読める日本語で出ます。ところが「社名入りのロゴを作って」と頼むと、文字化けした記号の羅列になります。
なので、ロゴはシンボルマークだけを画像で作り、社名や屋号はHTML/CSSのテキストで載せる。文字はコード、絵はAIという切り分けにしました。
主題ズレは自動検証で捕まらない
枚数が増えると、1〜2枚は必ず「ファイル名と中身が合っていない画像」が混ざります。
不動産サイト向けに「地域の街並み」として作らせた画像が、なぜか衣類の写真になっている。そういうことが起きます。サイズもファイル形式も正しいので、機械的な検証は全部通ってしまいます。
これだけは人が見るしかありません。30枚作ったら4〜5枚を開いて確認する、という工程を必須にしています。
10. 同じ形は、サイト制作にもそのまま使える
この分業は記事だけの話ではありません。
サイト制作でも構造は同じです。要件定義・サイトマップ・ワイヤーフレーム・コーディングはClaude Code、その中で使う画像はCodex。変わるのは枚数とサイズだけです。
| | 記事1本 | サイト1つ | |—|—|—| | 画像枚数 | 3枚前後 | 30枚以上 | | サイズ | 1600×900に統一 | 用途ごとに使い分け | | 所要時間 | 数分 | 30分前後 |
`image-gen-jobs.json` に30件書いて、同じスクリプトを叩くだけです。スキル定義もそのまま使えます。
注意点は枚数に比例して増えます。ロゴの日本語崩れ、透過が必要なアイコンやあしらい、主題ズレ。どれも記事1本では出会わないか、出会っても1枚で済むものが、サイト制作では確実に何枚か出ます。
11. 業務に載せる前に決めておくこと
最後に、実際に運用へ載せるときの注意を2つだけ。
画像の指示文に、外から拾った文章をそのまま入れない
競合サイトの調査結果やWebクリップした記事を、そのまま画像の指示文へ貼り込むのは避けています。
Codexは指示を読んで動くエージェントなので、貼り込んだ文章の中に別の指示が紛れていた場合、それを実行してしまう可能性があります。収集した資料からは「色」「業種」「雰囲気」といった短い属性だけを取り出し、指示文そのものは自分で組み立てる。この運用にしています。
公開した画像から、自分の環境がバレることはない
これは気になったので実際に調べました。生成した画像に何のデータが埋め込まれているかを、ファイルの中身を直接見て確認しています。
| 形式 | 埋め込まれていたもの | |—|—| | PNG | 画像本体、色空間、向きとサイズ(68バイト)のみ | | WebP | 画像本体のみ |
作者名、ソフト名、ローカルのファイルパス、ユーザー名、位置情報。どれも入っていませんでした。WordPressに入稿するWebPに至っては、変換の時点で全部落ちています。
公開した画像から制作環境が特定される心配は、しなくて大丈夫です。
まとめ
置くファイルは3つ。`SKILL.md`、`codex-image-gen.mjs`、`image-gen-jobs.json` です。
- Claude CodeとCodexの分業は、コマンド1本で繋がる。特別な連携機構は要らない
- 画像生成にAPIキーは不要。Codexの内蔵ツールを使えばサブスクの範囲で完結する
- ただしプログラムから呼ぶとstdinで永久ハングする。`child.stdin?.end()` が必須
- 掲載したスクリプト(73行)とスキル定義をそのまま置けば、「画像作って」で通る
- プロンプトには背景・文字・構図・様式・禁止事項の5つを必ず書く
- 透過は使えない。ロゴの日本語は崩れる。主題ズレは人が見るしかない
- 同じ形はサイト制作にも使える。変わるのは枚数とサイズだけ
「1枚作れた」で止まっている記事は既にたくさんあります。この記事が、その先へ進もうとしている人の時間を少しでも節約できれば十分です。
CodeClimbでは、こうした「AIを使ってみる」から「AIを業務フローに組み込む」までの設計と実装をお手伝いしています。
今回のような画像生成に限らず、見積作成、日報、問い合わせ対応、社内の繰り返し作業など、判断は人が持ったまま、繰り返しだけを機械に渡すという考え方はそのまま応用できます。
自社のどの業務なら組めそうか判断がつかない、という段階でも構いません。まずは現状の業務を伺うところからご相談ください。
