Claude Opus 5.5 jest już dostępny w SeedRouter

Nano Banana Pro w Claude Code: skill, który generuje i edytuje obrazy

Daj Claude Code skill Nano Banana Pro: mały skrypt, który wysyła żądanie, odpytuje zadanie i zapisuje obraz, oraz plik SKILL.md wywoływany po nazwie.

Czytaj jako Markdown

Claude Code może generować i edytować obrazy za pomocą Nano Banana Pro dzięki skillowi: folderowi z plikiem SKILL.md i krótkim skryptem, który wywołuje SeedRouter API. Wpisujesz /nano-banana-pro i opisujesz obraz; Claude pisze prompt i uruchamia skrypt, a skrypt wysyła żądanie, odpytuje zadanie i zapisuje obraz w twoim projekcie. Ten sam folder działa też w OpenAI Codex. SeedRouter nie udostępnia oficjalnego skilla ani serwera MCP, więc ten poradnik daje ci gotowy do skopiowania. Format skilla jest zgodny z dokumentacją Anthropic i OpenAI, sprawdzoną 29 września 2026 roku.

Jak Claude Code tworzy obrazy z Nano Banana Pro?

Claude Code sam nie rysuje obrazów. Uruchamia polecenia, więc może uruchomić skrypt, który wywołuje API do obrazów. Gdy skill jest zainstalowany, jedno żądanie przebiega tak:

  1. Wywołujesz skill i opisujesz obraz, na przykład /nano-banana-pro a hero image for the pricing page.
  2. Claude zamienia twój opis w prompt dla Nano Banana Pro i wybiera rozmiar oraz proporcje.
  3. Uruchamia skrypt. Skrypt wysyła żądanie do POST https://api.seedrouter.ai/v1/images/generations i dostaje ID zadania.
  4. Skrypt co kilka sekund odpytuje GET /v1/tasks/{id}, aż obraz będzie gotowy, a potem pobiera go do folderu images/.
  5. Claude podaje ścieżkę pliku i może od razu użyć obrazu w twoim kodzie.

Skrypt, a nie same instrukcje, sprawia, że wywołania API są dokładne: treść żądania, pętla odpytywania i zapis pliku są za każdym razem takie same, niezależnie od tego, jaki prompt napisze Claude.

Czego potrzebujesz na start?

  • Klucza API SeedRouter, wyeksportowanego w terminalu, z którego uruchamiasz Claude Code:
export SEEDROUTER_API_KEY="your-key"
  • Kredytów. Każde uruchomienie to jedno płatne żądanie. Nowe konta zaczynają z niewielkim darmowym saldem, a nieudane żądania nie są rozliczane.
  • Pythona 3. Skrypt korzysta tylko z biblioteki standardowej, więc nie trzeba niczego instalować.

Skrypt: wysyłanie, odpytywanie i zapis

Zapisz to jako scripts/nano_banana_pro.py w folderze skilla:

#!/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()

Co robi:

  • Wysyła tylko raz. --prompt to tekst, --ref dodaje URL obrazu referencyjnego (powtórz, żeby dodać kilka), a --ratio i --size ustawiają imageConfig. Treść żądania to format generateContent od Google z polem model, zgodnie z dokumentacją API Nano Banana Pro.
  • Wypisuje ID zadania zaraz po jego utworzeniu, jeszcze przed czekaniem.
  • Odpytuje, potem zapisuje. Gdy zadanie się zakończy, pobiera każdy obraz do images/ i wypisuje każdą ścieżkę. Gdy zadanie się nie powiedzie, wypisuje powód.
  • Wznawia zamiast wysyłać ponownie. Jeśli czas oczekiwania minie, --resume <task id> sprawdza to samo zadanie jeszcze raz. Ponowne wysłanie oznaczałoby drugie płatne żądanie.
  • Wysyła nagłówek User-Agent. Zostaw tę linię: niektóre serwery odrzucają domyślny User-Agent Pythona i bez niej pobieranie może się nie udać z błędem 403.

Możesz przetestować go osobno, zanim użyje go Claude:

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

Sam skill: co wpisać w SKILL.md?

Dokumentacja Claude Code opisuje skill jako katalog z plikiem SKILL.md: „frontmatter YAML między znacznikami ---, który mówi Claude, kiedy użyć skilla, oraz treść markdown z instrukcjami, których Claude przestrzega, gdy skill działa”. Pliki pomocnicze, na przykład folder scripts/, leżą obok.

Zapisz to jako SKILL.md w tym samym folderze:

---
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.

Ważne są tu dwa pola:

  • disable-model-invocation: true oznacza, że tylko ty możesz uruchomić skill. Dokumentacja Claude Code zaleca to dla „przepływów pracy z efektami ubocznymi albo takich, których moment chcesz kontrolować”. Każde uruchomienie kosztuje, więc Claude nie powinien sam decydować o wygenerowaniu obrazu.
  • ${CLAUDE_SKILL_DIR} jest zastępowane folderem samego skilla, więc skrypt działa niezależnie od tego, gdzie zainstalujesz skill.

Gdzie umieścić skill i jak go uruchomić?

Claude Code wczytuje skille głównie z dwóch miejsc:

MiejsceŚcieżkaDostępny w
Osobiste~/.claude/skills/nano-banana-pro/Wszystkich twoich projektach na tym komputerze
Projekt.claude/skills/nano-banana-pro/Tym repozytorium; zrób commit, żeby udostępnić go zespołowi

Gotowy folder wygląda tak:

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

Uruchom Claude Code w terminalu z ustawioną zmienną SEEDROUTER_API_KEY i wpisz nazwę skilla, a po niej to, czego chcesz:

/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 pokazuje prompt i opcje, ty zatwierdzasz, a obraz trafia do images/. Jeśli nie zezwoliłeś wcześniej na to polecenie, Claude Code poprosi też o pozwolenie przed uruchomieniem skryptu, co daje drugą kontrolę, zanim cokolwiek zostanie naliczone.

O samym prompcie więcej mówi poradnik pisania promptów dla Nano Banana Pro: o strukturze, tekście na obrazie i referencjach.

Czy Codex może używać tego samego skilla Nano Banana Pro?

Tak. Oba narzędzia trzymają się otwartego standardu Agent Skills. Dokumentacja Codex od OpenAI mówi, że skill „to katalog z plikiem SKILL.md oraz opcjonalnymi skryptami i materiałami referencyjnymi”, a plik „musi zawierać name i description”; skill powyżej ma jedno i drugie.

Codex szuka skilli w innych folderach:

MiejsceŚcieżka
Osobiste~/.agents/skills/nano-banana-pro/
Repozytorium.agents/skills/nano-banana-pro/

Skopiuj tam folder albo utwórz do niego dowiązanie symboliczne; oba narzędzia obsługują foldery skilli podpięte dowiązaniami. W Codex uruchom /skills albo wpisz $nano-banana-pro, żeby go wywołać.

Warto znać dwie różnice:

  • Ścieżka skryptu. ${CLAUDE_SKILL_DIR} to podstawienie Claude Code. Codex pokazuje modelowi ścieżkę pliku każdego skilla, więc model znajdzie scripts/nano_banana_pro.py obok SKILL.md; jeśli uruchomi złą ścieżkę, powiedz mu, gdzie jest skrypt.
  • Automatyczne użycie. disable-model-invocation to pole Claude Code. W Codex odpowiednikiem jest plik agents/openai.yaml w folderze skilla z allow_implicit_invocation: false w sekcji policy, dzięki czemu Codex uruchamia skill tylko wtedy, gdy go wywołasz.

Skrypt potrzebuje dostępu do sieci, żeby połączyć się z api.seedrouter.ai. Jeśli twój agent działa w piaskownicy bez sieci, zezwól na dostęp do sieci w tej sesji.

Jak edytować obrazy, które już są w projekcie?

Nano Banana Pro edytuje na podstawie obrazów referencyjnych, a API przyjmuje je tylko jako publiczne adresy URL. Plik z twojego dysku trzeba najpierw gdzieś umieścić, na przykład we własnym buckecie, a potem przekazać przez --ref.

Wygenerowane obrazy są już hostowane: każde ukończone zadanie zwraca obraz jako URL. Żeby dopracować wynik, przekaż ten URL z powrotem jako referencję razem z pożądaną zmianą:

/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 ponownie używa URL poprzedniego obrazu przez --ref i pisze prompt edycji, który mówi, co ma zostać bez zmian. W przypadku edycji w wielu turach, w której model zachowuje własny kontekst między turami, dokumentacja API wyjaśnia, jak odsyłać wcześniejsze tury; powyższy skrypt wysyła jedną turę naraz.

Jeśli już używasz GPT Image 2 z agenta AI, artykuł GPT Image 2 w Codex i Claude Code opisuje tamtą konfigurację, opartą na prompcie, który wklejasz agentowi.

Najczęściej zadawane pytania

Czy SeedRouter ma oficjalny skill albo serwer MCP dla Nano Banana Pro?

Nie. SeedRouter go nie udostępnia. Skill z tego poradnika to zwykły folder, który należy do ciebie i który możesz zmieniać; wywołuje publiczne API twoim kluczem.

Dlaczego skrypt odpytuje zadanie zamiast czekać na obraz?

W SeedRouter żądania Nano Banana Pro to zadania: wysłanie zwraca ID zadania, a obraz pojawia się, gdy zadanie się zakończy. Odpytywanie utrzymuje krótkie połączenia, a jeśli czekanie zostanie przerwane, ID zadania nadal jest ważne.

Czy mogę użyć tego samego skilla dla Nano Banana 2?

Tak, po drobnych zmianach. Zmień w skrypcie wartość domyślną i opcje --model na gemini-3.1-flash-image i dodaj 512 do opcji --size — ten rozmiar obsługuje Nano Banana 2, a Pro nie. Artykuł Nano Banana 2 vs Pro vs 2 Lite porównuje modele.

Czy wczytanie skilla coś kosztuje?

Nie. To, że Claude czyta SKILL.md, nic nie kosztuje w SeedRouter. Każde uruchomienie skryptu to jedno żądanie rozliczane według stawki ze strony modelu, a nieudane zadanie nie jest rozliczane.

Zacznij generować z Claude Code

Utwórz folder, wyeksportuj klucz i najpierw wypróbuj /nano-banana-pro na małym obrazie. Aktualne ceny są na stronie Nano Banana Pro, a wszystkie pola żądania w dokumentacji API.

Powiązane poradniki