luckiest-co 1.0.27 → 1.0.29

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 (42) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/package.json +1 -1
  4. package/skills/luckiest-ad-creative/CHANGELOG.md +3 -0
  5. package/skills/luckiest-ad-creative/SKILL.md +5 -3
  6. package/skills/luckiest-brandkit/ATTRIBUTION.md +8 -0
  7. package/skills/luckiest-brandkit/CHANGELOG.md +26 -0
  8. package/skills/luckiest-brandkit/SKILL.md +173 -0
  9. package/skills/luckiest-brandkit/references/picks-and-review.md +48 -0
  10. package/skills/luckiest-brandkit/references/prompt-recipes.md +79 -0
  11. package/skills/luckiest-brandkit/scripts/composite_mark.py +36 -0
  12. package/skills/luckiest-brandkit/scripts/composite_screen.py +37 -0
  13. package/skills/luckiest-brandkit/scripts/contact_sheet.py +31 -0
  14. package/skills/luckiest-brandkit/scripts/make_refs.mjs +25 -0
  15. package/skills/luckiest-plan/SKILL.md +2 -0
  16. package/skills/luckiest-video/CHANGELOG.md +3 -0
  17. package/skills/luckiest-video/SKILL.md +5 -3
  18. package/skills/luckiest-video-studio/CHANGELOG.md +10 -0
  19. package/skills/luckiest-video-studio/SKILL.md +14 -3
  20. package/skills/luckiest-video-studio/references/step-2b-storyboard.md +17 -5
  21. package/skills/luckiest-video-studio/references/step-3-compose.md +12 -0
  22. package/skills/luckiest-video-studio-art-director/ATTRIBUTION.md +20 -0
  23. package/skills/luckiest-video-studio-art-director/CHANGELOG.md +28 -0
  24. package/skills/luckiest-video-studio-art-director/LICENSE-iart +21 -0
  25. package/skills/luckiest-video-studio-art-director/LICENSE-skillme +21 -0
  26. package/skills/luckiest-video-studio-art-director/SKILL.md +297 -0
  27. package/skills/luckiest-video-studio-cards/CHANGELOG.md +3 -0
  28. package/skills/luckiest-video-studio-cards/SKILL.md +5 -3
  29. package/skills/luckiest-video-studio-director/ATTRIBUTION.md +16 -0
  30. package/skills/luckiest-video-studio-director/CHANGELOG.md +18 -0
  31. package/skills/luckiest-video-studio-director/LICENSE-iart +21 -0
  32. package/skills/luckiest-video-studio-director/LICENSE-skillme +21 -0
  33. package/skills/luckiest-video-studio-director/SKILL.md +198 -0
  34. package/skills/luckiest-video-studio-director/scripts/breakdown.mjs +160 -0
  35. package/skills/luckiest-video-studio-recreate/CHANGELOG.md +3 -0
  36. package/skills/luckiest-video-studio-recreate/SKILL.md +6 -4
  37. package/skills/luckiest-video-studio-reel/CHANGELOG.md +3 -0
  38. package/skills/luckiest-video-studio-reel/SKILL.md +5 -3
  39. package/skills/luckiest-video-studio-script/CHANGELOG.md +3 -0
  40. package/skills/luckiest-video-studio-script/SKILL.md +8 -3
  41. package/skills/luckiest-video-studio-talk/CHANGELOG.md +3 -0
  42. package/skills/luckiest-video-studio-talk/SKILL.md +5 -3
@@ -9,7 +9,7 @@
9
9
  "name": "luckiest",
10
10
  "source": "./",
11
11
  "description": "Plan, go, finish, plus bundled free Luckiest skills that work in Claude Code, web chat, and Cowork.",
12
- "version": "0.1.26",
12
+ "version": "0.1.28",
13
13
  "author": { "name": "Luckiest" }
14
14
  }
15
15
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luckiest",
3
3
  "description": "Plan, go, finish. Guided planning, progress dashboards, and your luckiest.co tribe inside Claude Code.",
4
- "version": "0.1.26",
4
+ "version": "0.1.28",
5
5
  "author": { "name": "Luckiest" }
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luckiest-co",
3
- "version": "1.0.27",
3
+ "version": "1.0.29",
4
4
  "description": "Luckiest for Claude Code: plan, go, finish. Your luckiest.co skills and tribe, inside Claude.",
5
5
  "bin": {
6
6
  "luckiest-co": "./bin/install.js"
@@ -1,5 +1,8 @@
1
1
  # Changelog — luckiest-ad-creative
2
2
 
3
+ ## 1.2.0 — 2026-10-05
4
+ - Video ads use the director and art director when installed.
5
+
3
6
  ## 1.1.1 — 2026-10-03
4
7
  - Points at `luckiest-video-studio-composition` (when installed) for focal point, grid, white space, and safe areas.
5
8
 
@@ -3,7 +3,7 @@ name: luckiest-ad-creative
3
3
  description: "Generates, iterates, and scales ad creative — headlines, descriptions, primary text, or full ad variations — for any paid advertising platform, and iterates from real performance data. Use when the user mentions 'ad copy variations,' 'ad creative,' 'generate headlines,' 'RSA headlines,' 'bulk ad copy,' 'ad iterations,' 'creative testing,' 'ad performance optimization,' 'write me some ads,' 'Facebook ad copy,' 'Google ad headlines,' 'LinkedIn ad text,' or 'I need more ad variations.' Use whenever someone needs to produce ad copy at scale or iterate on existing ads. For campaign strategy and targeting, see luckiest-ads. For landing page copy, see luckiest-copywriting."
4
4
  license: See ATTRIBUTION.md
5
5
  metadata:
6
- version: "1.1.1"
6
+ version: "1.2.0"
7
7
  listing_id: luckiest-ad-creative
8
8
  author: luckiest
9
9
  ---
@@ -14,9 +14,9 @@ This skill drives an expert performance creative strategist. The goal is to gene
14
14
 
15
15
  ## Staying current
16
16
 
17
- On activation, call the Luckiest MCP check_updates tool with { listingId: "9ce2c363-e379-45f7-b7d2-c398992ed30f", installedSemver: "1.1.0" }. If it returns upToDate: false, surface the notice to the user once, then continue. Do nothing further if upToDate: true. Never block on this check — if the tool is unavailable, proceed.
17
+ On activation, call the Luckiest MCP check_updates tool with { listingId: "9ce2c363-e379-45f7-b7d2-c398992ed30f", installedSemver: "1.2.0" }. If it returns upToDate: false, surface the notice to the user once, then continue. Do nothing further if upToDate: true. Never block on this check — if the tool is unavailable, proceed.
18
18
 
19
- When the skill's work is done, call the Luckiest MCP report_usage tool once with { listing_id: "luckiest-ad-creative", skill_version: "1.1.1", matched: true, success: <true if the skill completed, false otherwise> }. Metadata only, never prompt text. Never block on it — if the tool is unavailable, skip silently.
19
+ When the skill's work is done, call the Luckiest MCP report_usage tool once with { listing_id: "luckiest-ad-creative", skill_version: "1.2.0", matched: true, success: <true if the skill completed, false otherwise> }. Metadata only, never prompt text. Never block on it — if the tool is unavailable, skip silently.
20
20
 
21
21
  ## Before Starting
22
22
 
@@ -152,6 +152,8 @@ For image and video ad creative, use generative AI tools and code-based video re
152
152
  - **Platform image specs** — Correct dimensions for every ad placement
153
153
  - **Cost comparison** — Pricing for 100+ ad variations across tools
154
154
 
155
+ **Video ads:** if the ad is a video and `luckiest-video-studio-director` is installed, use its insight and scored-angle steps to pick the concept and its five-beat shot list for the cut. If `luckiest-video-studio-art-director` is installed, lock the look with it before building.
156
+
155
157
  **Composition:** if `luckiest-video-studio-composition` is installed, read it to place the focal point, pick the grid, and keep white space and platform safe areas. Check the headline, product, and CTA against the placement's safe area.
156
158
 
157
159
  **Recommended workflow for scaled production:**
@@ -0,0 +1,8 @@
1
+ # Attribution
2
+
3
+ luckiest-brandkit is an original Luckiest skill. It is not adapted from a third-party skill.
4
+
5
+ It calls three other Luckiest skills at run time: luckiest-video-studio-art-director
6
+ (look and design-system rules), luckiest-video-studio-composition
7
+ (placement rules, itself adapted from iart.ai `shot-composition`, MIT) and
8
+ luckiest-upscale-image (Real-ESRGAN models from Upscayl). See their own ATTRIBUTION files.
@@ -0,0 +1,26 @@
1
+ # Changelog — luckiest-brandkit
2
+
3
+ ## 1.0.0 — 2026-10-05
4
+ - New original Luckiest skill, built from a real 14-shot Luckiest brand mockup run.
5
+ - Pipeline: style block, composed prompt sheet (luckiest-video-studio-composition),
6
+ logo reference export, 3-shot approval batch, parallel generation, QA with
7
+ full-resolution text crops, real-logo fixes, local upscale, contact sheet.
8
+ - Scripts: `make_refs.mjs` (SVG to padded reference PNG via sips),
9
+ `composite_mark.py` (erase + multiply a real mark onto fabric or paper),
10
+ `composite_screen.py` (perspective-warp exact artwork onto a board or screen,
11
+ lit by the surface's own falloff), `contact_sheet.py`.
12
+ - Lessons baked in: no hex codes or UI labels in prompts, max two set planes as
13
+ leading lines, models draw custom symbols sideways so composite the real SVG,
14
+ one locked poster recipe per series, upscale loop that resumes.
15
+ - Sub-skills: the existing `luckiest-video-studio-art-director` (design system
16
+ first, rules with reasons, look lock; motion sections skipped for stills) and
17
+ `luckiest-video-studio-composition` (per-frame placement plus `frame_check.py`
18
+ on stills). Stills-specific art direction lives in `references/prompt-recipes.md`
19
+ (style skeleton, stills levers, poster recipe) and `references/picks-and-review.md`
20
+ (variant rejection, note-to-lever table, contact sheet review).
21
+ - Step 8: set review of the contact sheet before delivery.
22
+ - Network hook: offer to share the contact sheet with the tribe after delivery.
23
+ - Improve pass (/refract) and trend pass: not run. Original skill, scoped to the
24
+ pipeline as run. Trend pass: no actionable signal sought.
25
+ - Thumbnail: description matches "campaign"/"creative" and routes to the
26
+ `megaphone` scene in ListingThumbnail.jsx, not the hash fallback.
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: luckiest-brandkit
3
+ description: >-
4
+ Produce a full set of photoreal brand mockups for a campaign or portfolio: merch
5
+ (hat, hoodie, tee), print (business cards, letterhead, posters, gift card, brand
6
+ book), devices, billboard, office signage, and a welcome kit, all in one shared art
7
+ direction with the brand's real logo. Writes one style block plus a composed prompt
8
+ per shot, exports the logo SVGs as reference images, runs a 3-shot test batch for
9
+ approval, generates the rest, fixes wrong logos and text by compositing the real
10
+ SVG or artwork, upscales, and delivers a contact sheet. Trigger on "brand mockups",
11
+ "product shots for my brand", "brand kit images", "mock up my logo on merch",
12
+ "billboard mockup", "poster mockups", "agency portfolio shots", "brand identity
13
+ presentation", or "/luckiest-brandkit". For one marketing image use luckiest-image.
14
+ For framing a single shot use luckiest-video-studio-composition.
15
+ argument-hint: "[shot list or brief] [--shots 01,04,06] [--out .luckiest/shots]"
16
+ user-invocable: true
17
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep
18
+ metadata:
19
+ version: "1.0.0"
20
+ listing_id: luckiest-brandkit
21
+ author: luckiest
22
+ ---
23
+
24
+ # Brand kit mockups
25
+
26
+ Turns a style brief and a shot list into a finished, consistent set of brand
27
+ mockups. The work happens in an image-generation MCP (any that exposes generate,
28
+ retouch-erase, and file upload), plus four local scripts in `scripts/`.
29
+
30
+ ## Staying current
31
+
32
+ On activation, call the Luckiest MCP `check_updates` tool with
33
+ `{ listingId: "luckiest-brandkit", installedSemver: "1.0.0" }`. If
34
+ `upToDate: false`, surface the `notice` once and continue. Never block on it.
35
+
36
+ When done, call `report_usage` once with
37
+ `{ listing_id: "luckiest-brandkit", skill_version: "1.0.0", matched: true, success: <true|false> }`.
38
+ Metadata only, never prompt text. Skip silently if unavailable.
39
+
40
+ ## Output layout
41
+
42
+ ```
43
+ <out>/ default .luckiest/shots/
44
+ prompts.md style block, per-shot plan, locked decisions
45
+ refs/ logo PNGs + ids of uploaded references
46
+ raw/NN-name-{a,b}.png generated variants; raw/NN-name.png = the pick
47
+ raw/work/ erased plates and other in-between files (never upscaled)
48
+ qa.md one row per shot, pass or fix
49
+ final/NN-name.png upscaled picks + contact-sheet.png
50
+ ```
51
+
52
+ Never commit `<out>` unless asked. It holds hundreds of MB.
53
+
54
+ ## Sub-skills
55
+
56
+ | Step | Sub-skill | Owns |
57
+ |---|---|---|
58
+ | 1, 4, 5, 8 | `luckiest-video-studio-art-director` | The look of the whole set. Use section 0 (design system first), 0b (rules with a reason and an example path), and 3 (palette, accent budget, faces, texture, banned list). Skip its "Video-safe color" and "Type in motion" parts and its motion, timing, and `art-direction.json` sections. Stills rules live in this skill's `references/` |
59
+ | 2, 6 | `luckiest-video-studio-composition` | Where things sit inside each frame: placement system, focal point, white space, the 20 rules |
60
+
61
+ Load [references/prompt-recipes.md](references/prompt-recipes.md) whenever you
62
+ write or edit the style block or a shot prompt. Load
63
+ [references/picks-and-review.md](references/picks-and-review.md) at the test
64
+ batch, at every A/B pick, when the user gives a note, and before delivery.
65
+
66
+ If a sub-skill is not installed, say so in one line and do its step with the
67
+ rules in this skill's references.
68
+
69
+ ## 1. Brief and brand assets
70
+
71
+ - Take the user's STYLE block and shot list as given. Run the art director's
72
+ design-system search and look lock to fill any row the block leaves open, plus
73
+ the stills levers in prompt-recipes.md. Write the whole block from those when
74
+ there is none.
75
+ - Find the real logo SVGs (wordmark, symbol). Search `public/`, `assets/`,
76
+ brand docs, and any JS that builds SVG strings. If the logo only exists inside
77
+ JS, render it to plain SVG files first. Flatten gradients to the solid brand
78
+ color when the style says "one accent color".
79
+
80
+ ## 2. Prompt sheet (compose every shot first)
81
+
82
+ Load `luckiest-video-studio-composition` and give every shot, before any
83
+ generation: one placement system, the focal point as a fraction of the frame,
84
+ the tilt direction, the empty-space side, and one to three of the 20 rules.
85
+ Write it all to `prompts.md` as a table plus one entry per shot:
86
+ `SHOT` (object and set), `COMPOSITION`, `TEXT` (every exact string).
87
+
88
+ Then apply the art director's prompt rules. The two that broke real runs:
89
+
90
+ 1. Never put hex codes, labels, or UI words in a prompt. The model prints them
91
+ (`#EE425C` and "domain card" appeared on a generated iPad screen).
92
+ 2. End every prompt with the full list of allowed text, stated as the only
93
+ text, and a list of what must not appear.
94
+
95
+ ## 3. Reference images
96
+
97
+ ```bash
98
+ node scripts/make_refs.mjs <out>/refs wordmark.svg:#FFFFFF wordmark-white.svg:#0A0A0A symbol.svg:#FFFFFF symbol-white.svg:#0A0A0A
99
+ ```
100
+
101
+ Upload each PNG to the image MCP and record the returned ids in `refs/ids.md`.
102
+ Attach the matching reference to every shot that shows the logo.
103
+
104
+ ## 4. Test batch, then lock the look
105
+
106
+ Generate 3 representative shots (one merch, one poster, one device) with 2
107
+ variants each, on a reference-capable model with exact aspect ratios (Nano
108
+ Banana Pro worked; check the MCP's model list). Pick per shot with the rules
109
+ in picks-and-review.md, then ask the user to approve or adjust. Turn each note
110
+ into a set-wide lever change, rerun the batch, and lock only after a clear
111
+ approval. Write the locked model, picks, and recipe under "Locked" in `prompts.md`.
112
+
113
+ ## 5. Generate the rest
114
+
115
+ Queue every remaining shot in parallel, 2 variants each, same model and
116
+ references. Download each variant to `raw/`. Build A/B pairs side by side,
117
+ pick with picks-and-review.md, and copy each pick to `raw/NN-name.png`.
118
+
119
+ ## 6. QA and fixes
120
+
121
+ Crop every text region at full resolution and read it. Thumbnails hide
122
+ misspellings. Check composition on each pick with the composition sub-skill's
123
+ frame check. Its `--review` mode expects a video run folder, so call the script
124
+ directly on stills, with the focal point you planned in step 2. It writes
125
+ overlay, squint, and thumb images next to its input, so run it on a copy in
126
+ `raw/work/` to keep them out of the upscale loop and the contact sheet:
127
+
128
+ ```bash
129
+ mkdir -p <out>/raw/work && cp <out>/raw/NN-name.png <out>/raw/work/
130
+ python3 ~/.claude/skills/luckiest-video-studio-composition/scripts/frame_check.py <out>/raw/work/NN-name.png --focal <x>,<y> --aspect 4:5
131
+ ```
132
+
133
+ Read the squint image it writes: the subject must be the first thing you see.
134
+ Log each shot in `qa.md`: text, accent color, composition, verdict, note. Fix
135
+ in this order, cheapest first:
136
+
137
+ | Problem | Fix |
138
+ |---|---|
139
+ | Logo drawn wrong or sideways on a surface (models do this often with custom letterforms) | Mask the mark, run the MCP retouch in `erase` mode, then `scripts/composite_mark.py erased.png symbol-ink-on-white.png out.png --x --y --height [--rotate] [--squash] [--dot]` |
140
+ | A screen, board, or poster must show exact existing artwork | `scripts/composite_screen.py photo.png art.png out.png TL TR BR BL`. Zoom each corner to read inner-corner pixels first |
141
+ | Misspelled or leaked text | Retouch `replace` on that region with the exact string, or regenerate the shot with the text list tightened |
142
+ | Composition off | Regenerate with the corrected COMPOSITION line. Prompt edits that try to keep the rest of the image rarely fix a mark |
143
+
144
+ An image-model "edit" that asks to replace a logo usually returns the same
145
+ wrong logo. Go straight to erase + composite after one failed try.
146
+
147
+ ## 7. Upscale and deliver
148
+
149
+ Upscale with `luckiest-upscale-image` (`remacri-4x`, scale 2). It takes about
150
+ 5 minutes per image on Apple Silicon, so run the loop in the background with a
151
+ long timeout and skip files that already exist, so a restart resumes:
152
+
153
+ ```bash
154
+ for f in <out>/raw/[0-9][0-9]-*.png; do n=$(basename "$f"); case "$n" in *-[a-z].png) continue;; esac; [ -s "<out>/final/$n" ] && continue; ~/.claude/skills/luckiest-upscale-image/scripts/upscale.sh "$f" "<out>/final/$n" remacri-4x 2; done
155
+ python3 scripts/contact_sheet.py <out>/final <out>/final/contact-sheet.png
156
+ ```
157
+
158
+ Check: `final/` holds one file per shot plus the contact sheet. Compare one
159
+ crop before and after the upscale. After step 8 passes, send the contact sheet
160
+ and a downscaled preview. Files over about 7 MB may not reach phone viewers.
161
+
162
+ ## 8. Set review
163
+
164
+ Review the contact sheet as one campaign with the "Contact sheet review" steps
165
+ in picks-and-review.md (accent use, light side, angle rhythm, named
166
+ exceptions), judged against the art director's look lock. Append keep or
167
+ reshoot per shot to `qa.md`. Reshoot before
168
+ delivery when it flags one, then rebuild the sheet.
169
+
170
+ ## Share with your tribe
171
+
172
+ After delivery, offer once to share the contact sheet with the user's Luckiest
173
+ tribe for feedback. Never post automatically.
@@ -0,0 +1,48 @@
1
+ # Picks, notes, and set review
2
+
3
+ Load this at the test batch, at every A/B pick, when the user gives a note, and before delivery. These are the stills-specific art-direction calls. The look itself (palette, accent budget, faces, rules with reasons) comes from `luckiest-video-studio-art-director` sections 0, 0b, and 3.
4
+
5
+ ## Test batch and picks
6
+
7
+ Ask for 3 shots that stress the direction differently (one object, one print
8
+ piece with text, one device or scene), 2 variants each.
9
+
10
+ For each shot, pick one and say why in one line. Reject a variant, however
11
+ striking, when it:
12
+
13
+ - adds a second accent color or a second accent dot
14
+ - adds a frame, a colored wall, props, or more set planes than the block allows
15
+ - changes the light side or softens the shadows
16
+ - prints text that is not on the shot's text list
17
+
18
+ Then judge the three picks together. They should read as one shoot: same light,
19
+ same palette, same grain. If one is the odd one out, reshoot it before locking.
20
+
21
+ ## Turn user notes into direction
22
+
23
+ The user's notes are about the set, even when they name one shot. Translate
24
+ each note into a lever change and apply it to every shot:
25
+
26
+ | Note heard | Lever change |
27
+ |---|---|
28
+ | "Too many platforms" | Set: max two planes, used as leading lines |
29
+ | "Make the poster more creative" | Camera and light for the poster series. Use the poster series recipe in prompt-recipes.md |
30
+ | "Shrink the text 20%" | Type: headline share of the object width, written as a percent |
31
+ | "Add the logo somewhere" | Type: name the placement and attach the wordmark reference |
32
+
33
+ Rerun the test batch after any lever change. Lock only after a clear approval.
34
+ Write the locked model, picks, and recipe under "Locked" in `prompts.md`, so the
35
+ remaining shots use it word for word.
36
+
37
+ ## Contact sheet review
38
+
39
+ Open `final/contact-sheet.png` and review the set as a whole before any single frame:
40
+
41
+ 1. **Squint.** The accent color appears once per frame, in the same role.
42
+ 2. **Light.** Every shadow falls the same way. Flag any shot lit from another side.
43
+ 3. **Rhythm.** Neighboring shots vary angle and scale (rule 13 in luckiest-video-studio-composition). Three identical angles in a row read as a template.
44
+ 4. **Exceptions.** Any shot that breaks the direction on purpose (exact
45
+ artwork on a billboard, for example) is named in `qa.md` with the reason.
46
+
47
+ Append one line per shot to `qa.md`: keep, or reshoot with the lever to change.
48
+
@@ -0,0 +1,79 @@
1
+ # Prompt recipes
2
+
3
+ Load this when writing the style block or a shot prompt. Every recipe here came
4
+ from a real 14-shot run (Luckiest brand, 2026-10-05) and fixed something a first
5
+ draft got wrong.
6
+
7
+ ## Stills levers
8
+
9
+ The video art director's look table covers palette, accent, faces, and texture.
10
+ Stills also need these fixed once for the whole set. A set drifts when any is left open.
11
+
12
+ | Lever | Decide | Default that worked |
13
+ |---|---|---|
14
+ | Light | One source, its side, shadow quality | One hard light, upper left, long crisp black shadows |
15
+ | Materials | Surface and finish per object type | Textured cotton paper, heavyweight cotton, matte only |
16
+ | Set | What the subject sits on, and how much of it | One or two raw planes at most, edges used as leading lines |
17
+ | Camera | Angle per category | High three-quarter for objects, low close three-quarter for posters, straight on for walls |
18
+ | Space | Empty share of the frame | 60% |
19
+
20
+ ## Style block skeleton
21
+
22
+ Fill each slot. Prepend the whole block to every shot.
23
+
24
+ ```
25
+ Moody editorial brand mockup for an award-winning design agency portfolio.
26
+ Minimal set: <material> with <texture>. One or two simple planes at most, never
27
+ a stack of blocks or steps. Each plane edge is a leading line toward the subject.
28
+ A single hard directional light from the <side> casts long, crisp, deep-black shadows.
29
+ Palette: <neutrals>. The only color is <one accent, described in words, no hex>.
30
+ Materials: <paper/fabric/finish>, matte, no gloss.
31
+ <Camera angle>, medium-format photograph with photoreal micro-texture, cinematic,
32
+ 60% negative space.
33
+ ```
34
+
35
+ Then the shot: `SHOT:` object and set, `COMPOSITION:` placement in percent of
36
+ the frame, and a closing text line:
37
+
38
+ ```
39
+ The only text is exactly "<string 1>", "<string 2>", and the "<Brand>" wordmark,
40
+ spelled correctly. No other text, logos, extra colors, gradients, props, glossy
41
+ plastic, or soft flat lighting.
42
+ ```
43
+
44
+ ## Rules
45
+
46
+ | Rule | Why |
47
+ |---|---|
48
+ | Describe colors in words ("one small coral-red dot"), never hex | Hex codes get printed onto surfaces |
49
+ | Never name UI parts ("domain card", "button", "nav") as labels | They get printed as text. Describe the shape instead ("one small white rounded card that shows only the price") |
50
+ | Ask for "no menus, paragraphs, small print, URLs" on screens and letterheads | Models fill empty screens and paper with fake copy |
51
+ | Max two set planes, stated as leading lines | Without it, sets fill with stacked plinths and steps that compete with the subject |
52
+ | Name the light direction and where the shadow falls | Keeps the series consistent and gives each shot a diagonal |
53
+ | State the empty side ("the upper-left 60% is empty concrete") | Models center everything by default |
54
+ | Attach the logo as a reference and describe its shape in words | The reference alone is not enough for custom letterforms |
55
+ | Wordmark references work. Symbol references often come back rotated or simplified | Plan to composite the symbol on fabric and signage |
56
+
57
+ ## Poster series recipe (approved composition)
58
+
59
+ Use one recipe for every poster so the series reads as a set:
60
+
61
+ - Low, close three-quarter camera from the lower left, looking slightly up.
62
+ - Unframed poster leaning at a steep 28 degree tilt, top edge to the right.
63
+ - One diagonal cone of light from the upper left frames the poster like a spotlight (rule 12, isolate).
64
+ - Headline about 60% of the poster width, upper left of the poster, accent period on a phi point (rule 20).
65
+ - One short line right under the headline, the small wordmark bottom right of the poster.
66
+ - Dark variant: black paper, white type, the same accent.
67
+
68
+ ## Billboard or screen with existing artwork
69
+
70
+ Do not ask the model to repaint finished artwork. Generate the structure with a
71
+ plain board, then warp the real artwork on with `scripts/composite_screen.py`.
72
+ The artwork may carry its own colors and gradients. Say in `qa.md` that the
73
+ shot is an intentional exception to the one-accent rule.
74
+
75
+ ## Picking between variants
76
+
77
+ Reject a variant that adds a second accent dot, a frame, a colored wall, or
78
+ extra platforms, even when it is more striking. Consistency across the set
79
+ beats any single frame.
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env python3
2
+ """Print a real logo mark onto a surface (fabric, paper) that the model drew wrong.
3
+
4
+ Erase the bad mark first (image retouch, mode erase), then:
5
+ composite_mark.py <erased.png> <mark-ink-on-white.png> <out.png> --x X --y Y --height H
6
+ [--rotate DEG] [--squash 0.86] [--dot "#EE425C"]
7
+
8
+ Multiply blend keeps folds and shading. --squash fakes top-down foreshortening.
9
+ --dot adds a small accent circle right of the mark's foot.
10
+ """
11
+ import argparse
12
+ from PIL import Image, ImageChops, ImageDraw, ImageFilter
13
+
14
+ a = argparse.ArgumentParser()
15
+ a.add_argument("base"); a.add_argument("mark"); a.add_argument("out")
16
+ a.add_argument("--x", type=int, required=True); a.add_argument("--y", type=int, required=True)
17
+ a.add_argument("--height", type=int, required=True)
18
+ a.add_argument("--rotate", type=float, default=0); a.add_argument("--squash", type=float, default=1.0)
19
+ a.add_argument("--dot", default=None)
20
+ o = a.parse_args()
21
+
22
+ base = Image.open(o.base).convert("RGB")
23
+ m = Image.open(o.mark).convert("L")
24
+ m = m.crop(Image.eval(m, lambda p: 255 - p).getbbox())
25
+ m = m.resize((max(1, int(m.width * o.height / m.height)), o.height), Image.LANCZOS)
26
+ art = Image.new("L", (m.width + (40 if o.dot else 0), m.height), 255); art.paste(m, (0, 0))
27
+ art = Image.merge("RGB", [art] * 3)
28
+ if o.dot:
29
+ r = max(3, o.height // 16); cx, cy = m.width + 22, int(o.height * 0.80)
30
+ ImageDraw.Draw(art).ellipse((cx - r, cy - r, cx + r, cy + r), fill=o.dot)
31
+ art = art.resize((art.width, max(1, int(art.height * o.squash))), Image.LANCZOS)
32
+ art = art.rotate(o.rotate, Image.BICUBIC, expand=True, fillcolor=(255, 255, 255)).filter(ImageFilter.GaussianBlur(0.6))
33
+ region = base.crop((o.x, o.y, o.x + art.width, o.y + art.height))
34
+ base.paste(ImageChops.multiply(region, art), (o.x, o.y))
35
+ base.save(o.out)
36
+ print(o.out)
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env python3
2
+ """Warp exact artwork onto a flat surface in a photo (billboard, screen, poster, sign).
3
+
4
+ composite_screen.py <photo.png> <art.png> <out.png> TLx,TLy TRx,TRy BRx,BRy BLx,BLy [--fit crop|stretch]
5
+
6
+ Corners are the surface's inner corners in photo pixels, clockwise from top left.
7
+ --fit crop (default) center-crops the art to the surface's aspect. The art is lit by
8
+ the surface's own smoothed light falloff, so old text on the surface never shows through.
9
+ """
10
+ import argparse, math
11
+ import numpy as np
12
+ from PIL import Image, ImageChops, ImageFilter
13
+
14
+ a = argparse.ArgumentParser()
15
+ a.add_argument("photo"); a.add_argument("art"); a.add_argument("out")
16
+ a.add_argument("corners", nargs=4); a.add_argument("--fit", choices=["crop", "stretch"], default="crop")
17
+ o = a.parse_args()
18
+
19
+ bg = Image.open(o.photo).convert("RGB"); art = Image.open(o.art).convert("RGB")
20
+ dst = [tuple(map(float, c.split(","))) for c in o.corners]
21
+ if o.fit == "crop": # aspect from the average edge lengths of the quad
22
+ d = lambda p, q: math.dist(p, q)
23
+ ratio = (d(dst[0], dst[1]) + d(dst[3], dst[2])) / (d(dst[0], dst[3]) + d(dst[1], dst[2]))
24
+ w, h = art.size
25
+ if w / h > ratio: nw = int(h * ratio); art = art.crop(((w - nw) // 2, 0, (w + nw) // 2, h))
26
+ else: nh = int(w / ratio); art = art.crop((0, (h - nh) // 2, w, (h + nh) // 2))
27
+ src = [(0, 0), (art.width, 0), (art.width, art.height), (0, art.height)]
28
+ A, B = [], []
29
+ for (x, y), (u, v) in zip(dst, src): # PIL maps output -> input
30
+ A += [[x, y, 1, 0, 0, 0, -u * x, -u * y], [0, 0, 0, x, y, 1, -v * x, -v * y]]; B += [u, v]
31
+ k = tuple(np.linalg.solve(np.array(A, float), np.array(B, float)))
32
+ warped = art.transform(bg.size, Image.PERSPECTIVE, k, Image.BICUBIC)
33
+ mask = Image.new("L", art.size, 255).transform(bg.size, Image.PERSPECTIVE, k, Image.BICUBIC).filter(ImageFilter.GaussianBlur(1))
34
+ # max filter removes dark text from the light map, blur keeps only the falloff
35
+ lum = bg.convert("L").filter(ImageFilter.MaxFilter(31)).filter(ImageFilter.GaussianBlur(40)).point(lambda p: min(255, int(p * 255 / 225)))
36
+ Image.composite(ImageChops.multiply(warped, Image.merge("RGB", [lum] * 3)), bg, mask).save(o.out)
37
+ print(o.out)
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env python3
2
+ """Grid every image in a folder onto a near-black sheet with tracked labels.
3
+
4
+ contact_sheet.py <dir> <out.png> [--cols 5] [--cell 640]
5
+
6
+ Files sort by name, so prefix shots with 01-, 02-, ... Labels come from the file name.
7
+ """
8
+ import argparse, glob, os
9
+ from PIL import Image, ImageDraw, ImageFont
10
+
11
+ a = argparse.ArgumentParser()
12
+ a.add_argument("dir"); a.add_argument("out")
13
+ a.add_argument("--cols", type=int, default=5); a.add_argument("--cell", type=int, default=640)
14
+ o = a.parse_args()
15
+ fs = sorted(f for f in glob.glob(os.path.join(o.dir, "*")) if f.lower().endswith((".png", ".jpg", ".jpeg", ".webp"))
16
+ and os.path.abspath(f) != os.path.abspath(o.out))
17
+ if not fs: raise SystemExit("no images")
18
+ cols, cell, g, lab = o.cols, o.cell, 32, 40
19
+ rows = -(-len(fs) // cols)
20
+ sheet = Image.new("RGB", (cols * cell + (cols + 1) * g, rows * (cell + lab) + (rows + 1) * g), (14, 14, 14))
21
+ d = ImageDraw.Draw(sheet)
22
+ try: font = ImageFont.truetype("/System/Library/Fonts/Supplemental/Arial.ttf", 20)
23
+ except OSError: font = ImageFont.load_default()
24
+ for i, f in enumerate(fs):
25
+ im = Image.open(f).convert("RGB"); im.thumbnail((cell, cell), Image.LANCZOS)
26
+ x0 = g + (i % cols) * (cell + g); y0 = g + (i // cols) * (cell + lab + g)
27
+ sheet.paste(im, (x0 + (cell - im.width) // 2, y0 + (cell - im.height) // 2))
28
+ name = os.path.splitext(os.path.basename(f))[0].upper().replace("-", " · ")
29
+ d.text((x0, y0 + cell + 10), " ".join(name), fill=(150, 150, 150), font=font)
30
+ sheet.save(o.out)
31
+ print(o.out, len(fs))
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ // Rasterize brand SVGs into padded reference PNGs for image models.
3
+ // usage: node make_refs.mjs <out-dir> <file.svg>[:bg] ... (bg = hex like #FFFFFF, omit for transparent)
4
+ // Each SVG is wrapped with 12% padding and rendered ~3000px wide by macOS `sips`.
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ import { execFileSync } from "node:child_process";
8
+ const [out, ...items] = process.argv.slice(2);
9
+ if (!out || !items.length) { console.error("usage: make_refs.mjs <out-dir> <file.svg>[:#bg] ..."); process.exit(1); }
10
+ fs.mkdirSync(out, { recursive: true });
11
+ for (const item of items) {
12
+ const [file, bg] = item.split(/:(?=#)/);
13
+ const svg = fs.readFileSync(file, "utf8");
14
+ const vb = (svg.match(/viewBox="([^"]+)"/) || [])[1];
15
+ if (!vb) { console.error(`no viewBox in ${file}`); process.exit(1); }
16
+ const [x, y, w, h] = vb.trim().split(/[\s,]+/).map(Number);
17
+ const p = Math.max(w, h) * 0.12, W = w + 2 * p, H = h + 2 * p, S = 3000 / W;
18
+ const inner = svg.replace(/^[\s\S]*?<svg[^>]*>/, "").replace(/<\/svg>\s*$/, "");
19
+ const rect = bg ? `<rect x="${x - p}" y="${y - p}" width="${W}" height="${H}" fill="${bg}"/>` : "";
20
+ const wrapped = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${x - p} ${y - p} ${W} ${H}" width="${Math.round(W * S)}" height="${Math.round(H * S)}">${rect}${inner}</svg>`;
21
+ const base = path.join(out, path.basename(file, ".svg") + (bg ? `-on-${bg.slice(1).toLowerCase()}` : ""));
22
+ fs.writeFileSync(base + ".svg", wrapped);
23
+ execFileSync("sips", ["-s", "format", "png", base + ".svg", "--out", base + ".png"], { stdio: "ignore" });
24
+ console.log(base + ".png");
25
+ }
@@ -82,6 +82,8 @@ Include non-coding work too. Marketing, content, design, research, and ops tasks
82
82
 
83
83
  Route all draft tasks in ONE `skill_router` call from the luckiest MCP server: pass `prompts` as an array of every task title. It returns `results`, one entry per task with `skills` (matching owned skills) and `who` (up to 3 tribe members who finished a similar task before). Attach the suggested skill(s) to each task, and attach `who` so the plan can carry who has done this kind of work. If the server rejects `prompts` (older server), fall back to one `skill_router` call per task, issued in parallel in a single message, never one at a time.
84
84
 
85
+ For any task that makes a video, reel, demo, explainer, or video ad, add a task before it routed to **luckiest-video-studio-director** (intent, angle, hook, shot list) and **luckiest-video-studio-art-director** (look and motion language), when those skills are installed and `skill_router` did not already suggest them. Make the video task build on it.
86
+
85
87
  Then tag each task with a model tier. If the `luckiest-model-router` skill is installed, route every task in one batch call: `python3 <luckiest-model-router dir>/scripts/route.py --model --batch` with a JSON array of `{ title, skill, depends_on }` on stdin. `skill` is the task's first suggested skill, and `depends_on` lists the indexes of earlier tasks it builds on. Add `--prefer cheap` when the user asked to keep costs down, or `--prefer quality` when they asked for the best result. Keep each task's returned `model` and `reason`. If the skill is not installed or the script fails, skip tagging and let the server pick the model. Show the tier next to the task's skill as **Haiku**, **Sonnet** or **Opus**, with the task type, for example "**Copywriting** · **Sonnet** (implement)".
86
88
 
87
89
  For each task, write a one-line "done means..." in chat (not in the title). Give every coding task a check it can run: one of the commands found in Step 4, narrowed to that task when possible (for example `npm test -- billing`). Give non-coding tasks a plain check the user can look at (for example "the FAQ section shows on /pricing with 5 questions"). When `who` is not empty, add a short line naming those people, for example "Done before by: **Sam**, **Alex**."
@@ -1,5 +1,8 @@
1
1
  # Changelog — luckiest-video
2
2
 
3
+ ## 1.2.0 — 2026-10-05
4
+ - Runs the director and art director before multi-shot prompts when installed.
5
+
3
6
  ## 1.1.1 — 2026-10-03
4
7
  - Points at `luckiest-video-studio-composition` (when installed) for focal point, grid, white space, and safe areas.
5
8
 
@@ -3,7 +3,7 @@ name: luckiest-video
3
3
  description: "When the user wants to create, generate, or produce video content using AI tools or programmatic frameworks. Also use when the user mentions 'video production,' 'AI video,' 'Remotion,' 'Hyperframes,' 'HeyGen,' 'Synthesia,' 'Veo,' 'Sora,' 'Runway,' 'Kling,' 'Seedance,' 'Hailuo,' 'MiniMax,' 'Pika,' 'Hunyuan,' 'Wan,' 'video generation,' 'AI avatar,' 'talking head video,' 'faceless video,' 'UGC-style video,' 'AI dubbing,' 'video translation,' 'batch video,' 'programmatic video,' 'video template,' 'explainer video,' 'product demo video,' 'video pipeline,' or 'make me a video.' Use this for video creation, generation, and production workflows. For video content strategy and what to post, see luckiest-social. For paid video ad creative, see luckiest-ad-creative."
4
4
  license: See ATTRIBUTION.md
5
5
  metadata:
6
- version: "1.1.1"
6
+ version: "1.2.0"
7
7
  listing_id: luckiest-video
8
8
  author: luckiest
9
9
  ---
@@ -14,9 +14,9 @@ An expert video producer that helps create marketing videos using AI generation
14
14
 
15
15
  ## Staying current
16
16
 
17
- On activation, call the Luckiest MCP check_updates tool with { listingId: "2991a487-dd00-4f65-a9cd-b51fc34fedd1", installedSemver: "1.1.0" }. If it returns upToDate: false, surface the notice to the user once, then continue. Do nothing further if upToDate: true. Never block on this check — if the tool is unavailable, proceed.
17
+ On activation, call the Luckiest MCP check_updates tool with { listingId: "2991a487-dd00-4f65-a9cd-b51fc34fedd1", installedSemver: "1.2.0" }. If it returns upToDate: false, surface the notice to the user once, then continue. Do nothing further if upToDate: true. Never block on this check — if the tool is unavailable, proceed.
18
18
 
19
- When the skill's work is done, call the Luckiest MCP report_usage tool once with { listing_id: "luckiest-video", skill_version: "1.1.1", matched: true, success: <true if the skill completed, false otherwise> }. Metadata only, never prompt text. Never block on it — if the tool is unavailable, skip silently.
19
+ When the skill's work is done, call the Luckiest MCP report_usage tool once with { listing_id: "luckiest-video", skill_version: "1.2.0", matched: true, success: <true if the skill completed, false otherwise> }. Metadata only, never prompt text. Never block on it — if the tool is unavailable, skip silently.
20
20
 
21
21
  ## Before Starting
22
22
 
@@ -173,6 +173,8 @@ cinematic color grading, 4K
173
173
  - Forgetting style — "cinematic," "documentary," "commercial"
174
174
  - Requesting text in video — AI models struggle with readable text
175
175
 
176
+ **Direction:** for a multi-shot video or ad, if `luckiest-video-studio-director` is installed, run its steps 1 to 4 (intent, scored angle, hook, shot list) before writing prompts, and if `luckiest-video-studio-art-director` is installed, lock the palette, texture, and motion personality so every shot matches.
177
+
176
178
  **Composition:** if `luckiest-video-studio-composition` is installed, read it to place the focal point, pick the grid, and keep white space and platform safe areas for each shot's framing before you write the camera part of the prompt.
177
179
 
178
180
  **For detailed prompting guides**: load [references/ai-video-prompting.md](references/ai-video-prompting.md) when writing or refining a generation prompt, choosing camera vocabulary, or troubleshooting weak results.
@@ -1,5 +1,15 @@
1
1
  # Changelog — luckiest-video-studio
2
2
 
3
+ ## 1.8.0 — 2026-10-05
4
+ - Step 2 hands off to `luckiest-video-studio-director` (intent, hook, shot list)
5
+ and `luckiest-video-studio-art-director` (`art-direction.json`) before planning.
6
+ - Step 4 adds the art-direction review and the director's score loop (all 8+).
7
+
8
+ ## 1.7.2 (2026-10-05)
9
+ From a real luckiest.co launch video run end to end (storyboard approvals, render, QA gates, Concat export matching the render at 58 dB PSNR):
10
+ - Step 2b: capture live site pages with headless Chrome (wait budget, crop out cookie banners); the style frame is now a `hyperframes snapshot` still, no video render.
11
+ - Step 3: the project layout HyperFrames 0.8 needs: root `index.html` hosts every scene, per-scene files with their own composition id, assets and fonts under `composition/assets/` with root-relative paths, no named font fallbacks, ids on timed elements, and a one-pass hold-frame snapshot before the full render.
12
+
3
13
  ## 1.7.1 (2026-10-04)
4
14
  - `assemble-concat.mjs` tested end to end against Concat 0.2.5. Fixes found by the
5
15
  live run and by reading Concat's source: progress events between replies no