Install
openclaw skills install cf-img-genAI image generation via Cloudflare Workers AI (free tier, FLUX models) with optional prompt enhancement via Ollama or the primary LLM agent. Use when generating images from text prompts, creating visual assets, or when the user asks to generate/create an image. Triggers: 'generate image', 'create image', 'draw me', 'make an image', 'imagine', image generation requests. Zero cost on free tier (10K neurons/day).
openclaw skills install cf-img-genFree AI image generation using Cloudflare Workers AI, with optional prompt enhancement to refine and expand short prompts into detailed, vivid descriptions before generation.
Two enhancement paths:
Before using this skill, you need:
Copy the cf-img-gen directory to your OpenClaw workspace skills folder:
cp -r cf-img-gen ~/.openclaw/workspace/skills/cf-img-gen
Copy the example env file and fill in your credentials:
# Create the credentials file
mkdir -p ~/.openclaw/workspace/ACCESS
cat > ~/.openclaw/workspace/ACCESS/cloudflare-workers-ai.env << 'EOF'
CF_WORKERS_AI_TOKEN=your_api_token_here
CF_WORKERS_AI_ACCOUNT=your_account_id_here
EOF
# Edit with your actual credentials
nano ~/.openclaw/workspace/ACCESS/cloudflare-workers-ai.env
chmod 600 ~/.openclaw/workspace/ACCESS/cloudflare-workers-ai.env
cd ~/.openclaw/workspace/skills/cf-img-gen
node cf-img-gen.js "a test image of a blue circle" --width 512 --height 512
You should see output like:
🎨 Generating with flux-schnell (512x512)...
✅ Saved: /home/user/.openclaw/media/cf-img-gen/cf-img-1234567890.jpg
MEDIA:/home/user/.openclaw/media/cf-img-gen/cf-img-1234567890.jpg
The skill reads Cloudflare credentials from ~/.openclaw/workspace/ACCESS/cloudflare-workers-ai.env.
Create this file with the following format:
CF_WORKERS_AI_TOKEN=your_api_token_here
CF_WORKERS_AI_ACCOUNT=your_account_id_here
Ollama prompt enhancement can use either a local or remote Ollama instance.
Defaults (no configuration needed for local Ollama):
http://localhost:11434llama3.2:3b30000 msCustomizing Ollama connection:
Via environment variables:
export OLLAMA_HOST=http://192.168.1.100:11434
export OLLAMA_MODEL=qwen2.5:7b
Via CLI flags:
node cf-img-gen.js "red panda" --ollama --ollama-host http://192.168.1.100:11434 --ollama-model qwen2.5:7b
Via API options (see API Reference).
Setting up a remote Ollama server:
If running Ollama on a different machine, ensure it's accessible:
# On the Ollama server, bind to all interfaces
OLLAMA_HOST=0.0.0.0 ollama serve
Then connect from your client:
node cf-img-gen.js "red panda" --ollama --ollama-host http://your-server-ip:11434
Generated images are saved to: ~/.openclaw/media/cf-img-gen/
The directory is created automatically on first run.
const imgGen = require('./cf-img-gen');
// ── Basic usage (no enhancement) ──
const result = await imgGen.generate({ prompt: "a red panda in space" });
// ── With image options ──
const result = await imgGen.generate({
prompt: "a cyberpunk city at night",
width: 1024,
height: 768,
model: "flux-dev",
steps: 8,
});
// ── With Ollama prompt enhancement (default local) ──
const result = await imgGen.generate({
prompt: "red panda",
ollama: true,
});
// ── With Ollama using custom model and remote host ──
const result = await imgGen.generate({
prompt: "red panda",
ollama: {
host: "http://192.168.1.100:11434",
model: "qwen2.5:7b",
timeout: 30000,
},
});
// ── With primary LLM agent enhancement ──
// (The calling LLM enhances the prompt before calling generate)
const enhancedPrompt = "A fluffy red panda sitting on a mossy branch in a misty forest, soft morning light filtering through the canopy, detailed fur texture, cinematic composition, 8K quality";
const result = await imgGen.generate({
prompt: "red panda",
llm: { enhancedPrompt },
});
// ── Check enhancement results ──
if (result.prompt.enhanced) {
console.log("Original:", result.prompt.original);
console.log("Enhanced:", result.prompt.enhanced);
console.log("Source:", result.enhancement.source); // 'llm' or 'ollama'
}
# Basic generation (default: 1024x1024, flux-schnell)
node cf-img-gen.js "a sunset over the ocean"
# Specify dimensions
node cf-img-gen.js "a mountain landscape" --width 1024 --height 768
# Use a different model
node cf-img-gen.js "a detailed portrait" --model flux-dev
# More inference steps for higher quality
node cf-img-gen.js "a complex scene" --model flux-dev --steps 8
# Enable Ollama prompt enhancement (default local model)
node cf-img-gen.js "red panda" --ollama
# Ollama with custom model
node cf-img-gen.js "red panda" --ollama --ollama-model qwen2.5:7b
# Ollama with remote host
node cf-img-gen.js "red panda" --ollama --ollama-host http://192.168.1.100:11434
# Provide a pre-enhanced prompt (from LLM agent)
node cf-img-gen.js "red panda" --enhanced-prompt "A fluffy red panda sitting on a mossy branch in a misty forest, soft morning light, detailed fur, cinematic"
# Combined: Ollama + custom model + image options
node cf-img-gen.js "red panda" --ollama --ollama-model llama3.2:3b --width 1024 --height 1024 --model flux-dev
# Show help
node cf-img-gen.js --help
When an LLM agent (like Jerith) handles image generation requests:
generate() with the original prompt + your enhanced version via llm.enhancedPromptMEDIA:<filepath> for Discord auto-attachExample agent workflow:
User: "draw me a red panda"
Agent thinks: "Short prompt — I should enhance it."
Enhanced: "A fluffy red panda sitting on a mossy branch in a misty bamboo forest, soft golden morning light filtering through the canopy, detailed fur texture with warm russet and cream tones, shallow depth of field, cinematic composition, peaceful atmosphere, 8K quality"
Agent calls:
generate({
prompt: "draw me a red panda",
llm: { enhancedPrompt: "A fluffy red panda sitting on..." }
})
Agent responds:
🎨 Generated with flux-schnell (1024x1024) [llm enhanced]
MEDIA:/path/to/image.jpg
When to enhance:
When multiple enhancement options are provided, the skill uses this priority:
llm.enhancedPrompt — pre-enhanced by the primary LLM agent (highest priority)ollama — Ollama LLM enhancementIf llm.enhancedPrompt is provided, Ollama is skipped entirely. If skipEnhance is true, all enhancement is bypassed.
The calling LLM agent (e.g. Jerith) enhances the prompt before calling generate().
Advantages:
How to use:
// The agent enhances the prompt itself, then passes it
const result = await imgGen.generate({
prompt: "red panda",
llm: {
enhancedPrompt: "A fluffy red panda in a misty forest, golden light, cinematic"
},
});
CLI equivalent:
node cf-img-gen.js "red panda" --enhanced-prompt "A fluffy red panda in a misty forest, golden light, cinematic"
A local or remote Ollama LLM handles enhancement automatically.
Advantages:
How to use:
const result = await imgGen.generate({
prompt: "red panda",
ollama: true, // uses defaults
});
// Or with custom options
const result = await imgGen.generate({
prompt: "red panda",
ollama: {
host: "http://192.168.1.100:11434",
model: "qwen2.5:7b",
timeout: 30000,
},
});
If Ollama is unreachable (not running, network error, timeout), the skill falls back to the original prompt without throwing an error. A warning is logged to stderr. LLM agent enhancement has no failure mode — the agent either provides an enhanced prompt or doesn't.
| Model | Size | Speed | Quality | Best For |
|---|---|---|---|---|
llama3.2:3b (default) | 3B | Fast | Good | General use, quick enhancement |
qwen2.5:7b | 7B | Medium | Great | Better detail, creative prompts |
llama3.1:8b | 8B | Medium | Great | Balanced quality/speed |
mistral:7b | 7B | Medium | Good | Alternative to llama |
| Model | API Key | Speed | Quality | Best For |
|---|---|---|---|---|
| FLUX.1 Schnell | flux-schnell | ~1-3s | Good | Quick generations, general use (default) |
| FLUX.1 Dev | flux-dev | ~5-10s | Great | Higher quality, more detail |
| Stable Diffusion XL | sdxl | ~3-5s | Good | SDXL-style outputs |
| DreamShaper 8 LCM | dreamshaper | ~2-4s | Good | Artistic/stylized images |
Recommendation: Use flux-schnell for quick iterations and general use. Switch to flux-dev with higher steps (6-8) for final/high-quality outputs.
generate(options)Generate an image from a text prompt, with optional prompt enhancement.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
prompt | string | required | Text description of the image to generate |
width | number | 1024 | Image width in pixels |
height | number | 1024 | Image height in pixels |
model | string | flux-schnell | Model to use (see Models table) |
steps | number | 4 | Number of inference steps (higher = more detail, slower) |
ollama | object|true|null | null | Enable Ollama prompt enhancement. Pass true for defaults, or an object with { host, model, timeout } |
llm | object|null | null | Pre-enhanced prompt from the primary LLM agent. Object with { enhancedPrompt: "..." } |
skipEnhance | boolean | false | If true, skip all prompt enhancement |
Enhancement priority: llm.enhancedPrompt > ollama > original prompt
Ollama options (when ollama is an object):
| Field | Type | Default | Description |
|---|---|---|---|
host | string | http://localhost:11434 | Ollama server URL (local or remote) |
model | string | llama3.2:3b | Ollama model to use for enhancement |
timeout | number | 30000 | Request timeout in milliseconds |
Returns: Promise<object>
{
filepath: "/home/user/.openclaw/media/cf-img-gen/cf-img-1234567890.jpg",
source: "cloudflare-workers-ai",
model: "flux-schnell",
width: 1024,
height: 1024,
cost: 0,
size: 184320, // bytes
prompt: {
original: "red panda",
enhanced: "A fluffy red panda sitting on a mossy branch...", // null if not enhanced
used: "A fluffy red panda sitting on a mossy branch..."
},
enhancement: {
source: "llm", // 'llm' or 'ollama' (null if not enhanced)
ollama: null, // { host, model } if Ollama was used, else null
llm: {
note: "Enhanced by primary LLM agent before calling generate()"
} // null if LLM was not used
}
}
Throws: Error if prompt is missing, credentials are invalid, or Cloudflare API request fails. Ollama failures are non-fatal (falls back to original prompt).
enhancePromptOllama(prompt, options)Standalone function to enhance a prompt via Ollama without generating an image.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
prompt | string | required | Original prompt to enhance |
options.host | string | http://localhost:11434 | Ollama server URL |
options.model | string | llama3.2:3b | Ollama model to use |
options.timeout | number | 30000 | Request timeout in ms |
Returns: Promise<string> — The enhanced prompt (or original on failure).
MODELSObject mapping model names to Cloudflare API identifiers:
{
'flux-schnell': '@cf/black-forest-labs/flux-1-schnell',
'flux-dev': '@cf/black-forest-labs/flux-1-dev',
'sdxl': '@cf/stabilityai/stable-diffusion-xl-base-1.0',
'dreamshaper': '@cf/lykon/dreamshaper-8-lcm',
}
The credentials file doesn't exist at ~/.openclaw/workspace/ACCESS/cloudflare-workers-ai.env. Create it from the example file:
cp skills/cf-img-gen/cloudflare-workers-ai.env.example \
~/.openclaw/workspace/ACCESS/cloudflare-workers-ai.env
# Then edit with your credentials
The env file exists but doesn't contain the expected variables. Ensure the file has:
CF_WORKERS_AI_TOKEN=your_token
CF_WORKERS_AI_ACCOUNT=your_account_id
No quotes, no extra spaces around =.
Your API token is invalid or doesn't have Workers AI permissions. Check:
You've hit the rate limit. The free tier allows ~10K neurons/day. Wait a moment and try again.
The API returned a 200 but without image data. This can happen with:
Try again with a different prompt or model.
Ollama prompt enhancement failed. The skill will fall back to the original prompt. To fix:
ollama serveollama pull llama3.2:3bThe Ollama model returned an empty or malformed response. Try:
qwen2.5:7b instead of llama3.2:3b)Large images or high step counts can take longer. The Cloudflare timeout is set to 120 seconds. The Ollama timeout defaults to 30 seconds (configurable via --ollama-timeout or ollama.timeout).
cf-img-gen/
├── cf-img-gen.js # Main module (CLI + programmatic API)
├── SKILL.md # This file — installation and usage guide
├── cloudflare-workers-ai.env.example # Template for credentials
└── CHANGELOG.md # Version history
Output images are stored separately:
~/.openclaw/media/cf-img-gen/
├── cf-img-1700000000000.jpg
├── cf-img-1700000001000.jpg
└── ...