| name | creative-production-moodboard-explorer |
| description | Use when a user asks Creative Production to generate several concept images, image options, visual directions, mood boards, visual territories, audience feel, campaign references, or brand direction before mood-board remixing, asset production, or polish. |
Mood Board Explorer
Build a personalized image-first mood-board stream from a light intake plus inferred profile/context.
Read references/experience-contract.md before writing the user-facing handoff or reporting artifact links.
Read references/artifact-contracts.md before creating, repairing, or reporting artifacts.
Read references/codex-exec-image-generation.md before running image generation.
Read references/image-building-strategy.md alongside the Codex exec contract for first-pass imagery rules.
Pipeline Role
This skill owns the Explore stage in the Explore > Build > Polish workflow.
Use it as the broad visual front door for campaign mood, brand direction, creative territories, audience feel, editorial references, and profile-aware inspiration. It produces directional evidence and handoff specs, not canonical production assets.
When Creative Production is invoked for a direct multi-image concept request, such as "generate some images for a new movie," route here instead of generating isolated chat images. Treat the prompt as a light visual brief, run the intake gate when needed, generate one self-contained visual reference per tile, save the run, and hand off through the inline mood board.
Explorer outputs should include a reviewable board or gallery, source/context signals, visual territory notes, prompt/spec metadata, recommended directions, and a concise build handoff for the next skill.
Use active Build/Polish owners only after a canonical or selected base exists:
- Use the mood-board app's Remix controls for controlled variations after a generated board or selected territory has concrete outputs to vary.
generative-polish for publish-bound marketing finish.
If the anchor is a specific product, packaging reference, or product concept and the user wants family-level coverage or review galleries, hand off to offer-explorer.
Workflow
-
Run the intake gate.
- Read
references/intake.md before creating a mood board spec.
- Choose the intake depth from the Mood Board Qualification Scale in
references/intake.md.
- Every fresh mood board request must go through intake before spec writing, image generation, or HTML board creation.
- When MCP widgets are available, render
render_moodboard_board_widget with no images and an intake payload. The mood-board app detects the empty image list and shows the intake suggestions inside the board surface.
- The chat around the board surface should handle brand/source material, exclusions, and any optional 1-3 reference image request. The empty-board intake should stay to compact question-led chip groups defined in
references/intake.md.
- After rendering the empty-board intake, stop and wait for the user selection or app follow-up. Do not create the board spec in the same step.
- When the request is already an app follow-up such as "Continue with this qualified moodboard intake and create the board," treat intake as complete and proceed directly to context gathering and generation.
- If MCP widgets are unavailable, ask the same intake questions in chat, wait for the answer, and state that the board intake surface could not be used.
-
Gather profile/context.
- Read local project instructions such as
AGENTS.md when present.
- Use user-provided profile, recent workspace artifacts, or relevant local notes.
- Infer durable preferences, mood, audience, palette, source imagery, must-have motifs, and constraints. Avoid exposing private details or internal scaffolding in the board.
-
Create the board spec.
- Write a JSON spec with
meta, signals, and 16-30 items.
- Each item needs
id, title, caption, source, tone, motif, palette, and prompt.
- When the board will be shown in the MCP mood-board app, have the model author image-specific
remixSuggestions keyed by style, palette, scene, props, character, and format whenever you can infer useful directions from that tile. Each suggestion should include , , and . Write 1-2 sharp riffs/extensions per slot from the item title, caption, prompt, palette, motif, or source context; the builder may mix those custom options with deterministic fallback suggestions, but each slot must show exactly three options. Do not rely on generic fixed remix copy when the image context gives you sharper directions.
python3 <skill>/scripts/create_mood_board.py --spec <spec.json> --output <output-dir> --force
node <output-dir>/server.mjs
- Choose an output directory under a stable workspace path such as
outputs/moodboards/<brief-slug>/, unless the user provides a durable destination.
- The generated app must include the local HTML/debug artifact and colocated generated assets so the run can be reopened or debugged later.
- Do not stop at a prompt list, JSON spec, image files, or chat-only summary. The user-facing output of this skill is the inline MCP mood-board widget rendered through
render_moodboard_board_widget.
- Use the inline MCP mood-board widget as the normal review handoff. Keep the local HTML page, local server URL, and server command for explicit debug or inspection requests.
- MCP handoff invariant: never pass arbitrary local files from chat image generation,
.open-cowork/generated_images, downloads, or other external folders directly as items[].imageUrl, items[].path, or routes[] to render_moodboard_board_widget. First persist those files into the saved runDirectory under generated/, materialize widget previews under generated/mcp-thumbs/, update data/stream.json so imageUrl points at /generated/mcp-thumbs/*.jpg, keep the full-resolution file in sourceImageUrl, then render the widget with runDirectory.
- Generate images with the confirmed path.
- Before high-volume generation, state the planned image count and review surface.
- Confirm before generating more than 12 images in one pass. "One pass" means the user-approved generation scope for the turn, not a transport batch size.
- Use the largest supported request batch for the approved count. The local moodboard
/api/images endpoint accepts up to 64 images and routes them through Codex exec workers, so send 64 or fewer approved images in one request. For approved runs above 64, chunk into groups of 64. Reduce the request size only after a concrete worker failure, timeout, or transport error.
- For follow-up generation or annotation/remix requests that ask for multiple new images, default to the same Codex exec-backed
/api/images batch path rather than generating one-off images in chat. Use a single batch for 64 or fewer approved follow-up images, then retry only the failed item ids when the status file shows partial failure.
- Do not run a separate manual worker probe. The
/api/images endpoint calls runtime/codex_exec_image_batch.py, and that runner automatically performs a preflight before launching the full image set.
- If local Codex CLI state has previously shown
Operation not permitted, or the current sandbox is likely to block ~/.open-cowork state access, request escalated/outside-sandbox execution when starting the local mood-board server instead of first burning a sandboxed generation attempt.
- If preflight still says Codex cannot initialize local state because
~/.open-cowork is read-only or an in-process app-server client cannot start, disclose that runtime issue briefly, rerun the local mood-board server with escalated permissions, and retry the same approved batch with a new idempotency key. Do not treat this as a prompt-quality failure.
- Call the local app server. The server exposes a per-run token at
/api/session; include it in X-BV-Run-Token and set confirmGenerate: true so generation cannot be triggered by an untrusted local page:
node -e "const fs=require('fs'); const crypto=require('crypto'); const base='http://127.0.0.1:<port>'; const data=JSON.parse(fs.readFileSync('<output-dir>/data/stream.json','utf8')); const idempotencyKey=crypto.createHash('sha256').update(JSON.stringify(data.items.map(i=>i.id))).digest('hex').slice(0,16); fetch(base+'/api/session').then(r=>r.json()).then(s=>fetch(base+'/api/images',{method:'POST',headers:{'content-type':'application/json','x-bv-run-token':s.runToken},body:JSON.stringify({images:data.items,confirmGenerate:true,idempotencyKey})})).then(r=>r.json()).then(j=>console.log(JSON.stringify(j,null,2)))"
-
Verify visually.
- Use the local URL or browser only for agent-side verification when needed; do not present it to the user as the review surface.
- Check that the canvas is image-first, clean, and not repetitive.
- Confirm primary click selection, expand-to-view, remove, copy, and Open in actions work.
- Note that clipboard image copy can be browser-permission dependent; the local server clipboard bridge should keep image copy working without routing the visible UI through Finder.
- After the initial generated batch succeeds, render
render_moodboard_board_widget with the saved runDirectory in the same turn so the generated images and inline mood board appear together.
- Before handoff, ensure the saved
data/stream.json uses /generated/mcp-thumbs/*.jpg preview images for imageUrl and preserves full-resolution generated PNGs in sourceImageUrl. The local server should do this automatically after generation; if an inline MCP page reports totalItemCount greater than itemCount, treat it as a preview/materialization bug rather than a generation failure. The fix is to materialize or repair the item preview under generated/mcp-thumbs/, point imageUrl at that preview, keep the full-resolution asset in sourceImageUrl, and refresh the mounted board from the saved run.
- If the chat transcript shows attached/generated images but the inline MCP board shows placeholder tiles, diagnose it as a saved-run materialization problem first. Check
data/stream.json, run-state.json, and generated/mcp-thumbs/; repair the saved run and refresh from runDirectory instead of rerendering with raw local image paths.
- When a follow-up creates new images for an existing mood board, persist them into the existing
runDirectory. If the local mood-board server already updated data/stream.json, do not call append_moodboard_board_items; the mounted board detects the saved run update through its status/page refresh tools.
- Use
append_moodboard_board_items only when the new image files/items were produced outside the mood-board server and still need to be merged into the saved run. The append tool owns widget-preview materialization for those external follow-up images: saved stream items should use /generated/mcp-thumbs/*.jpg for imageUrl and preserve full-resolution images in . After append, verify the existing mounted board with and ; do not re-render after append unless there is no visible board, the mounted board is stale after status/page refresh, or the user explicitly asks for a separate board.
Output Defaults
- White background unless the user asks otherwise.
- Dense rounded masonry image board.
- No visible titles, captions, filters, or explanatory UI on the board itself.
- Primary tile click toggles multi-select and selected images attach to the thread composer when the host attachment bridge is available.
- A hover-only expand control opens the large image viewer with copy/Open in actions.
- Tile-level remove controls that persist through browser local storage.
Exit Criteria
A successful explorer run ends with:
- reviewable visual options;
- source and context signals;
- selected or recommended directions;
- a build handoff naming the next skill and the asset to build;
- an inline MCP mood-board widget for review, plus a durable output path for the board data and generated images;
- clear caveats about generated text, claims, logos, product fidelity, private details, or unsupported visual assumptions.
User-Facing Handoff
Describe the board as a creative starting point, not as generated files. Name the visual territories, the number of images or routes, what the user should choose next, and the likely business assets this direction can become.
Lead with the inline MCP mood board, not the launcher, local HTML, server URL, screenshot, or artifact inventory. Mention the static HTML artifact only when the user explicitly asks to debug, inspect, or open the local HTML/server version.
When the mood board is the only reviewable artifact, the primary handoff surface is the inline MCP mood board. Ask the user to pick the strongest direction before using the board's Remix controls or moving into polish. Do not create or lead with a start-here, index, output folder, manifest, screenshot, HTML link, local URL, or artifact inventory for a normal mood-board-only run.
When image generation is paused because the user has not approved a large run, do not lead with a web artifact. State the planned image count and inline MCP review surface, then ask for approval to generate that set through Codex exec workers. Do not make the spec, manifest, output folder, local HTML artifact, local URL, fallback choices, or worker internals more prominent than the approval action.
If a later step creates remixed outputs from the board, the handoff focus stays on the current mood-board review and its Remix action. Mention the original mood board only as secondary context when it helps.
Files
assets/mood-board-app/: reusable static app template and local image-generation server.
scripts/create_mood_board.py: copies the template and writes a board spec.
scripts/embed_moodboard_images.py: copies generated files into the standard moodboard app and refreshes static artifacts.
references/intake.md: compact intake questions and prompt-shaping guidance.