@fionoble/image-gen-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # @fionoble/image-gen-cli
2
+
3
+ A CLI tool for generating and editing images using OpenAI's `gpt-image-1` model. Comes with a [Claude Code](https://claude.com/claude-code) skill for seamless AI-assisted image generation.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g @fionoble/image-gen-cli
9
+ ```
10
+
11
+ Or use without installing:
12
+
13
+ ```bash
14
+ npx @fionoble/image-gen-cli -p "A cat in a spacesuit" -o cat.png
15
+ ```
16
+
17
+ ### Prerequisites
18
+
19
+ - Node.js 18+
20
+ - An [OpenAI API key](https://platform.openai.com/api-keys) set as `OPENAI_API_KEY`
21
+
22
+ ```bash
23
+ export OPENAI_API_KEY="sk-..."
24
+ ```
25
+
26
+ ## CLI Usage
27
+
28
+ ```
29
+ image-gen [options]
30
+ ```
31
+
32
+ ### Options
33
+
34
+ | Flag | Description | Default |
35
+ |------|-------------|---------|
36
+ | `-p, --prompt <text>` | Image prompt (required) | - |
37
+ | `-i, --image <path>` | Input image for editing | - |
38
+ | `-o, --output <path>` | Output file path | `generated-<timestamp>.png` |
39
+ | `-s, --size <size>` | `1024x1024`, `1024x1536`, `1536x1024`, `auto` | `auto` |
40
+ | `-q, --quality <quality>` | `low`, `medium`, `high`, `auto` | `auto` |
41
+ | `-n, --count <n>` | Number of images to generate | `1` |
42
+ | `-m, --model <model>` | OpenAI model | `gpt-image-1` |
43
+ | `--install-skill` | Install the Claude Code skill | - |
44
+ | `--uninstall-skill` | Remove the Claude Code skill | - |
45
+
46
+ ### Examples
47
+
48
+ Generate an image:
49
+
50
+ ```bash
51
+ image-gen -p "A watercolor painting of a Japanese garden" -q high -o garden.png
52
+ ```
53
+
54
+ Edit an existing image:
55
+
56
+ ```bash
57
+ image-gen -p "Make the sky a dramatic sunset" -i photo.png -o photo-sunset.png
58
+ ```
59
+
60
+ Generate a logo:
61
+
62
+ ```bash
63
+ image-gen -p "Minimalist coffee shop logo" -q high -s 1024x1024 -o logo.png
64
+ ```
65
+
66
+ ## Claude Code Skill
67
+
68
+ Install the skill so Claude Code can generate images for you:
69
+
70
+ ```bash
71
+ image-gen --install-skill
72
+ # or
73
+ npx @fionoble/image-gen-cli --install-skill
74
+ ```
75
+
76
+ Once installed, the `/image-gen` skill is available in Claude Code. You can either:
77
+
78
+ - Invoke it directly: `/image-gen create a logo for my app`
79
+ - Or just ask naturally: "generate an image of a cat in space"
80
+
81
+ Claude will craft a detailed prompt, pick appropriate settings, generate the image, and display the result.
82
+
83
+ To remove the skill:
84
+
85
+ ```bash
86
+ image-gen --uninstall-skill
87
+ ```
88
+
89
+ ## License
90
+
91
+ ISC
package/index.js ADDED
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const OpenAI = require("openai").default;
6
+
7
+ function printUsage() {
8
+ console.log(`Usage: image-gen [options]
9
+
10
+ Generate or edit images using OpenAI's gpt-image-1 model.
11
+
12
+ Options:
13
+ -p, --prompt <text> Image prompt (required)
14
+ -i, --image <path> Input image for editing (optional)
15
+ -o, --output <path> Output file path (default: generated-<timestamp>.png)
16
+ -s, --size <size> Image size: 1024x1024, 1024x1536, 1536x1024, auto (default: auto)
17
+ -q, --quality <quality> Quality: low, medium, high, auto (default: auto)
18
+ -n, --count <n> Number of images to generate (default: 1)
19
+ -m, --model <model> Model: gpt-image-1 (default: gpt-image-1)
20
+ --install-skill Install the Claude Code skill to ~/.claude/skills/
21
+ --uninstall-skill Remove the Claude Code skill
22
+ -h, --help Show this help message
23
+
24
+ Environment:
25
+ OPENAI_API_KEY Required. Your OpenAI API key.
26
+
27
+ Examples:
28
+ image-gen -p "A cat in a spacesuit"
29
+ image-gen -p "Make the background blue" -i photo.png
30
+ image-gen -p "A logo for a coffee shop" -s 1024x1024 -q high -o logo.png
31
+ npx @fionoble/image-gen-cli --install-skill
32
+ `);
33
+ }
34
+
35
+ function installSkill() {
36
+ const os = require("os");
37
+ const skillDir = path.join(os.homedir(), ".claude", "skills", "image-gen");
38
+ const source = path.join(__dirname, "skill", "SKILL.md");
39
+
40
+ if (!fs.existsSync(source)) {
41
+ console.error("Error: SKILL.md not found in package. Try reinstalling.");
42
+ process.exit(1);
43
+ }
44
+
45
+ fs.mkdirSync(skillDir, { recursive: true });
46
+ fs.copyFileSync(source, path.join(skillDir, "SKILL.md"));
47
+ console.log(`Claude Code skill installed to ${skillDir}/SKILL.md`);
48
+ }
49
+
50
+ function uninstallSkill() {
51
+ const os = require("os");
52
+ const skillDir = path.join(os.homedir(), ".claude", "skills", "image-gen");
53
+ const skillFile = path.join(skillDir, "SKILL.md");
54
+
55
+ if (fs.existsSync(skillFile)) {
56
+ fs.unlinkSync(skillFile);
57
+ fs.rmdirSync(skillDir);
58
+ console.log("Claude Code skill removed.");
59
+ } else {
60
+ console.log("Skill not installed, nothing to remove.");
61
+ }
62
+ }
63
+
64
+ function parseArgs(argv) {
65
+ const args = {
66
+ prompt: null,
67
+ image: null,
68
+ output: null,
69
+ size: "auto",
70
+ quality: "auto",
71
+ count: 1,
72
+ model: "gpt-image-1",
73
+ };
74
+
75
+ for (let i = 2; i < argv.length; i++) {
76
+ const arg = argv[i];
77
+ switch (arg) {
78
+ case "-p":
79
+ case "--prompt":
80
+ args.prompt = argv[++i];
81
+ break;
82
+ case "-i":
83
+ case "--image":
84
+ args.image = argv[++i];
85
+ break;
86
+ case "-o":
87
+ case "--output":
88
+ args.output = argv[++i];
89
+ break;
90
+ case "-s":
91
+ case "--size":
92
+ args.size = argv[++i];
93
+ break;
94
+ case "-q":
95
+ case "--quality":
96
+ args.quality = argv[++i];
97
+ break;
98
+ case "-n":
99
+ case "--count":
100
+ args.count = parseInt(argv[++i], 10);
101
+ break;
102
+ case "-m":
103
+ case "--model":
104
+ args.model = argv[++i];
105
+ break;
106
+ case "--install-skill":
107
+ installSkill();
108
+ process.exit(0);
109
+ case "--uninstall-skill":
110
+ uninstallSkill();
111
+ process.exit(0);
112
+ case "-h":
113
+ case "--help":
114
+ printUsage();
115
+ process.exit(0);
116
+ default:
117
+ if (!args.prompt) {
118
+ args.prompt = arg;
119
+ } else {
120
+ console.error(`Unknown option: ${arg}`);
121
+ process.exit(1);
122
+ }
123
+ }
124
+ }
125
+
126
+ return args;
127
+ }
128
+
129
+ function resolveOutputPath(output, index, count) {
130
+ if (output && count === 1) {
131
+ return path.resolve(output);
132
+ }
133
+ const timestamp = Date.now();
134
+ const base = output
135
+ ? path.parse(output)
136
+ : { dir: ".", name: `generated-${timestamp}`, ext: ".png" };
137
+ if (count > 1) {
138
+ return path.resolve(base.dir, `${base.name}-${index + 1}${base.ext || ".png"}`);
139
+ }
140
+ return path.resolve(base.dir, `${base.name}${base.ext || ".png"}`);
141
+ }
142
+
143
+ async function generateImage(client, args) {
144
+ console.log(`Generating image with prompt: "${args.prompt}"`);
145
+
146
+ const params = {
147
+ model: args.model,
148
+ prompt: args.prompt,
149
+ n: args.count,
150
+ size: args.size,
151
+ quality: args.quality,
152
+ };
153
+
154
+ const result = await client.images.generate(params);
155
+
156
+ const paths = [];
157
+ for (let i = 0; i < result.data.length; i++) {
158
+ const outputPath = resolveOutputPath(args.output, i, args.count);
159
+ const imageBytes = Buffer.from(result.data[i].b64_json, "base64");
160
+ fs.writeFileSync(outputPath, imageBytes);
161
+ paths.push(outputPath);
162
+ console.log(`Saved: ${outputPath}`);
163
+ }
164
+ return paths;
165
+ }
166
+
167
+ async function editImage(client, args) {
168
+ const imagePath = path.resolve(args.image);
169
+ if (!fs.existsSync(imagePath)) {
170
+ console.error(`Input image not found: ${imagePath}`);
171
+ process.exit(1);
172
+ }
173
+
174
+ console.log(`Editing image "${imagePath}" with prompt: "${args.prompt}"`);
175
+
176
+ const imageFile = fs.createReadStream(imagePath);
177
+
178
+ const params = {
179
+ model: args.model,
180
+ prompt: args.prompt,
181
+ image: imageFile,
182
+ n: args.count,
183
+ size: args.size,
184
+ quality: args.quality,
185
+ };
186
+
187
+ const result = await client.images.edit(params);
188
+
189
+ const paths = [];
190
+ for (let i = 0; i < result.data.length; i++) {
191
+ const outputPath = resolveOutputPath(args.output, i, args.count);
192
+ const imageBytes = Buffer.from(result.data[i].b64_json, "base64");
193
+ fs.writeFileSync(outputPath, imageBytes);
194
+ paths.push(outputPath);
195
+ console.log(`Saved: ${outputPath}`);
196
+ }
197
+ return paths;
198
+ }
199
+
200
+ async function main() {
201
+ const args = parseArgs(process.argv);
202
+
203
+ if (!args.prompt) {
204
+ console.error("Error: --prompt is required");
205
+ printUsage();
206
+ process.exit(1);
207
+ }
208
+
209
+ if (!process.env.OPENAI_API_KEY) {
210
+ console.error("Error: OPENAI_API_KEY environment variable is not set");
211
+ process.exit(1);
212
+ }
213
+
214
+ const client = new OpenAI();
215
+
216
+ try {
217
+ if (args.image) {
218
+ await editImage(client, args);
219
+ } else {
220
+ await generateImage(client, args);
221
+ }
222
+ } catch (err) {
223
+ console.error(`Error: ${err.message}`);
224
+ if (err.status) {
225
+ console.error(`Status: ${err.status}`);
226
+ }
227
+ process.exit(1);
228
+ }
229
+ }
230
+
231
+ main();
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@fionoble/image-gen-cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI tool for OpenAI image generation and editing, with a Claude Code skill",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "image-gen": "./index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "skill/SKILL.md"
12
+ ],
13
+ "scripts": {
14
+ "test": "echo \"Error: no test specified\" && exit 1"
15
+ },
16
+ "keywords": [
17
+ "openai",
18
+ "image-generation",
19
+ "gpt-image",
20
+ "cli",
21
+ "claude-code",
22
+ "ai"
23
+ ],
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/Fionoble/image-gen-cli.git"
27
+ },
28
+ "author": "Fionoble",
29
+ "license": "ISC",
30
+ "type": "commonjs",
31
+ "dependencies": {
32
+ "openai": "^6.25.0"
33
+ }
34
+ }
package/skill/SKILL.md ADDED
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: image-gen
3
+ description: Generate or edit images using OpenAI's gpt-image-1 model. Use when the user asks to generate, create, or edit images using AI.
4
+ allowed-tools: Bash, Read
5
+ ---
6
+
7
+ # image-gen
8
+
9
+ Generate or edit images using OpenAI's gpt-image-1 model via the `image-gen` CLI tool.
10
+
11
+ ## Tool Location
12
+
13
+ Run with `image-gen` (if globally installed via `npm link`) or `npx image-gen-cli`.
14
+
15
+ ## Usage
16
+
17
+ ```
18
+ image-gen [options]
19
+ ```
20
+
21
+ ### Options
22
+
23
+ | Flag | Description | Default |
24
+ |------|-------------|---------|
25
+ | `-p, --prompt <text>` | Image prompt (required) | - |
26
+ | `-i, --image <path>` | Input image path for editing | - |
27
+ | `-o, --output <path>` | Output file path | `generated-<timestamp>.png` |
28
+ | `-s, --size <size>` | `1024x1024`, `1024x1536`, `1536x1024`, `auto` | `auto` |
29
+ | `-q, --quality <quality>` | `low`, `medium`, `high`, `auto` | `auto` |
30
+ | `-n, --count <n>` | Number of images | `1` |
31
+ | `-m, --model <model>` | OpenAI model | `gpt-image-1` |
32
+
33
+ ### Environment
34
+
35
+ Requires `OPENAI_API_KEY` to be set in the environment.
36
+
37
+ ## Instructions
38
+
39
+ When the user asks you to generate or edit an image:
40
+
41
+ 1. **Craft a detailed prompt** from the user's request. Good prompts are specific about style, composition, colors, lighting, and mood. Expand brief requests into rich descriptions.
42
+
43
+ 2. **Choose appropriate settings:**
44
+ - Use `-q high` for logos, artwork, or when quality matters
45
+ - Use `-q low` for quick drafts or iterations
46
+ - Use `-s 1024x1536` for portraits/vertical images
47
+ - Use `-s 1536x1024` for landscapes/horizontal images
48
+ - Use `-s 1024x1024` for square images (icons, profile pictures, logos)
49
+
50
+ 3. **For image editing** (`-i` flag): When the user provides an existing image and wants modifications, use the edit mode. The input image must be a valid PNG file.
51
+
52
+ 4. **Output path**: Always use `-o` to save to a descriptive filename in the current working directory unless the user specifies otherwise.
53
+
54
+ 5. **After generation**: Read and display the generated image to the user using the Read tool so they can see the result. Ask if they want any changes.
55
+
56
+ ## Examples
57
+
58
+ Generate a new image:
59
+ ```bash
60
+ image-gen -p "A watercolor painting of a serene Japanese garden with cherry blossoms, koi pond, and a small wooden bridge, soft morning light" -q high -s 1536x1024 -o japanese-garden.png
61
+ ```
62
+
63
+ Edit an existing image:
64
+ ```bash
65
+ image-gen -p "Change the sky to a dramatic sunset with orange and purple clouds" -i photo.png -q high -o photo-sunset.png
66
+ ```
67
+
68
+ Generate a logo:
69
+ ```bash
70
+ image-gen -p "Minimalist logo for a coffee shop called 'Bean & Brew', clean lines, modern design, coffee cup icon" -q high -s 1024x1024 -o logo.png
71
+ ```