Claude Opus 5.5 est disponible sur SeedRouter

Nano Banana Pro dans Claude Code : un skill qui génère et retouche des images

Donnez à Claude Code un skill Nano Banana Pro : un petit script qui envoie la requête, interroge la tâche et enregistre l’image, plus un SKILL.md.

Lire en Markdown

Claude Code peut générer et retoucher des images avec Nano Banana Pro grâce à un skill : un dossier contenant un fichier SKILL.md et un court script qui appelle l’API SeedRouter. Vous tapez /nano-banana-pro et décrivez l’image ; Claude rédige le prompt et lance le script, qui envoie la requête, interroge la tâche et enregistre l’image dans votre projet. Le même dossier fonctionne aussi dans OpenAI Codex. SeedRouter ne fournit ni skill officiel ni serveur MCP, ce guide vous en donne donc un à copier. Le format du skill suit la documentation d’Anthropic et d’OpenAI, vérifiée le 29 septembre 2026.

Comment Claude Code crée-t-il des images avec Nano Banana Pro ?

Claude Code ne dessine pas lui-même. Il exécute des commandes, il peut donc lancer un script qui appelle une API d’images. Avec un skill en place, une requête se déroule ainsi :

  1. Vous appelez le skill et décrivez l’image, par exemple /nano-banana-pro a hero image for the pricing page.
  2. Claude transforme votre description en prompt Nano Banana Pro et choisit la taille et le ratio d’aspect.
  3. Il lance le script. Le script envoie la requête à POST https://api.seedrouter.ai/v1/images/generations et reçoit un ID de tâche.
  4. Le script interroge GET /v1/tasks/{id} toutes les quelques secondes jusqu’à ce que l’image soit prête, puis la télécharge dans un dossier images/.
  5. Claude vous indique le chemin du fichier et peut ensuite utiliser l’image dans votre code.

Un script, plutôt que de simples instructions, garde les appels à l’API exacts : le corps de la requête, la boucle d’interrogation et l’enregistrement du fichier sont identiques à chaque fois, quel que soit le prompt rédigé par Claude.

De quoi avez-vous besoin pour commencer ?

  • Une clé API SeedRouter, exportée dans le terminal depuis lequel vous lancez Claude Code :
export SEEDROUTER_API_KEY="your-key"
  • Des crédits. Chaque exécution correspond à une requête payante. Les nouveaux comptes commencent avec un petit solde gratuit, et les requêtes échouées ne sont pas facturées.
  • Python 3. Le script n’utilise que la bibliothèque standard, il n’y a donc rien à installer.

Le script : envoyer, interroger et enregistrer

Enregistrez ceci sous scripts/nano_banana_pro.py dans le dossier du skill :

#!/usr/bin/env python3
import argparse
import json
import os
import pathlib
import sys
import time
import urllib.error
import urllib.request

API = "https://api.seedrouter.ai/v1"
AGENT = "nano-banana-pro-skill/1.0"
MIME = {
    ".jpg": "image/jpeg",
    ".jpeg": "image/jpeg",
    ".png": "image/png",
    ".webp": "image/webp",
    ".heic": "image/heic",
    ".heif": "image/heif",
}
RATIOS = ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"]


def call(method, path, body=None):
    request = urllib.request.Request(
        API + path,
        data=None if body is None else json.dumps(body).encode(),
        method=method,
        headers={
            "Authorization": "Bearer " + os.environ["SEEDROUTER_API_KEY"],
            "Content-Type": "application/json",
            "User-Agent": AGENT,
        },
    )
    try:
        with urllib.request.urlopen(request, timeout=60) as response:
            return json.load(response)
    except urllib.error.HTTPError as error:
        sys.exit(f"HTTP {error.code}: {error.read().decode()}")


def submit(args):
    parts = [{"text": args.prompt}]
    for url in args.ref:
        suffix = pathlib.PurePosixPath(url.split("?")[0]).suffix.lower()
        if suffix not in MIME:
            sys.exit(f"Cannot tell the image type of {url}; use a .jpg, .png, .webp, .heic or .heif URL.")
        parts.append({"fileData": {"mimeType": MIME[suffix], "fileUri": url}})
    image_config = {}
    if args.ratio:
        image_config["aspectRatio"] = args.ratio
    if args.size:
        image_config["imageSize"] = args.size
    generation_config = {"responseModalities": ["IMAGE"]}
    if image_config:
        generation_config["imageConfig"] = image_config
    body = {
        "model": args.model,
        "contents": [{"role": "user", "parts": parts}],
        "generationConfig": generation_config,
    }
    return call("POST", "/images/generations", body)["id"]


def wait(task_id, out_dir, timeout):
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        task = call("GET", "/tasks/" + task_id)
        if task["status"] == "completed":
            out_dir.mkdir(parents=True, exist_ok=True)
            extension = "jpg" if task["output"]["output_format"] == "jpeg" else task["output"]["output_format"]
            for index, image in enumerate(task["output"]["data"]):
                path = out_dir / f"{task_id}-{index}.{extension}"
                download = urllib.request.Request(image["url"], headers={"User-Agent": AGENT})
                with urllib.request.urlopen(download, timeout=120) as response:
                    path.write_bytes(response.read())
                print(path)
            return
        if task["status"] == "failed":
            sys.exit(f"Task {task_id} failed: {task['error']['message']}")
        time.sleep(3)
    sys.exit(f"Task {task_id} is still processing. Resume with --resume {task_id}")


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--prompt")
    parser.add_argument("--ref", action="append", default=[])
    parser.add_argument("--ratio", choices=RATIOS)
    parser.add_argument("--size", choices=["1K", "2K", "4K"])
    parser.add_argument("--model", default="gemini-3-pro-image",
                        choices=["gemini-3-pro-image", "gemini-3-pro-image-official"])
    parser.add_argument("--out", default="images")
    parser.add_argument("--timeout", type=int, default=600)
    parser.add_argument("--resume")
    args = parser.parse_args()
    if args.resume:
        task_id = args.resume
    elif args.prompt:
        task_id = submit(args)
        print(f"task {task_id}", file=sys.stderr)
    else:
        parser.error("--prompt or --resume is required")
    wait(task_id, pathlib.Path(args.out), args.timeout)


if __name__ == "__main__":
    main()

Ce qu’il fait :

  • Il envoie une seule fois. --prompt est le texte, --ref ajoute l’URL d’une image de référence (à répéter pour en ajouter plusieurs), et --ratio et --size règlent imageConfig. Le corps de la requête suit le format generateContent de Google avec un champ model, comme le définit la référence de l’API Nano Banana Pro.
  • Il affiche l’ID de tâche dès que la tâche est créée, avant d’attendre.
  • Il interroge, puis enregistre. Quand la tâche est terminée, il télécharge chaque image dans images/ et affiche chaque chemin. Quand la tâche échoue, il affiche la raison.
  • Il reprend au lieu de renvoyer. Si l’attente expire, --resume <task id> vérifie à nouveau la même tâche. Un second envoi serait une seconde requête payante.
  • Il envoie un en-tête User-Agent. Gardez cette ligne : certains serveurs refusent celui de Python par défaut, et sans elle le téléchargement peut échouer avec une erreur 403.

Vous pouvez le tester seul avant que Claude l’utilise :

python3 scripts/nano_banana_pro.py --prompt "A ceramic teapot on a linen tablecloth, soft window light" --ratio 16:9 --size 2K

Le skill : que mettre dans SKILL.md ?

La documentation de Claude Code décrit un skill comme un répertoire contenant un fichier SKILL.md : « un frontmatter YAML entre des marqueurs --- qui indique à Claude quand utiliser le skill, et un contenu markdown avec les instructions que Claude suit quand le skill s’exécute ». Les fichiers annexes, comme un dossier scripts/, se placent à côté.

Enregistrez ceci sous SKILL.md dans le même dossier :

---
name: nano-banana-pro
description: Generate or edit an image with Nano Banana Pro (gemini-3-pro-image) through the SeedRouter API and save it into the project. Use when the user asks for an image, illustration, icon, poster or edit of an existing image.
argument-hint: "[what the image should show]"
disable-model-invocation: true
---

Create an image for this request: $ARGUMENTS

1. Write one prompt in full sentences: subject, framing, action, setting and style. Put any text that must appear in the image in double quotes and say where it goes. For an edit, say what changes and what must stay the same.
2. Choose --ratio from 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9 and --size from 1K, 2K, 4K (4K only for print).
3. Reference images must be public HTTPS URLs ending in .jpg, .png, .webp, .heic or .heif, passed with --ref. If the user points to a local file, ask for a public URL instead. Never send base64.
4. Show the user the prompt and options, and wait for approval. Each run is a paid request.
5. Run: python3 ${CLAUDE_SKILL_DIR}/scripts/nano_banana_pro.py --prompt "..." [--ratio R] [--size S] [--ref URL]
6. If it stops with "still processing", run it again with --resume and the same task ID. Never submit the same request twice.
7. Report the saved file paths. If the task failed, explain the reason and suggest a change to the prompt.

Deux champs comptent ici :

  • disable-model-invocation: true signifie que vous seul pouvez lancer le skill. La documentation de Claude Code le recommande pour les « workflows qui ont des effets de bord ou dont vous voulez contrôler le moment ». Chaque exécution coûte de l’argent : Claude ne doit donc pas décider seul de générer une image.
  • ${CLAUDE_SKILL_DIR} est remplacé par le dossier du skill, le script s’exécute donc quel que soit l’endroit où vous avez installé le skill.

Où placer le skill, et comment le lancer ?

Claude Code charge les skills depuis deux emplacements principaux :

EmplacementCheminDisponible dans
Personnel~/.claude/skills/nano-banana-pro/tous vos projets sur cette machine
Projet.claude/skills/nano-banana-pro/ce dépôt ; commitez-le pour le partager avec votre équipe

Le dossier final ressemble à ceci :

nano-banana-pro/
├── SKILL.md
└── scripts/
    └── nano_banana_pro.py

Lancez Claude Code dans un terminal où SEEDROUTER_API_KEY est défini, puis tapez le nom du skill suivi de ce que vous voulez :

/nano-banana-pro a 16:9 hero image for the pricing page: a calm desk with a laptop, a notebook and a cup of tea, soft morning light, muted green palette, no text

Claude affiche le prompt et les options, vous validez, et l’image arrive dans images/. Sauf si vous avez déjà autorisé la commande, Claude Code demande aussi la permission avant de lancer le script, ce qui fait une seconde vérification avant toute facturation.

Pour le prompt lui-même, le guide des prompts Nano Banana Pro détaille la structure, le texte dans l’image et les références.

Codex peut-il utiliser le même skill Nano Banana Pro ?

Oui. Les deux outils suivent le standard ouvert Agent Skills. La documentation Codex d’OpenAI indique qu’un skill « est un répertoire avec un fichier SKILL.md plus des scripts et références facultatifs », et que ce fichier « doit inclure name et description », ce qui est le cas du skill ci-dessus.

Codex cherche les skills dans d’autres dossiers :

EmplacementChemin
Personnel~/.agents/skills/nano-banana-pro/
Dépôt.agents/skills/nano-banana-pro/

Copiez-y le dossier, ou créez un lien symbolique vers lui ; les deux outils suivent les dossiers de skills liés symboliquement. Dans Codex, lancez /skills ou tapez $nano-banana-pro pour l’appeler.

Deux différences à connaître :

  • Le chemin du script. ${CLAUDE_SKILL_DIR} est une substitution propre à Claude Code. Codex fournit au modèle le chemin du fichier de chaque skill, il peut donc trouver scripts/nano_banana_pro.py à côté de SKILL.md ; s’il lance le mauvais chemin, indiquez-lui où se trouve le script.
  • L’utilisation automatique. disable-model-invocation est un champ de Claude Code. L’équivalent dans Codex est un fichier agents/openai.yaml dans le dossier du skill, avec allow_implicit_invocation: false sous policy, pour que Codex n’exécute le skill que lorsque vous l’appelez.

Le script a besoin d’un accès réseau pour joindre api.seedrouter.ai. Si votre agent tourne dans un bac à sable sans réseau, autorisez l’accès réseau pour cette session.

Comment retoucher des images déjà présentes dans votre projet ?

Nano Banana Pro retouche à partir d’images de référence, et l’API ne les accepte que sous forme d’URL publiques. Un fichier sur votre disque doit d’abord être hébergé quelque part, par exemple dans votre propre bucket de stockage, puis transmis avec --ref.

Les images générées sont déjà hébergées : chaque tâche terminée renvoie l’image sous forme d’URL. Pour affiner un résultat, renvoyez cette URL comme référence avec la modification voulue :

/nano-banana-pro edit the last image: keep the desk and the laptop, change the tea cup to a glass of water, and make the light warmer

Claude réutilise l’URL de l’image précédente avec --ref et rédige un prompt de retouche qui précise ce qui doit rester identique. Pour une retouche sur plusieurs tours qui conserve le contexte propre du modèle entre les tours, la référence de l’API explique comment renvoyer les tours précédents ; le script ci-dessus envoie un tour à la fois.

Si vous utilisez déjà GPT Image 2 depuis un agent de code, GPT Image 2 dans Codex et Claude Code présente cette configuration, construite autour d’un prompt que vous collez dans l’agent.

Questions fréquentes

Existe-t-il un skill ou un serveur MCP Nano Banana Pro officiel de SeedRouter ?

Non. SeedRouter n’en fournit pas. Le skill de ce guide est un simple dossier qui vous appartient et que vous pouvez modifier, et il appelle l’API publique avec votre clé.

Pourquoi le script interroge-t-il la tâche au lieu d’attendre l’image ?

Sur SeedRouter, les requêtes Nano Banana Pro sont des tâches : l’envoi renvoie un ID de tâche, et l’image arrive quand la tâche est terminée. L’interrogation garde des connexions courtes, et si l’attente est interrompue, l’ID de tâche reste valable.

Puis-je utiliser le même skill pour Nano Banana 2 ?

Oui, avec de petites modifications. Remplacez la valeur par défaut et les choix de --model du script par gemini-3.1-flash-image, et ajoutez 512 aux choix de --size, une taille que Nano Banana 2 prend en charge et Pro non. Nano Banana 2 vs Pro vs 2 Lite compare les modèles.

Le chargement du skill coûte-t-il quelque chose ?

Non. Que Claude lise SKILL.md ne coûte rien sur SeedRouter. Chaque exécution du script correspond à une requête, facturée au tarif indiqué sur la page du modèle, et une tâche qui échoue n’est pas facturée.

Commencez à générer depuis Claude Code

Créez le dossier, exportez votre clé et essayez d’abord /nano-banana-pro sur une petite image. Les prix actuels figurent sur la page Nano Banana Pro, et tous les champs de requête dans la référence de l’API.

Guides associés