@oaklandzoo/ostup 0.2.0 → 0.3.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/package.json +1 -1
- package/src/templates.mjs +2 -0
- package/templates/.claude/commands/generate-image-prompt.md +118 -0
- package/templates/.claude/commands/generate-image.md +168 -0
- package/templates/.claude/commands/preflight.md +8 -0
- package/templates/AGENTS.md +1 -1
- package/templates/START_HERE.md +2 -0
package/package.json
CHANGED
package/src/templates.mjs
CHANGED
|
@@ -26,6 +26,8 @@ export const REGISTRY = [
|
|
|
26
26
|
{ src: '.claude/commands/update-gui.md', dest: '.claude/commands/update-gui.md' },
|
|
27
27
|
{ src: '.claude/commands/update-backend.md', dest: '.claude/commands/update-backend.md' },
|
|
28
28
|
{ src: '.claude/commands/add-storage.md', dest: '.claude/commands/add-storage.md' },
|
|
29
|
+
{ src: '.claude/commands/generate-image-prompt.md', dest: '.claude/commands/generate-image-prompt.md' },
|
|
30
|
+
{ src: '.claude/commands/generate-image.md', dest: '.claude/commands/generate-image.md' },
|
|
29
31
|
{ src: 'CLAUDE.md', dest: 'CLAUDE.md' },
|
|
30
32
|
{ src: 'AGENTS.md', dest: 'AGENTS.md' },
|
|
31
33
|
{ src: 'START_HERE.md', dest: 'START_HERE.md' },
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Compose an image-generation prompt from the project brief plus 2-3 clarifying questions. Outputs a copy-pasteable prompt the operator pastes into DALL-E, Midjourney, Imagen, or any image tool. No API call, no key required.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Generate image prompt (composer only)
|
|
6
|
+
|
|
7
|
+
Use this when you need an image asset the project does not have yet. Composer only: produces a prompt for the operator to paste elsewhere. When the resulting image is dropped into `inputs/images/`, run `/update-image` to promote it per CLAUDE.md Part 19.
|
|
8
|
+
|
|
9
|
+
## Step 1: identify the asset type
|
|
10
|
+
|
|
11
|
+
If the operator named a type (e.g. `/generate-image-prompt hero`), use it. Otherwise ask.
|
|
12
|
+
|
|
13
|
+
Asset types:
|
|
14
|
+
|
|
15
|
+
| Type | Dimensions | Notes |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `hero` | 1920x1080 | Focal point off-center to leave room for overlaid headline |
|
|
18
|
+
| `background` | 2400x3000 or 1920x2400 | Full-bleed, subtle or busy is operator's call |
|
|
19
|
+
| `og-image` | 1200x630 | Bold, brand-forward, high contrast for social previews |
|
|
20
|
+
| `favicon` | 512x512 source | Mark only, no scene, must read at 16x16 |
|
|
21
|
+
| `infographic` | operator-defined | Clean type, flat or isometric, tight palette |
|
|
22
|
+
| `brand-scene` | 1920x1080 | Lifestyle or product photography style |
|
|
23
|
+
| `card` | 1200x900 or 1080x1080 | Focal image with headline headroom |
|
|
24
|
+
| `logo` | 1024x1024 | Mark only, transparent background preferred |
|
|
25
|
+
|
|
26
|
+
## Step 2: read the project context
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
[ -f docs/branding/ostup-brand-brief.md ] && cat docs/branding/ostup-brand-brief.md 2>/dev/null
|
|
30
|
+
[ -f inputs/INGEST_MANIFEST.md ] && cat inputs/INGEST_MANIFEST.md 2>/dev/null
|
|
31
|
+
[ -f inputs/README.md ] && cat inputs/README.md 2>/dev/null
|
|
32
|
+
ls inputs/images/ 2>/dev/null
|
|
33
|
+
grep -A 5 "Brand\|palette\|Visual identity\|tone" CLAUDE.md AGENTS.md 2>/dev/null | head -40
|
|
34
|
+
[ -f docs/brief.md ] && cat docs/brief.md 2>/dev/null
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Absorb: brand voice, color palette, mood, any existing visual style references, anything the brief specifies.
|
|
38
|
+
|
|
39
|
+
## Step 3: ask at most 3 clarifying questions
|
|
40
|
+
|
|
41
|
+
Tailor per asset type. Defaults below.
|
|
42
|
+
|
|
43
|
+
For `hero`:
|
|
44
|
+
- What is the subject in one phrase?
|
|
45
|
+
- Mood: bold / quiet / playful / serious?
|
|
46
|
+
- Any image already in `inputs/images/` to riff on?
|
|
47
|
+
|
|
48
|
+
For `og-image`:
|
|
49
|
+
- What headline word or short phrase should dominate?
|
|
50
|
+
- Same palette as the rest of the site or a contrast variant?
|
|
51
|
+
|
|
52
|
+
For `favicon`:
|
|
53
|
+
- Use the existing logo mark, or a simplified abstraction of it?
|
|
54
|
+
|
|
55
|
+
For `background`:
|
|
56
|
+
- Specific subject or abstract texture?
|
|
57
|
+
- Light or dark dominant?
|
|
58
|
+
|
|
59
|
+
For others: subject, palette, mood unless the brief makes it obvious.
|
|
60
|
+
|
|
61
|
+
## Step 4: compose the prompt
|
|
62
|
+
|
|
63
|
+
Use this exact output shape. Fill every field. Honor the brand palette from the brief.
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
PROMPT
|
|
67
|
+
------
|
|
68
|
+
<one paragraph, vivid, specific. Cover: subject, composition, lighting, color
|
|
69
|
+
palette (echo the brief), style references like "editorial photography" or
|
|
70
|
+
"isometric flat illustration" or "product hero shot". End with concrete
|
|
71
|
+
detail anchors.>
|
|
72
|
+
|
|
73
|
+
MODEL RECOMMENDATION
|
|
74
|
+
--------------------
|
|
75
|
+
<pick one with a one-line reason:
|
|
76
|
+
- DALL-E 3: photorealism, reliable text-following
|
|
77
|
+
- Midjourney v6: strongest art direction, painterly
|
|
78
|
+
- Imagen: best typography
|
|
79
|
+
- Stable Diffusion via Replicate: fastest iteration, lowest cost>
|
|
80
|
+
|
|
81
|
+
SIZE / ASPECT RATIO
|
|
82
|
+
-------------------
|
|
83
|
+
<exact dims for the asset type from Step 1>
|
|
84
|
+
|
|
85
|
+
NEGATIVE PROMPT (if applicable)
|
|
86
|
+
-------------------------------
|
|
87
|
+
<one line: things to exclude. e.g. "no text, no people, no logos in frame, no watermarks">
|
|
88
|
+
|
|
89
|
+
STYLE NOTES
|
|
90
|
+
-----------
|
|
91
|
+
<one line: e.g. "seed=2024 for reproducibility, subject off-center to leave
|
|
92
|
+
right third clear for overlaid headline">
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Step 5: report
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
Composed prompt for <asset type>.
|
|
99
|
+
|
|
100
|
+
Paste the PROMPT block above into your chosen image tool. When the image is
|
|
101
|
+
back, save it to inputs/images/ with a clear filename (e.g.
|
|
102
|
+
inputs/images/hero-v1.png).
|
|
103
|
+
|
|
104
|
+
Then run /update-image <slot> to promote it into the project and verify
|
|
105
|
+
visually per CLAUDE.md Part 19.
|
|
106
|
+
|
|
107
|
+
To skip the paste-into-another-tool step, use /generate-image instead. That
|
|
108
|
+
calls Vercel AI Gateway directly and saves the result to inputs/images/
|
|
109
|
+
(requires VERCEL_AI_GATEWAY_KEY in env).
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Hard rules
|
|
113
|
+
|
|
114
|
+
- Always honor the brand palette from the brief. Do not invent colors.
|
|
115
|
+
- Always specify exact dimensions.
|
|
116
|
+
- Never claim done. This command only composes a prompt.
|
|
117
|
+
- If the brief and operator answers conflict, surface the conflict and ask. Do not silently choose one.
|
|
118
|
+
- The PROMPT block must be copy-pasteable as-is; do not wrap it in commentary.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Compose an image-generation prompt AND call Vercel AI Gateway to actually generate the image. Saves to inputs/images/ and appends to MANIFEST.md. Requires VERCEL_AI_GATEWAY_KEY. Per CLAUDE.md Part 19, use /update-image to promote into the project.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Generate image (composer plus API call)
|
|
6
|
+
|
|
7
|
+
Same flow as `/generate-image-prompt`, but calls Vercel AI Gateway and saves the result. Operator skips the paste-into-another-tool step.
|
|
8
|
+
|
|
9
|
+
## Step 1: preflight
|
|
10
|
+
|
|
11
|
+
Check the key exists:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
if [ -n "$VERCEL_AI_GATEWAY_KEY" ]; then
|
|
15
|
+
echo "VERCEL_AI_GATEWAY_KEY: present"
|
|
16
|
+
else
|
|
17
|
+
echo "VERCEL_AI_GATEWAY_KEY: MISSING"
|
|
18
|
+
echo "Get a key: https://vercel.com/dashboard/ai-gateway"
|
|
19
|
+
echo "Set it in .env.local (export VERCEL_AI_GATEWAY_KEY=...) and rerun."
|
|
20
|
+
echo "Aborting."
|
|
21
|
+
fi
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
If the key is missing, stop and ask the operator to set it. Do not call the API without a key.
|
|
25
|
+
|
|
26
|
+
## Step 2: identify the asset type, read context, ask clarifying questions
|
|
27
|
+
|
|
28
|
+
Run Steps 1-3 of `/generate-image-prompt`. Compose the prompt in memory (or print it first for operator review if scope is significant).
|
|
29
|
+
|
|
30
|
+
## Step 3: surface cost estimate before calling
|
|
31
|
+
|
|
32
|
+
Print exactly:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
About to call Vercel AI Gateway:
|
|
36
|
+
Model: openai/dall-e-3
|
|
37
|
+
Size: 1024x1024
|
|
38
|
+
Quality: standard
|
|
39
|
+
Estimated cost: ~$0.04 (DALL-E 3 standard 1024x1024)
|
|
40
|
+
|
|
41
|
+
Proceed? (y/n)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Wait for operator confirmation. If they answer no, stop. If they answer yes (or the agent was invoked with `--yes` semantics from /update-image), proceed.
|
|
45
|
+
|
|
46
|
+
Cost reference (verify against current Vercel AI Gateway pricing before claiming numbers):
|
|
47
|
+
|
|
48
|
+
| Model | Size | Cost per image |
|
|
49
|
+
|---|---|---:|
|
|
50
|
+
| openai/dall-e-3 | 1024x1024 standard | ~$0.04 |
|
|
51
|
+
| openai/dall-e-3 | 1024x1024 hd | ~$0.08 |
|
|
52
|
+
| openai/dall-e-3 | 1792x1024 standard | ~$0.08 |
|
|
53
|
+
| openai/dall-e-3 | 1792x1024 hd | ~$0.12 |
|
|
54
|
+
| stability-ai/stable-diffusion-xl | 1024x1024 | ~$0.003 |
|
|
55
|
+
|
|
56
|
+
If size or model differs from defaults, recompute and surface.
|
|
57
|
+
|
|
58
|
+
## Step 4: call the API
|
|
59
|
+
|
|
60
|
+
Use bash and curl. OpenAI-compatible endpoint via Vercel AI Gateway.
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
TIMESTAMP=$(date +%s)
|
|
64
|
+
TYPE="<asset-type>"
|
|
65
|
+
OUT="inputs/images/${TYPE}-${TIMESTAMP}.png"
|
|
66
|
+
mkdir -p inputs/images
|
|
67
|
+
|
|
68
|
+
# Use a heredoc to safely encode the prompt
|
|
69
|
+
PROMPT_JSON=$(cat <<'JSON_EOF'
|
|
70
|
+
{
|
|
71
|
+
"model": "openai/dall-e-3",
|
|
72
|
+
"prompt": "<COMPOSED_PROMPT_GOES_HERE>",
|
|
73
|
+
"size": "1024x1024",
|
|
74
|
+
"quality": "standard",
|
|
75
|
+
"n": 1,
|
|
76
|
+
"response_format": "b64_json"
|
|
77
|
+
}
|
|
78
|
+
JSON_EOF
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
curl -s https://ai-gateway.vercel.sh/v1/images/generations \
|
|
82
|
+
-H "Authorization: Bearer $VERCEL_AI_GATEWAY_KEY" \
|
|
83
|
+
-H "Content-Type: application/json" \
|
|
84
|
+
-d "$PROMPT_JSON" > /tmp/ostup-img-response.json
|
|
85
|
+
|
|
86
|
+
# Verify success
|
|
87
|
+
if ! grep -q "b64_json" /tmp/ostup-img-response.json 2>/dev/null; then
|
|
88
|
+
echo "API call failed. Response:"
|
|
89
|
+
cat /tmp/ostup-img-response.json
|
|
90
|
+
exit 1
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Extract base64 and write the PNG
|
|
94
|
+
python3 -c "
|
|
95
|
+
import json, base64, sys
|
|
96
|
+
with open('/tmp/ostup-img-response.json') as f:
|
|
97
|
+
d = json.load(f)
|
|
98
|
+
b64 = d['data'][0]['b64_json']
|
|
99
|
+
with open('$OUT', 'wb') as f:
|
|
100
|
+
f.write(base64.b64decode(b64))
|
|
101
|
+
print('Saved:', '$OUT')
|
|
102
|
+
"
|
|
103
|
+
|
|
104
|
+
rm -f /tmp/ostup-img-response.json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
If the model returns a URL instead of base64 (some configurations), fall back to:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
URL=$(python3 -c "import json; print(json.load(open('/tmp/ostup-img-response.json'))['data'][0]['url'])")
|
|
111
|
+
curl -sL -o "$OUT" "$URL"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Step 5: append to manifest
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
MANIFEST="inputs/images/MANIFEST.md"
|
|
118
|
+
|
|
119
|
+
# Initialize if missing
|
|
120
|
+
if [ ! -f "$MANIFEST" ]; then
|
|
121
|
+
echo "# Image manifest" > "$MANIFEST"
|
|
122
|
+
echo "" >> "$MANIFEST"
|
|
123
|
+
echo "Generated images, prompts used, models, and timestamps." >> "$MANIFEST"
|
|
124
|
+
echo "" >> "$MANIFEST"
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
cat >> "$MANIFEST" <<EOF
|
|
128
|
+
|
|
129
|
+
## ${TIMESTAMP} — <asset-type>
|
|
130
|
+
|
|
131
|
+
- **File:** \`${OUT}\`
|
|
132
|
+
- **Model:** openai/dall-e-3
|
|
133
|
+
- **Size:** 1024x1024
|
|
134
|
+
- **Quality:** standard
|
|
135
|
+
- **Cost:** ~\$0.04
|
|
136
|
+
- **Prompt:**
|
|
137
|
+
> <COMPOSED_PROMPT_SUMMARY_ONE_LINE>
|
|
138
|
+
|
|
139
|
+
EOF
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Step 6: report and offer to promote
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
Generated <asset type>: inputs/images/<asset-type>-<timestamp>.png
|
|
146
|
+
Manifest updated: inputs/images/MANIFEST.md
|
|
147
|
+
|
|
148
|
+
Want to promote it into the project now? Running /update-image <slot> will:
|
|
149
|
+
1. Copy this image into public/<slot>/
|
|
150
|
+
2. Update any code references
|
|
151
|
+
3. Commit + push
|
|
152
|
+
4. Wait for Vercel deploy
|
|
153
|
+
5. Run scripts/screenshot.sh and read the PNG to verify visually
|
|
154
|
+
|
|
155
|
+
Proceed with /update-image? (y/n)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If operator agrees, run the full `/update-image` routine. Otherwise stop.
|
|
159
|
+
|
|
160
|
+
## Hard rules
|
|
161
|
+
|
|
162
|
+
- Generated images land in `inputs/images/` ONLY. Never directly in `public/`. The operator (or `/update-image`) promotes.
|
|
163
|
+
- Every generation appends a manifest line with prompt + model + size + timestamp + cost.
|
|
164
|
+
- Cost is always surfaced before the API call. No surprise charges.
|
|
165
|
+
- Missing `VERCEL_AI_GATEWAY_KEY` fails fast with a clear pointer to the dashboard URL.
|
|
166
|
+
- Brand palette from the brief must be in the prompt. No "free interpretation."
|
|
167
|
+
- This command does not promote the image. `/update-image` handles promotion + Part 19 visual verification.
|
|
168
|
+
- If the API call fails (rate limit, content policy, network), report the full error and do NOT retry silently.
|
|
@@ -34,6 +34,14 @@ echo "=== Local tools ==="
|
|
|
34
34
|
node --version
|
|
35
35
|
[ -d "/Applications/Google Chrome.app" ] && echo "Chrome: present" || echo "Chrome: MISSING (operator must install for visual verification per CLAUDE.md Part 19)"
|
|
36
36
|
[ -x "scripts/screenshot.sh" ] && echo "scripts/screenshot.sh: ready" || echo "scripts/screenshot.sh: MISSING or not executable"
|
|
37
|
+
|
|
38
|
+
echo ""
|
|
39
|
+
echo "=== AI Gateway (for /generate-image) ==="
|
|
40
|
+
if [ -n "$VERCEL_AI_GATEWAY_KEY" ]; then
|
|
41
|
+
echo "VERCEL_AI_GATEWAY_KEY: present (image generation enabled)"
|
|
42
|
+
else
|
|
43
|
+
echo "VERCEL_AI_GATEWAY_KEY: not set (/generate-image will fail until set; get one at https://vercel.com/dashboard/ai-gateway; /generate-image-prompt still works as composer-only)"
|
|
44
|
+
fi
|
|
37
45
|
```
|
|
38
46
|
|
|
39
47
|
## Step 2: print the SESSION READY summary
|
package/templates/AGENTS.md
CHANGED
|
@@ -29,7 +29,7 @@ Operator materials live in `{{INPUTS_PATH}}`. Read `{{INPUTS_PATH}}README.md` fo
|
|
|
29
29
|
|
|
30
30
|
Session lifecycle: `/bootstrap`, `/prompt-start`, `/prompt-mid`, `/prompt-end`, `/preflight`
|
|
31
31
|
|
|
32
|
-
Building: `/create-prd`, `/generate-tasks`, `/update-image`, `/update-gui`, `/update-backend`, `/add-storage`
|
|
32
|
+
Building: `/create-prd`, `/generate-tasks`, `/update-image`, `/update-gui`, `/update-backend`, `/add-storage`, `/generate-image-prompt`, `/generate-image`
|
|
33
33
|
|
|
34
34
|
See each file under `.claude/commands/` for the full routine.
|
|
35
35
|
|
package/templates/START_HERE.md
CHANGED
|
@@ -57,6 +57,8 @@ Type these in your CLI agent. Each runs a structured routine.
|
|
|
57
57
|
| `/update-gui` | Make a UI change, deploy, screenshot, confirm the visual change matches intent. Enforces visual verification. | Any UI tweak. |
|
|
58
58
|
| `/update-backend` | Make a backend/API change, deploy, probe the live endpoint, confirm behavior. | Any server/API change. |
|
|
59
59
|
| `/add-storage` | Provision a Vercel Blob, KV, Postgres, or Edge Config store + scaffold a typed `src/lib/<type>.ts` helper + pull env vars. | When you need persistent storage. |
|
|
60
|
+
| `/generate-image-prompt` | Compose an image-generation prompt from the project brief + 2-3 questions. No API call. Paste the prompt into your preferred image tool. | When you need a visual asset and want to use Midjourney, DALL-E, Imagen, etc. directly. |
|
|
61
|
+
| `/generate-image` | Compose the prompt AND call Vercel AI Gateway, saving the image to `inputs/images/`. Requires `VERCEL_AI_GATEWAY_KEY`. | When you want the image generated in-line without leaving your agent. |
|
|
60
62
|
|
|
61
63
|
## Three workflows
|
|
62
64
|
|