# 让 Claude Code 自己把图画了：chatgpt-imagegen 的初心与原理

> 一句话：让 Claude Code 在「需要一张图」的时候，**自己把图画了**——不用人去 ChatGPT 里画好再贴回来，也不用为它单独开一个 `OPENAI_API_KEY`。

![Claude Code 自己把网页里缺的那张图画了：i do it myself](https://img.leeguoo.com/media/885d47ec-d67e-462c-97b6-073eabae6c5f/hero-autonomy.png)

## 1. 初心：别让 agent 卡在「等人画图」

让 Claude Code 这样的 agent 真正端到端地做项目，你迟早撞到同一堵墙：**它需要一张图。**

一个 README 的 hero banner、一个 app 的占位图标、一张落地页的配图、一份原型的 mockup、几张 sprite……代码它能写，图它画不出来。于是流程断在这里：

- **要么**给它配一个 `OPENAI_API_KEY` 走官方图像 API——额外的钥匙、额外的计费、额外的配置，还和你的 ChatGPT 订阅是两套账；
- **要么**你亲自打开 ChatGPT，把图生成好，再下载、贴回项目里——agent 停在那儿干等，「自主」二字荡然无存。

chatgpt-imagegen 的初心就是把这堵墙拆了：**agent 缺图，自己造，零人工接手。** 用的是你**本来就有**的 ChatGPT 订阅，不需要 API key，不需要起任何网关服务。

## 2. 一条命令，agent 就能用

它是一个**单文件、零依赖**的 Python CLI（只用标准库），装成 skill 之后，agent 直接调：

```bash
chatgpt-imagegen "a watercolor cat sitting on a windowsill" -o assets/cat.png
# -> assets/cat.png  (1,344,804 bytes)
```

为 agent 优化的细节都在：`--quiet` 时 stdout **只**输出保存路径（方便 `OUT=$(...)` 接管），进度条走 stderr；每个后端有跨进程并发锁，agent 批量 fan-out 也不会把账号打爆。

![一条命令：文字进去，图片文件出来，无需 API key，无需人工](https://img.leeguoo.com/media/7ec4d116-8f96-4df0-8827-992bc9b24b1f/one-command.png)

## 3. 核心原理：两个后端，两个计费桶

这是整个项目最关键的设计。同一个 ChatGPT 订阅，其实有**两个**能出图的入口，花的是**两个不同的额度桶**：

![两个后端：web 走已登录浏览器（省 Codex 额度），codex 走计量直连](https://img.leeguoo.com/media/8b7dd618-86f7-40e3-b8aa-39ef9fc9cf2f/cover.png)

| 后端 | 怎么出图 | 花哪个额度 | 适合谁 |
| --- | --- | --- | --- |
| **`web`**（默认） | 用 [`chrome-use`](https://github.com/leeguooooo/chrome-use) 驱动你**已登录的真实 Chrome**，在普通对话里出图 | **对话额度**，**不碰**计量的 Codex-usage | 笔记本/台式机，开着登录好的 Chrome；**免费账号也能用** |
| **`codex`** | 无头 POST 到 `backend-api/codex/responses`，复用 `~/.codex/auth.json` | **Codex-usage**（计量桶，通常是你想省的那个） | 服务器/无头 agent 机器，没有浏览器 |

默认是 `auto`：**先试 web**（省 Codex 额度），只有当浏览器不可用（没装 chrome-use / 没登录）时才回退到 codex。这条策略的意思是——**能不花计量额度，就不花。**

### 为什么 web 后端非得开一个真浏览器？

直觉上，「在普通对话里出图」似乎直接 POST 那个 `backend-api/*` 接口就行。我们真去试了一发裸客户端（只带 accessToken、不带任何浏览器凭证），结果挺反直觉——防线其实是**三层**，硬点不在你以为的地方：

| 层 | 裸 headless 能不能过 | 说明 |
| --- | --- | --- |
| **Cloudflare** `cf_clearance` | **能过** | 实测本机裸 `urllib` 打 `sentinel/chat-requirements` 直接 200。CF 是 IP 信誉/启发式判定，不是硬墙——换个差 IP 才可能被挑战 |
| **Sentinel PoW** | 能（离线复刻） | hashcash 式纯计算题，`sdk.js` 算法已知，能自己算；但随 OpenAI 轮换而脆 |
| **Turnstile** | **过不了** | 交互式的 Cloudflare 反机器人 token，裸客户端**造不出来**，只能由真实浏览器现场产出 |

所以真正卡死「无浏览器直连」的，**不是 Cloudflare，也不是 PoW，是 Turnstile**。而且就算想「借浏览器只取这个 token、其余 headless」也行不通：Turnstile token 单次、短时、绑定本次挑战——你等于每个请求都得开一次浏览器，「无浏览器」直接自相矛盾。

这就是 web 后端非得驱动一个**真实、已登录的 Chrome**、而不是直接调接口的全部原因，也是为什么它必须用 `chrome-use`（真实 Chrome 连接），而不是普通无头 driver。想彻底不开浏览器，现成的路只有 `codex` 后端——代价是认 Codex 额度。

## 4. image 模型，效果是真的好

省额度不等于降画质——web 后端走的就是 ChatGPT 网页里那个原生图像生成器，效果跟你在 app 里手打一样。下面三张都是这个工具**真实产出**的（文生图 + 图生图各有）：



| 文生图 | 图生图：把水彩猫改成金光油画 | 图生图：把 logo 贴上木牌 |
| --- | --- | --- |
| ![文生图：白底草莓](https://img.leeguoo.com/media/751116c9-3829-4bde-9000-e4e2cd47ebd4/real-strawberry.png) | ![图生图：金光油画猫](https://img.leeguoo.com/media/7b6038a8-47b1-4f40-add8-7f8177cd4868/real-cat-goldenhour.png) | ![图生图：木牌 logo](https://img.leeguoo.com/media/c266f47a-e55a-40ad-8f9b-bbbe755e06fb/real-logo-sign.png) |

## 5. 图生图：给它一张参考图

传一张参考图（`-i`），它就**改图**而不是从零画——和你把图拖进 ChatGPT 输入框让它重绘是同一回事。两个后端各有实现：

- **web**：把参考图经 `chrome-use upload` 注入到 composer 的标准 `<input type="file">`，再发编辑指令——**零站点适配**，不消耗 Codex 额度；
- **codex**：把参考图作为 `input_image` 内容块塞进请求，强制触发图像工具。

```bash
# 把一张 logo 改成赛博朋克霓虹招牌
chatgpt-imagegen "把它做成赛博朋克霓虹招牌" -i logo.png -o neon.png
```

![把参考图拖进输入框，出一张改好的新图](https://img.leeguoo.com/media/79c167d1-7486-4295-aa2f-590533005000/img2img-flow.png)

### 一个有意思的原理坑：怎么认出「生成的那张图」

web 后端是在驱动一个真实页面，所以它得**从 DOM 里把生成的图认出来**，这里有三个反直觉的点：

1. 新版 ChatGPT 的图走 `backend-api/estuary/content`，不再是老的 `oaiusercontent`；
2. 图生图时，你上传的**参考图会在用户气泡里以一个全新 src 回显**——一不小心就把「你自己上传的原图」当成结果抓走；
3. 生成图是一张**独立的图像卡片**，并不包在助手消息元素里。

所以正确的判定是：**在 `<main>` 里找匹配图床域名的新图，但排除掉任何属于用户气泡的图。**

![在 main 里找生成图，但排除用户气泡里的上传图](https://img.leeguoo.com/media/4055de23-2c4e-46fd-b438-5828de68d92e/detect.png)

## 6. 为 agent 而生的设计思路

把这些原则连起来，就是这个项目的设计取向：

- **单文件、零依赖、纯标准库**——agent 拉过去就能跑，没有 `pip install`、没有虚拟环境、没有常驻进程；
- **可作为 skill 安装**——`npx skills add leeguooooo/chatgpt-imagegen -g`，Claude Code / Codex / Cursor 等都能直接调；
- **默认省钱**——auto 模式优先走不计量的 web；真要快或在无头机器上，再用 codex；
- **结果落进工作区**——agent 拿到的就是一个保存好的文件路径，直接进 repo；
- **对话自动归档**——web 后端把每次出图的对话归进一个 ChatGPT Project（默认 `imagegen`），不污染你的历史。

一句话：它不是给人用的图像工具套了个 CLI，而是**从一开始就为「agent 自己缺资源自己造」这件事设计的**。

## 7. 上手

```bash
# 作为 skill（推荐，给 agent 用）
npx skills add leeguooooo/chatgpt-imagegen -g

# 或者独立 CLI（零依赖，单文件）
git clone https://github.com/leeguooooo/chatgpt-imagegen
```

然后对你的 agent 说一句「给 README 画个 hero 图」就行——剩下的它自己来。

工具仓库：[chatgpt-imagegen](https://github.com/leeguooooo/chatgpt-imagegen) ｜ 背后的浏览器自动化引擎：[chrome-use](https://github.com/leeguooooo/chrome-use)。

> 题外话：这篇文章里那些**故意画烂**的涂鸦原理图，和上面那几张**好看的**示例图，全是这个工具自己出的。烂的是讲解风格，好看的是它真实的本事——这反差本身，就是它最好的演示。
