
Six hooks per ad set. Across a book of brands. Every refresh cycle. The hook count piles up fast — and most of them are mediocre on the first pass, so the real number after rewrites is multiples of the initial brief.
I tried doing this in plain ChatGPT for about three months. The output was always the same: generic openers like "Discover the secret to..." or "Are you tired of...". Usable as raw material if I rewrote every line, which defeated the point. So I built a small Claude Code skill that gives me 9 hooks structured by psychological trigger type, from a one-line brief I can write in 15 seconds. It's not the production version I use for paying clients — that one is in a paid pack — but the starter does about 70% of the job and it's free.
This article is the starter skill, copy-pasteable, runnable as written. And a note on what changes when you need the full version.
Why hook prompts go wrong in plain chat
The default "give me 10 hooks for [product]" prompt fails for two reasons.
First, there's no trigger framework. The model has read a million marketing blog posts, so when you ask for hooks, it averages across them. You get blandness — a statistical mean of every hook ever written. The way around this is to tell the model exactly which psychological lever to pull on each hook, and to vary the lever across the batch. Curiosity. Identity. Specificity. The output stops looking averaged.
Second, there's no context discipline. ChatGPT doesn't remember your brand, your audience's awareness level, your offer's mechanism, or what's failed before. Every prompt starts from zero, so the output starts from zero. Claude Code skills fix this — a skill is a markdown file the model reads every time you invoke it, so the framework and the examples ride along automatically. You write the brief; the skill carries the structure.
The 3 trigger types this starter uses
- Specificity / numerical — A named result paired with a timeframe or quantity. Example: "Cut your laundry static in 6 washes."
- Identity / people-like-me — The buyer recognizing themselves on the page. Example: "For moms whose hormones turned on them after kid #2."
- Contrarian / pattern-interrupt — Direct challenge to what the audience has been told. Example: "Stop using dryer sheets — they're coating your skin in stearic acid."
Three is enough to teach the model variance. The production version uses five, but you'd be surprised how far three gets you on a Tuesday morning.
The starter skill
Two files. The first is the skill itself — what Claude reads when you invoke it. The second is an example brief, so the model has a format to anchor on.
~/.claude/skills/hook-generator/SKILL.md
---
name: hook-generator
description: Generate 9 ad hook variations from a one-line brief, structured across 3 psychological trigger types. Use when the user asks to "generate hooks for [product]", "write hooks for [audience]", or invokes /hook-generator.
---
# hook-generator — Starter
You produce 9 ad hooks from a one-line brief. The hooks are structured into 3 trigger types (3 hooks each). Your output must follow the structure exactly.
## Inputs
The user provides a brief that names (1) the product and (2) the target audience. Example: "dryer sheet alternative, target moms with hormone sensitivities."
If either piece is missing, ask for it before generating. Do not invent the audience.
## The 3 trigger types
1. **Specificity / numerical.** A concrete result with a number, timeframe, or named quantity. The hook must include at least one number or a specific measurable claim. No "improve your laundry" — only "softer laundry in 3 washes."
2. **Identity / people-like-me.** A statement that names the audience directly, so they recognize themselves. The hook must reference a specific life situation, role, or struggle. No "for women" — only "for women whose periods got worse after age 35."
3. **Contrarian / pattern-interrupt.** A direct challenge to the conventional advice or default product the audience uses. The hook must call out a specific belief, ingredient, or behavior. No "rethink your routine" — only "stop using dryer sheets — they leave stearic acid on your skin."
## Output format
Return a markdown table. Group hooks by trigger type. Three hooks per type. No commentary before or after the table.
| # | Trigger | Hook |
|---|---------|------|
| 1 | Specificity | [hook] |
| 2 | Specificity | [hook] |
| 3 | Specificity | [hook] |
| 4 | Identity | [hook] |
| 5 | Identity | [hook] |
| 6 | Identity | [hook] |
| 7 | Contrarian | [hook] |
| 8 | Contrarian | [hook] |
| 9 | Contrarian | [hook] |
## Rules
- Mobile-first. 1-2 lines max per hook.
- Every hook must be specific enough that it couldn't apply to a different product. If you can drop the product name from one brief into another and the hook still works, rewrite it.
- No exclamation points. No "imagine if." No "discover the secret."
- No banned generic openers: "Are you tired of," "What if you could," "Introducing."
- When in doubt, lean concrete. A real number beats a clever phrase.
## Reference
See `examples/sample-brief.md` for the brief format and one full example output.
~/.claude/skills/hook-generator/examples/sample-brief.md
# Sample brief format
A brief is one line. Two parts: product + audience.
## Format
`[product description], target [audience description]`
## Examples
- `dryer sheet alternative, target moms with hormone sensitivities`
- `magnesium glycinate supplement, target women 35-55 with sleep issues`
- `protein bar with 22g protein and 4g sugar, target busy professionals avoiding crash`
- `cast iron seasoning kit, target home cooks intimidated by maintenance`
## What a good brief includes
- The product or category (not the brand name — the model doesn't need it)
- One concrete differentiator if there is one (the 22g protein, the hormone-safe formula)
- The audience pain or context, not just demographics ("hormone sensitivities" beats "women 30-50")
That's the whole skill. About 60 lines of markdown total. The "logic" lives in the instructions — no Python, no API calls, no separate runner. Claude reads the skill, follows the structure, returns hooks.
How to use it
Three steps.
mkdir -p ~/.claude/skills/hook-generator/examples
Then paste the two files above into:
~/.claude/skills/hook-generator/SKILL.md~/.claude/skills/hook-generator/examples/sample-brief.md
From inside Claude Code, invoke:
generate hooks for: dryer sheet alternative, target moms with hormone sensitivities
Claude reads the skill, follows the trigger structure, returns 9 hooks. End to end, the first run takes about 8 seconds.
Example output
Here's what came back for that exact brief on the first try. Fake brand context: a hormone-safe laundry softener that uses fermented coconut oil instead of synthetic fragrance and quaternary ammonium compounds.
| # | Trigger | Hook |
|---|---|---|
| 1 | Specificity | Softer towels in 3 washes — zero quats, zero fragrance migraines. |
| 2 | Specificity | One bottle replaces 6 months of dryer sheets. $0.18 per load. |
| 3 | Specificity | 96% of testers stopped reacting to laundry within 14 days. |
| 4 | Identity | For moms who got a "fragrance sensitivity" diagnosis after kid #2. |
| 5 | Identity | The laundry softener for women whose periods turned their skin against them. |
| 6 | Identity | If perimenopause made every fabric softener feel like sandpaper, this is for you. |
| 7 | Contrarian | Stop using dryer sheets. They coat your skin in stearic acid for 3 days. |
| 8 | Contrarian | Fabric softener is the #1 endocrine disruptor in your laundry room — and nobody talks about it. |
| 9 | Contrarian | Your dermatologist blamed the detergent. It was actually the softener. |
Most of these are usable as Meta primary text openers. Hooks 1, 4, and 7 are the ones I'd push into a test today.
Where the starter falls short
I run this on small client work and personal projects. For paid client refresh cycles, it's not enough. The gaps:
- 3 trigger types vs. 5 in production. Two important categories are missing from the starter. You'd notice on longer batches — output starts to feel repetitive after 20 hooks.
- 3 hooks per type vs. 2 in production (10 total). The production version generates 10 hooks structured for higher diversity per trigger. Sounds backward — fewer hooks per type, more total — but the production logic spreads the load across more triggers so each trigger gets the strongest version, not the third-best.
- No brand-tone alignment. The production version reads a brand tone-of-voice file and constrains every hook to it. The starter writes in a neutral DR voice — fine for utility brands, off for any client with a distinct verbal identity.
- No hook-trend integration. The production version cross-checks against current winning hook patterns from the trend radar I run weekly. The starter is stuck with whatever the model already knew.
- No batch mode. You run it one brief at a time. For a Monday morning across multiple brands, that's multiple invocations.
The production version
I rebuilt this skill into a full version with the missing pieces — 5 triggers, 10 hooks, brand-tone awareness, trend integration. It lives in the Creative Engine pack on operatorstack.app/packs/creative-engine, $129, alongside the rest of my creative production stack (ad copy frameworks, UGC briefs, image prompt generators, persona architects). That's the version I use on paying client work.
Bonus: an LLM eval loop
If you want the starter to refine itself, add a second pass. After Claude returns the 9 hooks, ask: "Rate each hook 1-5 on its trigger fit, and rewrite the lowest-scoring one in each category." The model will critique its own output, name the weakest hook per trigger, and regenerate it. You end up with 9 hooks where the bottom 3 have been replaced. It adds maybe 10 seconds and noticeably improves the floor.
For higher rigor: give the model a list of "tells" that mark a generic hook (starts with "Discover," contains "secret," uses "transform," no concrete number), and have it self-flag any hook that contains a tell before scoring. The eval becomes deterministic instead of vibes-based.
The takeaway
A Claude Code skill is just a markdown file with structure. You don't need a framework, a Python runner, or an API integration to get more useful output than ChatGPT gives you. You need to name the levers, show the format, and constrain the generic.
If you'd rather have the production version with all 5 triggers and brand-tone alignment, the Creative Engine pack is at operatorstack.app/packs/creative-engine. Or if you want someone running this — and the rest of the system — against your account directly, let's talk.