octocode-cli 1.3.0 → 1.5.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.
Files changed (106) hide show
  1. package/README.md +129 -28
  2. package/out/chunks/chunk-7476PETK.js +309 -0
  3. package/out/chunks/chunk-CVNNNSMQ.js +26 -0
  4. package/out/chunks/chunk-OQBJTZWK.js +60 -0
  5. package/out/chunks/chunk-UCZCF3BQ.js +9 -0
  6. package/out/chunks/command-help-specs-JZXVSLZ5.js +8 -0
  7. package/out/chunks/commands-XBFPLHSQ.js +8 -0
  8. package/out/chunks/help-P7TCOYAJ.js +10 -0
  9. package/out/chunks/main-help-ULF5PAQY.js +10 -0
  10. package/out/chunks/prompts-5E6VKRX5.js +8 -0
  11. package/out/chunks/spinner-URV2OX6O.js +8 -0
  12. package/out/chunks/tool-command-M6VA7P2F.js +8 -0
  13. package/out/octocode-cli.js +1 -1
  14. package/package.json +5 -3
  15. package/skills/README.md +60 -58
  16. package/skills/agentic-flow-best-practices/SKILL.md +280 -0
  17. package/skills/agentic-flow-best-practices/references/agent-collaboration-patterns.md +75 -0
  18. package/skills/agentic-flow-best-practices/references/pr-review-agent-example.md +47 -0
  19. package/skills/agentic-flow-best-practices/references/resources.md +112 -0
  20. package/skills/octocode-brainstorming/.env.example +11 -0
  21. package/skills/octocode-brainstorming/SKILL.md +262 -0
  22. package/skills/octocode-brainstorming/scripts/tavily-search.mjs +138 -0
  23. package/skills/octocode-chrome-devtools/README.md +541 -0
  24. package/skills/octocode-chrome-devtools/SKILL.md +197 -0
  25. package/skills/octocode-chrome-devtools/agents/openai.yaml +7 -0
  26. package/skills/octocode-chrome-devtools/references/CDP_AGENT_REFERENCE.md +401 -0
  27. package/skills/octocode-chrome-devtools/references/CHROME_FLAGS.md +234 -0
  28. package/skills/octocode-chrome-devtools/references/INTENTS.md +108 -0
  29. package/skills/octocode-chrome-devtools/references/INTENTS_AUTH.md +179 -0
  30. package/skills/octocode-chrome-devtools/references/INTENTS_AUTOMATION.md +214 -0
  31. package/skills/octocode-chrome-devtools/references/INTENTS_DEBUG.md +329 -0
  32. package/skills/octocode-chrome-devtools/references/INTENTS_ENVIRONMENT.md +237 -0
  33. package/skills/octocode-chrome-devtools/references/INTENTS_INSPECT.md +263 -0
  34. package/skills/octocode-chrome-devtools/references/INTENTS_STORAGE_CONSENT.md +214 -0
  35. package/skills/octocode-chrome-devtools/references/RECOVERY.md +39 -0
  36. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS.md +43 -0
  37. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_ASYNC_WORKERS.md +345 -0
  38. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_BROWSER.md +403 -0
  39. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_OBSERVE.md +275 -0
  40. package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_SPECIAL.md +18 -0
  41. package/skills/octocode-chrome-devtools/scripts/cdp-runner.mjs +503 -0
  42. package/skills/octocode-chrome-devtools/scripts/cdp-sandbox.mjs +123 -0
  43. package/skills/octocode-chrome-devtools/scripts/cdp-template.mjs +81 -0
  44. package/skills/octocode-chrome-devtools/scripts/octocode-chrome-devtools.vpn.example.json +8 -0
  45. package/skills/octocode-chrome-devtools/scripts/open-browser.mjs +362 -0
  46. package/skills/octocode-chrome-devtools/scripts/sourcemap-resolver.mjs +193 -0
  47. package/skills/octocode-chrome-devtools/scripts/undercover.mjs +226 -0
  48. package/skills/octocode-design/README.md +2 -2
  49. package/skills/octocode-documentation-writer/README.md +1 -1
  50. package/skills/octocode-engineer/README.md +1 -1
  51. package/skills/octocode-engineer/SKILL.md +137 -306
  52. package/skills/octocode-engineer/references/cli-reference.md +13 -0
  53. package/skills/octocode-engineer/references/output-files.md +3 -3
  54. package/skills/octocode-engineer/scripts/run.js +146 -146
  55. package/skills/octocode-engineer/src/pipeline/main.ts +1 -17
  56. package/skills/octocode-engineer/src/pipeline/progress.ts +4 -0
  57. package/skills/octocode-engineer/src/reporting/summary-md.test.ts +48 -0
  58. package/skills/octocode-engineer/src/reporting/summary-md.ts +43 -2
  59. package/skills/octocode-install/SKILL.md +1 -1
  60. package/skills/octocode-pull-request-reviewer/README.md +5 -5
  61. package/skills/octocode-pull-request-reviewer/SKILL.md +1 -1
  62. package/skills/octocode-research/AGENTS.md +1 -1
  63. package/skills/octocode-research/README.md +2 -2
  64. package/skills/octocode-research/docs/ARCHITECTURE.md +1 -1
  65. package/skills/octocode-research/scripts/server.js +184 -239
  66. package/skills/octocode-research/src/routes/github.ts +4 -21
  67. package/skills/octocode-research/src/routes/local.ts +4 -21
  68. package/skills/octocode-research/src/utils/fileContentTransform.ts +44 -0
  69. package/skills/octocode-search-skill/SKILL.md +337 -0
  70. package/skills/octocode-search-skill/references/agent-skills-guide.md +177 -0
  71. package/skills/octocode-search-skill/references/discovery-surfaces.md +162 -0
  72. package/skills/octocode-search-skill/references/fetch-and-create-locally.md +57 -0
  73. package/skills/octocode-search-skill/references/install-reference.md +130 -0
  74. package/skills/octocode-search-skill/references/references-template.md +27 -0
  75. package/skills/octocode-search-skill/references/references.md +62 -0
  76. package/skills/octocode-slides/README.md +307 -0
  77. package/skills/octocode-slides/SKILL.md +410 -0
  78. package/skills/octocode-slides/references/01-brief.md +156 -0
  79. package/skills/octocode-slides/references/02-research.md +149 -0
  80. package/skills/octocode-slides/references/03-outline.md +172 -0
  81. package/skills/octocode-slides/references/04-design.md +301 -0
  82. package/skills/octocode-slides/references/05-implementation.md +213 -0
  83. package/skills/octocode-slides/references/06-review.md +258 -0
  84. package/skills/octocode-slides/references/animation.md +281 -0
  85. package/skills/octocode-slides/references/design-system.md +316 -0
  86. package/skills/octocode-slides/references/html-templates.md +673 -0
  87. package/skills/octocode-slides/references/image-generation.md +448 -0
  88. package/skills/octocode-slides/references/resources.md +840 -0
  89. package/skills/octocode-slides/references/slide-rules.md +541 -0
  90. package/skills/octocode-slides/references/wireframes.md +727 -0
  91. package/skills/octocode-slides/scripts/animation.js +182 -0
  92. package/skills/octocode-slides/scripts/base.css +353 -0
  93. package/skills/octocode-slides/scripts/base.html +655 -0
  94. package/skills/octocode-slides/scripts/generate_image.py +221 -0
  95. package/skills/octocode-slides/scripts/navbridge.js +79 -0
  96. package/skills/octocode-slides/scripts/presenter.js +316 -0
  97. package/skills/octocode-slides/scripts/slide.html +248 -0
  98. package/skills/octocode-stats/SKILL.md +73 -0
  99. package/skills/octocode-stats/assets/template.html +1332 -0
  100. package/skills/octocode-stats/scripts/build_dashboard.mjs +407 -0
  101. package/out/chunks/chunk-LH4AZJPA.js +0 -389
  102. package/out/chunks/command-help-specs-CQ3RBLP6.js +0 -8
  103. package/out/chunks/commands-M3QTWKWE.js +0 -51
  104. package/out/chunks/help-XPXP46ZT.js +0 -10
  105. package/out/chunks/main-help-HXFAFHPG.js +0 -10
  106. package/out/chunks/tool-command-VHFLPIHY.js +0 -8
@@ -0,0 +1,448 @@
1
+ # Image Generation — Nano Banana 2 (Gemini 3.1 Flash Image)
2
+
3
+ > **Status:** Opt-in. The default image rule in `references/05-implementation.md` is still "do not silently generate". This doc tells you **how** to generate when the user explicitly asks for it, and how to keep the output consistent with the deck's design system.
4
+
5
+ ---
6
+
7
+ ## TL;DR — which path
8
+
9
+ | Path | Use when | Auth | Effort |
10
+ |------|----------|------|--------|
11
+ | **A — Direct API via `google-genai` SDK** (default) | Standard case. Stable, scriptable, no third party. | `GEMINI_API_KEY` (AI Studio) | Add `scripts/generate_image.py`, set `GEMINI_API_KEY`. |
12
+ | **B — Third-party CLI (`belt` from inference.sh)** | User already on inference.sh, wants one-liner shell calls, or needs Google Search grounding out of the box. | `belt login` (inference.sh account) | `npm i -g @inferencesh/cli`, `belt login`. |
13
+ | **C — Gemini CLI + `mcp-nanobanana-go` MCP server** | User is already using Gemini CLI day-to-day and has a GCP project. Image generation via native MCP tool-calling. | Google Cloud ADC (`gcloud auth application-default login`) + `GOOGLE_CLOUD_PROJECT` | Install the Go binary MCP server + configure `~/.gemini/settings.json`. See Path C below. |
14
+
15
+ > **Note on the official `gemini` CLI**: The CLI itself does **not** have a built-in `generate image` command. Images are only possible via Path C (an MCP server that plugs into Gemini CLI). Do not propose "just run `gemini generate image …`" — that does not exist.
16
+
17
+ **Model code:** `gemini-3.1-flash-image-preview` (Nano Banana 2). For maximum factual accuracy / studio quality, swap to `gemini-3-pro-image-preview` (Nano Banana Pro). Legacy = `gemini-2.5-flash-image` (Nano Banana 1, original).
18
+
19
+ ---
20
+
21
+ ## When to invoke during the six-phase flow
22
+
23
+ Image generation is a **Phase 5 (Implementation)** decision, never a Phase 1–4 ask. Trigger conditions, all required:
24
+
25
+ 1. The user has **explicitly opted in** ("generate images", "make the hero image", "create the assets"). Implicit opt-in (e.g. `slide notes` say `IMAGE`) is not enough.
26
+ 2. The slide's outline row gives a concrete `data-expected` description (subject, style, mood, composition).
27
+ 3. The deck's `DESIGN.md` has a locked aesthetic — colors, lighting, style — so generated images don't fight the theme.
28
+ 4. Required credentials are available: `GEMINI_API_KEY` (Path A/B) or GCP ADC + `GOOGLE_CLOUD_PROJECT` (Path C).
29
+
30
+ If any condition is missing → keep the `image-ph` / `image-ph-bleed` placeholder. Never half-generate.
31
+
32
+ ---
33
+
34
+ ## Path A — Direct API (recommended)
35
+
36
+ ### Setup
37
+
38
+ Drop a one-file helper into the **skill** (not the deck) so every generated deck shares the same script:
39
+
40
+ ```
41
+ skills/octocode-slides/scripts/generate_image.py ← new helper
42
+ ```
43
+
44
+ The helper is a thin wrapper around `google-genai`:
45
+
46
+ ```python
47
+ from google import genai
48
+ from google.genai import types
49
+ client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
50
+ response = client.models.generate_content(
51
+ model="gemini-3.1-flash-image-preview",
52
+ contents=[prompt, *reference_images],
53
+ config=types.GenerateContentConfig(
54
+ response_modalities=["TEXT", "IMAGE"],
55
+ image_config=types.ImageConfig(image_size=resolution, aspect_ratio=ratio),
56
+ ),
57
+ )
58
+ ```
59
+
60
+ Full reference implementation: [`intellectronica/agent-skills/skills/nano-banana-2/scripts/generate_image.py`](https://github.com/intellectronica/agent-skills/blob/main/skills/nano-banana-2/scripts/generate_image.py).
61
+
62
+ ### Invocation
63
+
64
+ Always run from the deck root (`.octocode/slides/{{slideName}}/`) so the image lands in `assets/` next to where the slide references it:
65
+
66
+ ```bash
67
+ cd .octocode/slides/{{slideName}}
68
+ uv run /absolute/path/to/skills/octocode-slides/scripts/generate_image.py \
69
+ --prompt "<prompt>" \
70
+ --filename "assets/{{slug}}-{{timestamp}}.png" \
71
+ --resolution 2K \
72
+ --aspect-ratio 16:9
73
+ ```
74
+
75
+ ### Flags
76
+
77
+ | Flag | Default | Slide guidance |
78
+ |------|---------|---------------|
79
+ | `--prompt` | required | Use the Slide Image Prompt template below |
80
+ | `--filename` | required | `assets/{{slug}}-yyyy-mm-dd-hh-mm-ss.png` — slug matches the slide file |
81
+ | `--resolution` | `1K` | `1K` for inline / decorative · `2K` for `slide--two-col` half · `4K` only for full-bleed `slide--image` |
82
+ | `--aspect-ratio` | model default | `16:9` matches the 1280×720 slide canvas · `1:1` for inline tiles · `2:3` / `3:4` for portrait insets |
83
+ | `--input-image` | none | Repeat up to 14 times for character/object consistency across the deck |
84
+ | `--api-key` | `GEMINI_API_KEY` env | Use the env var; pass the flag only when a per-deck key is required |
85
+
86
+ ### Environment
87
+
88
+ ```bash
89
+ export GEMINI_API_KEY="..." # get from https://aistudio.google.com/apikey
90
+ command -v uv >/dev/null # required
91
+ ```
92
+
93
+ If `uv` is not installed: `brew install uv` (macOS) or `curl -LsSf https://astral.sh/uv/install.sh | sh`.
94
+
95
+ ---
96
+
97
+ ## Path B — Third-party CLI (`belt`)
98
+
99
+ Only when the user explicitly prefers inference.sh, or the deck needs Google Search grounding (real-time facts in images — weather, news, current events):
100
+
101
+ ```bash
102
+ belt login
103
+ belt app run google/gemini-3-1-flash-image-preview --input '{
104
+ "prompt": "<prompt>",
105
+ "aspect_ratio": "16:9",
106
+ "resolution": "2K",
107
+ "enable_google_search": true,
108
+ "images": ["assets/reference.png"]
109
+ }'
110
+ ```
111
+
112
+ Save the returned image into `assets/{{slug}}-{{timestamp}}.png` manually (the CLI prints a URL/path; download with `curl`).
113
+
114
+ ---
115
+
116
+ ## Path C — Gemini CLI + `mcp-nanobanana-go` (official Google MCP)
117
+
118
+ Use when the user is already working inside Gemini CLI and has a Google Cloud project.
119
+
120
+ ### How it works
121
+
122
+ [`mcp-nanobanana-go`](https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/tree/main/experiments/mcp-genmedia/mcp-genmedia-go/mcp-nanobanana-go) is an official Google MCP server that exposes `nanobanana_image_generation` as a tool. When configured in Gemini CLI, the agent can call it directly during a session — no Python, no `uv`.
123
+
124
+ ### Setup
125
+
126
+ **1. Install the MCP server binary:**
127
+
128
+ ```bash
129
+ curl -sL https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-creative-studio/main/experiments/mcp-genmedia/mcp-genmedia-go/install-online.sh | bash
130
+ # Adds mcp-nanobanana-go to ~/.local/bin — ensure that is on $PATH
131
+ ```
132
+
133
+ **2. Set required env vars:**
134
+
135
+ ```bash
136
+ export GOOGLE_CLOUD_PROJECT="your-gcp-project-id"
137
+ export GOOGLE_CLOUD_LOCATION="us-central1" # optional, this is the default
138
+ gcloud auth application-default login # once — sets up ADC
139
+ ```
140
+
141
+ **3. Configure Gemini CLI** (`~/.gemini/settings.json`):
142
+
143
+ ```json
144
+ {
145
+ "mcpServers": {
146
+ "nanobanana": {
147
+ "command": "mcp-nanobanana-go",
148
+ "args": [],
149
+ "env": {
150
+ "GOOGLE_CLOUD_PROJECT": "${GOOGLE_CLOUD_PROJECT}",
151
+ "GOOGLE_CLOUD_LOCATION": "${GOOGLE_CLOUD_LOCATION}"
152
+ }
153
+ }
154
+ }
155
+ }
156
+ ```
157
+
158
+ **4. Install the image-artist skill** (optional but recommended — teaches Gemini CLI prompting best practices):
159
+
160
+ ```bash
161
+ cp -r /path/to/vertex-ai-creative-studio/experiments/mcp-genmedia/skills/genmedia-image-artist \
162
+ ~/.gemini/skills/
163
+ ```
164
+
165
+ ### Invocation
166
+
167
+ Inside a Gemini CLI session, just describe what you want. The agent calls `nanobanana_image_generation` automatically:
168
+
169
+ ```text
170
+ > Generate a cinematic hero image of a futuristic city at dusk, 16:9, for the title slide
171
+ ```
172
+
173
+ Output goes to the `GENMEDIA_BUCKET` GCS bucket, or you can specify a local path in the prompt.
174
+
175
+ ### Env vars for Path C
176
+
177
+ | Variable | Required | Default | Notes |
178
+ |----------|----------|---------|-------|
179
+ | `GOOGLE_CLOUD_PROJECT` | Yes | — | Your GCP project ID |
180
+ | `GOOGLE_CLOUD_LOCATION` | No | `us-central1` | Vertex AI region |
181
+ | `GENMEDIA_BUCKET` | No | — | Default GCS output bucket |
182
+ | `ALLOW_UNSAFE_MODELS` | No | `false` | Bypass model validation for pre-release strings |
183
+
184
+ Auth uses [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials) — **not** `GEMINI_API_KEY`. ADC resolves in this order: `gcloud auth application-default login` → service account key file (`GOOGLE_APPLICATION_CREDENTIALS`).
185
+
186
+ ### Path C vs Path A — when to choose
187
+
188
+ | | Path A (Python SDK) | Path C (Gemini CLI MCP) |
189
+ |-|---------------------|------------------------|
190
+ | Auth | `GEMINI_API_KEY` from AI Studio | GCP ADC + project |
191
+ | Control | Full programmatic control | Agent-driven, conversational |
192
+ | Scripting | `uv run generate_image.py …` | Gemini CLI session |
193
+ | Billing | AI Studio quota | Vertex AI quota |
194
+ | Reference images | Up to 14 via `--input-image` | Via `images` param in tool call |
195
+ | Best for | Automated slide builds, CI | Interactive sessions, rapid iteration |
196
+
197
+ ---
198
+
199
+ ## Slide Image Prompt template
200
+
201
+ The slide's `data-expected` description is too thin to send to the model directly. Expand it through this template — same shape as `references/04-design.md`'s design tokens, so generated images stay consistent with the theme:
202
+
203
+ ```
204
+ Create a {{layout}} image of: {{subject}}.
205
+ Style: {{style}} — anchored to the deck's visual system ({{primary_color}}, {{accent_color}}, {{mood}}).
206
+ Composition: {{shot}} ({{focal_point}} dominant, {{rule_of_thirds | centered | rule_of_fifths}}).
207
+ Lighting: {{lighting}}.
208
+ Background: {{background}} — must work behind {{light | dark}} caption overlay.
209
+ Negative space: leave {{top | bottom | left | right}} {{30%}} clear for text.
210
+ Avoid: text, watermarks, logos, hands with malformed fingers, signature artifacts, clichéd stock-photo poses.
211
+ ```
212
+
213
+ For full-bleed `slide--image` slides, the `.image-overlay` gradient sits on top — generate **without** built-in text; let the slide system render the caption.
214
+
215
+ ### Style anchors (pick one per deck, write into `DESIGN.md`)
216
+
217
+ | Style | When |
218
+ |-------|------|
219
+ | `photorealistic, editorial photography, 50mm` | Executive / business decks, real-world subjects |
220
+ | `clean vector illustration, flat color, geometric` | Product / SaaS, technical concepts |
221
+ | `3D render, soft studio lighting, isometric` | Architecture, infrastructure diagrams as hero |
222
+ | `watercolor / hand-drawn` | Storytelling decks, education, non-technical audiences |
223
+ | `cinematic, anamorphic, shallow depth of field` | Mood / opener / closer slides |
224
+
225
+ Pick **one** style for the whole deck. Mixing styles is visual slop — counts against Visual Slop Test signal #5 (palette inconsistency).
226
+
227
+ ---
228
+
229
+ ## Resolution × slide-type matrix
230
+
231
+ | Slide type | Resolution | Aspect ratio | Why |
232
+ |------------|-----------|--------------|-----|
233
+ | `slide--image` (full-bleed) | `4K` | `16:9` | Edges visible at presentation zoom |
234
+ | `slide--two-col` (image side) | `2K` | `4:5` or `1:1` | Half the canvas — 2K is the sweet spot |
235
+ | Inline tile in `content` / `stats` | `1K` | `1:1` | Decorative, small |
236
+ | Portrait inset (speaker, product) | `2K` | `2:3` or `3:4` | Vertical composition |
237
+ | Thumbnail / draft pass | `512px` | match final | Iterate prompt cheaply, then re-run at target res |
238
+
239
+ **Workflow:** draft at `512px` until the prompt is right, then re-run at the target resolution. Don't burn 4K calls on prompt iteration.
240
+
241
+ ---
242
+
243
+ ## Character / object consistency across slides
244
+
245
+ When the deck reuses a subject (mascot, product, recurring person) on multiple slides, use the **reference-image** flag so the model sees the same subject every time:
246
+
247
+ ```bash
248
+ uv run generate_image.py \
249
+ --prompt "<scene description>. Keep subject identity from reference image." \
250
+ --filename "assets/scene-2.png" \
251
+ --input-image "assets/scene-1.png" \
252
+ --resolution 2K
253
+ ```
254
+
255
+ Up to **14** reference images per call. For a campaign:
256
+ - pass the product render once
257
+ - pass the brand mark once
258
+ - pass any prior generated scenes
259
+
260
+ This is the only reliable way to stop the model from drifting between slides.
261
+
262
+ ---
263
+
264
+ ## Asset save location (path contract)
265
+
266
+ Generated images live in **the deck's `assets/` folder**, never in the skill folder:
267
+
268
+ ```
269
+ .octocode/slides/{{slideName}}/
270
+ ├── assets/
271
+ │ ├── {{slug}}-yyyy-mm-dd-hh-mm-ss.png ← generated
272
+ │ ├── {{slug}}-yyyy-mm-dd-hh-mm-ss-1k.png ← draft (delete after final)
273
+ │ └── user-provided.png ← untouched
274
+ ```
275
+
276
+ Slides reference them with the existing one-level-up pattern: `../assets/{{filename}}`. No change to the path contract in `SKILL.md → Output structure`.
277
+
278
+ ---
279
+
280
+ ## Integration with existing image-handling rule
281
+
282
+ `references/05-implementation.md` currently says:
283
+
284
+ > *For any missing image, do not search, download, generate, or silently substitute an image. Render the `PLACEHOLDER` component...*
285
+
286
+ This still holds as the default. **Generation is opt-in.** The decision table becomes:
287
+
288
+ | Image status in brief | What to do in HTML |
289
+ |-----------------------|--------------------|
290
+ | `ready` — file path provided | `<img src="../assets/{{filename}}">` |
291
+ | `placeholder` — user will provide later | `image-ph` / `image-ph-bleed` component |
292
+ | `generate` — user opted in **and** `data-expected` is concrete | Run `generate_image.py` → save to `assets/` → `<img>` it. Keep the `data-expected` on the element as a comment for traceability. |
293
+ | anything ambiguous | Treat as `placeholder` |
294
+
295
+ The `data-expected` attribute is what becomes (after expansion via the Slide Image Prompt template) the `--prompt` to the helper.
296
+
297
+ ---
298
+
299
+ ## Phase 6 review checks for generated images
300
+
301
+ Add these to the Slop / handoff pass when any image was generated:
302
+
303
+ - [ ] **Style consistency** — every generated image uses the same `Style anchor` from `DESIGN.md`. Mixed styles = automatic Visual Slop hit.
304
+ - [ ] **No hallucinated text** — model-rendered text on the image (sign, billboard, UI mock) is checked against the deck's claim. If text doesn't match, regenerate with `Avoid: text, signs, UI text` and add real text in HTML overlay.
305
+ - [ ] **Hands, faces, fingers** — Nano Banana 2 is good but not perfect. Spot-check at 4K; if a hand is malformed, regenerate or crop.
306
+ - [ ] **No watermark / signature** — sometimes the model adds a fake signature corner; reroll if present.
307
+ - [ ] **Caption legibility** — for full-bleed images with overlay text, verify the overlay gradient still reads against the generated image. Adjust gradient stops in slide CSS if needed.
308
+ - [ ] **Provenance note** — every generated image is marked in `request.md → Images` with model code, prompt, and timestamp. Counts as Content Slop signal #3 (uncited source) if missing.
309
+
310
+ ---
311
+
312
+ ## Cost & rate-limit notes
313
+
314
+ | Resolution | Approx. credits per image | Notes |
315
+ |-----------|--------------------------|-------|
316
+ | `512px` | lowest | Iterate freely |
317
+ | `1K` | low | Default |
318
+ | `2K` | ~2× 1K | Most slide images |
319
+ | `4K` | ~4× 1K | Reserve for full-bleed final |
320
+
321
+ The Gemini 3.1 Flash Image Preview tier is rate-limited per minute and per day. For a 20-slide deck with 6 images, expect ~10–12 API calls (drafts + finals). Don't generate during Phase 4 previews — wait for the design direction to lock.
322
+
323
+ ---
324
+
325
+ ## Quick recipes
326
+
327
+ **Full-bleed hero, photorealistic:**
328
+ ```bash
329
+ uv run scripts/generate_image.py \
330
+ --prompt "Wide cinematic shot: empty modern office at blue hour, desks lit only by laptop screens, deep shadows, anamorphic lens flare. Negative space on right 40% for caption overlay. Avoid: people, text, signage." \
331
+ --filename "assets/title-2026-05-10-22-14-00.png" \
332
+ --resolution 4K --aspect-ratio 16:9
333
+ ```
334
+
335
+ **Two-column product render, vector style:**
336
+ ```bash
337
+ uv run scripts/generate_image.py \
338
+ --prompt "Clean isometric vector illustration of a server rack, flat colors matching #0EA5E9 primary and #F59E0B accent, white background, no text, no shadows beyond soft drop." \
339
+ --filename "assets/architecture-2026-05-10-22-15-30.png" \
340
+ --resolution 2K --aspect-ratio 4:5
341
+ ```
342
+
343
+ **Iterate on a draft until prompt is right:**
344
+ ```bash
345
+ for variant in "morning fog" "blue hour" "neon rain"; do
346
+ uv run scripts/generate_image.py \
347
+ --prompt "Tokyo street, $variant, cinematic, no text" \
348
+ --filename "assets/draft-${variant// /-}.png" \
349
+ --resolution 512px --aspect-ratio 16:9
350
+ done
351
+ # Then re-run the winner at 4K with the same prompt.
352
+ ```
353
+
354
+ ---
355
+
356
+ ## When to escalate to Nano Banana Pro
357
+
358
+ Swap `--model gemini-3-pro-image-preview` (and adjust the helper accordingly) when:
359
+
360
+ - The image must be **factually accurate** (real building, real product, branded element). Pro has stronger world knowledge.
361
+ - The slide is the **deck's one surprise moment** (see SKILL.md → Storytelling → "One surprise per deck"). Pay the quality premium once.
362
+ - The audience is **Executive** depth — fewer slides, each carrying more weight.
363
+
364
+ Otherwise stay on Flash Image (Nano Banana 2) — the speed difference matters more during iteration than the quality delta in slide-scale viewing.
365
+
366
+ ---
367
+
368
+ ## Env Params Best Practice — How to Pass API Keys to Skills
369
+
370
+ This section documents the canonical pattern for declaring and resolving environment parameters in any skill that calls external APIs.
371
+
372
+ ### Resolution order (two-layer pattern)
373
+
374
+ The `intellectronica/agent-skills` nano-banana reference implementation defines the authoritative precedence:
375
+
376
+ 1. `--api-key` CLI argument — use when the user provides a key inline during the chat session, or when a per-deck override is required.
377
+ 2. `GEMINI_API_KEY` environment variable — the ambient default; set once in the shell profile and forget.
378
+ 3. If neither is found → **exit loudly** with clear instructions for both options.
379
+
380
+ ```python
381
+ def get_api_key(provided_key: str | None) -> str | None:
382
+ if provided_key:
383
+ return provided_key
384
+ return os.environ.get("GEMINI_API_KEY")
385
+
386
+ api_key = get_api_key(args.api_key)
387
+ if not api_key:
388
+ print("Error: No API key provided.", file=sys.stderr)
389
+ print(" 1. Provide --api-key argument", file=sys.stderr)
390
+ print(" 2. Set GEMINI_API_KEY environment variable", file=sys.stderr)
391
+ sys.exit(1)
392
+ ```
393
+
394
+ ### How to document env vars in a SKILL.md
395
+
396
+ Declare env requirements in a `## Prerequisites` section at the top, before any workflow steps. Use a table — agents scan tables faster than prose.
397
+
398
+ **`## Prerequisites`**
399
+
400
+ **`### Environment`**
401
+
402
+ | Variable | Required | How to get it | Setup |
403
+ |----------|----------|---------------|-------|
404
+ | `GEMINI_API_KEY` | Yes (Path A/B) | [AI Studio](https://aistudio.google.com/apikey) | `export GEMINI_API_KEY="..."` |
405
+ | `GOOGLE_CLOUD_PROJECT` | Yes (Path C) | GCP Console | `export GOOGLE_CLOUD_PROJECT="my-project"` |
406
+ | `GOOGLE_CLOUD_LOCATION` | No (Path C) | — | Defaults to `us-central1` |
407
+
408
+ **`### Setup check`**
409
+
410
+ ```bash
411
+ # Path A
412
+ echo $GEMINI_API_KEY && command -v uv
413
+ # Path C
414
+ gcloud auth application-default print-access-token && echo $GOOGLE_CLOUD_PROJECT
415
+ ```
416
+
417
+ ### Rules
418
+
419
+ - **Never hardcode keys** in SKILL.md examples. Use `"..."` or `"your-key-here"` as placeholders.
420
+ - **Never commit `.env` files** containing real keys.
421
+ - **Prefer env vars over CLI args** for ambient credentials. Reserve `--api-key` for explicit per-invocation overrides.
422
+ - **Fail loudly** — a missing key should print the exact export command the user needs, not a generic error.
423
+ - **Document the source** — link to where the user gets the key (AI Studio, GCP Console, etc.).
424
+ - **For GCP tools** — use ADC (`gcloud auth application-default login`), not service account keys, for local development. Document the command explicitly.
425
+
426
+ ---
427
+
428
+ ## References
429
+
430
+ ### Path A — Direct API
431
+ - **Reference helper script:** [`intellectronica/agent-skills/skills/nano-banana-2/scripts/generate_image.py`](https://github.com/intellectronica/agent-skills/blob/main/skills/nano-banana-2/scripts/generate_image.py)
432
+ - **Nano Banana 2 SKILL.md (canonical API key pattern):** [`intellectronica/agent-skills/skills/nano-banana-2/SKILL.md`](https://github.com/intellectronica/agent-skills/blob/main/skills/nano-banana-2/SKILL.md)
433
+ - **Official model docs:** [ai.google.dev/gemini-api/docs/image-generation](https://ai.google.dev/gemini-api/docs/image-generation)
434
+ - **API key:** [aistudio.google.com/apikey](https://aistudio.google.com/apikey)
435
+
436
+ ### Path B — Third-party CLI
437
+ - **`belt` CLI:** [`inference-sh/skills/tools/image/nano-banana-2`](https://github.com/inference-sh/skills/tree/main/tools/image/nano-banana-2)
438
+ - **Grounded generation pipeline:** [`GeeveGeorge/openNanoBanana`](https://github.com/GeeveGeorge/openNanoBanana)
439
+
440
+ ### Path C — Gemini CLI MCP
441
+ - **`mcp-nanobanana-go` server:** [`GoogleCloudPlatform/vertex-ai-creative-studio/experiments/mcp-genmedia/mcp-genmedia-go/mcp-nanobanana-go`](https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/tree/main/experiments/mcp-genmedia/mcp-genmedia-go/mcp-nanobanana-go)
442
+ - **Easy installer:** [`install-online.sh`](https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/blob/main/experiments/mcp-genmedia/mcp-genmedia-go/install-online.sh)
443
+ - **`genmedia-image-artist` skill:** [`GoogleCloudPlatform/vertex-ai-creative-studio/experiments/mcp-genmedia/skills/genmedia-image-artist/SKILL.md`](https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/blob/main/experiments/mcp-genmedia/skills/genmedia-image-artist/SKILL.md)
444
+ - **ENV_VARS reference:** [`mcp-genmedia-go/ENV_VARS.md`](https://github.com/GoogleCloudPlatform/vertex-ai-creative-studio/blob/main/experiments/mcp-genmedia/mcp-genmedia-go/ENV_VARS.md)
445
+ - **Gemini CLI repo:** [`google-gemini/gemini-cli`](https://github.com/google-gemini/gemini-cli)
446
+
447
+ ### Shared / Pro
448
+ - **Alternative skill (Pro variant):** [`steipete/agent-scripts/skills/nano-banana-pro`](https://github.com/steipete/agent-scripts/tree/main/skills/nano-banana-pro)