# Image Gen

Generate images via Nano Banana (Gemini 2.5/3.1 Flash Image) on OpenRouter.

- Repository: https://github.com/EverMind-AI/Raven (5958 stars)
- Category: Media
- License: Apache-2.0
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add EverMind-AI/Raven --skill image-gen -g -a claude-code -y`
Codex: `npx skills add EverMind-AI/Raven --skill image-gen -g -a codex -y`
Cursor: `npx skills add EverMind-AI/Raven --skill image-gen -g -a cursor -y`
Gemini CLI: `npx skills add EverMind-AI/Raven --skill image-gen -g -a gemini-cli -y`

## Description

Generate images via Nano Banana (Gemini 2.5/3.1 Flash Image) on OpenRouter. Use when the user asks to draw, illustrate, render or generate any kind of picture/diagram/scene.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# image-gen, Nano Banana via OpenRouter

Generates one or more images from a text prompt (and optionally one or more
input images) by calling Google's **Nano Banana** family on OpenRouter:

  - `google/gemini-2.5-flash-image`, original (Nano Banana)
  - `google/gemini-3.1-flash-image-preview`, latest (Nano Banana 2)

OpenRouter speaks the OpenAI-compatible chat-completions API for these
models, with two extras:

  1. The request must include `"modalities": ["image", "text"]` so the
     server knows to return image bytes, not just a description.
  2. The response carries images in a top-level ``message.images`` array
     (NOT in ``content``, that field still holds optional commentary text).

## Quick recipe

```python
import os, base64, json, urllib.request

KEY = os.environ["OPENROUTER_API_KEY"]
MODEL = "google/gemini-2.5-flash-image"   # or 3.1 for "Nano Banana 2"

def generate_image(prompt: str, out_path: str = "out.png") -> str:
    req = urllib.request.Request(
        "https://openrouter.ai/api/v1/chat/completions",
        data=json.dumps({
            "model": MODEL,
            "messages": [{"role": "user", "content": prompt}],
            "modalities": ["image", "text"],
        }).encode(),
        headers={
            "Authorization": f"Bearer {KEY}",
            "Content-Type": "application/json",
        },
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=120) as resp:
        data = json.loads(resp.read())

    msg = data["choices"][0]["message"]
    # ``message.images[i].image_url.url`` is a data URI:
    #   "data:image/png;base64,<base64-bytes>"
    url = msg["images"][0]["image_url"]["url"]
    b64 = url.split(",", 1)[1]
    with open(out_path, "wb") as f:
        f.write(base64.b64decode(b64))

    text_note = msg.get("content") or ""
    return f"Wrote {out_path} ({len(b64)//1024} KB). Model said: {text_note[:200]!r}"
```

## Request shape (full)

The rest: https://github.com/EverMind-AI/Raven/blob/HEAD/demos/skill_retrieval/skills/image-gen/SKILL.md
