Add gemini.google.com Nano Banana domain skill - #536
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
✅ Skill review passedReviewed 1 file(s) — no findings. |
There was a problem hiding this comment.
3 issues found across 1 file
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="domain-skills/gemini/nano-banana-images.md">
<violation number="1" location="domain-skills/gemini/nano-banana-images.md:15">
P3: It's unclear how calling `clipboard.read()` by itself causes the image to land in the composer — normally you'd still need to dispatch the read data into the focused element (e.g. via a synthetic `paste` event). If there's an implicit step, spelling it out would make this recipe reproducible.</violation>
<violation number="2" location="domain-skills/gemini/nano-banana-images.md:19">
P1: The `canvas.toBlob()` call on line 19 passes `'image/png'` as the first argument, but `toBlob()` requires a **callback function** as its first parameter. Passing a string will throw a `TypeError` at runtime and the `blob` variable will never be populated, breaking the entire clipboard extraction flow.
Fix by wrapping it in a Promise or passing a callback:
```javascript
const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
`navigator.clipboard.write([new ClipboardItem({'image/png': blob})])`
or inline:
canvas.toBlob(blob => navigator.clipboard.write([new ClipboardItem({'image/png': blob})]), 'image/png');
```</violation>
<violation number="3" location="domain-skills/gemini/nano-banana-images.md:20">
P3: This osascript one-liner writes to `f`, but `f` is never opened/defined in the snippet — running it verbatim will error. Consider showing the full sequence (`open for access ... with write permission`, write, `close access`) so the recipe is actually copy-pasteable.</violation>
</file>Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
|
|
||
| ## Extracting generated images (works, no download dialog) | ||
| - Generated images are `blob:` URLs, typically 825x1024. `curl` can't fetch them. | ||
| - In page JS: draw the `<img>` to a canvas (same-origin, not tainted), `canvas.toBlob('image/png')`, then `navigator.clipboard.write([new ClipboardItem({'image/png': blob})])`. |
There was a problem hiding this comment.
P1: The canvas.toBlob() call on line 19 passes 'image/png' as the first argument, but toBlob() requires a callback function as its first parameter. Passing a string will throw a TypeError at runtime and the blob variable will never be populated, breaking the entire clipboard extraction flow.
Fix by wrapping it in a Promise or passing a callback:
const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
`navigator.clipboard.write([new ClipboardItem({'image/png': blob})])`or inline:
canvas.toBlob(blob => navigator.clipboard.write([new ClipboardItem({'image/png': blob})]), 'image/png');Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At domain-skills/gemini/nano-banana-images.md, line 19:
<comment>The `canvas.toBlob()` call on line 19 passes `'image/png'` as the first argument, but `toBlob()` requires a **callback function** as its first parameter. Passing a string will throw a `TypeError` at runtime and the `blob` variable will never be populated, breaking the entire clipboard extraction flow.
Fix by wrapping it in a Promise or passing a callback:
```javascript
const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
`navigator.clipboard.write([new ClipboardItem({'image/png': blob})])`
or inline:
canvas.toBlob(blob => navigator.clipboard.write([new ClipboardItem({'image/png': blob})]), 'image/png');
```</comment>
<file context>
@@ -0,0 +1,29 @@
+
+## Extracting generated images (works, no download dialog)
+- Generated images are `blob:` URLs, typically 825x1024. `curl` can't fetch them.
+- In page JS: draw the `<img>` to a canvas (same-origin, not tainted), `canvas.toBlob('image/png')`, then `navigator.clipboard.write([new ClipboardItem({'image/png': blob})])`.
+- On the host: save clipboard to file — `osascript -e 'write (the clipboard as «class PNGf») to f'`. Repeat per image.
+- Select images with `document.querySelectorAll('img')` filtered by `naturalWidth > 700`; DOM order is chronological.
</file context>| ## Attaching a local image (works) | ||
| 1. Put the image on the OS clipboard (macOS: `osascript -e 'set the clipboard to (read (POSIX file "/path/img.jpg") as JPEG picture)'`). | ||
| 2. Make the Gemini tab frontmost and click into the composer. | ||
| 3. Trigger `await navigator.clipboard.read()` in page context via CDP. First call may hang ~45s on a permission grant; after it resolves the image appears as a composer attachment. |
There was a problem hiding this comment.
P3: It's unclear how calling clipboard.read() by itself causes the image to land in the composer — normally you'd still need to dispatch the read data into the focused element (e.g. via a synthetic paste event). If there's an implicit step, spelling it out would make this recipe reproducible.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At domain-skills/gemini/nano-banana-images.md, line 15:
<comment>It's unclear how calling `clipboard.read()` by itself causes the image to land in the composer — normally you'd still need to dispatch the read data into the focused element (e.g. via a synthetic `paste` event). If there's an implicit step, spelling it out would make this recipe reproducible.</comment>
<file context>
@@ -0,0 +1,29 @@
+## Attaching a local image (works)
+1. Put the image on the OS clipboard (macOS: `osascript -e 'set the clipboard to (read (POSIX file "/path/img.jpg") as JPEG picture)'`).
+2. Make the Gemini tab frontmost and click into the composer.
+3. Trigger `await navigator.clipboard.read()` in page context via CDP. First call may hang ~45s on a permission grant; after it resolves the image appears as a composer attachment.
+
+## Extracting generated images (works, no download dialog)
</file context>
| ## Extracting generated images (works, no download dialog) | ||
| - Generated images are `blob:` URLs, typically 825x1024. `curl` can't fetch them. | ||
| - In page JS: draw the `<img>` to a canvas (same-origin, not tainted), `canvas.toBlob('image/png')`, then `navigator.clipboard.write([new ClipboardItem({'image/png': blob})])`. | ||
| - On the host: save clipboard to file — `osascript -e 'write (the clipboard as «class PNGf») to f'`. Repeat per image. |
There was a problem hiding this comment.
P3: This osascript one-liner writes to f, but f is never opened/defined in the snippet — running it verbatim will error. Consider showing the full sequence (open for access ... with write permission, write, close access) so the recipe is actually copy-pasteable.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At domain-skills/gemini/nano-banana-images.md, line 20:
<comment>This osascript one-liner writes to `f`, but `f` is never opened/defined in the snippet — running it verbatim will error. Consider showing the full sequence (`open for access ... with write permission`, write, `close access`) so the recipe is actually copy-pasteable.</comment>
<file context>
@@ -0,0 +1,29 @@
+## Extracting generated images (works, no download dialog)
+- Generated images are `blob:` URLs, typically 825x1024. `curl` can't fetch them.
+- In page JS: draw the `<img>` to a canvas (same-origin, not tainted), `canvas.toBlob('image/png')`, then `navigator.clipboard.write([new ClipboardItem({'image/png': blob})])`.
+- On the host: save clipboard to file — `osascript -e 'write (the clipboard as «class PNGf») to f'`. Repeat per image.
+- Select images with `document.querySelectorAll('img')` filtered by `naturalWidth > 700`; DOM order is chronological.
+
</file context>
| - On the host: save clipboard to file — `osascript -e 'write (the clipboard as «class PNGf») to f'`. Repeat per image. | |
| - On the host: save clipboard to file — `osascript -e 'set f to (open for access (POSIX file "/path/out.png") with write permission)' -e 'write (the clipboard as «class PNGf») to f' -e 'close access f'`. Repeat per image. |
Documents field-tested mechanics for automating Nano Banana image generation on gemini.google.com: CSP traps (localhost fetch/img blocked, no persistent file input), a working clipboard-bridge recipe for attaching local images, blob image extraction via canvas + clipboard, wait/verification guidance, and known small-text fidelity limits.
🤖 Generated with Claude Code
Summary by cubic
Adds a new domain skill doc for
gemini.google.comNano Banana image generation/editing, with field-tested automation guidance. Covers CSP traps, clipboard-based local image attachment, blob image extraction via canvas, practical waits/verification, and small-text fidelity limits.Written for commit 237facc. Summary will update on new commits.