Nano Banana — Gemini Image Generation
Image generation skill using Google Gemini API. Supports 4K, character consistency mode, and native text-in-image.
API Key Setup
Set the GEMINI_API_KEY environment variable before using this skill:
export GEMINI_API_KEY="your-api-key-here"
You can add this to your shell profile (~/.zshrc, ~/.bashrc) or use a .env file.
Image Generation
curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"parts": [{"text": "Your prompt here"}]}],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"]
}
}' | python3 -c "
import sys, json, base64, datetime, os
data = json.load(sys.stdin)
if 'error' in data:
print(f'Error: {data[\"error\"][\"message\"]}', file=sys.stderr)
sys.exit(1)
saved = False
for candidate in data.get('candidates', []):
for part in candidate.get('content', {}).get('parts', []):
if 'inlineData' in part:
mime = part['inlineData'].get('mimeType', 'image/png')
ext = 'png' if 'png' in mime else 'jpg' if 'jpeg' in mime or 'jpg' in mime else 'webp'
out_dir = os.environ.get('NANO_BANANA_OUTPUT', '/tmp')
filename = os.path.join(out_dir, f'nano-banana-{datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")}.{ext}')
with open(filename, 'wb') as f:
f.write(base64.b64decode(part['inlineData']['data']))
print(f'Saved: {filename}')
saved = True
elif 'text' in part:
print(part['text'])
if candidate.get('finishReason') not in (None, 'STOP'):
print(f'Warning: finishReason={candidate[\"finishReason\"]}', file=sys.stderr)
if not saved:
print('Error: no image returned (empty response, safety block, or text-only reply)', file=sys.stderr)
sys.exit(1)
"
Size / Aspect Ratio
Specify directly in your prompt:
- Square: "generate a square 1024x1024 image of ..."
- Landscape: "generate a wide landscape 1536x1024 image of ..."
- Portrait: "generate a tall portrait 1024x1536 image of ..."
- 4K: "generate a high-resolution 4K image of ..."
Character Consistency Mode
To maintain the same character across multiple images, keep a fixed character description in every prompt:
"A cute bear character named Kuma, brown fur, round ears, wearing a blue scarf.
[Include this exact description in every image prompt]
In this image, Kuma is sitting at a desk coding."
Image Editing (Partial Modification)
Read an existing image as base64 and send it alongside the edit instruction:
IMAGE_B64=$(base64 -i /path/to/existing-image.png) && curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"contents\": [{\"parts\": [
{\"text\": \"Edit this image: describe your edits here\"},
{\"inlineData\": {\"mimeType\": \"image/png\", \"data\": \"$IMAGE_B64\"}}
]}],
\"generationConfig\": {
\"responseModalities\": [\"TEXT\", \"IMAGE\"]
}
}" | python3 -c "
import sys, json, base64, datetime, os
data = json.load(sys.stdin)
if 'error' in data:
print(f'Error: {data[\"error\"][\"message\"]}', file=sys.stderr)
sys.exit(1)
saved = False
for candidate in data.get('candidates', []):
for part in candidate.get('content', {}).get('parts', []):
if 'inlineData' in part:
mime = part['inlineData'].get('mimeType', 'image/png')
ext = 'png' if 'png' in mime else 'jpg' if 'jpeg' in mime or 'jpg' in mime else 'webp'
out_dir = os.environ.get('NANO_BANANA_OUTPUT', '/tmp')
filename = os.path.join(out_dir, f'nano-banana-edit-{datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")}.{ext}')
with open(filename, 'wb') as f:
f.write(base64.b64decode(part['inlineData']['data']))
print(f'Saved: {filename}')
saved = True
elif 'text' in part:
print(part['text'])
if candidate.get('finishReason') not in (None, 'STOP'):
print(f'Warning: finishReason={candidate[\"finishReason\"]}', file=sys.stderr)
if not saved:
print('Error: no image returned (empty response, safety block, or text-only reply)', file=sys.stderr)
sys.exit(1)
"
Usage Guide
- Convert the user's request into an English prompt (English yields better quality)
- Be specific with descriptions (style, colors, composition, background)
- Generated images are saved to
$NANO_BANANA_OUTPUT(defaults to/tmp/) - View the result with the Read tool and share with the user
- For consistent character style, use: "cute forest animal, chibi style, warm colors, studio ghibli inspired"
Model Reference
| Model | Notes |
|---|---|
gemini-3.1-flash-image-preview |
Default. 4K support, best quality |
gemini-2.5-flash-image |
Stable fallback |
gemini-3-pro-image-preview |
Pro quality |
Change the model name in the URL to try different models.
Environment Variables
| Variable | Default | Description |
|---|---|---|
GEMINI_API_KEY |
(required) | Your Google Gemini API key |
NANO_BANANA_OUTPUT |
/tmp |
Output directory for generated images |