@aicopycoders/exodus 2026.6.2400
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.
- package/assets/references/awareness-framework.md +156 -0
- package/assets/references/cast-video.md +165 -0
- package/assets/references/copy-blocks.md +138 -0
- package/assets/references/creative-strategy.md +990 -0
- package/assets/references/editing-rules.md +81 -0
- package/assets/references/hook-quality-checklist.md +153 -0
- package/assets/references/iterations.md +73 -0
- package/assets/references/scrawls.md +483 -0
- package/assets/references/segments.md +79 -0
- package/assets/skills/exodus/SKILL.md +50 -0
- package/assets/skills/exodus-brand/SKILL.md +117 -0
- package/assets/skills/exodus-browse/SKILL.md +96 -0
- package/assets/skills/exodus-creative/SKILL.md +94 -0
- package/assets/skills/exodus-drive/SKILL.md +118 -0
- package/assets/skills/exodus-foundation/SKILL.md +170 -0
- package/assets/skills/exodus-genesis/SKILL.md +159 -0
- package/assets/skills/exodus-idea/SKILL.md +78 -0
- package/assets/skills/exodus-image/SKILL.md +224 -0
- package/assets/skills/exodus-meme/SKILL.md +183 -0
- package/assets/skills/exodus-primer/SKILL.md +145 -0
- package/assets/skills/exodus-strategist/SKILL.md +217 -0
- package/assets/skills/exodus-swipe/SKILL.md +85 -0
- package/assets/skills/exodus-template/SKILL.md +106 -0
- package/assets/skills/exodus-write/SKILL.md +157 -0
- package/assets/skills/genesis-bots/.env.example +12 -0
- package/assets/skills/genesis-bots/README.txt +29 -0
- package/assets/skills/genesis-bots/SKILL.md +219 -0
- package/assets/skills/genesis-bots/scripts/genesis-stream.mjs +307 -0
- package/assets/skills/genesis-bots/scripts/genesis-stream.py +220 -0
- package/dist/bin/exodus.d.ts +2 -0
- package/dist/bin/exodus.js +177 -0
- package/dist/commands/__tests__/genesis.hookgate.test.d.ts +1 -0
- package/dist/commands/__tests__/genesis.hookgate.test.js +12 -0
- package/dist/commands/brand.d.ts +24 -0
- package/dist/commands/brand.js +292 -0
- package/dist/commands/browse.d.ts +9 -0
- package/dist/commands/browse.js +132 -0
- package/dist/commands/creative.d.ts +2 -0
- package/dist/commands/creative.js +223 -0
- package/dist/commands/doctor.d.ts +21 -0
- package/dist/commands/doctor.js +590 -0
- package/dist/commands/drive.d.ts +2 -0
- package/dist/commands/drive.js +154 -0
- package/dist/commands/foundation.d.ts +2 -0
- package/dist/commands/foundation.js +468 -0
- package/dist/commands/genesis.d.ts +64 -0
- package/dist/commands/genesis.js +564 -0
- package/dist/commands/idea.d.ts +53 -0
- package/dist/commands/idea.js +333 -0
- package/dist/commands/image.d.ts +2 -0
- package/dist/commands/image.js +249 -0
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.js +70 -0
- package/dist/commands/keys.d.ts +2 -0
- package/dist/commands/keys.js +101 -0
- package/dist/commands/meme.d.ts +12 -0
- package/dist/commands/meme.js +272 -0
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.js +158 -0
- package/dist/commands/primer.d.ts +2 -0
- package/dist/commands/primer.js +540 -0
- package/dist/commands/read-doc.d.ts +3 -0
- package/dist/commands/read-doc.js +62 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.js +205 -0
- package/dist/commands/swipe.d.ts +2 -0
- package/dist/commands/swipe.js +398 -0
- package/dist/commands/template.d.ts +2 -0
- package/dist/commands/template.js +225 -0
- package/dist/commands/whoami.d.ts +2 -0
- package/dist/commands/whoami.js +51 -0
- package/dist/lib/ad-library-write.d.ts +15 -0
- package/dist/lib/ad-library-write.js +67 -0
- package/dist/lib/assets.d.ts +3 -0
- package/dist/lib/assets.js +23 -0
- package/dist/lib/backend-hint.d.ts +2 -0
- package/dist/lib/backend-hint.js +22 -0
- package/dist/lib/cc-command.d.ts +1 -0
- package/dist/lib/cc-command.js +13 -0
- package/dist/lib/client.d.ts +23 -0
- package/dist/lib/client.js +213 -0
- package/dist/lib/format.d.ts +8 -0
- package/dist/lib/format.js +172 -0
- package/dist/lib/intel-format.d.ts +1 -0
- package/dist/lib/intel-format.js +38 -0
- package/dist/lib/keys-sync.d.ts +16 -0
- package/dist/lib/keys-sync.js +88 -0
- package/dist/lib/layout.d.ts +38 -0
- package/dist/lib/layout.js +153 -0
- package/dist/lib/load-env.d.ts +1 -0
- package/dist/lib/load-env.js +47 -0
- package/dist/lib/pixar-orchestrator-types.d.ts +54 -0
- package/dist/lib/pixar-orchestrator-types.js +1 -0
- package/dist/lib/poll.d.ts +14 -0
- package/dist/lib/poll.js +32 -0
- package/dist/lib/preflight.d.ts +18 -0
- package/dist/lib/preflight.js +56 -0
- package/dist/lib/prompts.d.ts +9 -0
- package/dist/lib/prompts.js +99 -0
- package/dist/lib/reel-write.d.ts +14 -0
- package/dist/lib/reel-write.js +59 -0
- package/dist/lib/release.d.ts +4 -0
- package/dist/lib/release.js +81 -0
- package/dist/lib/scaffold.d.ts +8 -0
- package/dist/lib/scaffold.js +67 -0
- package/dist/lib/scout-hydrate.d.ts +1 -0
- package/dist/lib/scout-hydrate.js +10 -0
- package/dist/lib/state.d.ts +6 -0
- package/dist/lib/state.js +49 -0
- package/dist/lib/template-constants.d.ts +4 -0
- package/dist/lib/template-constants.js +85 -0
- package/dist/lib/version.d.ts +1 -0
- package/dist/lib/version.js +19 -0
- package/package.json +30 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: exodus-genesis
|
|
3
|
+
description: Run the standalone Exodus Genesis pipeline — Luke's full writing process across two voices (MarioBot + Infeed VSL) on the brand primer. The default is one pass per bot = 2 variants (1 Mario × Brand + 1 Infeed × Brand); the user can run more passes to widen coverage and bring in the Top-Ads-Biased primer. Includes the per-variant editing menu (Natural Language / Shorten / Cut / Simplify / Make Better). `--reel` also writes ads on the spot from a pasted Instagram/TikTok reel — it transcribes the reel into an idea and writes it through this same writer (just another input, nothing custom); to COLLECT reels/ideas into a bank to curate before writing, that's the `exodus-idea` skill. Only invoke when the user has explicitly invoked Exodus: they said "exodus" in the request ("run the exodus genesis pipeline", "exodus, run another pass", "exodus, make me ads from this reel"), named this skill or /exodus-genesis, ran an `npx exodus` command, or the `exodus` hub skill routed here. Never claim generic requests ("run the Genesis pipeline", "write ads from this reel") — in shared folders those may belong to the user's other tools; if the user did not say exodus, this skill is not for them. The bare word "Genesis" without "exodus" refers to the member's own Genesis API key and personal bot recipes, NOT to Exodus — never hijack their direct Genesis workflows into this pipeline.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```operator-guide
|
|
7
|
+
Inputs (choose one source):
|
|
8
|
+
brief — concept, derived hook, or paste of the source ad (genesis run --brief)
|
|
9
|
+
reel — an Instagram/TikTok reel URL to write ads from (genesis --reel "<url>")
|
|
10
|
+
Optional:
|
|
11
|
+
seeds — per-run creative angles extracted from the source ad
|
|
12
|
+
(file path with one seed per line, OR an inline string)
|
|
13
|
+
awareness (default: problem-aware)
|
|
14
|
+
passes — writing passes per bot (1-5, default 1). 1 pass = 2 variants
|
|
15
|
+
(1 Mario × Brand + 1 Infeed × Brand). Each added pass writes one
|
|
16
|
+
more Mario + one more Infeed; pass 2 brings in the Top-Ads-Biased primer.
|
|
17
|
+
variants — advanced: raw total count (1-10) that overrides passes
|
|
18
|
+
ad-account — Meta ad account ID for the top-ads track
|
|
19
|
+
Returns:
|
|
20
|
+
Google Doc with one tab per variant (Headlines + Hook + Body Copy)
|
|
21
|
+
Per-variant editing menu surfaced on the dashboard run page
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
# Genesis — Brief + Seeds → Mario + Infeed Variants → Editing Menu
|
|
25
|
+
|
|
26
|
+
Luke's full Ad Writing Process end-to-end:
|
|
27
|
+
|
|
28
|
+
- Two parallel hook voices (MarioBot + InfeedVSL) producing ~40 hooks total
|
|
29
|
+
- Body-copy variants in two voices, **scaled by passes**:
|
|
30
|
+
- **Mario × Brand primer** — established brand voice
|
|
31
|
+
- **Infeed × Brand primer** — InfeedVSL voice on the same brand reference
|
|
32
|
+
- **Top-Ads-Biased** — primed with the brand's actual top performers (CTR × spend),
|
|
33
|
+
so output is biased toward what's currently winning. This enters on the **2nd pass**.
|
|
34
|
+
- 15-point QA across every variant
|
|
35
|
+
- Editing menu on the dashboard (5 transforms per variant)
|
|
36
|
+
|
|
37
|
+
**The default is one pass per bot — 2 variants** (1 Mario × Brand + 1 Infeed × Brand): the
|
|
38
|
+
fastest useful read on the two voices against the same brief. Scale up with **passes** when the
|
|
39
|
+
user wants a heavier pass — a new sprint, a fatigue plateau, or wider coverage (see *Passes —
|
|
40
|
+
How Much Coverage* below).
|
|
41
|
+
|
|
42
|
+
> If the user hasn't named the pipeline specifically and just wants Exodus to "write some ads,"
|
|
43
|
+
> start from the `exodus-write` skill — it walks brand → foundation → brief → here, and it owns the passes menu.
|
|
44
|
+
> This skill owns the run once the brief, awareness, and pass count are settled. If the user
|
|
45
|
+
> invoked Genesis directly and didn't say how many, surface the same quick passes menu (default
|
|
46
|
+
> 1 pass = 2 variants, recommended) before firing — don't silently assume a big run.
|
|
47
|
+
|
|
48
|
+
## Workflow
|
|
49
|
+
|
|
50
|
+
### 1. Shape the brief (Stage 4)
|
|
51
|
+
|
|
52
|
+
Genesis writes from a **brief** — a 1–2 paragraph natural-language *description* of the ad, not the ad itself. If the user gave you an idea, a winning ad, or a rough angle, you write the brief from it; surface it for a quick gut-check before running.
|
|
53
|
+
|
|
54
|
+
A brief covers: what the ad is about · what happens in it · the emotional core (heartbreak, rage, shame, mischief…) · the mechanism bridge to the product · the tone · why it's vicious. It is NOT the copy, NOT a hook list, NOT a format spec, and NOT over-specified — leave the bots room.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
BRIEF: "[short evocative title]"
|
|
58
|
+
Hook: "[verbatim hook if from a swipe/organic source, else a hook DIRECTION or leave open]"
|
|
59
|
+
Source: [where the idea came from]
|
|
60
|
+
[1–2 paragraphs: scenario, emotional core, mechanism bridge, tone, why it works]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Worked brief examples and the awareness→primer mapping are in `references/awareness-framework.md`. Hook direction and the vicious standard are in `references/hook-quality-checklist.md`.
|
|
64
|
+
|
|
65
|
+
### 1b. Writing from a reel (`--reel`)
|
|
66
|
+
|
|
67
|
+
When the user pastes an Instagram/TikTok reel and wants ads from it, you don't shape a brief by hand — the reel *is* the source. Fire it in the background:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx @aicopycoders/exodus genesis --reel "<url>" --awareness <level> [--passes n]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
This transcribes the reel into an Idea Bank "organic" idea, then writes that idea through this same Genesis writer (Mario + Infeed) — a reel is just another input to the standard writer. It banks the idea (so there's a reusable record) AND writes in one shot, returning a Genesis run. Capture is async, so it takes a beat longer than a typed brief before writing starts. If the reel is private/region-locked/has no transcript, capture yields nothing — surface that and ask for an alternate. When the user wants to collect several reels to curate *before* writing, route to the `exodus-idea` skill instead.
|
|
74
|
+
|
|
75
|
+
### 2. Extract seeds (when there's a source ad)
|
|
76
|
+
|
|
77
|
+
When the user pastes a winning ad, extract seeds yourself. A seed is a creative angle, mechanism, or pattern surfaced from the source — examples:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
Coffee = morning ritual — swap to gym, sex, alcohol tolerance, social media
|
|
81
|
+
"It's not low T..." — reframe to "It's too high cortisol"
|
|
82
|
+
Defective mitochondria — mechanism seed (cell-energy story)
|
|
83
|
+
The whole ad is mechanism-heavy — replicate this structure
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Save to `/tmp/genesis-seeds.txt` (one per line, `#` comments allowed), or pass `--seeds "..."` inline. Skip seeds when there's no source ad — the brief carries the load.
|
|
87
|
+
|
|
88
|
+
### 3. Resolve awareness + pass count, then run in background
|
|
89
|
+
|
|
90
|
+
**Awareness is your call** (Principle 2) — state your read, don't make the user pick: "this reads problem-aware because X — sound right?" The primer is awareness-keyed: `--awareness` picks which of the brand's two foundation primers (`primerUnawareProblemAware` cold / `primerSolutionProductAware` warm) the bots receive. Default `problem-aware` when unsure. Pick ONE level; never mix buckets in a run.
|
|
91
|
+
|
|
92
|
+
**Pass count is the user's knob** — if they didn't specify, surface a quick menu (1 pass / 2 variants recommended · 2 passes / 4 variants · more) rather than assuming. Always `run_in_background: true` — these runs are past the 10-min foreground cap.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Default — 1 pass per bot = 2 variants (1 Mario × Brand + 1 Infeed × Brand):
|
|
96
|
+
npx @aicopycoders/exodus genesis run --brief "<brief>" --awareness <level>
|
|
97
|
+
|
|
98
|
+
# More coverage — 2 passes = 4 variants (adds the Top-Ads-Biased pass):
|
|
99
|
+
npx @aicopycoders/exodus genesis run --brief "<brief>" --awareness <level> --passes 2
|
|
100
|
+
|
|
101
|
+
# With seeds:
|
|
102
|
+
npx @aicopycoders/exodus genesis run --brief "<brief>" --seeds /tmp/genesis-seeds.txt --awareness <level> --passes 2
|
|
103
|
+
|
|
104
|
+
# Manual hook selection — pause after hook generation:
|
|
105
|
+
npx @aicopycoders/exodus genesis run --brief "<brief>" --awareness <level> --stop-at-hooks
|
|
106
|
+
|
|
107
|
+
# Force auto-select (overrides a saved "manual" preference):
|
|
108
|
+
npx @aicopycoders/exodus genesis run --brief "<brief>" --awareness <level> --auto-hooks
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`--brief` accepts inline text or a file path. `--passes <n>` (1–5) is the friendly knob; `--variants <n>` (1–10) is an advanced raw-total override that wins if both are given.
|
|
112
|
+
|
|
113
|
+
**Hook Selection Mode:**
|
|
114
|
+
The pipeline can pause after Genesis generates hooks, allowing the user to pick which hooks to keep before writing body copy. This is controlled by a persisted per-user preference (manual or auto-select).
|
|
115
|
+
|
|
116
|
+
- **`--stop-at-hooks`** — pause after hook generation. The run lands in `awaiting_hook_selection` status and the CLI prints a dashboard URL. The user reviews and picks hooks on the run-detail page; the pipeline then continues automatically to body-copy generation.
|
|
117
|
+
- **`--auto-hooks`** — force auto-select for this run (overrides a saved "manual" default). The pipeline auto-computes the strongest hooks and runs straight through without pausing.
|
|
118
|
+
- **Saved preference** — the first time a user runs Genesis (or when no preference is saved), you should ask once: *"Want to choose the hooks yourself, or have me auto-pick and write straight through?"* Then run with `--stop-at-hooks` (manual mode) or `--auto-hooks` (auto mode), and after reporting the result, offer to save the choice with `npx @aicopycoders/exodus genesis hook-pref <manual|auto>` so you don't ask again. If the user has already set a preference via `hook-pref`, skip the question and just run with the saved default.
|
|
119
|
+
|
|
120
|
+
> "Genesis run started at problem-aware — 1 pass per bot (2 variants: Mario × Brand + Infeed × Brand). I'll surface the Doc when it lands."
|
|
121
|
+
|
|
122
|
+
Status check (only if user asks): `npx @aicopycoders/exodus status --id <runId> --type genesis` — `--type genesis` required.
|
|
123
|
+
|
|
124
|
+
### 4. Report
|
|
125
|
+
|
|
126
|
+
Per the **Default Post-Run Reporting** rule in `exodus-strategist`: surface the Doc URL and the variant breakdown plus a 2-line take. At the default that's **V1 Mario × Brand, V2 Infeed × Brand**; with more passes, each added pass is another Mario + Infeed pair, and **pass 2 uses the Top-Ads-Biased primer**. **Plus one Genesis-specific check**: if a 2nd pass was requested and the top-ads primer was empty (account has no qualifying ads, or lookup failed), that pass's two variants silently fall back to the brand primer — surface it so the user knows they got brand-primer variants instead of top-ads-biased ones.
|
|
127
|
+
|
|
128
|
+
Mention the **editing menu** on the run-detail page (5 buttons per variant: Natural Language, Shorten, Cut, Simplify, Make Better — each appends a new tab with the edited version, originals stay).
|
|
129
|
+
|
|
130
|
+
Don't auto-`read-doc` every variant. Pull the Doc only if the user wants vicious-hook critique, or you're picking the strongest variant for a follow-up.
|
|
131
|
+
|
|
132
|
+
Then propose 1-2 fitting next moves: apply Shorten/Make Better to a specific variant, run another Genesis pass with different seeds or awareness, or pair with the `exodus-image` skill to render statics from the winning variant.
|
|
133
|
+
|
|
134
|
+
## Cleanup & QA (Stage 6 — built into the pipeline)
|
|
135
|
+
|
|
136
|
+
You do **not** hand-clean Genesis output. The pipeline runs Luke's cleanup + a 15-point QA pass on every variant before the Google Doc is written, so the Doc lands as a clean deliverable:
|
|
137
|
+
|
|
138
|
+
- Bot commentary stripped — emotional-excavation notes, STEP/TEST labels, quality-gate/viciousness checks, hook-analysis paragraphs, category labels.
|
|
139
|
+
- Markdown artifacts stripped — `**`, `*`, `##`, `---`, backticks.
|
|
140
|
+
- Body copy continues from the hook (never repeats it), runs 700–1500 words — a design target of the writing process, not a hard limit of the bots (use the editing menu's Shorten/Cut if the user wants tighter) — and reads at a 3rd–5th-grade level.
|
|
141
|
+
- Google Doc formatting: 14pt throughout, bold only on section/item labels (HEADLINES:, HOOKS:, BODY COPY 1/2:, H1:, Hook 1:), clean spacing.
|
|
142
|
+
|
|
143
|
+
What still needs *your* judgment after the run: **verify any statistics, studies, or claims** — Genesis bots fabricate proof points (Principle 14). Fact-check before anything ships. If you spot junk that slipped past cleanup, that's a Tool Feedback item (see `exodus-strategist`).
|
|
144
|
+
|
|
145
|
+
## Passes — How Much Coverage
|
|
146
|
+
|
|
147
|
+
`--passes` is the friendly knob: one pass = one Mario + one Infeed. The user owns this number — menu it when unspecified, don't assume.
|
|
148
|
+
|
|
149
|
+
- **1 pass = 2 variants (default)** — one Mario × Brand + one Infeed × Brand. The fastest two-voice read.
|
|
150
|
+
- **2 passes = 4 variants** — adds a Mario + Infeed pair on the **Top-Ads-Biased** primer (falls back to brand if the account has no qualifying winners).
|
|
151
|
+
- **3–5 passes = 6–10 variants** — wider net for a sprint; the extra passes repeat the Mario × Brand + Infeed × Brand pairing.
|
|
152
|
+
- **Advanced — `--variants <n>` (1–10)** — a raw total that overrides `--passes`. Odd counts alternate Mario → Infeed (e.g. `--variants 3` = Mario, Infeed, Mario), with the top-ads primer entering on the 3rd variant.
|
|
153
|
+
|
|
154
|
+
## Common Failure Modes
|
|
155
|
+
|
|
156
|
+
- **In-feed-vsl-bot fails** — InfeedVSL hook generation degrades to Mario-only; the Infeed variant still runs if recovered. Note in report.
|
|
157
|
+
- **Top-ads primer empty (2+ passes)** — the 2nd pass's two variants fall back to the brand primer. Pipeline completes; flag it.
|
|
158
|
+
- **Pipeline timeout** — rare, and only realistic on a large pass count. Check run-detail for partial variants; trigger an editing pass from the UI to recover usable output.
|
|
159
|
+
- **`status` 400 "Invalid generation ID format"** — missing `--type genesis`.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: exodus-idea
|
|
3
|
+
description: Capture, curate, and write from the Exodus Idea Bank — the brand's home for formed ideas (a hook + a short concept) you collect now and write later, living in the Exodus dashboard. The Organic capture path transcribes a pasted Instagram/TikTok reel into a reusable idea; `idea write` (or `organic --write`) escalates a banked idea to the Genesis writer. If the user instead wants ads written from a reel RIGHT NOW in one shot — "exodus, make me ads from this reel" — that's the `exodus-genesis` skill (`--reel`); use this skill when the bank itself is the point (collect, curate, then write). Only invoke when the user has explicitly invoked Exodus — they said "exodus" in the request ("exodus, add this to my idea bank", "save these reels to the exodus idea bank", "exodus, write idea O3"), named this skill or /exodus-idea, ran an `npx @aicopycoders/exodus idea` command, referenced Exodus idea-bank keys from a prior run (O3, G1, S4), or the exodus hub skill routed here — gate "idea bank" mentions to Exodus context. Never claim generic idea or note-taking requests ("save this idea for later", "show me my ideas") — in shared folders those may belong to the user's other tools. The bare word "Genesis" without "exodus" refers to the member's own Genesis API key and personal bot recipes, NOT to Exodus.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```operator-guide
|
|
7
|
+
Idea Bank = formed ideas (hook + 1-2 line concept), brand-agnostic, written later.
|
|
8
|
+
Capture (three sources):
|
|
9
|
+
gambit "<brain-dump>" split a freeform dump into discrete ideas
|
|
10
|
+
organic "<url> ..." [--write] pull ONE idea from each IG/TikTok reel (transcribe → extract)
|
|
11
|
+
swipe [--limit n] extract concepts from the saved swipe library
|
|
12
|
+
Curate:
|
|
13
|
+
list [--source ..] [--status raw|writing|written|archived] [--limit n]
|
|
14
|
+
note <KEY> "<steering>" · edit <KEY> "<new concept>" · add "<hook>" [--desc ..] · rm <KEY> [--hard]
|
|
15
|
+
Write:
|
|
16
|
+
write <KEYS> [--awareness <level>] [--passes n] one Genesis run per key (brief-mode)
|
|
17
|
+
Keys look like G1 (gambit) · O2 (organic) · S4 (swipe). Capture is fire-and-forget on Trigger.
|
|
18
|
+
Returns: banked ideas appear in `idea list`; writes return a Genesis run + Google Doc per key.
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
# Idea Bank — Collect Now, Write Later
|
|
22
|
+
|
|
23
|
+
The Idea Bank is where formed ideas live between "I saw something worth using" and "write it." An idea is a **hook + a short concept** — not the finished ad. Capture cheaply, curate the keepers, then escalate the ones you like to the Genesis writer. The analysis happens at capture; writing is a plain brief-mode Genesis run, so the brand's voice/steering is applied by the writers (Mario + Infeed), not baked into the idea — banked ideas stay reusable across runs.
|
|
24
|
+
|
|
25
|
+
> **Reel → ads, one shot vs. bank-first.** Both this skill and `exodus-genesis` can write from a pasted reel. Use **the `exodus-genesis` skill (`--reel`)** when the user wants ads *now* from one reel and doesn't care about the bank. Use **`exodus-idea`** when the bank is the point — they're collecting several reels/angles, want to review before writing, or are working through a list. `idea organic --write` is the middle path: capture to the bank AND write in one shot.
|
|
26
|
+
|
|
27
|
+
## Workflow
|
|
28
|
+
|
|
29
|
+
### 1. Capture — get ideas into the bank
|
|
30
|
+
|
|
31
|
+
Pick the source from what the user handed you:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Reels — transcribe each IG/TikTok link into one reusable idea:
|
|
35
|
+
npx @aicopycoders/exodus idea organic "https://www.instagram.com/reel/abc https://www.tiktok.com/@x/video/123"
|
|
36
|
+
|
|
37
|
+
# Brain-dump — split a freeform stream into discrete ideas:
|
|
38
|
+
npx @aicopycoders/exodus idea gambit "joint pain at 40, sleep angle, grounding vs pills"
|
|
39
|
+
|
|
40
|
+
# Swipes — mine concepts from the saved competitor-ad library:
|
|
41
|
+
npx @aicopycoders/exodus idea swipe --limit 10
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Capture is **fire-and-forget** (it scrapes/transcribes/extracts on the queue). Don't poll — tell the user the ideas will land in the bank, and that `idea list` shows them as they arrive. A reel that's private, region-locked, or has no transcript just won't produce an idea; surface that if the user expected one.
|
|
45
|
+
|
|
46
|
+
### 2. Curate — make the keepers writable
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npx @aicopycoders/exodus idea list --source organic --status raw # review what landed
|
|
50
|
+
npx @aicopycoders/exodus idea note O2 "lean harder on the cortisol angle, never mention sleep meds"
|
|
51
|
+
npx @aicopycoders/exodus idea edit O2 "A 40-something realizes their 'bad sleep' is actually high cortisol…"
|
|
52
|
+
npx @aicopycoders/exodus idea add "It's not low T — it's too high cortisol" --desc "reframe hook" --source gambit
|
|
53
|
+
npx @aicopycoders/exodus idea rm O5 # archive a dud (--hard to delete)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`note` attaches persistent steering that rides along into the Genesis run as a Direction block. `edit` rewrites the concept itself. Keys are stable (`O2`, `G1`, `S4`).
|
|
57
|
+
|
|
58
|
+
### 3. Write — escalate to Genesis
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Write the ones the user picked — one Genesis run per key:
|
|
62
|
+
npx @aicopycoders/exodus idea write O2,G1 --awareness solution-aware
|
|
63
|
+
|
|
64
|
+
# Or capture a reel AND write it immediately (bank-and-write in one shot):
|
|
65
|
+
npx @aicopycoders/exodus idea organic "https://www.instagram.com/reel/abc" --write --awareness problem-aware
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`write` is fire-and-forget — it dispatches a brief-mode Genesis run per key (Mario + Infeed, default 1 pass = 2 variants; `--passes`/`--variants` scale it) and links each idea to its run. **Awareness is your call** (state your read; default `problem-aware`). The idea flips to `writing`, then `written` with a Doc link once the run lands.
|
|
69
|
+
|
|
70
|
+
### 4. Report
|
|
71
|
+
|
|
72
|
+
Per the **Default Post-Run Reporting** rule in `exodus-strategist`: for a capture, confirm what's being pulled and where it'll show up (`idea list`). For a write, surface the dispatched run(s) and that status flips to `written` with a Doc link — then propose a next move (curate the rest, write a second batch, or pair a strong result with the `exodus-image` skill).
|
|
73
|
+
|
|
74
|
+
## Notes
|
|
75
|
+
|
|
76
|
+
- **Banked ideas are brand-agnostic and reusable** — the same idea can be written for different awareness levels or re-run later. Don't re-capture a reel you've already banked; `idea list --source organic` first.
|
|
77
|
+
- **Reel capture reuses the same transcription as the `exodus-genesis` skill's `--reel` path** — both go reel → transcribe → organic idea → Genesis writer (the standard writer, nothing custom).
|
|
78
|
+
- A reel write models the reel's *angle*; the Genesis writers apply the brand's primer, hook bank, and steering, so the output is on-brand without the idea itself being brand-specific.
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: exodus-image
|
|
3
|
+
description: The front door for making static image ads with Exodus — and the skill that WALKS THE USER THROUGH the setup instead of guessing. When the user hands over one or more finished ads and wants statics, it presents clean menus (which ads, which engines, aspect, count, steering, template formats), confirms a final render count, and fires nothing until the user says go. Only invoke when the user has explicitly invoked Exodus: they said "exodus" in the request ("exodus, turn this copy into images", "exodus, make me some statics", "exodus, render this ad"), named this skill or /exodus-image, ran an `npx exodus` command, or the `exodus` hub skill routed here — then use it FIRST when the user wants Exodus images and hasn't already nailed down every detail. Never claim generic image requests ("make images", "I need visuals for this ad") — in shared folders those may belong to the user's other tools; if the user did not say exodus, this skill is not for them. For meme formats specifically, use `exodus-meme`. Do not jump straight to running a render — the whole point of this skill is to ask first.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Image — The Guided Static-Image Flow
|
|
7
|
+
|
|
8
|
+
This skill turns "here are some ads, make me images" into a short, menu-driven
|
|
9
|
+
setup, then fires the right render runs. The failure it exists to kill is the
|
|
10
|
+
old behavior: reading one line, guessing an engine, skipping the steering
|
|
11
|
+
question, and firing a batch the user never got to shape. **You ask first. You
|
|
12
|
+
fire nothing until the user has confirmed the full spec — including steering.**
|
|
13
|
+
|
|
14
|
+
The work runs through two base commands underneath you:
|
|
15
|
+
|
|
16
|
+
- **`exodus image`** — engine-direct renders from copy (`native`, `copy-derived`).
|
|
17
|
+
- **`exodus template run`** — spreads copy across structured ad-type formats
|
|
18
|
+
(testimonial, hero, UGC, infographic, +29). This is the command that exposes
|
|
19
|
+
manual format picking, per-format counts, and the realism enhancer.
|
|
20
|
+
|
|
21
|
+
You compose those commands *after* the user has answered the menus — not before.
|
|
22
|
+
|
|
23
|
+
## How to ask: menus, not walls of text
|
|
24
|
+
|
|
25
|
+
Use the **AskUserQuestion** tool for every choice. That renders a clean picker
|
|
26
|
+
the user can click through — which is exactly what makes this feel guided
|
|
27
|
+
instead of like a wall of text they have to read and reply to in prose. Two
|
|
28
|
+
practical limits to design around:
|
|
29
|
+
|
|
30
|
+
- **Max 4 options per question, max 4 questions per call.** When a list is
|
|
31
|
+
longer (the 33 formats, or more than 4 ads), don't dump it as prose — group it
|
|
32
|
+
into buckets, or offer "all / a subset" and collect the subset as a follow-up.
|
|
33
|
+
- Every question auto-includes an **"Other"** free-text choice, so users can
|
|
34
|
+
always type their own answer (a custom count, their own steering line, a
|
|
35
|
+
specific format slug). Lean on that instead of trying to enumerate everything.
|
|
36
|
+
|
|
37
|
+
## Be adaptive — start where the user already is
|
|
38
|
+
|
|
39
|
+
Read the request before asking anything. Whatever the user already specified,
|
|
40
|
+
**pre-fill it and skip that question.** Only ask for what's genuinely still open.
|
|
41
|
+
|
|
42
|
+
- "Here's a bunch of ads, make me some images" → wide open. Walk the full flow.
|
|
43
|
+
- "Make me native ads from these" → engine is decided. Skip the engine question;
|
|
44
|
+
confirm the ads, aspect, count, and steering, then go.
|
|
45
|
+
- "10 copy-derived statics of this ad, 1:1" → almost everything is set. You still
|
|
46
|
+
owe them the steering question (see below), then confirm and fire.
|
|
47
|
+
- "Just make a dramatic woman-in-red image" — no copy, a pure visual direction →
|
|
48
|
+
this is the light path. Run native straight from the direction (steering *is*
|
|
49
|
+
the brief), no menu needed:
|
|
50
|
+
`npx @aicopycoders/exodus image --type native --steer "<direction>"`.
|
|
51
|
+
|
|
52
|
+
The rule of thumb: the menus exist to capture decisions the user hasn't made
|
|
53
|
+
yet. Don't re-ask what they've already told you, and don't make a one-off
|
|
54
|
+
visual-direction render sit through a four-wave setup.
|
|
55
|
+
|
|
56
|
+
## Steering is always on the table
|
|
57
|
+
|
|
58
|
+
Whenever a Native engine (Native or Copy-Derived) is in the run, **always ask
|
|
59
|
+
the steering question.** This is the step that used to get skipped, and it's the
|
|
60
|
+
single biggest lever the user has over how the images come out — a direction
|
|
61
|
+
that every image leans into ("make it aggressive and intense", "moody, clinical",
|
|
62
|
+
"nasty toenail fungus, unfiltered"). Never decide steering for them and never
|
|
63
|
+
quietly skip it. Steering applies to the Native engines; Template gets its own
|
|
64
|
+
configuration (formats + realism) instead.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## The flow
|
|
69
|
+
|
|
70
|
+
Think of it as waves. Collapse or skip any wave whose answers the user already
|
|
71
|
+
gave; the order is the spine, not a script to read aloud.
|
|
72
|
+
|
|
73
|
+
### Wave 0 — Read the ads, set the frame
|
|
74
|
+
|
|
75
|
+
If the user dropped ad copy, parse it into a numbered list and give each ad a
|
|
76
|
+
2–4 word descriptor so the menus are legible — e.g. "Ad #1 — wife/relational",
|
|
77
|
+
"Ad #2 — free-T science". State a one-line read and that nothing fires until they
|
|
78
|
+
confirm. Stage long copy to temp files if you need to (e.g. `/tmp/exodus-ad1.txt`)
|
|
79
|
+
so the commands stay clean.
|
|
80
|
+
|
|
81
|
+
### Wave 1 — The basics (one AskUserQuestion call)
|
|
82
|
+
|
|
83
|
+
Ask only the still-open ones of these:
|
|
84
|
+
|
|
85
|
+
- **Which ads?** Default option "All N ads" (recommended), plus "a subset" → let
|
|
86
|
+
them name which in Other. (Don't try to list more than ~3 ads as individual
|
|
87
|
+
options — the 4-option cap will truncate them; all-or-subset scales.)
|
|
88
|
+
- **Which engines?** multiSelect — **Native** · **Copy-Derived** · **Template**.
|
|
89
|
+
(Native = a straight render of the ad; Copy-Derived = variations worked off the
|
|
90
|
+
copy; Template = a spread across ad-type formats.)
|
|
91
|
+
- **Aspect ratio(s)?** **1:1** (feed) · **4:5** · **9:16**. Note in the option
|
|
92
|
+
text that Template only supports 1:1 and 9:16, so if they pick 4:5 it applies to
|
|
93
|
+
the Native engines only.
|
|
94
|
+
- **How many per Native engine** (per ad, per aspect)? e.g. **4** (test batch) ·
|
|
95
|
+
**10** · Other. Only ask if a Native engine is selected.
|
|
96
|
+
|
|
97
|
+
### Wave 2 — Configuration (branch on the engines chosen)
|
|
98
|
+
|
|
99
|
+
- If **Native and/or Copy-Derived** is in the run → ask **steering** (always):
|
|
100
|
+
how do they want to provide it? Options: **one direction for all** · **per-ad
|
|
101
|
+
steering** (you'll menu each ad next) · **none**. The words are theirs — if they
|
|
102
|
+
pick "one direction" or "per-ad", collect the actual text in Other or in Wave 3.
|
|
103
|
+
- If **Template** is in the run → ask **mode** (**Auto** = you spread the formats,
|
|
104
|
+
they give a total count per ad · **Manual** = they pick the formats and the
|
|
105
|
+
count per format), and the **realism enhancer** (**On** pushes photoreal output ·
|
|
106
|
+
**Off**). In Auto, the count question means "total images per ad"; in Manual it
|
|
107
|
+
means "per format" — say which in the option text so it isn't ambiguous.
|
|
108
|
+
|
|
109
|
+
### Wave 3 — Per-ad steering (only if they chose "per-ad")
|
|
110
|
+
|
|
111
|
+
One AskUserQuestion question per ad (batch into multiple calls if more than 4
|
|
112
|
+
ads). For each ad, read it and offer **2–3 suggested steering directions you
|
|
113
|
+
derive from that ad's angle** plus Other so they can type their own. You're a
|
|
114
|
+
strategist here — propose real angles ("lean into the relational stakes",
|
|
115
|
+
"clinical, data-forward", "visceral before/after"), don't offer generic filler.
|
|
116
|
+
|
|
117
|
+
### Wave 4 — Template formats (only if Template + Manual)
|
|
118
|
+
|
|
119
|
+
Present the 33 formats as a **menu grouped into purpose buckets**, never as a
|
|
120
|
+
prose dump. Offer these top-level choices first:
|
|
121
|
+
|
|
122
|
+
- **Smart pick (recommended)** — you choose the high-converting DR set that fits
|
|
123
|
+
these ads (e.g. testimonial · founder-note · before-after · comparison ·
|
|
124
|
+
scientific · statistics · cost-of-inaction · problem-solution). Fastest path,
|
|
125
|
+
and usually the right one.
|
|
126
|
+
- **Pick categories** — multiSelect over the 8 buckets below.
|
|
127
|
+
- **Specific formats** — they name slugs in Other.
|
|
128
|
+
- **All 33** — the full spread (watch the cap; see Wave 5).
|
|
129
|
+
|
|
130
|
+
The 8 buckets (slugs the `--quantities` flag expects):
|
|
131
|
+
|
|
132
|
+
| Bucket | Formats |
|
|
133
|
+
|---|---|
|
|
134
|
+
| Social proof | testimonial · multi-testimonial · ugc · comment · happy-avatar |
|
|
135
|
+
| Authority / story | founder-note · handwritten · holding-sign · writing-on-body |
|
|
136
|
+
| News | native-news · breaking-news · screenshot |
|
|
137
|
+
| Data / science | scientific · statistics · infographic · comparison · before-after |
|
|
138
|
+
| Listicle / steps | step-by-step · carousel · quiz-interactive · post-it-notes |
|
|
139
|
+
| Problem framing | problem-solution · cost-of-inaction |
|
|
140
|
+
| Product | product-breakdown · hero · receipt |
|
|
141
|
+
| Bold / graphic | bold · headline · meme · collage · lofi · animation · sale-promotional-offer |
|
|
142
|
+
|
|
143
|
+
(For the full named list, `npx @aicopycoders/exodus template ad-types` prints all 33.)
|
|
144
|
+
|
|
145
|
+
### Wave 5 — Confirm the math, then fire
|
|
146
|
+
|
|
147
|
+
Before running anything, show a compact **render-count summary** so the user sees
|
|
148
|
+
exactly what they're about to get:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
Engine Per ad × N ads Total
|
|
152
|
+
Native (steered) 10 4 40
|
|
153
|
+
Copy-Derived 10 4 40
|
|
154
|
+
Template (8 fmt×2) 16 4 64
|
|
155
|
+
─────────
|
|
156
|
+
144 images
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**The 50-image cap:** a single Template run tops out at 50 images. If the manual
|
|
160
|
+
counts or auto target for an ad would exceed 50, say so plainly and either trim
|
|
161
|
+
or split across runs — don't let it fail silently at the backend. Auto mode also
|
|
162
|
+
caps at 50 per run.
|
|
163
|
+
|
|
164
|
+
Then wait for a clear "go" and fire the commands.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Building the commands
|
|
169
|
+
|
|
170
|
+
Compose these only after the confirm. Use `npx @aicopycoders/exodus`.
|
|
171
|
+
|
|
172
|
+
**Native / Copy-Derived** — one invocation per selected ad (the single `--ad`
|
|
173
|
+
slot is why per-ad steering works), repeated per aspect:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
npx @aicopycoders/exodus image --type native --ad "<ad copy>" --variations 10 --aspect 1:1 --steer "<direction>"
|
|
177
|
+
npx @aicopycoders/exodus image --type copy-derived --ad "<ad copy>" --variations 10 --aspect 1:1 --steer "<direction>"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Flags: `--type native|copy-derived`, `--ad "<copy>"`, `--variations N`,
|
|
181
|
+
`--aspect 1:1|4:5|9:16`, `--steer "<direction>"` (drop `--steer` if they chose
|
|
182
|
+
"none"), `--name "<label>"` (optional).
|
|
183
|
+
|
|
184
|
+
**Template** — drive `exodus template run` (not `image --type template`), because
|
|
185
|
+
it's the path that exposes mode, per-format counts, and realism. One run per ad,
|
|
186
|
+
or pass a numbered list of ads in one `--input`:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Manual: pick formats + per-format counts
|
|
190
|
+
npx @aicopycoders/exodus template run --input "<ad copy>" --mode manual \
|
|
191
|
+
--quantities "testimonial:2,founder-note:2,before-after:2,comparison:2" \
|
|
192
|
+
--aspect 1:1 --realism realistic
|
|
193
|
+
|
|
194
|
+
# Auto: you spread formats, --requested-count is the total per ad
|
|
195
|
+
npx @aicopycoders/exodus template run --input "<ad copy>" --mode auto --requested-count 16 --aspect 1:1
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Flags: `--input "<copy or numbered list>"`, `--mode auto|manual`,
|
|
199
|
+
`--quantities "slug:N,slug:N"` (manual), `--requested-count N` (auto),
|
|
200
|
+
`--aspect 1:1|9:16`, `--realism off|realistic`. Slugs must come from the 33
|
|
201
|
+
above; `--quantities` rejects unknown ones.
|
|
202
|
+
|
|
203
|
+
During long batches, surface progress as runs kick off rather than going silent.
|
|
204
|
+
|
|
205
|
+
## Report
|
|
206
|
+
|
|
207
|
+
When the runs are enqueued, the CLI prints a dashboard URL and runId per run.
|
|
208
|
+
Report that plus a 1–2 line take, then stop — the kickoff confirms the run
|
|
209
|
+
*started*, not that renders are done. Native/Copy-Derived poll with
|
|
210
|
+
`npx @aicopycoders/exodus creative status --id <runId>`; Template progress shows live on the
|
|
211
|
+
dashboard (no CLI status endpoint). Everything lands in the creative-suite
|
|
212
|
+
library.
|
|
213
|
+
|
|
214
|
+
## What this skill does NOT do
|
|
215
|
+
|
|
216
|
+
- It doesn't fire before the user confirms the spec. Guessing the run and
|
|
217
|
+
skipping steering is the exact failure this skill replaces.
|
|
218
|
+
- It doesn't mine image concepts from a bare idea with no copy. If there's no
|
|
219
|
+
copy and no clear visual direction, route to the `exodus-write` skill to produce
|
|
220
|
+
copy first, then come back here.
|
|
221
|
+
- It doesn't write ad copy. Native/Copy-Derived/Template all render *from* copy
|
|
222
|
+
you already have (or a pure visual direction for the light native path).
|
|
223
|
+
- It is not for memes. Meme ads ride familiar meme formats — use the
|
|
224
|
+
`exodus-meme` skill for those.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: exodus-meme
|
|
3
|
+
description: Generate meme-style ad creative for the active brand — recommends meme formats for a brief (classic Imgflip templates + AI-image formats), then renders the whole batch server-side in ONE run; finished memes land in the dashboard's creative-suite library. Use it for both modes of meme work — "just make me memes" (auto-pick a strong diverse set and fire) and "walk me through it" (present the recommended formats by description and let the user choose). Only invoke when the user has explicitly invoked Exodus — they said "exodus" in the request (e.g. "exodus, make me meme ads", "exodus meme this offer"), named this skill or /exodus-meme, ran an `npx @aicopycoders/exodus meme` command, or the `exodus` hub skill routed here. Never claim generic meme requests ("make me a meme", "meme this", "imgflip meme") without exodus context — in shared folders those may belong to the user's other tools.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```operator-guide
|
|
7
|
+
Subcommands (three; the batch renders server-side via Trigger.dev):
|
|
8
|
+
exodus meme recommend --brief "<text>" [--avatar "<text>"]
|
|
9
|
+
exodus meme run --brief "<text>" --formats '<json>' [--formats-file <path>] [--avatar "<text>"] [--name "<label>"]
|
|
10
|
+
exodus meme regenerate --brief "<text>" --layer 1 --template-id <id> --template-name "<name>" --boxes <N> [--id <runId>]
|
|
11
|
+
exodus meme regenerate --brief "<text>" --layer 2|3 --format <formatId> [--hint "<text>"] [--id <runId>]
|
|
12
|
+
|
|
13
|
+
Flow:
|
|
14
|
+
1. recommend → { recommendations: [...] } — 15 picks (5 per layer), each with
|
|
15
|
+
name, layer, reasoning, ad_angle. Layer 1 = classic Imgflip templates;
|
|
16
|
+
layers 2/3 = AI-image formats.
|
|
17
|
+
2. run → pass the picked recommendation objects straight into --formats (JSON
|
|
18
|
+
array, 1–50; the CLI normalizes them). Returns { runId }. One enqueue —
|
|
19
|
+
closing the session does NOT kill the batch.
|
|
20
|
+
3. Poll: exodus status --id <runId> --type creative
|
|
21
|
+
Terminal statuses: complete | partial-error | error (also failed/cancelled).
|
|
22
|
+
4. regenerate → re-render one miss, synchronously (returns image_url).
|
|
23
|
+
|
|
24
|
+
Keys (strict BYOK, refused server-side before anything starts):
|
|
25
|
+
layer 1 needs the member's Imgflip login · layers 2/3 need their Kie.ai key ·
|
|
26
|
+
captions always need their LLM key. `npx @aicopycoders/exodus doctor` checks all three.
|
|
27
|
+
Returns: runId + dashboard URL /creative-suite/runs/<runId> (the visual review surface).
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
# Meme — Meme Ad Generator (Max's pipeline)
|
|
31
|
+
|
|
32
|
+
Meme ads ride a format the audience already recognizes — a familiar template or
|
|
33
|
+
a relatable AI-generated scene — and land the brand's point inside it. You drive
|
|
34
|
+
the pipeline in three moves: get format recommendations for the brief, pick the
|
|
35
|
+
formats worth rendering, and fire **one batched run**. The server orchestrates
|
|
36
|
+
everything from there (captions + renders via Trigger.dev), so there is no
|
|
37
|
+
per-meme captioning or rendering for you to compose, and a closed laptop no
|
|
38
|
+
longer kills a half-finished batch.
|
|
39
|
+
|
|
40
|
+
One thing to hold onto: **this is a no-visuals context.** The dashboard shows
|
|
41
|
+
thumbnails; you can't. Your job is to be the user's eyes — describe formats by
|
|
42
|
+
name, layer, and the `reasoning`/`ad_angle` the recommend call returns, and
|
|
43
|
+
point at the dashboard URL when it's time to actually look at rendered memes.
|
|
44
|
+
Never pretend to show an image.
|
|
45
|
+
|
|
46
|
+
## Two paths — read the request, pick the right one
|
|
47
|
+
|
|
48
|
+
**Quick batch** — "exodus, meme this offer", "make me some memes for <brief>".
|
|
49
|
+
The user wants memes, not a meeting. Run `recommend`, pick a strong diverse set
|
|
50
|
+
yourself (~6–10: mix classic templates and AI formats, apply the strategist
|
|
51
|
+
bars below), fire `run`, and report. Tell the user which formats you picked and
|
|
52
|
+
why in one or two lines — they can steer the next batch.
|
|
53
|
+
|
|
54
|
+
**Guided** — "walk me through it", "what formats are there?", or any sign the
|
|
55
|
+
user wants control over the picks. Run `recommend`, then present the
|
|
56
|
+
recommendations with **AskUserQuestion** (max 4 options per question — group
|
|
57
|
+
into the three layers or offer "my picks / classics only / AI only / let me
|
|
58
|
+
choose" buckets rather than dumping 15 raw entries). Describe each option by
|
|
59
|
+
its name + one-line reasoning, e.g. "Group Chat (AI) — lands the claim as a
|
|
60
|
+
screenshot conversation, good for skeptical audiences". Collect the picks,
|
|
61
|
+
confirm the count, then fire `run`.
|
|
62
|
+
|
|
63
|
+
In both paths, picking is where the strategist work happens:
|
|
64
|
+
|
|
65
|
+
- **Relatable beats clever.** A meme the audience has to decode is a scroll-past.
|
|
66
|
+
- **The format should fit the audience's actual feed.** A 55+ supplement buyer
|
|
67
|
+
and a 22-year-old skincare buyer do not share meme literacy.
|
|
68
|
+
- **Diversity over three flavors of one joke.** Spread across layers and angles;
|
|
69
|
+
a batch of near-duplicates wastes renders.
|
|
70
|
+
|
|
71
|
+
## Workflow
|
|
72
|
+
|
|
73
|
+
### 1. Recommend
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx @aicopycoders/exodus meme recommend --brief "<the offer / angle, in the brand's terms>"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Returns `{ recommendations: [...] }` — 15 picks, 5 per layer, each carrying
|
|
80
|
+
`format_id`, `layer`, `name`, `reasoning`, and `ad_angle` (layer-1 entries also
|
|
81
|
+
carry `imgflip_template_id` + `imgflip_box_count`). Layer 1 = classic Imgflip
|
|
82
|
+
templates; layers 2/3 = AI-image formats. Optional `--avatar "<text>"`
|
|
83
|
+
describes a recurring character/persona to thread through the batch.
|
|
84
|
+
|
|
85
|
+
Keep the JSON in your context — the picked entries go straight into `run`, and
|
|
86
|
+
the per-format fields are what `regenerate` needs later. Don't paste the raw
|
|
87
|
+
JSON at the user.
|
|
88
|
+
|
|
89
|
+
If the user asks for a specific template by name ("do a Drake one"), put that
|
|
90
|
+
in the brief — recommend reads it and will surface the template if it fits.
|
|
91
|
+
There's no separate catalog browse; recommend **is** the selection surface.
|
|
92
|
+
|
|
93
|
+
### 2. Run the batch
|
|
94
|
+
|
|
95
|
+
Pass the picked recommendation objects straight in — the CLI maps them onto the
|
|
96
|
+
run payload itself (don't restructure them):
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npx @aicopycoders/exodus meme run --brief "<same brief>" --formats '[<picked recommendation objects>]'
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
For bigger selections, write the array to a file and use `--formats-file
|
|
103
|
+
/tmp/meme-formats.json` — long JSON in shell quoting breaks easily. 1–50
|
|
104
|
+
formats per run; `--name "<label>"` labels the run; pass the same `--avatar`
|
|
105
|
+
you gave recommend, if any.
|
|
106
|
+
|
|
107
|
+
Returns `runId` + the dashboard URL. The whole batch renders server-side — tell
|
|
108
|
+
the user this explicitly, because it changes their behavior: they can close the
|
|
109
|
+
session and the run finishes anyway.
|
|
110
|
+
|
|
111
|
+
### 3. Poll
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npx @aicopycoders/exodus status --id <runId> --type creative
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Poll roughly every 45 seconds while the user is waiting (or just hand them the
|
|
118
|
+
dashboard URL if they'd rather watch it live). Treat these statuses as
|
|
119
|
+
terminal: `complete`, `partial-error`, `error` — plus `failed`/`cancelled`. The
|
|
120
|
+
status output includes `completedImages / totalImages` and, on failures, an
|
|
121
|
+
`errorMessage` naming what missed.
|
|
122
|
+
|
|
123
|
+
### 4. Regenerate the misses
|
|
124
|
+
|
|
125
|
+
`partial-error` means some renders failed and the rest landed. Name the misses
|
|
126
|
+
to the user and offer to re-render them — the format fields come from the
|
|
127
|
+
recommend output you're still holding:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# Classic (layer 1) miss:
|
|
131
|
+
npx @aicopycoders/exodus meme regenerate --brief "<brief>" --layer 1 \
|
|
132
|
+
--template-id <imgflip_template_id> --template-name "<name>" --boxes <imgflip_box_count> --id <runId>
|
|
133
|
+
|
|
134
|
+
# AI (layer 2/3) miss — --hint steers the re-roll:
|
|
135
|
+
npx @aicopycoders/exodus meme regenerate --brief "<brief>" --layer 2 --format <format_id> \
|
|
136
|
+
--hint "make the punchline land the product" --id <runId>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Regenerate is synchronous (caption + render server-side) and
|
|
140
|
+
returns the new `image_url` directly. Passing `--id <runId>` attaches the fresh
|
|
141
|
+
meme to the run so it shows up in the same library entry.
|
|
142
|
+
|
|
143
|
+
### 5. Report
|
|
144
|
+
|
|
145
|
+
Surface the dashboard URL (`/creative-suite/runs/<runId>`) + a 2-line
|
|
146
|
+
strategist take ("the classics carry the relatability, the Group Chat one is
|
|
147
|
+
the sleeper — review them in the library"). The dashboard is where the user
|
|
148
|
+
actually evaluates memes visually; your report gets them there with a point of
|
|
149
|
+
view, not a data dump. Don't paste recommend JSON, prompts, or caption
|
|
150
|
+
internals into chat.
|
|
151
|
+
|
|
152
|
+
## Failure Handling
|
|
153
|
+
|
|
154
|
+
- **400 "Missing required key(s)"** — the strict-BYOK preflight refused before
|
|
155
|
+
anything started. The message names the missing key: Imgflip login (classic
|
|
156
|
+
memes), Kie.ai key (AI memes), or an LLM key (captions, always). Run
|
|
157
|
+
`npx @aicopycoders/exodus doctor` to confirm, then send the user to **Settings → Keys** on
|
|
158
|
+
the dashboard. A batch with no layer-1 picks doesn't need Imgflip at all — if
|
|
159
|
+
the user lacks an Imgflip login, an AI-only batch is a legitimate fallback.
|
|
160
|
+
- **`partial-error`** — not a failed run; some memes landed. Report the
|
|
161
|
+
successes, name the misses from `errorMessage`, regenerate per step 4.
|
|
162
|
+
- **`error` / `failed`** — the batch died; the status `errorMessage` says why.
|
|
163
|
+
Fix the cause (usually a key issue mid-run) before re-firing, don't just retry.
|
|
164
|
+
- **No progress for 15+ minutes** — presume the run dead and say so rather than
|
|
165
|
+
polling forever; the dashboard run page shows the same stall.
|
|
166
|
+
- **Bearer/auth failure** — run `npx @aicopycoders/exodus doctor`; confirm `EXODUS_API_KEY`.
|
|
167
|
+
|
|
168
|
+
## What this skill does NOT do
|
|
169
|
+
|
|
170
|
+
- It doesn't compose per-meme caption/render steps — that surface is gone. One
|
|
171
|
+
`run` call is the whole batch.
|
|
172
|
+
- It doesn't browse a full format catalog. Recommend returns the working set;
|
|
173
|
+
steer it through the brief.
|
|
174
|
+
- It doesn't write ad copy — the brief is an offer/angle, not finished copy. For
|
|
175
|
+
copy, that's the `exodus-write` skill; for non-meme statics, `exodus-image`.
|
|
176
|
+
|
|
177
|
+
## Admin
|
|
178
|
+
|
|
179
|
+
- Backend: `/api/meme/{recommend,run,regenerate}` (Bearer-auth). `run` enqueues
|
|
180
|
+
the `meme-batch` Trigger.dev task; meme runs ride `creativeSuiteRuns` with
|
|
181
|
+
engine `meme`, which is why `exodus status --type creative` and
|
|
182
|
+
`exodus browse --agent meme` cover them.
|
|
183
|
+
- Finished runs appear in the creative-suite library alongside other engines.
|