Motion Graphics Animator

Shorts motion

by timscheuerai · MIT license · ★ 37 on GitHub

Shorts motion cover

Add on-brand motion graphics and retention pattern-interrupts to a talking-head short — cue-anchored stats, step lists, tier boards and lower-thirds, drawn per frame, plus zoom interrupts that plug retention leaks. Use when asked to add…

---
name: shorts-motion
description: Add on-brand motion graphics and retention pattern-interrupts to a talking-head short — cue-anchored stats, step lists, tier boards and lower-thirds, drawn per frame, plus zoom interrupts that plug retention leaks. Use when asked to add motion graphics, animations, overlays, b-roll cards, a tier list, or to improve a video's retention/pacing.
---

# shorts-motion

Stage 4 of shorts-edit. **Scout → Plan → Render → Verify.** Never skip the scout.

The pipeline already composites a **per-frame RGBA sequence** for captions, which means it
is *already a motion-graphics engine*: anything drawable in PIL can be animated at frame
resolution with **no extra ffmpeg input and no extra encode**.

---

## The three rules that make a graphic land

**1. ANCHOR TO THE WORDS, NEVER TO A TIMESTAMP.**

Overview

Stage 4 of shorts-edit. Scout → Plan → Render → Verify. Never skip the scout.

Manual install (npx, ZIP)
Claude Codenpx skills add timscheuerai/content-vault --skill shorts-motion -g -a claude-code
Claude Code (degit)npx degit timscheuerai/content-vault/skills/shorts-motion#main ~/.claude/skills/shorts-motion
Claude.ai / desktopZip the folder and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md10.4 KB
Read SKILL.md here
timscheuerai/main1 file shown
SKILL.md
Show the full text223 lines

shorts-motion

Stage 4 of shorts-edit. Scout → Plan → Render → Verify. Never skip the scout.

The pipeline already composites a per-frame RGBA sequence for captions, which means it is already a motion-graphics engine: anything drawable in PIL can be animated at frame resolution with no extra ffmpeg input and no extra encode.


The three rules that make a graphic land

1. ANCHOR TO THE WORDS, NEVER TO A TIMESTAMP.

Hand-typed times failed catastrophically and invisibly: six of eight graphics were out of sync and one revealed the "F" tier grade 5.7 seconds before he said it. In a tier list the grade IS the punchline. Every frame was individually correct; nothing flagged it.

The plan names a phrase, not a time. resolve_cue() finds when it is spoken and fires the payload — the grade filling, the number landing — exactly on the word.

{ "cue": "definitely f tier", "grade": "F", "label": "Instagram / TikTok" }

2. OVERLAY PANELS, NOT FULL-SCREEN CARDS.

A full-screen card doesn't add a graphic — it removes the presenter, and on a talking-head short the face is what carries it. Panels sit in the lower third; he stays on camera. Full-screen is reserved for a genuine chapter break or a hook.

3. THE MOTION MUST TRACK THE SPEECH.

A card that fades in is a slide. A number that counts up and lands on the word, a list that builds as he names each item, a tier chip that fills the instant he says "S tier" — those feel authored. Everything else feels pasted on.


Scout first — do not invent moments

python $S/motion_scout.py "<clip>"

It surfaces where a graphic would actually earn its place: hard numbers, enumerations, rankings, named tools. On the reference session it found one clip was a tier list (8 verdicts), another a 5-step system with a 0→300 users target, another carrying 14% / 11% / 0.5% reply rates. Content that was invisible to a blind pass.

Copy is editorial, never generated. Auto-deriving it from the transcript produced headlines like "step number five is actually relaunching your saas every two weeks with a launch". A bad graphic is worse than none. A clip with no plan entry simply gets none.

Primitives (motion.py)

kind use for motion
stat a hard number counts up and lands on the word
steps an enumeration rows build one at a time; the live row goes bold + emerald
tier a ranking chips greyed, the called grade fills emerald and pops
label anything else a lower-third chip — the lightest touch
logo naming a product brand mark parks just above the caption band
people real accounts profile cards, follower counts counting up
chips a list of sources small title-only cards landing left to right
leads a lead table LinkedIn rows stream, then the scores land on a second cue
flow a routing decision lanes greyed; each fills, and its wire draws, on its own cue

Everything except stat/table hangs off a y=470 baseline, which stops 29px clear of the caption band. Panels built that way need no caption lift and no caption hide — the captions just keep running. hide_frames had been applied to every mid-frame panel, which cost the Lovable clip 13 of its 73 seconds of captions to a collision the geometry ruled out.

Nested cues — when one panel spans several beats

A graphic that stays up across a long beat (the routing board: tier 1 at 28.0s, tier 2 at 30.1s, tier 3 at 34.3s) cannot stagger its rows off a frame counter — the stagger drifts the moment the speech does, which is the same class of failure as a hand-typed timestamp. Give each row its own cue; resolve_plan() resolves it to _at, in frames relative to the panel's window.

{"kind": "flow", "cue": "hand over all the", "dur": 12.6, "lanes": [
  {"cue": "tier one leads", "badge": "TIER 1", "to": "Sales team", "focal": true},
  {"cue": "tier two",       "badge": "TIER 2", "to": "Sequence", "tiles": ["...linkedin.png"]}
]}

A <name>_cue key on the graphic itself resolves the same way, to _at_<name>. That is how the lead table's grades wait for "score them against their ICP" instead of firing on the panel's own entrance four seconds earlier.

A primitive's payload is not always 0.7s after its entrance

LEAD/PAYLOAD encode one choreography: the panel arrives, then the number lands on the word. logo and chips have nothing that lands later — the mark appearing IS the payload. verify_motion.py assumed the PAYLOAD model for every kind, so holding a logo to "entrance + 0.7s == the word" pushed its entrance 0.7s ahead of the word. The Lovable mark sat on screen most of a second before he said "Lovable", and every run reported ok.

A verifier that models one primitive's choreography and applies it to all of them certifies the bug. ENTRANCE_IS_PAYLOAD in verify_motion.py is the per-kind offset; multi-lane boards skip the single-payload check and verify each lane's own cue instead.

New primitives must also be added to brand_lint.py's render list. Three shipped outside it once, which meant the one-green rule was enforced on the four oldest renderers and silently not on the newest.

The tier board (tierboard.py)

A different shape: one persistent, cumulative board, not eight panels flashing in and out. The hook shows the finished board with the lane contents blurred (tease the payoff, don't give it), then each channel drops onto its row as he says the grade. The viewer watches it fill in. That is the tier-list format.

It occupies the lower ~40%, so the captions lift to 60% height for exactly those frames rather than being hidden for 100 seconds.

A panel and a caption cannot share a row

Captions sit at 0.78H (y≈499). A stat panel starts at y=446, a steps panel at y=422. So a caption lands inside the panel, and white type on a white surface is invisible at full opacity.

The tier board already lifted the captions to 0.60H. Nothing lifted them for the other primitives, and it shipped — because a caption over a half-faded panel is still legible, so it looks fine in exactly the frames you happen to spot-check.

Any frame carrying a stat or steps panel lifts the captions to 0.60H. label is exempt: its chip sits at 0.86H, ~40px clear of the caption band.

build.py resolves the plan before caption_frames() and unions those windows into raise_frames. Order matters: the captions have to know about the panels before they draw.

label() accepts a kicker and does not draw it

The chip is one line by design; a kicker row would make it a panel. The argument stays in the signature so every primitive takes the same plan shape — but it is silently dropped, and that silence once cost a whole batch its step numbers. If you want the kicker seen, put it in text: "01 · Build in public".

Brand — do not invent values

From gtm-production/brand/BRAND.md:

surface #ffffff · ink #0a0a0a · muted #71717a · line #e4e4e7 · accent #10b981 (ONE dot, sparingly)
font-sans Helvetica Neue (the same face as the captions) · radius 6/10/14/20
"everything is ink, surface, and line" — no shadows, no gradients.

Retention: the 2026 five-second rule

Any 5-second block with no cut, zoom, text or sound change is a retention leak.

The reference clip failed badly: 97 of 107 seconds (91%) sat in a dead block, the worst a 16.8-second stretch. All the cuts and graphics clustered at beat boundaries, and beats run 11–17s.

Fix: automatic pattern interrupts. plan_chunks() splits long beats into ≤4.8s chunks with alternating framing — a snap change of camera mid-sentence. It is not a cut; the audio runs straight through. 18 interrupts, leak 91% → 0%.

Two things this depends on:

  • Fades only at real cut edges. A 30ms fade at a framing split dips the voice audibly. Verified: 0 discontinuities across all 18 internal joins.
  • Use ceil for the chunk count. Floor-plus-fudge left 5.7s chunks — still a leak.

A 3px drawbox progress bar is available (--progress) but is off by default — it reads as UI chrome bolted onto the frame. Cheap is not the same as good.


THE RENDERING TRAP: PIL alpha does not composite

ImageDraw with a partial-alpha fill OVERWRITES pixels. A chip fading in therefore punches a transparent hole straight through the white panel beneath it, and the video shows through — the selected tier chip rendered as a black box instead of a green one.

Draw everything at full opacity on its own layer, then fade the layer. Never draw with a variable alpha. To animate a colour, LERP the colour — not the alpha.

Text behind the subject

The "he's standing in front of the word" look. behind.py. Composite order per frame:

video  ->  big text  ->  the person, cut back out on top  ->  captions + board

Two things make it work:

  1. It stays inside ONE encode. The naive way is a second pass (render, re-read, segment, re-encode) — and a second encode measurably softens the image. Instead the person is baked into the same per-frame RGBA overlay the captions use, cut from the raw source frames that ffmpeg is already decoding. The cut-out lands on top of itself: no seam.
  2. Any chunk carrying a behind-text is forced to wide. A zoomed chunk is scaled by zoompan inside ffmpeg, and re-deriving that transform in PIL would never match pixel-for-pixel — you would get a soft double-edge around him.

Layer order is the whole trick. Compositing the person LAST put his shoulder on top of the tier board and clipped the lanes. The person goes UNDER the UI: word, then him, then captions and board.

Segmentation: rembg (u2netp), ~0.2s/frame. Use it on 2-4 hero moments, not the clip.

"behind": [{"cue": "for sure s tier", "text": "S TIER", "dur": 1.9}]

Verify

python $S/verify_motion.py "<clip>"

Every graphic fires within 0.2s of its cue; no typo'd cue silently dropping a graphic; no overlapping panels; verdicts in ascending order.

1---
2name: shorts-motion
3description: Add on-brand motion graphics and retention pattern-interrupts to a talking-head short — cue-anchored stats, step lists, tier boards and lower-thirds, drawn per frame, plus zoom interrupts that plug retention leaks. Use when asked to add motion graphics, animations, overlays, b-roll cards, a tier list, or to improve a video's retention/pacing.
4---
5 
6# shorts-motion
7 
8Stage 4 of shorts-edit. **Scout → Plan → Render → Verify.** Never skip the scout.
9 
10The pipeline already composites a **per-frame RGBA sequence** for captions, which means it
11is *already a motion-graphics engine*: anything drawable in PIL can be animated at frame
12resolution with **no extra ffmpeg input and no extra encode**.
13 
14---
15 
16## The three rules that make a graphic land
17 
18**1. ANCHOR TO THE WORDS, NEVER TO A TIMESTAMP.**
19 
20Hand-typed times failed catastrophically and invisibly: six of eight graphics were out of
21sync and one revealed the **"F" tier grade 5.7 seconds before he said it**. In a tier list
22the grade IS the punchline. Every frame was individually correct; nothing flagged it.
23 
24The plan names a **phrase**, not a time. `resolve_cue()` finds when it is spoken and fires
25the payload — the grade filling, the number landing — exactly on the word.
26 
27```json
28{ "cue": "definitely f tier", "grade": "F", "label": "Instagram / TikTok" }
29```
30 
31**2. OVERLAY PANELS, NOT FULL-SCREEN CARDS.**
32 
33A full-screen card doesn't add a graphic — it *removes the presenter*, and on a talking-head
34short the face is what carries it. Panels sit in the lower third; he stays on camera.
35Full-screen is reserved for a genuine chapter break or a hook.
36 
37**3. THE MOTION MUST TRACK THE SPEECH.**
38 
39A card that fades in is a slide. A number that counts up and *lands* on the word, a list
40that builds as he names each item, a tier chip that fills the instant he says "S tier" —
41those feel authored. Everything else feels pasted on.
42 
43---
44 
45## Scout first — do not invent moments
46 
47```bash
48python $S/motion_scout.py "<clip>"
49```
50 
51It surfaces where a graphic would actually *earn* its place: hard numbers, enumerations,
52rankings, named tools. On the reference session it found one clip was a **tier list**
53(8 verdicts), another a **5-step system with a 0→300 users target**, another carrying
54**14% / 11% / 0.5% reply rates**. Content that was invisible to a blind pass.
55 
56**Copy is editorial, never generated.** Auto-deriving it from the transcript produced
57headlines like *"step number five is actually relaunching your saas every two weeks with a
58launch"*. A bad graphic is worse than none. A clip with no plan entry simply gets none.
59 
60## Primitives (`motion.py`)
61 
62| kind | use for | motion |
63|---|---|---|
64| `stat` | a hard number | counts up and lands on the word |
65| `steps` | an enumeration | rows build one at a time; the live row goes bold + emerald |
66| `tier` | a ranking | chips greyed, the called grade fills emerald and pops |
67| `label` | anything else | a lower-third chip — the lightest touch |
68| `logo` | naming a product | brand mark parks just above the caption band |
69| `people` | real accounts | profile cards, follower counts counting up |
70| `chips` | a list of sources | small title-only cards landing left to right |
71| `leads` | a lead table | LinkedIn rows stream, then the scores land on a second cue |
72| `flow` | a routing decision | lanes greyed; each fills, and its wire draws, on its own cue |
73 
74Everything except `stat`/`table` hangs off a **y=470 baseline**, which stops 29px clear of
75the caption band. Panels built that way need no caption lift and no caption hide — the
76captions just keep running. `hide_frames` had been applied to every mid-frame panel, which
77cost the Lovable clip 13 of its 73 seconds of captions to a collision the geometry ruled
78out.
79 
80## Nested cues — when one panel spans several beats
81 
82A graphic that stays up across a long beat (the routing board: tier 1 at 28.0s, tier 2 at
8330.1s, tier 3 at 34.3s) cannot stagger its rows off a frame counter — the stagger drifts
84the moment the speech does, which is the same class of failure as a hand-typed timestamp.
85Give each row its own `cue`; `resolve_plan()` resolves it to `_at`, in frames relative to
86the panel's window.
87 
88```json
89{"kind": "flow", "cue": "hand over all the", "dur": 12.6, "lanes": [
90 {"cue": "tier one leads", "badge": "TIER 1", "to": "Sales team", "focal": true},
91 {"cue": "tier two", "badge": "TIER 2", "to": "Sequence", "tiles": ["...linkedin.png"]}
92]}
93```
94 
95A `<name>_cue` key on the graphic itself resolves the same way, to `_at_<name>`. That is
96how the lead table's grades wait for "score them against their ICP" instead of firing on
97the panel's own entrance four seconds earlier.
98 
99## A primitive's payload is not always 0.7s after its entrance
100 
101`LEAD`/`PAYLOAD` encode one choreography: the panel arrives, *then* the number lands on
102the word. `logo` and `chips` have nothing that lands later — the mark appearing IS the
103payload. `verify_motion.py` assumed the PAYLOAD model for every kind, so holding a logo to
104"entrance + 0.7s == the word" pushed its *entrance* 0.7s ahead of the word. The Lovable
105mark sat on screen most of a second before he said "Lovable", and every run reported `ok`.
106 
107> A verifier that models one primitive's choreography and applies it to all of them
108> certifies the bug. `ENTRANCE_IS_PAYLOAD` in `verify_motion.py` is the per-kind offset;
109> multi-lane boards skip the single-payload check and verify each lane's own cue instead.
110 
111New primitives must also be added to `brand_lint.py`'s render list. Three shipped outside
112it once, which meant the one-green rule was enforced on the four oldest renderers and
113silently not on the newest.
114 
115## The tier board (`tierboard.py`)
116 
117A different shape: **one persistent, cumulative board**, not eight panels flashing in and
118out. The hook shows the finished board with the lane contents **blurred** (tease the payoff,
119don't give it), then each channel drops onto its row as he says the grade. The viewer
120watches it fill in. That *is* the tier-list format.
121 
122It occupies the lower ~40%, so the captions **lift to 60% height** for exactly those frames
123rather than being hidden for 100 seconds.
124 
125## A panel and a caption cannot share a row
126 
127Captions sit at **0.78H (y≈499)**. A `stat` panel starts at **y=446**, a `steps` panel at
128**y=422**. So a caption lands *inside* the panel, and white type on a white surface is
129invisible at full opacity.
130 
131The tier board already lifted the captions to 0.60H. Nothing lifted them for the other
132primitives, and it shipped — because a caption over a *half-faded* panel is still legible,
133so it looks fine in exactly the frames you happen to spot-check.
134 
135> **Any frame carrying a `stat` or `steps` panel lifts the captions to 0.60H.**
136> `label` is exempt: its chip sits at 0.86H, ~40px clear of the caption band.
137 
138`build.py` resolves the plan **before** `caption_frames()` and unions those windows into
139`raise_frames`. Order matters: the captions have to know about the panels before they draw.
140 
141## `label()` accepts a `kicker` and does not draw it
142 
143The chip is one line by design; a kicker row would make it a panel. The argument stays in
144the signature so every primitive takes the same plan shape — but it is **silently dropped**,
145and that silence once cost a whole batch its step numbers. If you want the kicker seen, put
146it in `text`: `"01 · Build in public"`.
147 
148## Brand — do not invent values
149 
150From `gtm-production/brand/BRAND.md`:
151```
152surface #ffffff · ink #0a0a0a · muted #71717a · line #e4e4e7 · accent #10b981 (ONE dot, sparingly)
153font-sans Helvetica Neue (the same face as the captions) · radius 6/10/14/20
154"everything is ink, surface, and line" — no shadows, no gradients.
155```
156 
157---
158 
159## Retention: the 2026 five-second rule
160 
161> Any 5-second block with no cut, zoom, text or sound change is a **retention leak**.
162 
163The reference clip failed badly: **97 of 107 seconds (91%)** sat in a dead block, the worst a
16416.8-second stretch. All the cuts and graphics clustered at beat boundaries, and beats run
16511–17s.
166 
167**Fix: automatic pattern interrupts.** `plan_chunks()` splits long beats into ≤4.8s chunks
168with alternating framing — a snap change of camera mid-sentence. It is *not* a cut; the
169audio runs straight through. **18 interrupts, leak 91% → 0%.**
170 
171Two things this depends on:
172- **Fades only at real cut edges.** A 30ms fade at a framing split dips the voice audibly.
173 Verified: 0 discontinuities across all 18 internal joins.
174- **Use `ceil` for the chunk count.** Floor-plus-fudge left 5.7s chunks — still a leak.
175 
176A 3px `drawbox` progress bar is available (`--progress`) but is **off by default** — it
177reads as UI chrome bolted onto the frame. Cheap is not the same as good.
178 
179---
180 
181## THE RENDERING TRAP: PIL alpha does not composite
182 
183**`ImageDraw` with a partial-alpha fill OVERWRITES pixels.** A chip fading in therefore
184punches a transparent **hole** straight through the white panel beneath it, and the video
185shows through — the selected tier chip rendered as a **black box** instead of a green one.
186 
187> **Draw everything at full opacity on its own layer, then fade the layer.**
188> Never draw with a variable alpha. To animate a colour, LERP the colour — not the alpha.
189 
190## Text behind the subject
191 
192The "he's standing in front of the word" look. `behind.py`. Composite order per frame:
193 
194 video -> big text -> the person, cut back out on top -> captions + board
195 
196Two things make it work:
197 
1981. **It stays inside ONE encode.** The naive way is a second pass (render, re-read, segment,
199 re-encode) — and a second encode measurably softens the image. Instead the person is baked
200 into the same per-frame RGBA overlay the captions use, cut from the **raw source** frames
201 that ffmpeg is already decoding. The cut-out lands on top of itself: no seam.
2022. **Any chunk carrying a behind-text is forced to `wide`.** A zoomed chunk is scaled by
203 zoompan inside ffmpeg, and re-deriving that transform in PIL would never match
204 pixel-for-pixel — you would get a soft double-edge around him.
205 
206**Layer order is the whole trick.** Compositing the person LAST put his shoulder on top of
207the tier board and clipped the lanes. The person goes UNDER the UI: word, then him, then
208captions and board.
209 
210Segmentation: `rembg` (u2netp), ~0.2s/frame. Use it on **2-4 hero moments**, not the clip.
211 
212```json
213"behind": [{"cue": "for sure s tier", "text": "S TIER", "dur": 1.9}]
214```
215 
216## Verify
217 
218```bash
219python $S/verify_motion.py "<clip>"
220```
221Every graphic fires within 0.2s of its cue; no typo'd cue silently dropping a graphic; no
222overlapping panels; verdicts in ascending order.
223 
View all files on GitHub →

Details

License
MIT
Stars on the repo
★ 37
Checked
Source
timscheuerai/content-vault ↗
Creator
timscheuerai · 15 listings
View creator

Similar skills

See all →
SkillSubscription Lifecycle Managerappeeky/aso-skills · by appeekyWhen the user wants to optimize their subscription business end-to-end — from trial start through renewal, cancellation, and win-back. Use when the user mentions "subscription lifecycle", "trial conversion", "churn", "cancellation", "win-back", "lapsed subscribers", "dunning", "billing retry", "grace period", "renewal rate", "subscriber LTV", or "resubscribe". For paywall design and pricing strategy, see monetization-strategy. For subscription analytics dashboards, see app-analytics.★ 2.2k GitHub starsSkillChurn Prevention Suitecoreyhaines31/marketingskills · by coreyhaines31Tell us about your subscription business and why people quit. Get back a ready-to-use plan to keep more customers and recover failed payments.★ 51.1k GitHub starsAgentRetention Strategy Developerdavila7/claude-code-templates · by davila7Use this agent when you need to assess customer health, develop retention strategies, identify upsell opportunities, or maximize customer lifetime value. Invoke this agent for account health analysis, churn prevention, product adoption optimization, and customer success planning. Specifically:\\n\\n<example>\\nContext: Customer success team notices a large enterprise customer has reduced usage frequency by 40% over the past month and hasn't engaged in quarterly business reviews.\\nuser: "We're concerned about TechCorp's engagement. Usage is down significantly. Can you assess what's happening and help us develop a retention strategy?"\\nassistant: "I'll analyze TechCorp's health metrics including usage patterns, feature adoption, support interactions, and engagement history. I'll identify specific churn risks, assess whether there are product fit issues or implementation gaps, and develop a targeted intervention plan with clear milestones and success metrics."\\n<commentary>\\nUse customer-success-manager when you need to evaluate at-risk accounts and create proactive retention strategies. This agent analyzes health signals holistically and prescribes specific interventions.\\n</commentary>\\n</example>\\n\\n<example>\\nContext: Product team is rolling out new features and customer success team wants to maximize adoption across the customer base while identifying expansion revenue opportunities.\\nuser: "We're launching three new features next month. How do we ensure our customers actually adopt them? And which customers might be willing to upgrade to higher tiers?"\\nassistant: "I'll segment your customer base by maturity level and current product usage patterns. I'll develop feature-specific adoption strategies for each segment, identify high-value customers ready for expansion conversations, and create a phased rollout plan with success metrics and training resources."\\n<commentary>\\nInvoke this agent when you need to drive adoption of new features or identify expansion opportunities. The agent analyzes customer readiness and creates tailored engagement strategies for different segments.\\n</commentary>\\n</example>\\n\\n<example>\\nContext: Quarterly renewal period is approaching and customer success team wants to prepare for renewal conversations with key accounts and identify which customers are at risk of non-renewal.\\nuser: "We have 40 accounts up for renewal in the next 90 days. Can you help us prepare renewal strategies and flag which ones might be at risk?"\\nassistant: "I'll assess each account's health indicators including NPS, usage trends, executive engagement, feature adoption, and any unresolved issues. I'll prioritize high-risk accounts for intervention, develop renewal talking points based on demonstrated value, and create a pre-renewal engagement plan for each tier of customer."\\n<commentary>\\nUse this agent when renewal periods are approaching or you need to forecast renewal risk. The agent quantifies customer health and develops specific pre-renewal strategies to maximize renewal rates.\\n</commentary>\\n</example>\\n\\nDoes not handle individual support tickets or FAQ/help-center content — hand those to customer-support. Does not own pre-sale technical POC/RFP work — hand that to sales-engineer. Does not finalize pricing or discount decisions — route to the account/deal team. Does not review or negotiate contract/legal terms — route to legal-advisor.★ 32.3k GitHub starsSkillCCO Plan Reviewalirezarezvani/claude-skills · by alirezarezvani/cs:cco-review <plan> — Retention-obsessed Chief Customer Officer interrogation of any plan that touches customer retention, segmentation, CS team sizing, or CS team hiring. Use when gross retention is slipping, before approving CSM headcount, or when deciding which customer segments to keep or fire.★ 26.3k GitHub starsSkillChurn Prevention Playbookalirezarezvani/claude-skills · by alirezarezvaniReduce voluntary and involuntary churn through cancel flow design, save offers, exit surveys, and dunning sequences. Use when designing or optimizing a cancel flow, building save offers, setting up dunning emails, or reducing failed-payment churn. Trigger keywords: cancel flow, churn reduction, save offers, dunning, exit survey, payment recovery, win-back, involuntary churn, failed payments, cancel page. NOT for customer health scoring or expansion revenue — use customer-success-manager for that.★ 26.3k GitHub starsSkillCustomer Health Monitoralirezarezvani/claude-skills · by alirezarezvaniMonitors customer health, predicts churn risk, and identifies expansion opportunities using weighted scoring models for SaaS customer success. Use when analyzing customer accounts, reviewing retention metrics, scoring at-risk customers, or when the user mentions churn, customer health scores, upsell opportunities, expansion revenue, retention analysis, or customer analytics. Runs three Python CLI tools to produce deterministic health scores, churn risk tiers, and prioritized expansion recommendations across Enterprise, Mid-Market, and SMB segments.★ 26.3k GitHub stars

More from timscheuerai

SkillLaunch Video Creatortimscheuerai/content-vault · by timscheueraiBuild a 30-60s motion-graphics launch video for a <YOUR_BRAND> product or feature. Remotion 4 React composition + ElevenLabs AI narration + sound effects + background music, beat-anchored timing, brand-aligned design system. Use when asked to "create a launch video", "make a product video", "video for X feature", "launch a new feature", or "/launch-video".★ 37 GitHub starsSkillLinkedIn Voice Copywritertimscheuerai/content-vault · by timscheueraiDraft LinkedIn posts in YOUR voice. Pulls hook frameworks, structural patterns, and CTA shapes from your real top-performing posts (corpus.md), runs the draft through a strict AI-slop blacklist, and outputs a post that reads like you wrote it. Use when asked to "write a linkedin post", "draft a post about X", "linkedin copy", "post idea", or "/linkedin-copywriter".★ 37 GitHub starsSkillLong-Form Draftertimscheuerai/content-vault · by timscheueraiDraft written long-form content (newsletter issue, blog post, Substack issue) in your voice. 800-2000 words, structured intro + body + CTA, paragraph-by-paragraph not list-by-list. Pulls voice from /linkedin-copywriter's corpus (same author, same register · longer arc). Runs the brand-doc skill checklist before output. Logs the row in the Notion Content DB and (for newsletters) drafts a separate punchy subject line. Use when asked to "write a newsletter", "draft a blog post", "long-form X", "Substack issue about Y", "weekly newsletter", or "/long-form". For spoken video scripts (YouTube longs / shorts) use /youtube-script instead · the cadence is fundamentally different.★ 37 GitHub starsSkillMathematical Animation Pipelinetimscheuerai/content-vault · by timscheueraiProduction pipeline for mathematical and technical animations using Manim Community Edition. Creates 3Blue1Brown-style explainer videos, algorithm visualizations, equation derivations, architecture diagrams, and data stories. Use when users request: animated explanations, math animations, concept visualizations, algorithm walkthroughs, technical explainers, 3Blue1Brown style videos, or any programmatic animation with geometric/mathematical content.★ 37 GitHub starsSkillContent Repurposertimscheuerai/content-vault · by timscheueraiTake one master content piece (Notion row, transcript, video, paragraph, URL) and spin off variants across channels. Hub-and-spoke repurposing engine. Reads the source, identifies key insights / hooks / quotable moments, then creates child rows in the Notion Content DB with drafts already written by calling sub-skills (linkedin-copywriter, x-copywriter, lead-magnet-creator, etc.). Use when asked to "repurpose this", "spin off variants", "turn this into LinkedIn + X + ...", "make derivatives of this webinar / video / post", or "/repurpose".★ 37 GitHub starsSkillContent Idea Pipelinetimscheuerai/content-vault · by timscheueraiThe single idea-generation pipeline for marketing content. Three input modes converging on Notion Status=Idea rows. Trend scan (X + LinkedIn creators + topic search) finds what's hot in the world. Performance scan (your own published rows + their engagement metrics) finds what's working for you so you can double down. Customer scan (HUMAN NOTES DB user-interview transcripts) finds the words, pains, and themes from real customer conversations. Hybrid mode runs all three, dedupes, and outputs a balanced backlog. Use when asked to "find content ideas", "what's working", "what's hot", "what are customers saying", "research", "scan trends", "give me ideas for the week", "/researcher", or proactively when the Notion Idea queue is empty.★ 37 GitHub stars