Banana Claws
Generate images via OpenRouter API (text-to-image) with automation-ready local scripts and a queue-first workflow. Use for single images or batched variants...
Description
name: banana-claws description: Generate images via OpenRouter API (text-to-image) with automation-ready local scripts and a queue-first workflow. Use for single images or batched variants (posters, thumbnails, illustrations, concept art), especially when agents must acknowledge quickly, process asynchronously, and return consolidated file attachments with structured success/failure records. homepage: https://github.com/ironystock/banana-claws user-invocable: true metadata: {"openclaw":{"emoji":"🍌","primaryEnv":"OPENROUTER_API_KEY","requires":{"bins":["python3"],"env":["OPENROUTER_API_KEY"]}}}
OpenRouter Image Generation
Generate images from prompts using OpenRouter's image generation endpoint.
Requirements
OPENROUTER_API_KEYin environmentpython3- Python package:
requests
Install dependency:
python3 -m pip install requests
FTUX preflight (run first)
python3 {baseDir}/scripts/preflight_check.py
python3 {baseDir}/scripts/preflight_check.py --json
If checks fail, tell the user exactly what is missing and provide copy/paste fix steps from the Fixups output.
Default model
google/gemini-3.1-flash-image-preview- Optional alternatives (if enabled on your account):
openai/gpt-5-image,openai/gpt-5-image-mini
Usage
python3 {baseDir}/scripts/generate_image.py \
--prompt "A cinematic portrait of a cyberpunk crab" \
--model google/gemini-3.1-flash-image-preview \
--image-size low \
--out ./generated/cyber-crab.png
Optional args:
--model openai/gpt-5-image
--model openai/gpt-5-image-mini
--image-size low|medium|high
--clarify-hints # print prompt-quality hints to stderr
--strict-clarify # fail fast when prompt appears underspecified
--baseline-image ./path/to/reference.png
--baseline-source-kind current_attachment|reply_attachment|explicit_path_or_url
--confirm-external-upload # required for local baseline file upload
--variation-strength low|medium|high
--must-keep "title placement"
--must-keep "logo mark"
--lock-palette
--lock-composition
--allow-no-baseline-on-edit-intent
Queue -> response pattern (avoid traffic jams)
When a user asks for multiple images/iterations, do not hold one long-running turn per image. Do not block waiting for a "single message with all files" if the adapter does not support it.
Hard contract for queue mode:
- NEVER run
run_image_queue.pyin the same foreground turn as enqueue for multi-image requests. - ALWAYS enqueue + immediate queued ack first, then background handoff.
Use a queue + batched response flow:
- Enqueue each requested image quickly.
- Immediately return with a short "queued" acknowledgement (do not wait for generation in the same turn).
- Drain queue in background (preferred: sub-agent/session worker).
- Send one consolidated completion status response when done.
- Always attach generated image files (never send only paths).
- If the messaging adapter allows only one media per send, post attachments as reply-chain messages under the consolidated completion status message (one file per message).
Enqueue command:
python3 {baseDir}/scripts/enqueue_image_job.py \
--prompt "A retro 80s crab poster" \
--model google/gemini-3.1-flash-image-preview \
--image-size low \
--clarify-hints \
--out ./generated/crab-01.png \
--request-id "discord-<message-id>"
Background queue handoff (recommended):
python3 {baseDir}/scripts/queue_and_return.py \
--prompt "A minimalist snow crab logo" \
--count 4 \
--request-id "discord-<message-id>" \
--out-dir ./generated \
--prefix crab-logo \
--queue-dir ./generated/imagegen-queue
Manual drain command (worker context only; not same foreground turn):
python3 {baseDir}/scripts/run_image_queue.py \
--queue-dir ./generated/imagegen-queue
# queue_and_return guardrails (optional tuning)
python3 {baseDir}/scripts/queue_and_return.py \
--max-background-workers 2 \
--orphan-timeout-sec 1800 \
...
Batch-enqueue N variants with consistent file names:
python3 {baseDir}/scripts/enqueue_variants.py \
--prompt "A minimalist snow crab logo" \
--count 4 \
--baseline-image ./generated/base-logo.png \
--variation-strength low \
--lock-palette \
--lock-composition \
--must-keep "wordmark placement" \
--must-keep "icon silhouette" \
--out-dir ./generated \
--prefix crab-logo \
--request-id "discord-<message-id>"
Useful options:
--max-jobs 3 # process only a subset for controlled batches
--start-index 5 # continue naming from prior batches
Data transmission notice (external provider)
- This skill sends prompts and generated/edit inputs to OpenRouter (
openrouter.ai). - If you pass
--baseline-image, that image content is transmitted to the provider as part of the request. - Do not submit sensitive/private images unless the user explicitly approves external transmission.
Notes
- If generation fails due to model/provider mismatch, retry with
--model openai/gpt-5-image-mini. - Local baseline uploads are deny-by-default; pass
--confirm-external-uploadonly when user explicitly approves sending that local file to provider. - Local baseline files are restricted to png/jpg/jpeg/webp, non-symlink regular files, workspace-local paths, and max size threshold.
- For iterative work, prefer
--image-size low; switch tomediumorhighfor final renders. - Use
--clarify-hintsto surface prompt-quality gaps early; use--strict-clarifyfor workflows that must fail on ambiguity. - Keep prompts explicit for text rendering tasks.
- Save outputs into workspace paths, not
/tmp, for durability. - When user asks for generated images in chat, attach the generated file in the response (do not only send a path).
- For queue mode, read results from:
.../imagegen-queue/results/*.json(success).../imagegen-queue/failed/*.json(failure details)
- Edit/variant intent prompts fail fast if no baseline is supplied (
--baseline-image) unless explicitly overridden. - Resolve baseline deterministically in caller: current-message attachment > replied-message attachment > clarification request.
- Pass
--baseline-source-kind current_attachment|reply_attachment|explicit_path_or_urlfor auditable provenance. - When baseline is supplied, rails default to low-variation + locked palette/composition unless explicitly changed.
- Queue results persist provider metadata (generation id + provider response payload/path) and drift diagnostics (
edit_intent_detected,baseline_applied,baseline_source,baseline_source_kind,baseline_resolution_policy,rails_applied) to help edits/debugging and smarter agent continuation. - Queue worker writes
handoff_mode+same_turn_drain_detectedso you can enforce true async behavior in tests/ops. enqueue_variants.pywrites<prefix>-manifest.jsonwith baseline, constraints, variant deltas, and output targets for reproducible reruns.
Reviews (0)
No reviews yet. Be the first to review!
Comments (0)
No comments yet. Be the first to share your thoughts!