@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.
Files changed (114) hide show
  1. package/assets/references/awareness-framework.md +156 -0
  2. package/assets/references/cast-video.md +165 -0
  3. package/assets/references/copy-blocks.md +138 -0
  4. package/assets/references/creative-strategy.md +990 -0
  5. package/assets/references/editing-rules.md +81 -0
  6. package/assets/references/hook-quality-checklist.md +153 -0
  7. package/assets/references/iterations.md +73 -0
  8. package/assets/references/scrawls.md +483 -0
  9. package/assets/references/segments.md +79 -0
  10. package/assets/skills/exodus/SKILL.md +50 -0
  11. package/assets/skills/exodus-brand/SKILL.md +117 -0
  12. package/assets/skills/exodus-browse/SKILL.md +96 -0
  13. package/assets/skills/exodus-creative/SKILL.md +94 -0
  14. package/assets/skills/exodus-drive/SKILL.md +118 -0
  15. package/assets/skills/exodus-foundation/SKILL.md +170 -0
  16. package/assets/skills/exodus-genesis/SKILL.md +159 -0
  17. package/assets/skills/exodus-idea/SKILL.md +78 -0
  18. package/assets/skills/exodus-image/SKILL.md +224 -0
  19. package/assets/skills/exodus-meme/SKILL.md +183 -0
  20. package/assets/skills/exodus-primer/SKILL.md +145 -0
  21. package/assets/skills/exodus-strategist/SKILL.md +217 -0
  22. package/assets/skills/exodus-swipe/SKILL.md +85 -0
  23. package/assets/skills/exodus-template/SKILL.md +106 -0
  24. package/assets/skills/exodus-write/SKILL.md +157 -0
  25. package/assets/skills/genesis-bots/.env.example +12 -0
  26. package/assets/skills/genesis-bots/README.txt +29 -0
  27. package/assets/skills/genesis-bots/SKILL.md +219 -0
  28. package/assets/skills/genesis-bots/scripts/genesis-stream.mjs +307 -0
  29. package/assets/skills/genesis-bots/scripts/genesis-stream.py +220 -0
  30. package/dist/bin/exodus.d.ts +2 -0
  31. package/dist/bin/exodus.js +177 -0
  32. package/dist/commands/__tests__/genesis.hookgate.test.d.ts +1 -0
  33. package/dist/commands/__tests__/genesis.hookgate.test.js +12 -0
  34. package/dist/commands/brand.d.ts +24 -0
  35. package/dist/commands/brand.js +292 -0
  36. package/dist/commands/browse.d.ts +9 -0
  37. package/dist/commands/browse.js +132 -0
  38. package/dist/commands/creative.d.ts +2 -0
  39. package/dist/commands/creative.js +223 -0
  40. package/dist/commands/doctor.d.ts +21 -0
  41. package/dist/commands/doctor.js +590 -0
  42. package/dist/commands/drive.d.ts +2 -0
  43. package/dist/commands/drive.js +154 -0
  44. package/dist/commands/foundation.d.ts +2 -0
  45. package/dist/commands/foundation.js +468 -0
  46. package/dist/commands/genesis.d.ts +64 -0
  47. package/dist/commands/genesis.js +564 -0
  48. package/dist/commands/idea.d.ts +53 -0
  49. package/dist/commands/idea.js +333 -0
  50. package/dist/commands/image.d.ts +2 -0
  51. package/dist/commands/image.js +249 -0
  52. package/dist/commands/init.d.ts +13 -0
  53. package/dist/commands/init.js +70 -0
  54. package/dist/commands/keys.d.ts +2 -0
  55. package/dist/commands/keys.js +101 -0
  56. package/dist/commands/meme.d.ts +12 -0
  57. package/dist/commands/meme.js +272 -0
  58. package/dist/commands/migrate.d.ts +3 -0
  59. package/dist/commands/migrate.js +158 -0
  60. package/dist/commands/primer.d.ts +2 -0
  61. package/dist/commands/primer.js +540 -0
  62. package/dist/commands/read-doc.d.ts +3 -0
  63. package/dist/commands/read-doc.js +62 -0
  64. package/dist/commands/status.d.ts +6 -0
  65. package/dist/commands/status.js +205 -0
  66. package/dist/commands/swipe.d.ts +2 -0
  67. package/dist/commands/swipe.js +398 -0
  68. package/dist/commands/template.d.ts +2 -0
  69. package/dist/commands/template.js +225 -0
  70. package/dist/commands/whoami.d.ts +2 -0
  71. package/dist/commands/whoami.js +51 -0
  72. package/dist/lib/ad-library-write.d.ts +15 -0
  73. package/dist/lib/ad-library-write.js +67 -0
  74. package/dist/lib/assets.d.ts +3 -0
  75. package/dist/lib/assets.js +23 -0
  76. package/dist/lib/backend-hint.d.ts +2 -0
  77. package/dist/lib/backend-hint.js +22 -0
  78. package/dist/lib/cc-command.d.ts +1 -0
  79. package/dist/lib/cc-command.js +13 -0
  80. package/dist/lib/client.d.ts +23 -0
  81. package/dist/lib/client.js +213 -0
  82. package/dist/lib/format.d.ts +8 -0
  83. package/dist/lib/format.js +172 -0
  84. package/dist/lib/intel-format.d.ts +1 -0
  85. package/dist/lib/intel-format.js +38 -0
  86. package/dist/lib/keys-sync.d.ts +16 -0
  87. package/dist/lib/keys-sync.js +88 -0
  88. package/dist/lib/layout.d.ts +38 -0
  89. package/dist/lib/layout.js +153 -0
  90. package/dist/lib/load-env.d.ts +1 -0
  91. package/dist/lib/load-env.js +47 -0
  92. package/dist/lib/pixar-orchestrator-types.d.ts +54 -0
  93. package/dist/lib/pixar-orchestrator-types.js +1 -0
  94. package/dist/lib/poll.d.ts +14 -0
  95. package/dist/lib/poll.js +32 -0
  96. package/dist/lib/preflight.d.ts +18 -0
  97. package/dist/lib/preflight.js +56 -0
  98. package/dist/lib/prompts.d.ts +9 -0
  99. package/dist/lib/prompts.js +99 -0
  100. package/dist/lib/reel-write.d.ts +14 -0
  101. package/dist/lib/reel-write.js +59 -0
  102. package/dist/lib/release.d.ts +4 -0
  103. package/dist/lib/release.js +81 -0
  104. package/dist/lib/scaffold.d.ts +8 -0
  105. package/dist/lib/scaffold.js +67 -0
  106. package/dist/lib/scout-hydrate.d.ts +1 -0
  107. package/dist/lib/scout-hydrate.js +10 -0
  108. package/dist/lib/state.d.ts +6 -0
  109. package/dist/lib/state.js +49 -0
  110. package/dist/lib/template-constants.d.ts +4 -0
  111. package/dist/lib/template-constants.js +85 -0
  112. package/dist/lib/version.d.ts +1 -0
  113. package/dist/lib/version.js +19 -0
  114. 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.