Seven-skill presentation system: ingest talks into a rhetoric vault, run interactive clarification, generate a speaker profile, create presentations that match your documented patterns, produce the deck illustrations + thumbnail visual layer, create and publish talk-content Agent Skills with talk pages to a Jekyll shownotes site, and verify a recorded screencast against its storyboard. Includes a 113-entry Presentation Patterns taxonomy (83 observable: 64 patterns + 19 antipatterns; 30 unobservable: 21 patterns + 9 antipatterns) for scoring, brainstorming, and go-live preparation.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Reference for Step 4 (deck illustrations) and Step 6 (apply to deck) in
SKILL.md. The illustration-rules and title-overlay-rules steering rules
are auto-loaded — apply them, don't restate them.
Before generating, ensure:
Lane and credentials — --image-lane auto prefers a compatible
subscription CLI. Existing pinned-model/exact-size requests use API;
--allow-cli-native explicitly permits OpenAI's unpinned native model and
observed dimensions. Force HTTP with --image-lane api, or require native
Codex with --image-lane cli --allow-cli-native. Gemini and Imagen remain
API-only. See image-provider-lanes.md for the
capability/authentication boundary and diagnostics.
API requests dispatch by model-name prefix:
gpt-image-* → OpenAI; imagen-* and gemini-* / nano-banana-* →
Google. Add whichever keys the run will actually use to
{vault}/secrets.json (preferred):
{
"gemini": { "api_key": "your-google-key" },
"openai": { "api_key": "your-openai-key" }
}Only vendors that select API need keys. Native-only runs never read
secrets.json or require an API key. Mixed comparison/exploration runs check
each API vendor on first use; provide those keys before starting to avoid
a partially rendered grid. A present but failing CLI never retries API.
Env-var fallbacks: GEMINI_API_KEY, OPENAI_API_KEY. Get keys from
https://aistudio.google.com/app/apikey (Google) and
https://platform.openai.com/api-keys (OpenAI).
Model availability — verify the baked model is accessible with your key.
The script reads it from outline.yaml's style_anchor.model field.
Imagen models have no edit endpoint — --edit, --build, and --fix
require a Gemini or OpenAI model.
Python 3.10+ — install the project's declared dependencies from
pyproject.toml. API-only plain generation uses the standard library;
masked edits need Pillow. The native lane also uses the co-shipped process
supervisor and its declared psutil dependency.
python3 "{speaker_toolkit_root}/skills/illustrations/scripts/generate-illustrations.py" outline.yaml remainingremaining skips slides whose images already exist; all regenerates every
slide; specific slides can be passed as 2 5 9 or a range 2-10.
Phase 2 strategy uses --style-explore (renders candidate styles × the
priority-driven model shortlist × formats into a structured style-explore/
grid) — see strategy.md Sub-steps 3 and 5.
--compare remains a quick single-slide model spot-check: it renders one
slide's prompt across the cached COMPARE_MODELS roster.
python3 "{speaker_toolkit_root}/skills/illustrations/scripts/generate-illustrations.py" outline.yaml --compare 2Output lands in illustrations/model-comparison/. The roster, vendor aliases,
and per-model attributes live in skills/illustrations/scripts/model_registry.py.
| Command | When to use | Output |
|---|---|---|
--edit N "<prompt>" | Removing content from an existing image | slide-NN-vM.ext |
--fix N "<prompt>" | Iterating on a near-perfect image (90%+ correct) | slide-NN-vM.ext (next version) |
-v 2 5 9 | Generate without overwriting the base image | slide-NN-vM.ext |
--edit and --fix auto-append the safety suffixes (DO NOT add any new elements, Let background continue naturally). The explicit preservation
list (Keep the X. Keep the Y.) must always be added manually — the script
cannot know what to preserve.
Each slide's format field defines its format code. The
apply-illustrations-to-deck.py script maps each code to a layout +
positioning:
| Outline Format | Layout | Image Handling |
|---|---|---|
FULL | BLANK | Full-bleed image at 16:9 slide dimensions (left=0, top=0, width=13.333", height=7.5"); title repositioned into the declared Safe zone |
FULL + text overlay | BLANK | Full-bleed image + text overlay |
IMG+TXT | TITLE only (no body) | Image ~60% of slide on the left, title + body on the right. Exact geometry is owned by the IMGTXT_* constants in skills/illustrations/scripts/apply-illustrations-to-deck.py (image left=0.3", top=0.8", width=8.0", height=5.9"; text column left=8.5", width≈4.5") — read the constants when debugging layout, not the table |
EXCEPTION | Per content type | No generated image — real asset from [IMAGE NN] placeholder; handled by presentation-creator's slide walk, not by this skill |
{talk-dir}/illustrations/
├── slide-01.jpg ← one file per illustrated slide
├── slide-02.png
├── slide-05-v2.jpg ← versioned iterations (--fix / --edit / -v)
├── builds/ ← progressive reveal build steps (see builds.md)
│ ├── slide-05-build-00.jpg
│ ├── slide-05-build-01.jpg
│ └── slide-05-build-02.jpg
└── model-comparison/ ← --compare output
{talk-dir}/style-explore/ ← --style-explore output (Phase 2 strategy)
├── candidates.json ← agent-written input (styles × shortlist × formats)
├── index.md ← contact sheet grouping every render by style
└── <style-slug>/<format>/<model>.<ext>The Safe zone: line in each FULL slide block tells the script to append a
TITLE SAFE ZONE directive to the prompt before generation. Five zones are
supported: upper_third, middle_third, lower_third, left_half,
right_half. See skills/illustrations/references/title-placement.md
for the outline schema and rules/title-overlay-rules.md
for the full policy (auto-loaded).
python3 "{speaker_toolkit_root}/skills/illustrations/scripts/apply-illustrations-to-deck.py" \
deck.pptx illustrations/ outline.yaml \
--out deck-with-titles.pptx \
--scrim-color 100903 --scrim-alpha 47553 # omit for plain 45% blackThe script:
Safe zone: field), records the illustration in a
backgrounds manifest (--backgrounds-out, default <out_stem>.backgrounds.json)
for the PowerPoint background pass below — it does NOT insert a picture shape.format: IMG+TXT, applies the IMG+TXT layout
(image ~60% on the left as a picture shape, title placeholder + body on the right).builds: block.Then set the FULL-slide backgrounds via the real PowerPoint app, so each illustration becomes the slide BACKGROUND FILL (covered by the layout's halftone-dot overlay) and survives — a python-pptx round-trip would drop it. Run this as the FINAL write of the build, AFTER speaker notes are injected:
# operate on a uniquely-named copy — PowerPoint keys open decks by filename
cp deck-with-titles.pptx deck-bg-src.pptx
bash "{speaker_toolkit_root}/skills/presentation-creator/scripts/apply-backgrounds.sh" \
deck-bg-src.pptx deck-final.pptx deck-with-titles.backgrounds.jsonmacOS + Microsoft PowerPoint only; see rules/deck-editing-rules.md.
If no scrim color is supplied, run python3 "{speaker_toolkit_root}/skills/illustrations/scripts/suggest-scrim-color.py" illustrations/
first to sample a deck-tuned color. For warm or cool styled decks, the
sampled color reads as "deeper shadow in the same style" instead of a flat
black film.
.tessl-plugin
rules
skills
illustrations
presentation-creator
references
patterns
build
deliver
prepare
scripts
screencast-recorder
shownotes-publisher
vault-clarification
vault-ingress
references
scripts
vault-profile