Cold Email Automation
Auto research public

Autonomous cold email campaign launcher. Takes one target company domain, scrapes their website, generates an ICP with Claude, pulls matching leads via Prospeo, enriches emails + company descriptions, personalizes each lead with…
--- name: auto-research-public description: Autonomous cold email campaign launcher. Takes one target company domain, scrapes their website, generates an ICP with Claude, pulls matching leads via Prospeo, enriches emails + company descriptions, personalizes each lead with parallel Claude Code Task sub-agents (A/B/C variants), and uploads as a live Smartlead campaign. Uses local JSON files for state (no database required). Use for automated daily campaign launches after you have an initial `client-profile.yaml` from /icp-onboarding. Triggers on "auto-research", "launch an automated campaign", "daily campaign", "run the research loop". --- # Auto Research (Public) Automated end-to-end campaign launcher. Feed it one target company domain, get back a live Smartlead campaign with per-lead personalization — in about 20 minutes. This is the beginner-friendly version of the GEX internal `auto-research-v2`. All state lives in local JSON files; no Supabase, no Trigger.dev. ## What you get - **Input:** one target company domain + your `client-profile.yaml` - **Output:** a running Smartlead campaign with: - 200-1,000 leads (depending on targeting tightness) - Per-lead personalization: 9 custom variables (situation, value, CTA × 3 variants) - A/B/C subject + body variants tested in parallel
Overview
Automated end-to-end campaign launcher. Feed it one target company domain, get back a live Smartlead campaign with per-lead personalization — in about 20 minutes.
What you get
- Inputone target company domain + your client-profile.yaml
- Outputa running Smartlead campaign with:
- 200-1,000 leads (depending on targeting tightness)
- Per-lead personalization9 custom variables (situation, value, CTA × 3 variants)
- A/B/C subject + body variants tested in parallel
- Campaign assigned to your available inboxes
Example prompts
/auto-research-public --domain=$(cat /tmp/auto/next-target.txtManual install (npx, ZIP)
npx skills add growthenginenowoslawski/coldoutboundskills --skill auto-research-public -g -a claude-codenpx degit growthenginenowoslawski/coldoutboundskills/skills/auto-research-public#main ~/.claude/skills/auto-research-publicConnects with Agent Alley MCP · agentalley.io/mcp
Files included
SKILL.md11.4 KB
Read SKILL.md here
Show the full text288 lines
Auto Research (Public)
Automated end-to-end campaign launcher. Feed it one target company domain, get back a live Smartlead campaign with per-lead personalization — in about 20 minutes.
This is the beginner-friendly version of the GEX internal auto-research-v2. All state lives in local JSON files; no Supabase, no Trigger.dev.
What you get
- Input: one target company domain + your
client-profile.yaml - Output: a running Smartlead campaign with:
- 200-1,000 leads (depending on targeting tightness)
- Per-lead personalization: 9 custom variables (situation, value, CTA × 3 variants)
- A/B/C subject + body variants tested in parallel
- Campaign assigned to your available inboxes
- Schedule: Mon-Fri 8am-5pm your timezone
Prerequisites
Before running:
-
client-profile.yamlexists (run/icp-onboardingif not) -
SMARTLEAD_API_KEYin env -
PROSPEO_API_KEYin env -
MILLIONVERIFIER_API_KEYin env (for email validation) - At least 20 Smartlead inboxes tagged "active" (run
/smartlead-inbox-managerfirst) - At least 1 campaign template in Smartlead (or the script creates a fresh one)
The orchestration (Claude Code runs this)
Unlike the other skills, this skill orchestrates through the Claude Code conversation itself — Claude does the reasoning (ICP generation, copy writing, personalization), and phase scripts do the heavy API I/O. This is the pattern from the GEX v2 internal.
Phase 1: Scrape the target company
npx tsx scripts/phase-scrape.ts --domain=<target.com> --out=/tmp/auto/scrape.json
Output: JSON with domain + text content from homepage, /about, /product, /pricing, /customers.
Claude reads the output and writes a short analysis to /tmp/auto/company-analysis.md:
- What the company does
- Who their likely customers are
- Social proof signals
- Potential angles for outreach
Phase 2: Claude generates ICP filters
Reading /tmp/auto/scrape.json + ~/cold-email-ai-skills/profiles/<slug>/client-profile.yaml, Claude writes Prospeo filters to /tmp/auto/filters.json:
{
"job_titles": ["VP Marketing", "Head of Marketing", ...],
"seniorities": ["Vice President", "Head", "Director"],
"industries": ["Software Development", "Financial Services"],
"company_size_min": 50,
"company_size_max": 500,
"countries": ["US"],
"excluded_industries": ["Religious Institutions", "Government Administration"]
}
Claude MUST use exact Prospeo industry names from ~/cold-email-ai-skills/skills/icp-onboarding/references/prospeo-industries.md.
Phase 3: Prospeo search
npx tsx scripts/phase-prospeo.ts --filters-file=/tmp/auto/filters.json --max-leads=1000 --out=/tmp/auto/leads.json
Output: JSON with leads array. Each lead has: first_name, last_name, email (may be empty), linkedin_url, job_title, company_name, company_domain, company_industry, company_headcount, company_description.
Phase 4: Email waterfall + description enrichment
npx tsx scripts/phase-enrich.ts --leads-file=/tmp/auto/leads.json --out=/tmp/auto/enriched.json
The script:
- Checks each lead for email; if missing, hits Prospeo's
enrich-personendpoint - If company_description is thin (<50 chars), scrapes company_domain homepage
- Runs MillionVerifier on every candidate email
- Writes enriched leads (only those with valid email) to output
Expect hit rates:
- Retail/SMB: ~99% email found
- B2B tech: ~65-80%
- Healthcare/public sector: ~25-40%
- MV rejection: ~20-30% of found emails
Phase 5: Copy writing (Claude)
Claude generates 3 copy variants (A, B, C) and writes to /tmp/auto/variants.json:
[
{
"variant": "A",
"subject": "<concrete, specific, <60 chars>",
"angle": "<pain observation>",
"body_template": "Hi {{first_name}},\n\n{{situation_line_a}}\n\n{{value_line_a}}\n\n{{cta_line_a}}\n\n%signature%\n\nP.S. If this isn't relevant, just let me know and I won't reach out again."
},
{
"variant": "B",
"subject": "<different angle>",
"angle": "<compliment + transition>",
"body_template": "..."
},
{
"variant": "C",
"subject": "<third angle>",
"angle": "<question>",
"body_template": "..."
}
]
Rules Claude MUST follow (run /spam-word-checker on output):
- No em dashes (—). Use commas or periods.
- No "leverage", "synergy", "solutions", "world-class", "cutting-edge".
- Body: 50-90 words max.
- Subject: under 60 chars, specific, no clickbait.
- End with
%signature%on its own line.
Phase 6: Personalization via Task sub-agents
Claude fans out to parallel Task sub-agents (one per variant × batch of 20-30 leads). See /personalization-subagent-pattern for the full pattern.
Per lead, each sub-agent writes to /tmp/auto/personalization-<batch>-variant-<X>.json:
[
{
"lead_id": "...",
"situation_line": "One sentence about the company.",
"value_line": "One sentence connecting to our offer.",
"cta_soft": "One soft ask sentence."
}
]
After all sub-agents finish, Claude merges by lead_id into /tmp/auto/personalized.json. Each lead now has 9 personalization fields.
Phase 7: Upload to Smartlead
npx tsx scripts/phase-upload.ts \
--leads-file=/tmp/auto/personalized.json \
--variants-file=/tmp/auto/variants.json \
--domain=<target.com> \
--inboxes-tag=active \
--inbox-count=10 \
--activate
This script:
- Creates a new Smartlead campaign named
[AUTO] <date> <target> Auto - Saves the 3-variant sequence with campaign-ID-scoped custom vars (
{{situation_line_a_{campaign_id}}}) - Selects N inboxes tagged "active" from Smartlead (LRU — least recently used first)
- Uploads leads in batches of 100 with custom fields mapped to their personalization
- Sets schedule (Mon-Fri 8am-5pm EST) and settings (tracking off, stop on reply)
- Activates the campaign
Outputs: { campaignId, inboxCount, leadsUploaded } to stdout.
Phase 8: Save experiment state (local JSON)
Write to ~/cold-email-ai-skills/profiles/<slug>/experiments/<YYYY-MM-DD>-<target>.json:
{
"date": "2026-04-17",
"target_domain": "example.com",
"smartlead_campaign_id": 123456,
"inboxes_assigned": [...],
"icp_filters": {...},
"variants": [...],
"lead_count_uploaded": 347,
"launched_at": "2026-04-17T14:23:00Z",
"status": "launched"
}
This is your experiment log. /experiment-design reads from here to compare runs. /positive-reply-scoring writes results back to this file after 21 days.
Running the full loop
To run all 8 phases in one command (with Claude orchestrating):
/auto-research-public --domain=<target.com>
Claude Code will execute each phase in order, pausing before phase 5 (copy) and phase 7 (upload) so you can review.
Daily / scheduled runs
Once comfortable, wrap it in a cron or use Claude Code's /loop skill to run daily:
/loop 1d /auto-research-public --domain=$(cat /tmp/auto/next-target.txt)
You need a way to pick the next target each day. Options:
- Maintain a
targets.txtlist and pop one per day - Let Claude pick based on TAM research (see
/GEX:Full-TAM-Waterfallfor inspiration) - Rotate through a list of competitors/lookalikes
State files (local JSON, no database)
Everything the skill needs lives under ~/cold-email-ai-skills/profiles/<slug>/:
profiles/
<business-slug>/
client-profile.yaml # from /icp-onboarding
lead-magnets.md # from /lead-magnet-brainstorm
experiments/
2026-04-16-targetco.json # per-campaign experiment log
2026-04-17-othertarget.json
scores/
123456-2026-05-07.json # from /positive-reply-scoring
Inbox assignment (no Supabase)
The GEX v2 uses a Supabase table auto_research_inbox_assignments to track which inboxes are assigned to which campaigns (to spread load). This public version:
- Queries Smartlead for inboxes tagged "active"
- Pulls each inbox's
daily_sent_countas a proxy for "how recently used" - Sorts ascending, picks the first N (least-sent-today = least recently used)
- Records the assignment in the local experiment JSON (not a database)
Works for <1000 inboxes. If you scale beyond that, migrate to a real DB.
Common issues
- Prospeo INVALID_FILTERS — Usually "industry name not in the 256 list." Check
/icp-onboardingreferences/prospeo-industries.md for exact matches. - Low email hit rate — If <30%, your list is targeting hard-to-find people (niche titles, small companies). Widen ICP or accept the cost.
- Sub-agent personalization repetitive — If you see the same phrasing across leads, rerun that batch with a diversity prompt. See
/personalization-subagent-patternreferences/failure-modes.md. - Smartlead "inbox not allowed" on upload — Inbox is flagged/blocked. The script skips and continues.
- Campaign stuck at 0 sends — Check campaign schedule, inbox warmup status (via
/smartlead-inbox-manager list-health), and that leads actually uploaded.
Cost per run
Typical run (1 target, 1000 leads pulled):
- Prospeo search: ~40 pages × search = ~$0.20
- Prospeo enrich-person (email finding for ~500 leads missing email): ~$5
- MillionVerifier validation: ~$0.50
- Smartlead send cost: ~$0.001/email sent over time
- Claude Code Task sub-agents: (uses your Claude Code plan — no extra API spend)
Total: ~$6-10 per campaign to reach 300-500 valid emails.
Scripts
scripts/phase-scrape.ts— website scrapescripts/phase-prospeo.ts— Prospeo paginated searchscripts/phase-enrich.ts— email waterfall + description enrichment + MillionVerifierscripts/phase-upload.ts— Smartlead campaign creation + uploadscripts/_lib.ts— shared API helpers
References
references/orchestration-checklist.md— full step-by-step for running the loop manuallyreferences/icp-to-prospeo.md— how to translate client-profile.yaml into Prospeo filter JSONreferences/copy-variant-guide.md— how to write 3 distinct A/B/C variants
What to do next
Wait 21 days for the campaign to accumulate reply data, then run /positive-reply-scoring on the launched campaign.
Meanwhile: continue the weekly rhythm via /cold-email-weekly-rhythm. Every Monday, /email-deliverability-audit on the new campaign to catch infrastructure issues early.
Or wait: this skill IS the automation loop. Next action can be "run again tomorrow with a different target domain" or integrate with /schedule skill to run daily.
Related skills
/icp-onboarding— produces client-profile.yaml (required input)/lead-magnet-brainstorm— produces the offer/CTA this campaign asks about/personalization-subagent-pattern— the fan-out pattern used in phase 6/smartlead-inbox-manager— must run BEFORE so inboxes are tagged/warmed/positive-reply-scoring— run AFTER 21 days to score the campaign/experiment-design— how to plan which target to try next
| 1 | |
| 2 | name auto-research-public |
| 3 | description Autonomous cold email campaign launcher. Takes one target company domain, scrapes their website, generates an ICP with Claude, pulls matching leads via Prospeo, enriches emails + company descriptions, personalizes each lead with parallel Claude Code Task sub-agents (A/B/C variants), and uploads as a live Smartlead campaign. Uses local JSON files for state (no database required). Use for automated daily campaign launches after you have an initial `client-profile.yaml` from /icp-onboarding. Triggers on "auto-research", "launch an automated campaign", "daily campaign", "run the research loop". |
| 4 | |
| 5 | |
| 6 | # Auto Research (Public) |
| 7 | |
| 8 | Automated end-to-end campaign launcher. Feed it one target company domain, get back a live Smartlead campaign with per-lead personalization — in about 20 minutes. |
| 9 | |
| 10 | This is the beginner-friendly version of the GEX internal `auto-research-v2`. All state lives in local JSON files; no Supabase, no Trigger.dev. |
| 11 | |
| 12 | ## What you get |
| 13 | |
| 14 | **Input:** one target company domain + your `client-profile.yaml` |
| 15 | **Output:** a running Smartlead campaign with: |
| 16 | 200-1,000 leads (depending on targeting tightness) |
| 17 | Per-lead personalization: 9 custom variables (situation, value, CTA × 3 variants) |
| 18 | A/B/C subject + body variants tested in parallel |
| 19 | Campaign assigned to your available inboxes |
| 20 | Schedule: Mon-Fri 8am-5pm your timezone |
| 21 | |
| 22 | ## Prerequisites |
| 23 | |
| 24 | Before running: |
| 25 | [ ] `client-profile.yaml` exists (run `/icp-onboarding` if not) |
| 26 | [ ] `SMARTLEAD_API_KEY` in env |
| 27 | [ ] `PROSPEO_API_KEY` in env |
| 28 | [ ] `MILLIONVERIFIER_API_KEY` in env (for email validation) |
| 29 | [ ] At least 20 Smartlead inboxes tagged "active" (run `/smartlead-inbox-manager` first) |
| 30 | [ ] At least 1 campaign template in Smartlead (or the script creates a fresh one) |
| 31 | |
| 32 | ## The orchestration (Claude Code runs this) |
| 33 | |
| 34 | Unlike the other skills, this skill orchestrates through the Claude Code conversation itself — Claude does the reasoning (ICP generation, copy writing, personalization), and phase scripts do the heavy API I/O. This is the pattern from the GEX v2 internal. |
| 35 | |
| 36 | ### Phase 1: Scrape the target company |
| 37 | |
| 38 | |
| 39 | npx tsx scripts/phase-scrape.ts --domain=<target.com> --out=/tmp/auto/scrape.json |
| 40 | |
| 41 | |
| 42 | Output: JSON with `domain` + text content from homepage, /about, /product, /pricing, /customers. |
| 43 | |
| 44 | Claude reads the output and writes a short analysis to `/tmp/auto/company-analysis.md`: |
| 45 | What the company does |
| 46 | Who their likely customers are |
| 47 | Social proof signals |
| 48 | Potential angles for outreach |
| 49 | |
| 50 | ### Phase 2: Claude generates ICP filters |
| 51 | |
| 52 | Reading `/tmp/auto/scrape.json` + `~/cold-email-ai-skills/profiles/<slug>/client-profile.yaml`, Claude writes Prospeo filters to `/tmp/auto/filters.json`: |
| 53 | |
| 54 | |
| 55 | { |
| 56 | "job_titles": ["VP Marketing", "Head of Marketing", ...], |
| 57 | "seniorities": ["Vice President", "Head", "Director"], |
| 58 | "industries": ["Software Development", "Financial Services"], |
| 59 | "company_size_min": 50, |
| 60 | "company_size_max": 500, |
| 61 | "countries": ["US"], |
| 62 | "excluded_industries": ["Religious Institutions", "Government Administration"] |
| 63 | } |
| 64 | |
| 65 | |
| 66 | Claude MUST use exact Prospeo industry names from `~/cold-email-ai-skills/skills/icp-onboarding/references/prospeo-industries.md`. |
| 67 | |
| 68 | ### Phase 3: Prospeo search |
| 69 | |
| 70 | |
| 71 | npx tsx scripts/phase-prospeo.ts --filters-file=/tmp/auto/filters.json --max-leads=1000 --out=/tmp/auto/leads.json |
| 72 | |
| 73 | |
| 74 | Output: JSON with `leads` array. Each lead has: `first_name`, `last_name`, `email` (may be empty), `linkedin_url`, `job_title`, `company_name`, `company_domain`, `company_industry`, `company_headcount`, `company_description`. |
| 75 | |
| 76 | ### Phase 4: Email waterfall + description enrichment |
| 77 | |
| 78 | |
| 79 | npx tsx scripts/phase-enrich.ts --leads-file=/tmp/auto/leads.json --out=/tmp/auto/enriched.json |
| 80 | |
| 81 | |
| 82 | The script: |
| 83 | Checks each lead for email; if missing, hits Prospeo's `enrich-person` endpoint |
| 84 | If company_description is thin (<50 chars), scrapes company_domain homepage |
| 85 | Runs MillionVerifier on every candidate email |
| 86 | Writes enriched leads (only those with valid email) to output |
| 87 | |
| 88 | Expect hit rates: |
| 89 | Retail/SMB: ~99% email found |
| 90 | B2B tech: ~65-80% |
| 91 | Healthcare/public sector: ~25-40% |
| 92 | MV rejection: ~20-30% of found emails |
| 93 | |
| 94 | ### Phase 5: Copy writing (Claude) |
| 95 | |
| 96 | Claude generates 3 copy variants (A, B, C) and writes to `/tmp/auto/variants.json`: |
| 97 | |
| 98 | |
| 99 | [ |
| 100 | { |
| 101 | "variant": "A", |
| 102 | "subject": "<concrete, specific, <60 chars>", |
| 103 | "angle": "<pain observation>", |
| 104 | "body_template": "Hi {{first_name}},\n\n{{situation_line_a}}\n\n{{value_line_a}}\n\n{{cta_line_a}}\n\n%signature%\n\nP.S. If this isn't relevant, just let me know and I won't reach out again." |
| 105 | }, |
| 106 | { |
| 107 | "variant": "B", |
| 108 | "subject": "<different angle>", |
| 109 | "angle": "<compliment + transition>", |
| 110 | "body_template": "..." |
| 111 | }, |
| 112 | { |
| 113 | "variant": "C", |
| 114 | "subject": "<third angle>", |
| 115 | "angle": "<question>", |
| 116 | "body_template": "..." |
| 117 | } |
| 118 | ] |
| 119 | |
| 120 | |
| 121 | Rules Claude MUST follow (run `/spam-word-checker` on output): |
| 122 | No em dashes (—). Use commas or periods. |
| 123 | No "leverage", "synergy", "solutions", "world-class", "cutting-edge". |
| 124 | Body: 50-90 words max. |
| 125 | Subject: under 60 chars, specific, no clickbait. |
| 126 | End with `%signature%` on its own line. |
| 127 | |
| 128 | ### Phase 6: Personalization via Task sub-agents |
| 129 | |
| 130 | Claude fans out to parallel Task sub-agents (one per variant × batch of 20-30 leads). See `/personalization-subagent-pattern` for the full pattern. |
| 131 | |
| 132 | Per lead, each sub-agent writes to `/tmp/auto/personalization-<batch>-variant-<X>.json`: |
| 133 | |
| 134 | |
| 135 | [ |
| 136 | { |
| 137 | "lead_id": "...", |
| 138 | "situation_line": "One sentence about the company.", |
| 139 | "value_line": "One sentence connecting to our offer.", |
| 140 | "cta_soft": "One soft ask sentence." |
| 141 | } |
| 142 | ] |
| 143 | |
| 144 | |
| 145 | After all sub-agents finish, Claude merges by lead_id into `/tmp/auto/personalized.json`. Each lead now has 9 personalization fields. |
| 146 | |
| 147 | ### Phase 7: Upload to Smartlead |
| 148 | |
| 149 | |
| 150 | npx tsx scripts/phase-upload.ts \ |
| 151 | --leads-file=/tmp/auto/personalized.json \ |
| 152 | --variants-file=/tmp/auto/variants.json \ |
| 153 | --domain=<target.com> \ |
| 154 | --inboxes-tag=active \ |
| 155 | --inbox-count=10 \ |
| 156 | --activate |
| 157 | |
| 158 | |
| 159 | This script: |
| 160 | Creates a new Smartlead campaign named `[AUTO] <date> <target> Auto` |
| 161 | Saves the 3-variant sequence with campaign-ID-scoped custom vars (`{{situation_line_a_{campaign_id}}}`) |
| 162 | Selects N inboxes tagged "active" from Smartlead (LRU — least recently used first) |
| 163 | Uploads leads in batches of 100 with custom fields mapped to their personalization |
| 164 | Sets schedule (Mon-Fri 8am-5pm EST) and settings (tracking off, stop on reply) |
| 165 | Activates the campaign |
| 166 | |
| 167 | Outputs: `{ campaignId, inboxCount, leadsUploaded }` to stdout. |
| 168 | |
| 169 | ### Phase 8: Save experiment state (local JSON) |
| 170 | |
| 171 | Write to `~/cold-email-ai-skills/profiles/<slug>/experiments/<YYYY-MM-DD>-<target>.json`: |
| 172 | |
| 173 | |
| 174 | { |
| 175 | "date": "2026-04-17", |
| 176 | "target_domain": "example.com", |
| 177 | "smartlead_campaign_id": 123456, |
| 178 | "inboxes_assigned": [...], |
| 179 | "icp_filters": {...}, |
| 180 | "variants": [...], |
| 181 | "lead_count_uploaded": 347, |
| 182 | "launched_at": "2026-04-17T14:23:00Z", |
| 183 | "status": "launched" |
| 184 | } |
| 185 | |
| 186 | |
| 187 | This is your experiment log. `/experiment-design` reads from here to compare runs. `/positive-reply-scoring` writes results back to this file after 21 days. |
| 188 | |
| 189 | ## Running the full loop |
| 190 | |
| 191 | To run all 8 phases in one command (with Claude orchestrating): |
| 192 | |
| 193 | |
| 194 | /auto-research-public --domain=<target.com> |
| 195 | |
| 196 | |
| 197 | Claude Code will execute each phase in order, pausing before phase 5 (copy) and phase 7 (upload) so you can review. |
| 198 | |
| 199 | ## Daily / scheduled runs |
| 200 | |
| 201 | Once comfortable, wrap it in a cron or use Claude Code's `/loop` skill to run daily: |
| 202 | |
| 203 | |
| 204 | /loop 1d /auto-research-public --domain=$(cat /tmp/auto/next-target.txt) |
| 205 | |
| 206 | |
| 207 | You need a way to pick the next target each day. Options: |
| 208 | Maintain a `targets.txt` list and pop one per day |
| 209 | Let Claude pick based on TAM research (see `/GEX:Full-TAM-Waterfall` for inspiration) |
| 210 | Rotate through a list of competitors/lookalikes |
| 211 | |
| 212 | ## State files (local JSON, no database) |
| 213 | |
| 214 | Everything the skill needs lives under `~/cold-email-ai-skills/profiles/<slug>/`: |
| 215 | |
| 216 | |
| 217 | profiles/ |
| 218 | <business-slug>/ |
| 219 | client-profile.yaml # from /icp-onboarding |
| 220 | lead-magnets.md # from /lead-magnet-brainstorm |
| 221 | experiments/ |
| 222 | 2026-04-16-targetco.json # per-campaign experiment log |
| 223 | 2026-04-17-othertarget.json |
| 224 | scores/ |
| 225 | 123456-2026-05-07.json # from /positive-reply-scoring |
| 226 | |
| 227 | |
| 228 | ## Inbox assignment (no Supabase) |
| 229 | |
| 230 | The GEX v2 uses a Supabase table `auto_research_inbox_assignments` to track which inboxes are assigned to which campaigns (to spread load). This public version: |
| 231 | |
| 232 | Queries Smartlead for inboxes tagged "active" |
| 233 | Pulls each inbox's `daily_sent_count` as a proxy for "how recently used" |
| 234 | Sorts ascending, picks the first N (least-sent-today = least recently used) |
| 235 | Records the assignment in the local experiment JSON (not a database) |
| 236 | |
| 237 | Works for <1000 inboxes. If you scale beyond that, migrate to a real DB. |
| 238 | |
| 239 | ## Common issues |
| 240 | |
| 241 | **Prospeo INVALID_FILTERS** — Usually "industry name not in the 256 list." Check `/icp-onboarding` references/prospeo-industries.md for exact matches. |
| 242 | **Low email hit rate** — If <30%, your list is targeting hard-to-find people (niche titles, small companies). Widen ICP or accept the cost. |
| 243 | **Sub-agent personalization repetitive** — If you see the same phrasing across leads, rerun that batch with a diversity prompt. See `/personalization-subagent-pattern` references/failure-modes.md. |
| 244 | **Smartlead "inbox not allowed" on upload** — Inbox is flagged/blocked. The script skips and continues. |
| 245 | **Campaign stuck at 0 sends** — Check campaign schedule, inbox warmup status (via `/smartlead-inbox-manager list-health`), and that leads actually uploaded. |
| 246 | |
| 247 | ## Cost per run |
| 248 | |
| 249 | Typical run (1 target, 1000 leads pulled): |
| 250 | Prospeo search: ~40 pages × search = ~$0.20 |
| 251 | Prospeo enrich-person (email finding for ~500 leads missing email): ~$5 |
| 252 | MillionVerifier validation: ~$0.50 |
| 253 | Smartlead send cost: ~$0.001/email sent over time |
| 254 | Claude Code Task sub-agents: (uses your Claude Code plan — no extra API spend) |
| 255 | |
| 256 | Total: **~$6-10 per campaign** to reach 300-500 valid emails. |
| 257 | |
| 258 | ## Scripts |
| 259 | |
| 260 | `scripts/phase-scrape.ts` — website scrape |
| 261 | `scripts/phase-prospeo.ts` — Prospeo paginated search |
| 262 | `scripts/phase-enrich.ts` — email waterfall + description enrichment + MillionVerifier |
| 263 | `scripts/phase-upload.ts` — Smartlead campaign creation + upload |
| 264 | `scripts/_lib.ts` — shared API helpers |
| 265 | |
| 266 | ## References |
| 267 | |
| 268 | `references/orchestration-checklist.md` — full step-by-step for running the loop manually |
| 269 | `references/icp-to-prospeo.md` — how to translate client-profile.yaml into Prospeo filter JSON |
| 270 | `references/copy-variant-guide.md` — how to write 3 distinct A/B/C variants |
| 271 | |
| 272 | ## What to do next |
| 273 | |
| 274 | **Wait 21 days** for the campaign to accumulate reply data, then run `/positive-reply-scoring` on the launched campaign. |
| 275 | |
| 276 | **Meanwhile:** continue the weekly rhythm via `/cold-email-weekly-rhythm`. Every Monday, `/email-deliverability-audit` on the new campaign to catch infrastructure issues early. |
| 277 | |
| 278 | **Or wait:** this skill IS the automation loop. Next action can be "run again tomorrow with a different target domain" or integrate with `/schedule` skill to run daily. |
| 279 | |
| 280 | ## Related skills |
| 281 | |
| 282 | `/icp-onboarding` — produces client-profile.yaml (required input) |
| 283 | `/lead-magnet-brainstorm` — produces the offer/CTA this campaign asks about |
| 284 | `/personalization-subagent-pattern` — the fan-out pattern used in phase 6 |
| 285 | `/smartlead-inbox-manager` — must run BEFORE so inboxes are tagged/warmed |
| 286 | `/positive-reply-scoring` — run AFTER 21 days to score the campaign |
| 287 | `/experiment-design` — how to plan which target to try next |
| 288 |
Details
- License
- MIT
- Stars on the repo
- ★ 736
- Checked
- Source
- growthenginenowoslawski/coldoutboundskills ↗
- Creator
- growthenginenowoslawski · 52 listings
Similar skills
See all →
SkillAI Sales Team Orchestrator
SkillABM Campaign Playbook
SkillDecision-Maker Shortlist
SkillAccount Fit Scorer
SkillApollo Hyper Orchestrator
SkillPersonalized B2B Outreach AgentMore from growthenginenowoslawski
SkillCompany Decision-Maker Finder
SkillCold Outreach Strategist
SkillClay Signal Playbooks
SkillCompetitor Engager Finder
SkillEmail Deliverability Crisis
SkillInbox Delivery Benchmarking