
Image Gen
- 217 installs
- Updated January 19, 2026
- infquest/vibe-ops-plugin
Generates and edits images with AI models (Gemini 2.5 Flash Image, Seedream 4.5), supporting aspect ratios, batch counts, and image-to-image edits.
About
Image-gen produces or edits images using AI models via a bundled script, collecting prompt, model, ratio, and count through guided questions. A developer uses it to generate new images or edit existing ones from a text prompt.
- Supports Gemini 2.5 Flash Image and Seedream 4.5 models
- Text-to-image and image-editing modes with selectable aspect ratios
Image Gen by the numbers
- 217 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #594 of 1,335 Generative Media skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/infquest/vibe-ops-plugin --skill image-genAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 217 |
|---|---|
| Last updated | January 19, 2026 |
| Repository | infquest/vibe-ops-plugin ↗ |
What it does
Generates and edits images with AI models (Gemini 2.5 Flash Image, Seedream 4.5), supporting aspect ratios, batch counts, and image-to-image edits.
Files
Image Generator
使用 AI 生成图片,支持多种模型和自定义选项。也支持传入图片进行二次编辑。
Prerequisites
1. MAX_API_KEY 环境变量(Max 自动注入) 2. Bun 1.0+(Max v0.0.27+ 内置,无需额外安装)
Instructions
你是一个 AI 图片生成助手。请按以下步骤操作:
Step 1: 检查环境变量
首先验证 MAX_API_KEY 是否已设置:
[ -n "$MAX_API_KEY" ] && echo "API_KEY_SET" || echo "API_KEY_NOT_SET"如果未设置,告诉用户:「请在 Max 设置中配置 Max API Key。」
Step 2: 检查 Bun 安装
which bun && bun --version || echo "NOT_INSTALLED"Bun 已内置于 Max 中,通常不需要额外安装。如果未找到,告诉用户重启 Max 应用。
Step 3: 收集用户需求
⚠️ 必须:使用 AskUserQuestion 工具收集用户的图片生成需求。不要跳过这一步。
使用 AskUserQuestion 工具收集以下信息:
1. 输入图片(可选):是否基于现有图片进行编辑
- 选项:
- "不需要 - 纯文本生成新图片 (Recommended)"
- "有图片 - 我想编辑一张现有图片"
- 如果用户选择编辑图片,询问图片路径
2. 图片描述(Prompt):让用户描述想要生成/编辑的图片
- 让用户手动输入详细描述
- 如果是编辑模式,提示用户描述想要的修改效果
- 提示用户:描述越详细,生成效果越好
3. 模型选择:选择使用哪个 AI 模型
- 选项:
- "Gemini 2.5 Flash Image - Google 图片生成模型 (Recommended)"
- "Seedream 4.5 - 字节跳动高质量模型"
4. 图片比例:选择输出比例
- 选项:
- "1:1 - 正方形 (Recommended)"
- "4:3 - 横向"
- "3:4 - 纵向"
- "16:9 - 横向宽屏"
- "9:16 - 纵向竖屏"
5. 生成数量:生成几张图片?
- 选项:
- "1 张 (Recommended)"
- "2 张"
- "4 张"
6. 保存位置:图片保存到哪里?
- 建议默认:当前目录,文件名为
generated_image_时间戳.png - 让用户可以自定义路径
Step 4: 执行脚本
使用 skill 目录下的 image-gen.js 脚本:
bun /path/to/skills/image-gen/image-gen.js "MODEL" "PROMPT" "ASPECT_RATIO" NUM_IMAGES "OUTPUT_DIR" "INPUT_IMAGE"参数说明:
- MODEL: gemini-pro / seedream
- PROMPT: 用户的图片描述
- ASPECT_RATIO: 图片比例(1:1, 4:3, 3:4, 16:9, 9:16)
- NUM_IMAGES: 生成数量
- OUTPUT_DIR: 保存目录
- INPUT_IMAGE: (可选)输入图片路径,用于图片编辑模式
示例(纯文本生成):
bun skills/image-gen/image-gen.js "gemini-pro" "一只在星空下的猫" "1:1" 1 "."示例(图片编辑):
bun skills/image-gen/image-gen.js "gemini-pro" "把背景换成海边" "1:1" 1 "." "/path/to/input.jpg"Step 5: 展示结果
生成完成后:
1. 告诉用户图片保存的完整路径 2. 显示生成的图片(如果系统支持):
# macOS 上打开图片
open "OUTPUT_PATH"3. 报告使用的 tokens/credits(如果 API 返回)
常见问题处理
API Key 无效:
- 请在 Max 设置中检查 Max API Key 是否正确配置
生成失败:
- 检查 prompt 是否包含违规内容
- 尝试换一个模型
- 检查网络连接
图片打不开:
- 确认文件完整下载
- 尝试使用其他图片查看器
示例交互
用户:帮我生成一张图片,一只在星空下的猫
助手: 1. 检查环境变量和 Bun ✓ 2. 使用 AskUserQuestion 询问用户偏好 3. 根据选择执行脚本 4. 展示生成的图片
交互风格
- 使用简单友好的语言
- 帮助用户优化 prompt(如果描述太简单,建议添加更多细节)
- 如果遇到错误,提供清晰的解决方案
- 生成成功后给予积极反馈
#!/usr/bin/env bun
import fs from 'fs';
import path from 'path';
// 配置
const API_KEY = process.env.MAX_API_KEY;
const MODEL = process.argv[2] || 'gemini-pro';
const PROMPT = process.argv[3] || 'A beautiful sunset over mountains';
const ASPECT_RATIO = process.argv[4] || '1:1';
const NUM_IMAGES = parseInt(process.argv[5]) || 1;
const OUTPUT_DIR = process.argv[6] || '.';
const INPUT_IMAGE = process.argv[7] || ''; // 可选:输入图片路径,用于图片编辑
// 模型映射
const MODEL_MAP = {
'gemini-pro': 'google/gemini-2.5-flash-image',
'seedream': 'bytedance-seed/seedream-4.5'
};
const modelId = MODEL_MAP[MODEL] || MODEL;
// 检查 API Key
if (!API_KEY) {
console.error('❌ 缺少 MAX_API_KEY 环境变量');
process.exit(1);
}
console.log(`🎨 开始生成图片...`);
console.log(`📝 提示词: ${PROMPT}`);
console.log(`🤖 模型: ${modelId}`);
console.log(`📐 比例: ${ASPECT_RATIO}`);
console.log(`🔢 数量: ${NUM_IMAGES}`);
if (INPUT_IMAGE) {
console.log(`🖼️ 输入图片: ${INPUT_IMAGE}`);
}
// 构建消息内容
let messageContent;
if (INPUT_IMAGE) {
// 图片编辑模式:读取输入图片并转为 base64
if (!fs.existsSync(INPUT_IMAGE)) {
console.error(`❌ 输入图片不存在: ${INPUT_IMAGE}`);
process.exit(1);
}
const imageBuffer = fs.readFileSync(INPUT_IMAGE);
const base64Image = imageBuffer.toString('base64');
const ext = path.extname(INPUT_IMAGE).toLowerCase().slice(1);
const mimeType = ext === 'jpg' ? 'image/jpeg' : `image/${ext}`;
messageContent = [
{
type: 'text',
text: `Edit this image: ${PROMPT}`
},
{
type: 'image_url',
image_url: {
url: `data:${mimeType};base64,${base64Image}`
}
}
];
} else {
// 纯文本生成模式
messageContent = `Generate an image: ${PROMPT}`;
}
// 使用 fetch 调用 API
try {
const response = await fetch('https://internal.infquest.com/api/openrouter/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify({
model: modelId,
messages: [
{
role: 'user',
content: messageContent
}
],
modalities: ['image', 'text'],
image_config: {
aspect_ratio: ASPECT_RATIO
},
max_tokens: 4096
})
});
const data = await response.json();
if (data.error) {
console.error(`❌ API 错误: ${data.error.message || JSON.stringify(data.error)}`);
process.exit(1);
}
// 检查响应格式
if (!data.choices || data.choices.length === 0) {
console.error('❌ 未能生成图片');
console.error('响应:', JSON.stringify(data, null, 2));
process.exit(1);
}
const message = data.choices[0].message;
const timestamp = Date.now();
let imageCount = 0;
// 处理 images 数组(OpenRouter Gemini 格式)
if (Array.isArray(message.images)) {
message.images.forEach((item, index) => {
if (item.type === 'image_url' && item.image_url?.url) {
const base64Match = item.image_url.url.match(/^data:image\/(\w+);base64,(.+)$/);
if (base64Match) {
const ext = base64Match[1] === 'jpeg' ? 'jpg' : base64Match[1];
const base64Data = base64Match[2];
const filename = NUM_IMAGES === 1
? `generated_image_${timestamp}.${ext}`
: `generated_image_${timestamp}_${index + 1}.${ext}`;
const filepath = path.join(OUTPUT_DIR, filename);
const imageBuffer = Buffer.from(base64Data, 'base64');
fs.writeFileSync(filepath, imageBuffer);
console.log(`✅ 图片已保存: ${filepath}`);
imageCount++;
}
}
});
}
// 处理 content 数组(其他模型格式)
if (imageCount === 0 && Array.isArray(message.content)) {
message.content.forEach((item, index) => {
if (item.type === 'image_url' && item.image_url?.url) {
const base64Match = item.image_url.url.match(/^data:image\/(\w+);base64,(.+)$/);
if (base64Match) {
const ext = base64Match[1] === 'jpeg' ? 'jpg' : base64Match[1];
const base64Data = base64Match[2];
const filename = `generated_image_${timestamp}_${index + 1}.${ext}`;
const filepath = path.join(OUTPUT_DIR, filename);
const imageBuffer = Buffer.from(base64Data, 'base64');
fs.writeFileSync(filepath, imageBuffer);
console.log(`✅ 图片已保存: ${filepath}`);
imageCount++;
}
}
});
}
if (imageCount === 0) {
console.log('ℹ️ 未找到图片,响应内容:');
console.log(message.content || '(空)');
} else {
console.log(`\n🎉 完成!共生成 ${imageCount} 张图片`);
}
} catch (e) {
console.error(`❌ 请求失败: ${e.message}`);
process.exit(1);
}