# Claude Code 接入 Nano Banana：配置与修复

> Claude Code 用 Skill 调 Nano Banana 最省事：模型填正式版 ID，preview 版已于 6 月 25 日关停；需开通计费，1K 图约 $0.067。

- URL: https://blog.laozhang.ai/zh/posts/nano-banana-claude-code
- Published: 2026-09-24
- Updated: 2026-09-24
- Author: LaoZhang AI Team (https://blog.laozhang.ai/zh/about)
- Category: Claude Code
- Tags: Claude Code, Nano Banana, Nano Banana 2, Claude Skills, MCP, Gemini API

---
Claude 本身不生成位图。"Claude Code 一句话出图"的实际分工是：Claude 理解你的需求、写好提示词、决定存到哪里，真正出图的是 Nano Banana，也就是 Google 的 Gemini 图片模型。把两者接起来有两种方式：**Skill** 让 Claude 运行一段本地脚本，**MCP** 让 Claude 调用一个常驻的工具服务。如果你只是想让 Claude 把头图、封面、图标直接生成到项目里的指定路径，Skill 最省事：一个 `SKILL.md`、一个 Python 脚本、一个环境变量。

截至 2026 年 9 月 24 日，不管走哪条路，能不能出图取决于三件事：

- **模型 ID 用正式版**：Nano Banana 2 是 `gemini-3.1-flash-image`，Pro 是 `gemini-3-pro-image`，Lite 是 `gemini-3.1-flash-lite-image`。带 `-preview` 后缀的两个 ID 已在 2026 年 6 月 25 日关停，初代 `gemini-2.5-flash-image` 将在 2026 年 10 月 2 日关停。今年上半年照着教程配好、现在突然不出图的，先查这一项。
- **开通计费**：Gemini API 上这几个图片模型都没有免费层。Nano Banana 2 输出一张 1K 图约 $0.067。
- **API Key 放进环境变量**：不要粘贴到对话里。

## Skill 还是 MCP，哪些环境用不了

两种方式都能让 Claude 出图，区别在于调用细节由谁掌控：

| | Skill | MCP |
| --- | --- | --- |
| 形式 | 一个文件夹：`SKILL.md` 说明何时用、怎么用，可附带脚本，Claude 用终端命令运行 | 一个独立进程，按 MCP 协议向 Claude 提供工具，例如 `generate_image` |
| 放在哪 | `~/.claude/skills/`（本机所有项目）或项目的 `.claude/skills/`（提交到仓库后团队共享） | 用 `claude mcp add` 注册，作用域分 local、project、user |
| 改模型、改保存位置 | 直接改脚本 | 只能用服务开放的参数；Google 的 nanobanana 扩展只认环境变量 `NANOBANANA_MODEL` |
| 适合 | 需求是"生成或修改一张图，存到某个路径" | 已经在用 Gemini CLI 的 nanobanana 扩展，或想要现成的图标、图案、连环画等命令 |

选择规则很简单：从零开始配，用 Skill；已经装了 nanobanana 扩展或基于它的 Skill，先按后文的对照表改一个环境变量，不必重装。Skill 和 MCP 的一般用法可以看 [Claude Code 最值得先用的 Skills](https://blog.laozhang.ai/zh/posts/claude-code-best-skills) 和 [Claude Code 最值得先加的 MCP](https://blog.laozhang.ai/zh/posts/claude-code-best-mcp-servers)；还没装 Claude Code 的话先看 [Claude Code 安装教程](https://blog.laozhang.ai/zh/posts/claude-code-install)。

下面的配置针对**在你自己电脑上运行的 Claude Code**。其他环境要注意：

- **Cowork 和云端会话**（包括 routines）不读取 `~/.claude/skills/`。Cowork 只加载在 claude.ai 账户里启用的 Skill；云端会话还会加载提交在仓库 `.claude/skills/` 里的 Skill。它们都不在你的终端里运行，本机 shell 设置的 `GEMINI_API_KEY` 不会跟过去，而 Key 也不该提交进仓库。
- **claude.ai 网页聊天**不能运行你电脑上的脚本。Claude 在那里能写 SVG 或绘图代码，但不会产出 Nano Banana 的照片级图片，详见 [Claude能生成图片吗？](https://blog.laozhang.ai/zh/posts/can-claude-generate-images)。

## 先把模型 ID 填对

下表是 Gemini API（AI Studio 的 API Key）上的状态与付费层标价，截至 2026 年 9 月 24 日，来源为 Google 的[弃用时间表](https://ai.google.dev/gemini-api/docs/deprecations)和[价格页](https://ai.google.dev/gemini-api/docs/pricing)：

| 模型 | 模型 ID | 状态 | 每张输出费用 | 说明 |
| --- | --- | --- | --- | --- |
| Nano Banana 2 | `gemini-3.1-flash-image` | 正式版，未公布关停日期 | 512：$0.045；1K：$0.067；2K：$0.101；4K：$0.151 | 通用首选，最多 14 张参考图 |
| Nano Banana 2 Lite | `gemini-3.1-flash-lite-image` | 正式版，未公布关停日期 | 1K：$0.0336 | 只出 1K；不适合多张参考图和多轮连续修改 |
| Nano Banana Pro | `gemini-3-pro-image` | 正式版，未公布关停日期 | 1K、2K：$0.134；4K：$0.24 | 用于最复杂的任务 |
| 初代 Nano Banana | `gemini-2.5-flash-image` | 2026 年 10 月 2 日关停 | — | Google 建议迁移到 2 Lite |
| Nano Banana 2 预览版 | `gemini-3.1-flash-image-preview` | 2026 年 6 月 25 日已关停 | — | 改为 `gemini-3.1-flash-image` |
| Nano Banana Pro 预览版 | `gemini-3-pro-image-preview` | 2026 年 6 月 25 日已关停 | — | 改为 `gemini-3-pro-image` |

三个正式版在 Gemini API 的免费层都标为"不可用"，必须给项目开通计费才能调用。生成的图片都带 SynthID 水印。如果你走的是 Vertex AI，模型 ID 相同，但关停日期和鉴权方式不同，参见 [Vertex AI 调用 Nano Banana：正确配置与费用](https://blog.laozhang.ai/zh/posts/vertex-ai-nano-banana-api)。三档模型怎么按任务挑，见 [Nano Banana 2 Lite、2 和 Pro 怎么选](https://blog.laozhang.ai/zh/posts/nano-banana-pro-vs-nano-banana-2)。

## 推荐做法：一个 Skill 加一个脚本

### 准备 Key 和依赖

1. 在 [Google AI Studio](https://aistudio.google.com/apikey) 创建 API Key，并为它所在的项目开通计费。
2. 用编辑器打开 `~/.zshrc`（bash 用户是 `~/.bashrc`），加一行：

   ```bash
   export GEMINI_API_KEY="你的 Key"
   ```

   保存后新开一个终端，再在里面启动 `claude`，Claude Code 才能继承这个变量。直接编辑文件，而不是用 `echo` 命令写入，可以避免 Key 留在 shell 历史里。
3. 安装 Google 的 Python SDK：

   ```bash
   python3 -m pip install google-genai
   ```

### 目录结构

只给当前项目用，放在项目里；想在所有项目里用，把同样的文件夹放到 `~/.claude/skills/nano-banana/`：

```text
.claude/skills/nano-banana/
├── SKILL.md
└── scripts/
    └── generate.py
```

文件夹名 `nano-banana` 就是命令名，之后可以输入 `/nano-banana` 直接调用。

![一次 /nano-banana 调用的四步：你发出请求，Claude 读 SKILL.md，运行 generate.py 从环境变量读 Key 并请求 Gemini API，图片存进项目指定路径](https://blog.laozhang.ai/posts/zh/nano-banana-claude-code/img/skill-call-flow.webp)

### SKILL.md

`description` 决定 Claude 什么时候自动用这个 Skill，写清触发场景；正文是 Claude 每次调用时遵循的步骤。`${CLAUDE_SKILL_DIR}` 会被 Claude Code 替换成这个 Skill 所在的目录，脚本路径因此不受当前工作目录影响。

```markdown
---
name: nano-banana
description: 用 Nano Banana（Gemini 图片模型）生成或修改位图并保存到项目中。用户要求生成头图、封面、插图、图标，或基于已有图片做修改时使用。
---

# 用 Nano Banana 出图

每次调用 scripts/generate.py 生成一张图。

1. 先确定输出路径（例如 docs/img/hero.png）、画幅比例和尺寸；用户没说时用 1:1、1K。
2. 模型默认 gemini-3.1-flash-image。用户要草稿或大量出图时用 gemini-3.1-flash-lite-image（只支持 1K，不适合多张参考图）；复杂画面或 4K 成品用 gemini-3-pro-image，调用前告诉用户单价更高。
3. 运行：
   python3 ${CLAUDE_SKILL_DIR}/scripts/generate.py "提示词" --out 输出路径 --aspect 16:9 --size 2K
   修改已有图片时加 --input 原图路径，可以重复传多张。
4. 不要读取、打印或向用户索要 API Key，脚本自己从环境变量 GEMINI_API_KEY 读取。
5. 退出码 2 表示缺少 Key 或模型 ID 不在允许列表；输出 No image returned 表示请求成功但没有返回图片；其他报错来自 API（例如 Key 无效）。都把脚本输出的原文告诉用户，不要自行换模型重试。
6. 成功后报告保存路径和所用模型。
```

### scripts/generate.py

```python
#!/usr/bin/env python3
"""Generate or edit one image with Nano Banana through the Gemini API.

Usage:
  python3 generate.py "prompt" --out images/hero.png [--model gemini-3.1-flash-image]
                      [--aspect 16:9] [--size 2K] [--input ref.png ...]
Reads the key from GEMINI_API_KEY (never from the command line).
"""
import argparse
import os
import pathlib
import sys

from google import genai
from google.genai import types

MODELS = {
    "gemini-3.1-flash-lite-image",  # Nano Banana 2 Lite, 1K only
    "gemini-3.1-flash-image",       # Nano Banana 2, 512/1K/2K/4K
    "gemini-3-pro-image",           # Nano Banana Pro, 1K/2K/4K
}

def main() -> int:
    p = argparse.ArgumentParser()
    p.add_argument("prompt")
    p.add_argument("--out", required=True)
    p.add_argument("--model", default="gemini-3.1-flash-image")
    p.add_argument("--aspect", default="1:1")
    p.add_argument("--size", default="1K")
    p.add_argument("--input", action="append", default=[])
    a = p.parse_args()

    if a.model not in MODELS:
        print(f"Unknown or retired model id: {a.model}. Use one of {sorted(MODELS)}", file=sys.stderr)
        return 2
    if not os.environ.get("GEMINI_API_KEY"):
        print("GEMINI_API_KEY is not set", file=sys.stderr)
        return 2

    contents = [a.prompt]
    for path in a.input:
        data = pathlib.Path(path).read_bytes()
        mime = "image/png" if path.lower().endswith(".png") else "image/jpeg"
        contents.append(types.Part.from_bytes(data=data, mime_type=mime))

    # Optional: a Gemini-compatible gateway, e.g. GEMINI_BASE_URL=https://api.laozhang.ai
    base_url = os.environ.get("GEMINI_BASE_URL")
    client = genai.Client(http_options=types.HttpOptions(base_url=base_url)) if base_url else genai.Client()
    resp = client.models.generate_content(
        model=a.model,
        contents=contents,
        config=types.GenerateContentConfig(
            response_modalities=["IMAGE"],
            image_config=types.ImageConfig(aspect_ratio=a.aspect, image_size=a.size),
        ),
    )

    for cand in resp.candidates or []:
        for part in (cand.content.parts if cand.content else []) or []:
            if part.inline_data and part.inline_data.data:
                out = pathlib.Path(a.out)
                out.parent.mkdir(parents=True, exist_ok=True)
                out.write_bytes(part.inline_data.data)
                print(f"saved {out} ({len(part.inline_data.data)} bytes)")
                return 0

    fb = getattr(resp, "prompt_feedback", None)
    reason = resp.candidates[0].finish_reason if resp.candidates else None
    print(f"No image returned. blockReason={getattr(fb, 'block_reason', None)} finishReason={reason}", file=sys.stderr)
    return 1

if __name__ == "__main__":
    sys.exit(main())
```

这个脚本有几处刻意的设计：

- **只接受三个正式版 ID**。填了已关停的 ID 会在本地直接退出，不会把请求发出去再等服务器报错；以后 Google 再发布新 ID，把它加进 `MODELS` 即可。
- **Key 只从 `GEMINI_API_KEY` 读取**，不接受命令行参数，Key 不会出现在 Claude 执行的命令和对话里。
- **`--input` 可以重复**，用于基于已有图片修改或多图参考。Nano Banana 2 最多接受 14 张参考图，Lite 不适合多图。
- **没拿到图时打印 `blockReason` 和 `finishReason`**，而不是笼统地报"失败"。遇到这种情况，按 [Nano Banana API 不出图：按返回字段逐项排查](https://blog.laozhang.ai/zh/posts/nano-banana-2-200-ok-no-image) 对照这两个字段处理。

脚本在 google-genai 2.25.0、Python 3.12 下只做过离线检查：不设 Key 或填入已关停的 ID 时退出码为 2；用无效 Key 请求 `gemini-3.1-flash-image`，请求能到达 Google 并返回 `API_KEY_INVALID`。还没有用真实 Key 出过图，所以第一次使用时先用 1K 生成一张，确认能保存成功，再改用大尺寸或 Pro。

### 在 Claude Code 里调用

直接调用：

```text
/nano-banana 为 README 生成一张 16:9、2K 的头图，主题是离线优先的笔记应用，扁平插画风格，存到 docs/img/hero.png
```

也可以用普通对话，Claude 会按 `description` 自动选用这个 Skill：

```text
把 assets/logo.png 改成深色背景版本，保持图形不变，另存为 assets/logo-dark.png
```

每次运行脚本前，Claude Code 默认会请你确认终端命令。每次调用都要付费，这个确认正好是一道成本关卡。如果确实想免确认，可以在 `SKILL.md` 的 frontmatter 里加一行，让这条命令自动放行：

```yaml
allowed-tools: Bash(python3 ${CLAUDE_SKILL_DIR}/scripts/generate.py *)
```

提示词怎么写更稳，可以参考 [如何给 Nano Banana 写提示词](https://blog.laozhang.ai/zh/posts/how-to-prompt-nano-banana)。

## 照旧教程配的不出图了：按接法对照修

先确认你用的是哪种接法、它默认调用哪个模型，再看它在 6 月 25 日和 10 月 2 日之后的状态：

![五种接法的对照：默认调用的模型、6 月 25 日和 10 月 2 日之后是否失效，以及各自的修法](https://blog.laozhang.ai/posts/zh/nano-banana-claude-code/img/route-fix-matrix.webp)

| 接法 | 默认调用的模型 | 2026 年 6 月 25 日之后 | 2026 年 10 月 2 日之后 | 修法 |
| --- | --- | --- | --- | --- |
| Google 的 Gemini CLI nanobanana 扩展（本身就是 MCP 服务） | 源码默认 `gemini-3.1-flash-image-preview` | 未设置 `NANOBANANA_MODEL` 时调用已关停的模型 | 同左 | 设置 `NANOBANANA_MODEL=gemini-3.1-flash-image` |
| cc-nano-banana 等调用该扩展的 Skill | 说明文档写默认 `gemini-2.5-flash-image`，实际由扩展决定；文档推荐的 Pro 写法是 `gemini-3-pro-image-preview` | 未设 `NANOBANANA_MODEL` 时同上；按文档填了 Pro 预览版的也失效 | 填 `gemini-2.5-flash-image` 的配置失效 | 同上，要 Pro 就填 `gemini-3-pro-image` |
| 自己写的脚本、固定填 `gemini-2.5-flash-image` | 初代 Nano Banana | 仍可用 | 失效 | 改为 `gemini-3.1-flash-image`，要最便宜就用 Lite |
| 通过 OpenRouter 调用 | `google/gemini-3.1-flash-image`（正式版） | 不受影响 | 不受影响 | 模型不用改；如果 Key 贴进过对话，换一个新 Key |
| 第三方托管的 Nano Banana MCP | 由服务商决定 | 看服务商是否已换正式版 | 同左 | 向服务商确认实际调用的模型 ID |

cc-nano-banana 和 nanobanana 扩展的修法一样：打开 `~/.zshrc`，加上

```bash
export NANOBANANA_MODEL=gemini-3.1-flash-image
```

然后重开终端和 Claude Code。要用 Pro 就填 `gemini-3-pro-image`，要最便宜就填 `gemini-3.1-flash-lite-image`。

有两点需要知道。第一，"默认安装现在出不了图"是根据扩展源码推断的：没设 `NANOBANANA_MODEL` 时，请求会发往 6 月 25 日已关停的 `gemini-3.1-flash-image-preview`；扩展不检查模型名，填什么就原样发出去，所以拼错或填成旧 ID 都要等请求到了 Google 才失败。第二，扩展会把错误包装成笼统的提示，比如 HTTP 400 统一提示"请求格式有误，可能是提示词触发了安全限制"。看到这类提示时，先确认模型 ID，再去改提示词。

截至 2026 年 9 月 24 日，扩展主分支最后一次提交还停在 2026 年 3 月 7 日，默认模型没有更新。只要继续用它，`NANOBANANA_MODEL` 这一行就得自己维护。

## 想走 MCP：把 nanobanana 扩展直接注册进 Claude Code

如果你想要扩展自带的图标、图案、连环画等功能，又不想经过 Gemini CLI，可以把它的 MCP 服务直接注册进 Claude Code。扩展需要 Node.js 20 以上：

```bash
git clone https://github.com/gemini-cli-extensions/nanobanana ~/tools/nanobanana
cd ~/tools/nanobanana && npm install

claude mcp add --env NANOBANANA_API_KEY="$GEMINI_API_KEY" \
  --env NANOBANANA_MODEL=gemini-3.1-flash-image \
  --transport stdio --scope user nanobanana \
  -- node ~/tools/nanobanana/mcp-server/dist/index.js

claude mcp list
```

几处细节：

- 仓库里没有提交构建产物 `dist/`，克隆后必须在仓库根目录跑一次 `npm install`：它会顺带安装 `mcp-server` 的依赖并完成构建。启动入口 `mcp-server/dist/index.js` 与扩展仓库 `gemini-extension.json` 里写的一致。
- `--env` 可以写多个，但它和服务名 `nanobanana` 之间必须隔着别的选项（这里是 `--transport stdio`），否则服务名会被当成又一个环境变量。`--` 之后的内容原样交给服务进程。
- `"$GEMINI_API_KEY"` 由 shell 展开，Key 不会出现在对话或命令历史里，但会以明文写进 Claude Code 的配置。不要用 `--scope project`，那样会写进项目根目录的 `.mcp.json`，一提交就泄露了。
- `claude mcp list` 显示 `✔ Connected` 才算连上；显示 `✘ Failed to connect` 时先检查 Node 版本和入口路径。进入 Claude Code 后也可以用 `/mcp` 查看状态。

连上后，Claude 能调用 `generate_image`、`edit_image`、`restore_image` 等工具。生成的图片存到服务进程工作目录下的 `nanobanana-output/`，一般就是你启动 Claude Code 的项目目录；需要放到别的位置时，让 Claude 生成后移过去。修改图片时，扩展会依次在当前目录、`./images/`、`./input/`、`./nanobanana-output/`、`~/Downloads/`、`~/Desktop/` 里找原图。

也有服务商提供托管的 Nano Banana MCP，给一个网址和他们的 Key 就能接入，省去本地安装。代价是你的提示词、参考图，通常还有 Key，都会经过对方的服务器，实际调用哪个模型、有没有换成正式版也由对方决定。接入前把这几点问清楚。

## Key 放哪：环境变量，而不是对话

Skill 和 MCP 两条路都把 Key 放在环境变量里，Claude 只知道变量名。如果你曾把 Key 直接粘贴进 Claude Code 对话、让它代为写进 `.env` 文件，这个 Key 已经留在会话记录里。处理办法是在 AI Studio 删除旧 Key、新建一个，再按前文写进 `~/.zshrc`。

项目里确实要用 `.env` 文件时，先把它加进 `.gitignore`。Skill 的 `SKILL.md` 里那条"不要读取、打印或索要 API Key"，是为了防止 Claude 为了排错而把 Key 打印到对话里。

## 费用：每张多少钱，怎么估

按 Google 付费层的标准价，费用基本等于"张数 × 每张输出价"。提示词和参考图按输入计费，金额比输出小得多；Batch 接口能打五折，但 Skill 这种即时调用用的是标准价。

举个例子：给 10 篇文章各做一张 16:9 的 2K 头图，平均每张重生成两次，一共 30 次调用：

- Nano Banana 2（2K）：30 × $0.101 = $3.03
- Nano Banana Pro（2K）：30 × $0.134 = $4.02
- 先用 Lite 出 1K 草稿，30 × $0.0336 ≈ $1.01，满意后再用 Nano Banana 2 出 10 张 2K 成品（10 × $0.101 = $1.01），合计约 $2.02

免费层不包括这些图片模型，更完整的价格与免费边界见 [Nano Banana API 价格](https://blog.laozhang.ai/zh/posts/nano-banana-api-pricing-free-vs-pro)。

如果你无法为 Gemini API 开通计费，脚本里预留的 `GEMINI_BASE_URL` 可以指向兼容 Gemini 原生接口的第三方服务，例如 [laozhang.ai](https://docs.laozhang.ai/api-capabilities/nano-banana-image.md)。截至 2026 年 9 月 24 日，它提供同样三个正式版模型，按次计费、不分分辨率：Lite $0.025、Nano Banana 2 $0.055、Pro $0.09。配置方法是在 `~/.zshrc` 里设置：

```bash
export GEMINI_BASE_URL=https://api.laozhang.ai
export GEMINI_API_KEY="laozhang.ai 的 Key"
```

它不是 Google：不适用 Google 的服务条款、数据条款和 SLA，提示词和图片会经过它的服务器。脚本指向这个地址时，请求能到达对方网关（无效 Key 返回 401），同样还没用真实 Key 出过图。能直接开通 Google 计费的话，用官方 Key 即可。

## 常见问题

**Claude 能自己画图，不接 Nano Banana 吗？**
Claude 能写 SVG、HTML、Canvas 或 Python 绘图代码，适合图标、图表和示意图，但不直接生成照片或插画这类位图。需要这类图片时才要接 Nano Banana，两者的边界见 [Claude能生成图片吗？](https://blog.laozhang.ai/zh/posts/can-claude-generate-images)。

**免费的 AI Studio Key 能用吗？**
Key 本身免费创建，但 Gemini API 上的 Nano Banana 2、2 Lite 和 Pro 都没有免费层，项目不开通计费就调用不了。

**Claude 说调用成功了，却没有图片文件？**
先看脚本输出：`saved ...` 表示文件已写入，确认路径即可；`No image returned` 后面的 `blockReason` 和 `finishReason` 说明了没出图的原因，按 [Nano Banana API 不出图：按返回字段逐项排查](https://blog.laozhang.ai/zh/posts/nano-banana-2-200-ok-no-image) 对照处理。

**Lite 能改图吗？**
能，但 Google 说明 Lite 不适合多张参考图和多轮连续修改，而且只出 1K。改 logo 配色这类单图修改可以先用 Lite 试；要合成多张参考图或反复迭代，用 Nano Banana 2。
