@allthingsclaude/blueprints 0.4.7 → 0.4.8

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 CHANGED
@@ -140,7 +140,7 @@ Control which models power your agents:
140
140
  | `/email` | Create on-brand HTML email templates (newsletters, announcements, transactional) |
141
141
  | `/pitch` | Create an on-brand HTML presentation deck with speaker notes |
142
142
  | `/og` | Auto-generate Open Graph images for all pages in your project |
143
- | `/imagine` | Generate images using Nano Banana 2 (Gemini/fal.ai) |
143
+ | `/imagine` | Generate images using Nano Banana 2 (Gemini/fal.ai) or GPT Image 2 (fal.ai), or both side-by-side |
144
144
  | `/storyboard` | Extract UI interaction specs from video mockups |
145
145
  | `/showcase` | Design an award-winning landing page with animations and micro-interactions |
146
146
  | `/diagram` | Generate Mermaid diagrams from your codebase |
@@ -442,7 +442,7 @@ Agents are specialized workers launched by commands. Each agent is assigned a mo
442
442
  | `finalize` | `/finalize` | Session wrap-up and commits |
443
443
  | `handoff` | `/handoff` | Context documentation |
444
444
  | `i18n` | `/i18n` | Internationalization auditing and setup |
445
- | `imagine` | `/imagine` | Image generation via Nano Banana 2 |
445
+ | `imagine` | `/imagine` | Image generation via Nano Banana 2 or GPT Image 2 |
446
446
  | `implement` | `/implement` | Autonomous plan execution |
447
447
  | `migrate` | `/migrate` | Dependency upgrades and migrations |
448
448
  | `og` | `/og` | Open Graph image generation for all pages |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: imagine
3
- description: Generate images via Nano Banana 2 API
3
+ description: Generate images via Nano Banana 2 or GPT Image 2
4
4
  tools: Bash
5
5
  model: {{MODEL}}
6
6
  author: "@markoradak"
@@ -16,8 +16,10 @@ You generate images by running a single Bash command. Nothing else.
16
16
  - Do NOT search the web or use the Write tool
17
17
  - If the command fails, report the error and stop immediately
18
18
  - ONLY use these exact API endpoints:
19
- - fal generate: `https://fal.run/fal-ai/nano-banana-2`
20
- - fal edit: `https://fal.run/fal-ai/nano-banana-2/edit`
19
+ - fal nano generate: `https://fal.run/fal-ai/nano-banana-2`
20
+ - fal nano edit: `https://fal.run/fal-ai/nano-banana-2/edit`
21
+ - fal gpt generate: `https://fal.run/openai/gpt-image-2`
22
+ - fal gpt edit: `https://fal.run/openai/gpt-image-2/edit`
21
23
  - gemini: `https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent`
22
24
 
23
25
  ## CRITICAL: Shell escaping
@@ -30,6 +32,7 @@ You generate images by running a single Bash command. Nothing else.
30
32
 
31
33
  Extract from the prompt you received:
32
34
  - `prompt` — the enhanced image prompt
35
+ - `model` — `nano-banana-2`, `gpt-image-2`, or `both`
33
36
  - `api` — "gemini" or "fal"
34
37
  - `mode` — "generate" or "edit"
35
38
  - `name` — snake_case name for the output file
@@ -37,9 +40,38 @@ Extract from the prompt you received:
37
40
  - `resolution` — "1K", "2K", or "4K"
38
41
  - `reference_images` — file paths (only if mode is "edit")
39
42
 
40
- Output file: `generated/imagine_{name}.png`
43
+ ## Template selection
41
44
 
42
- ## fal + generate
45
+ | model | mode | use template |
46
+ |------------------|----------|-----------------------------|
47
+ | nano-banana-2 | generate | `gemini + generate` if api=gemini, else `fal nano + generate` |
48
+ | nano-banana-2 | edit | `gemini + edit` if api=gemini, else `fal nano + edit` |
49
+ | gpt-image-2 | generate | `fal gpt + generate` |
50
+ | gpt-image-2 | edit | `fal gpt + edit` |
51
+ | both | generate | `both + generate` (parallel fal nano + fal gpt) |
52
+ | both | edit | `both + edit` (parallel fal nano + fal gpt) |
53
+
54
+ ## Output file(s)
55
+
56
+ - `model=nano-banana-2` or `gpt-image-2` → `generated/imagine_{name}.png`
57
+ - `model=both` → `generated/imagine_{name}_nano.png` AND `generated/imagine_{name}_gpt.png`
58
+
59
+ ## aspect_ratio → image_size preset (gpt-image-2 only)
60
+
61
+ gpt-image-2 doesn't take `aspect_ratio`/`resolution`. Map to fal preset name:
62
+
63
+ | aspect_ratio | image_size preset |
64
+ |--------------|--------------------|
65
+ | `1:1` | `square_hd` |
66
+ | `16:9` | `landscape_16_9` |
67
+ | `9:16` | `portrait_16_9` |
68
+ | `4:3` | `landscape_4_3` |
69
+ | `3:4` | `portrait_4_3` |
70
+ | anything else| `landscape_4_3` |
71
+
72
+ Always pass `quality: "high"` for gpt-image-2.
73
+
74
+ ## fal nano + generate
43
75
 
44
76
  Copy this template exactly, substituting PROMPT, NAME, ASPECT, RESOLUTION:
45
77
 
@@ -51,7 +83,7 @@ PROMPTEOF
51
83
  node -e 'var fs=require("fs");fs.writeFileSync("/tmp/imagine_payload.json",JSON.stringify({prompt:fs.readFileSync("/tmp/imagine_prompt.txt","utf-8").trim(),aspect_ratio:"ASPECT",resolution:"RESOLUTION"}))' && curl -s "https://fal.run/fal-ai/nano-banana-2" -H "Authorization: Key $FAL_KEY" -H "Content-Type: application/json" -d @/tmp/imagine_payload.json -o /tmp/imagine_resp.json && IMG=$(node -p 'JSON.parse(require("fs").readFileSync("/tmp/imagine_resp.json","utf-8")).images[0].url') && curl -s "$IMG" -o generated/imagine_NAME.png && rm -f /tmp/imagine_resp.json /tmp/imagine_payload.json /tmp/imagine_prompt.txt
52
84
  ```
53
85
 
54
- ## fal + edit
86
+ ## fal nano + edit
55
87
 
56
88
  Copy this template exactly, substituting PROMPT, NAME, ASPECT, RESOLUTION, PATH1/PATH2:
57
89
 
@@ -87,8 +119,62 @@ PROMPTEOF
87
119
  node -e 'var fs=require("fs"),prompt=fs.readFileSync("/tmp/imagine_prompt.txt","utf-8").trim(),imgs=["PATH1","PATH2"],parts=imgs.map(function(p){return {inline_data:{mime_type:"image/"+p.split(".").pop(),data:fs.readFileSync(p).toString("base64")}}});parts.push({text:prompt});fs.writeFileSync("/tmp/imagine_payload.json",JSON.stringify({contents:[{parts:parts}],generationConfig:{responseModalities:["IMAGE"],imageConfig:{aspectRatio:"ASPECT",imageSize:"RESOLUTION"}}}))' && curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent" -H "Content-Type: application/json" -H "x-goog-api-key: $GEMINI_API_KEY" -d @/tmp/imagine_payload.json -o /tmp/imagine_resp.json && node -e 'var fs=require("fs"),r=JSON.parse(fs.readFileSync("/tmp/imagine_resp.json","utf-8")),c=r.candidates,p=c&&c[0]&&c[0].content&&c[0].content.parts,i=p&&p.find(function(x){return x.inlineData||x.inline_data});if(!i){var e=r.error;console.error(e&&e.message||"No image");process.exit(1)}var d=i.inlineData||i.inline_data;fs.writeFileSync("generated/imagine_NAME.png",Buffer.from(d.data,"base64"))' && rm -f /tmp/imagine_resp.json /tmp/imagine_payload.json /tmp/imagine_prompt.txt
88
120
  ```
89
121
 
122
+ ## fal gpt + generate
123
+
124
+ Copy this template exactly, substituting PROMPT, NAME, IMAGE_SIZE (mapped from aspect_ratio per the table above):
125
+
126
+ ```
127
+ mkdir -p generated
128
+ cat << 'PROMPTEOF' > /tmp/imagine_prompt.txt
129
+ PROMPT
130
+ PROMPTEOF
131
+ node -e 'var fs=require("fs");fs.writeFileSync("/tmp/imagine_payload.json",JSON.stringify({prompt:fs.readFileSync("/tmp/imagine_prompt.txt","utf-8").trim(),image_size:"IMAGE_SIZE",quality:"high"}))' && curl -s "https://fal.run/openai/gpt-image-2" -H "Authorization: Key $FAL_KEY" -H "Content-Type: application/json" -d @/tmp/imagine_payload.json -o /tmp/imagine_resp.json && IMG=$(node -p 'JSON.parse(require("fs").readFileSync("/tmp/imagine_resp.json","utf-8")).images[0].url') && curl -s "$IMG" -o generated/imagine_NAME.png && rm -f /tmp/imagine_resp.json /tmp/imagine_payload.json /tmp/imagine_prompt.txt
132
+ ```
133
+
134
+ ## fal gpt + edit
135
+
136
+ Copy this template exactly, substituting PROMPT, NAME, IMAGE_SIZE, PATH1/PATH2:
137
+
138
+ ```
139
+ mkdir -p generated
140
+ cat << 'PROMPTEOF' > /tmp/imagine_prompt.txt
141
+ PROMPT
142
+ PROMPTEOF
143
+ node -e 'var fs=require("fs"),prompt=fs.readFileSync("/tmp/imagine_prompt.txt","utf-8").trim(),imgs=["PATH1","PATH2"],urls=imgs.map(function(p){return "data:image/"+p.split(".").pop()+";base64,"+fs.readFileSync(p).toString("base64")});fs.writeFileSync("/tmp/imagine_payload.json",JSON.stringify({prompt:prompt,image_urls:urls,image_size:"IMAGE_SIZE",quality:"high"}))' && curl -s "https://fal.run/openai/gpt-image-2/edit" -H "Authorization: Key $FAL_KEY" -H "Content-Type: application/json" -d @/tmp/imagine_payload.json -o /tmp/imagine_resp.json && IMG=$(node -p 'JSON.parse(require("fs").readFileSync("/tmp/imagine_resp.json","utf-8")).images[0].url') && curl -s "$IMG" -o generated/imagine_NAME.png && rm -f /tmp/imagine_resp.json /tmp/imagine_payload.json /tmp/imagine_prompt.txt
144
+ ```
145
+
146
+ ## both + generate
147
+
148
+ Runs fal nano-banana-2 and fal gpt-image-2 in parallel within a single Bash call. Substitute PROMPT, NAME, ASPECT, RESOLUTION, IMAGE_SIZE:
149
+
150
+ ```
151
+ mkdir -p generated
152
+ cat << 'PROMPTEOF' > /tmp/imagine_prompt.txt
153
+ PROMPT
154
+ PROMPTEOF
155
+ node -e 'var fs=require("fs"),p=fs.readFileSync("/tmp/imagine_prompt.txt","utf-8").trim();fs.writeFileSync("/tmp/imagine_nano_payload.json",JSON.stringify({prompt:p,aspect_ratio:"ASPECT",resolution:"RESOLUTION"}));fs.writeFileSync("/tmp/imagine_gpt_payload.json",JSON.stringify({prompt:p,image_size:"IMAGE_SIZE",quality:"high"}))' && (curl -s "https://fal.run/fal-ai/nano-banana-2" -H "Authorization: Key $FAL_KEY" -H "Content-Type: application/json" -d @/tmp/imagine_nano_payload.json -o /tmp/imagine_nano_resp.json & curl -s "https://fal.run/openai/gpt-image-2" -H "Authorization: Key $FAL_KEY" -H "Content-Type: application/json" -d @/tmp/imagine_gpt_payload.json -o /tmp/imagine_gpt_resp.json & wait) && NANO=$(node -p 'JSON.parse(require("fs").readFileSync("/tmp/imagine_nano_resp.json","utf-8")).images[0].url') && GPT=$(node -p 'JSON.parse(require("fs").readFileSync("/tmp/imagine_gpt_resp.json","utf-8")).images[0].url') && (curl -s "$NANO" -o generated/imagine_NAME_nano.png & curl -s "$GPT" -o generated/imagine_NAME_gpt.png & wait) && rm -f /tmp/imagine_nano_resp.json /tmp/imagine_gpt_resp.json /tmp/imagine_nano_payload.json /tmp/imagine_gpt_payload.json /tmp/imagine_prompt.txt
156
+ ```
157
+
158
+ ## both + edit
159
+
160
+ Runs fal nano-banana-2/edit and fal gpt-image-2/edit in parallel. Substitute PROMPT, NAME, ASPECT, RESOLUTION, IMAGE_SIZE, PATH1/PATH2:
161
+
162
+ ```
163
+ mkdir -p generated
164
+ cat << 'PROMPTEOF' > /tmp/imagine_prompt.txt
165
+ PROMPT
166
+ PROMPTEOF
167
+ node -e 'var fs=require("fs"),prompt=fs.readFileSync("/tmp/imagine_prompt.txt","utf-8").trim(),imgs=["PATH1","PATH2"],urls=imgs.map(function(p){return "data:image/"+p.split(".").pop()+";base64,"+fs.readFileSync(p).toString("base64")});fs.writeFileSync("/tmp/imagine_nano_payload.json",JSON.stringify({prompt:prompt,aspect_ratio:"ASPECT",resolution:"RESOLUTION",image_urls:urls}));fs.writeFileSync("/tmp/imagine_gpt_payload.json",JSON.stringify({prompt:prompt,image_urls:urls,image_size:"IMAGE_SIZE",quality:"high"}))' && (curl -s "https://fal.run/fal-ai/nano-banana-2/edit" -H "Authorization: Key $FAL_KEY" -H "Content-Type: application/json" -d @/tmp/imagine_nano_payload.json -o /tmp/imagine_nano_resp.json & curl -s "https://fal.run/openai/gpt-image-2/edit" -H "Authorization: Key $FAL_KEY" -H "Content-Type: application/json" -d @/tmp/imagine_gpt_payload.json -o /tmp/imagine_gpt_resp.json & wait) && NANO=$(node -p 'JSON.parse(require("fs").readFileSync("/tmp/imagine_nano_resp.json","utf-8")).images[0].url') && GPT=$(node -p 'JSON.parse(require("fs").readFileSync("/tmp/imagine_gpt_resp.json","utf-8")).images[0].url') && (curl -s "$NANO" -o generated/imagine_NAME_nano.png & curl -s "$GPT" -o generated/imagine_NAME_gpt.png & wait) && rm -f /tmp/imagine_nano_resp.json /tmp/imagine_gpt_resp.json /tmp/imagine_nano_payload.json /tmp/imagine_gpt_payload.json /tmp/imagine_prompt.txt
168
+ ```
169
+
90
170
  ## After the command completes
91
171
 
92
- Report the output path: `generated/imagine_{name}.png`
172
+ Report the output path(s):
173
+ - single model → `generated/imagine_{name}.png`
174
+ - both → `generated/imagine_{name}_nano.png` and `generated/imagine_{name}_gpt.png`
93
175
 
94
176
  If the command failed, report the error. Do NOT retry.
177
+
178
+ ### Known caveat
179
+
180
+ `gpt-image-2/edit` accepts `image_urls` per its schema, but the official examples only show HTTPS URLs. Data URIs may or may not be accepted — if you see an error like "invalid url" or "unable to fetch image" coming from the gpt-image-2 edit endpoint, surface it verbatim and stop. Do not attempt to upload reference images to a host as a workaround.
@@ -14,13 +14,23 @@ $ARGUMENTS
14
14
 
15
15
  ## Instructions
16
16
 
17
- 1. If no API key is available, stop and tell the user to set `GEMINI_API_KEY` or `FAL_KEY`.
17
+ 1. **API key check.** If no API key is available, stop and tell the user to set `GEMINI_API_KEY` or `FAL_KEY`.
18
18
 
19
- 2. Determine `api`: "gemini" if GEMINI_API_KEY is available, "fal" otherwise.
19
+ 2. **Determine `model`** one of `nano-banana-2`, `gpt-image-2`, or `both`. Resolve in this order; first match wins:
20
+ 1. **Explicit flag** in `$ARGUMENTS`: `--model=nano-banana-2`, `--model=gpt-image-2`, or `--model=both`. Strip the flag from the prompt.
21
+ 2. **Prefix**: `nano:`, `gpt:`, or `both:` at the start. Strip it.
22
+ 3. **Natural language mention**: phrases like "with gpt-image-2", "use gpt image", "using gpt", "with nano banana", "using nano", "with both models", "compare both", "render with both". Map to the right model and remove the directive cleanly from the prompt.
23
+ 4. **Auto-heuristic** — only if none of the above matched. Bias conservatively toward `nano-banana-2` since gpt-image-2 is materially more expensive on fal:
24
+ - **Strong text-rendering signals** → `gpt-image-2`. Only triggers when the user clearly wants legible text rendered: quoted strings the prompt asks to render (`"..."`, `'...'` paired with verbs like "that says", "with the words", "reading", "labeled"), or explicit "render this text", "billboard that reads", "sign that says", "headline:", "caption:", "infographic with text". Soft typography hints alone ("logo", "poster", "book cover", "magazine cover") do **not** trigger gpt — those go to nano.
25
+ - **Otherwise** → `nano-banana-2` (default — covers people, scenes, products, soft typography, and ambiguous cases).
20
26
 
21
- 3. Check if the user included any image file paths. If yes, mode is "edit". If no, mode is "generate".
27
+ 3. **Determine `api`** based on `model`:
28
+ - `gpt-image-2` or `both` → `fal` (requires `FAL_KEY`; if missing, stop and tell the user).
29
+ - `nano-banana-2` → `gemini` if `GEMINI_API_KEY` is available, else `fal`.
22
30
 
23
- 4. Determine `aspect_ratio` and `resolution`:
31
+ 4. **Mode**: if the user included any image file paths, `mode` is `edit`. Otherwise `generate`.
32
+
33
+ 5. **Determine `aspect_ratio` and `resolution`** (used by nano-banana-2; mapped to `image_size` preset by the agent for gpt-image-2):
24
34
  - If the user explicitly requests a size or ratio (e.g., "16:9", "square", "4K"), use that.
25
35
  - If the user describes where the image will be used, infer the best fit:
26
36
  - Hero banner / website header → `16:9`, `2K`
@@ -34,17 +44,21 @@ $ARGUMENTS
34
44
  - Valid aspect ratios: `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, `21:9`
35
45
  - Valid resolutions: `1K`, `2K`, `4K`
36
46
 
37
- 5. Enhance the user's description into a detailed prompt (~100 words max). Add lighting, composition, camera angle, style, mood — stay faithful to the original request.
47
+ 6. Enhance the user's description into a detailed prompt (~100 words max). Add lighting, composition, camera angle, style, mood — stay faithful to the original request. Do NOT strip out text the user wants rendered in the image (quoted strings, headlines, etc.) — preserve it verbatim.
38
48
 
39
- 6. Derive a short snake_case name (e.g., `mountain_cabin`).
49
+ 7. Derive a short snake_case name (e.g., `mountain_cabin`).
40
50
 
41
- 7. Launch the imagine agent via Task tool with `subagent_type="imagine"` passing:
51
+ 8. Launch the imagine agent via Task tool with `subagent_type="imagine"` passing:
42
52
  - `prompt`: the enhanced prompt text
43
- - `api`: "gemini" or "fal"
44
- - `mode`: "generate" or "edit"
53
+ - `model`: `nano-banana-2`, `gpt-image-2`, or `both`
54
+ - `api`: `gemini` or `fal`
55
+ - `mode`: `generate` or `edit`
45
56
  - `name`: the snake_case name
46
- - `aspect_ratio`: e.g., "16:9"
47
- - `resolution`: e.g., "2K"
57
+ - `aspect_ratio`: e.g., `16:9`
58
+ - `resolution`: e.g., `2K`
48
59
  - `reference_images`: list of absolute file paths (if edit mode)
49
60
 
50
- 8. After the agent returns, use the Read tool to display `generated/imagine_{name}.png` inline. Show the path.
61
+ 9. After the agent returns, display the output(s) inline with the Read tool:
62
+ - `model=nano-banana-2` or `gpt-image-2` → `generated/imagine_{name}.png`
63
+ - `model=both` → `generated/imagine_{name}_nano.png` AND `generated/imagine_{name}_gpt.png`
64
+ Show the path(s).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allthingsclaude/blueprints",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
4
4
  "description": "Claude Code commands and agents for enhanced AI-assisted development workflows",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",