| name | source-command-media-gen |
| description | Generate images (Nano Banana) or video (Veo) via Google AI Studio. Refuses cleanly without credentials. (ADR-0024) |
source-command-media-gen
Use this skill when the user asks to run the migrated source command media-gen.
Command Template
🎬 Media generation (Veo + Nano Banana)
Generate images or video on demand via the kit's media-provider
adapters. Two providers ship, both targeting Google AI Studio:
- Nano Banana — image (Imagen 3).
~$0.04 / image (dated
2026-06-02; verify at https://ai.google.dev/pricing).
- Veo — video.
~$0.50 / second; typical 8 s clip ~$4.00.
Authority: ADR-0024.
Setup (one time)
- Get a key at https://aistudio.google.com/apikey
- Copy
contextkit/.env.example to contextkit/.env, paste the key into
GOOGLE_AI_API_KEY=.
- (Optional) set
CONTEXTDEVKIT_MEDIA_MAX_USD=5.00 for a per-process
cost cap — the adapter refuses the next call that would exceed it.
- Run via Node's built-in env-file loader (Node 20.6+):
node --env-file=contextkit/.env contextkit/tools/scripts/media-gen.mjs <kind> ...
Usage
Image
node --env-file=contextkit/.env contextkit/tools/scripts/media-gen.mjs image \
--prompt "editorial product hero, asymmetric grid, single bold cyan accent" \
--out public/hero.png \
--aspect-ratio 16:9
Video
node --env-file=contextkit/.env contextkit/tools/scripts/media-gen.mjs video \
--prompt "macro slow-motion of a single drop of ink hitting paper" \
--out public/hero.mp4 \
--duration 8 \
--aspect-ratio 16:9
Dry-run (no API call, no charge)
node contextkit/tools/scripts/media-gen.mjs image --prompt "..." --out path.png --dry-run
Prints what would be sent, including whether the required env vars are
present. Useful for sanity-checking a prompt or confirming the cost
cap is configured before the first paid call.
Behaviour
- Refuse-on-missing-creds (rule 8). Without
GOOGLE_AI_API_KEY
set, the script exits with NO_CREDENTIALS pointing at
contextkit/.env.example. Never silently substitutes a placeholder.
- Refuse-on-content-policy. Google's API rejects some prompts;
the script exits with
CONTENT_POLICY. Refine the prompt and
retry.
- Cost-cap guard. When
CONTEXTDEVKIT_MEDIA_MAX_USD is set, the
adapters keep a per-process running total and refuse the next call
that would push it over the cap.
- Content-addressed cache (ticket 056). The result is keyed by
sha256(provider + prompt + options) and stored under
contextkit/.cache/media/<sha>.<ext>. Re-running the same prompt +
options copies the cached file to --out and makes no API call (it logs
cache hit (~$X saved)). Pass --no-cache to force a fresh call (bypasses
both the read and the write). The cache dir is gitignored; rm -rf to clear.
- Atomic file write. The output file is written with the parent
directory created on demand (
mkdir -p-style).
What this does NOT do
- No cache eviction. The cache never expires or LRU-evicts — it is local
and small by design;
rm -rf contextkit/.cache/media to clear it.
- No third provider. Runway, Luma, Midjourney are not in scope.
Rule 9 — next consumer justifies the next adapter.
- No automatic invocation. This command never runs by itself.
Each call is explicit and the user accepts the cost.
- No Vertex AI / OAuth flow. Single-key API only. ADR-0024 spells
out why (rule 1 — token refresh breaks zero-dep).
When to use it
- Hero imagery on a landing page when stock photos would read as
generic (most landing pages on the playbook's anti-Lovable list).
- Domain-specific renders for a marketing site (illustrate the
actual product, not "person at laptop").
- Demo footage when a real recording would be slower to produce
than to generate.