This system was built and deployed by a B2B marketing services founder who hit a 35% response rate on LinkedIn cold outreach. It's 95% automated, not 100% — and the 5% human touch is what makes the 35% work.
There are three parts: find and scrape leads, score them, then reach out with free value. The core idea is not sending more messages. It's sending fewer, better, more personalised messages that arrive with something the prospect actually wants.
Read the safety protocols section before you run anything at volume — the daily limits belong in every prompt you write.
Why this system works: value-first outreach at scale
Why value-driven outreach works and cold pitches don't
The founder who built this system put it simply: sending a connection request that says "Hey Bob, do you want me to help you?" is not working. It's recognised as a pitch, treated as noise, and ignored.
What he sends instead is a message saying your LinkedIn profile packaging isn't good enough, you could be converting better, and here's an improved version — take it for free. Professional banner, professional picture, professional headline, all generated by Claude. To Bob, it looks like a human spent real time on it.
Bob says: "Sure, sounds good. Thanks. Here's my email, send it over."
That's a conversation started. No pitch, no ask, just value delivered first.
The same principle applies across B2B niches:
- Selling SEO services — send a mini audit of their site
- Selling sales training — send a scorecard of their team's LinkedIn profiles
- Selling RevOps — send a one-page diagnosis of their pipeline structure
- Selling design — send a redesigned hero section for their landing page
- Selling content — send a repurposed version of their best-performing post
The value must be specific to them, generated by Claude, and delivered before any ask. That's what drives 30%+ response rates.
Why Claude Code, not a third-party tool
Third-party automation tools (Expandi, MeetAlfred, Phantombuster) have four problems for this workflow:
- They send generic messages. You can personalise the first line. You cannot generate a custom LinkedIn banner for each prospect.
- They flag LinkedIn accounts. LinkedIn can detect traffic patterns from automation tools. Claude Code drives your real Chrome browser via the computer-use connection, so LinkedIn sees normal browser activity.
- They require learning time. Claude Code requires zero — you describe what you want in plain English.
- They don't do the hard part. Scraping the profile, analysing their positioning, generating a custom visual asset, writing a message that references that asset: no third-party tool does all of this.
This system replaces what Clay would do (enrichment and signal research), what Figma or Canva would do (asset generation), and what a human outreach specialist would do (personalised message writing) — all inside one Claude Code session.
Part 1: finding and scraping leads
Scrape your first-degree LinkedIn connections, download the full dataset, and load it into a Claude Code project.
Step 1: find leads in Sales Navigator
Sales Navigator is the lead source. The system works specifically with your first-degree connections, which means you need to build the connection base first.
Phase A — send connection requests with no message. Research shows that sending a connection request without a message has a higher acceptance rate than sending one with a message. A message makes it look salesy; a clean request looks like a genuine peer who found you interesting.
"Open LinkedIn on my desktop. I want to send connection requests to [N] people.
Filters: [TITLE/INDUSTRY/LOCATION filters from Sales Navigator].
For each person:
- Send a connection request with no message (not a note, just the default request)
- Log the name, URL, and date to outreach/pending-connections.csv
- Respect the 20 connection requests per day limit. Stop when limit is reached.
- Wait 3-5 seconds between requests to mimic human behaviour.
Report: N sent, N remaining in today's quota."
Phase B — filter for accepted connections. Once connections start accepting (typically 3–7 days after sending), go to Sales Navigator and filter for first-degree connections only: set Connection = First degree, then add your other filters (title, industry, location, company size).
This is now the list of people you can actually reach out to via DM.
Step 2: scrape the lead list using Apify
Once you have the filtered Sales Navigator search showing your first-degree connections, extract the full list as structured data.
Tool: api.apify.com — LinkedIn Sales Navigator scraper. Free tier available, pay-per-run for larger lists.
- Go to Apify and find the LinkedIn Sales Navigator People scraper
- Copy the search URL from your Sales Navigator filter, including all your filters
- Extract your LinkedIn cookies using the Chrome extension Apify provides
- Paste the search URL and your cookies into the scraper
- Click Execute
- Download the output as CSV
The CSV contains name, title, company, LinkedIn URL, about section, work experience, location, and any other fields visible on their profile.
The founder scraped 600 first-degree connections this way, filtered to founders, CEOs, and business owners. The scraper returns the full dataset in a single run.
Step 3: load the CSV into Claude Code
# Project structure
.claude/
CLAUDE.md # Your ICP, offer, scoring criteria
leads.csv # The scraped Sales Navigator list
scored/ # Output folder for scored leads
outreach/ # Output folder for generated assets and messages
contact_log.csv # Every action logged here
Your CLAUDE.md for this project:
# LINKEDIN OUTREACH AGENT
## My offer
[ONE SENTENCE: what you sell and who you sell it to]
## ICP definition
- Titles: [LIST TARGET TITLES]
- Company size: [RANGE]
- Location: [GEOGRAPHY]
- Buying signals to look for: [DESCRIBE]
## Scoring criteria
Score leads 1-10 based on:
- Company size: [IDEAL SIZE = 10, TOO SMALL = 1]
- LinkedIn presence: [ACTIVE POSTER = +2, INACTIVE = -1]
- Location: [LIST PREFERRED LOCATIONS]
- Buying power signals: [FOUNDER/CEO = +3, MANAGER = +1]
- Profile quality: [WELL-PACKAGED = HIGHER PRIORITY for value-first outreach]
## Disqualification criteria (automatic 0 score)
- Non-paying countries: [LIST]
- Job seekers (open to work badge)
- Company type: [TYPES TO EXCLUDE]
## LinkedIn daily limits
- Connection requests: max 20 per day
- DMs: max 50 per day, randomised delays between sends
- Comments: max 15 per day
## Output format
All scored leads go to scored/leads_scored.html
All actions logged to outreach/contact_log.csv
Part 2: scoring leads with an HTML dashboard
Claude reads every lead from the CSV, scrapes their full LinkedIn profile, scores them against your criteria, and builds an HTML dashboard where you can filter, sort, and pick who to reach out to.
How the scoring system works
Claude doesn't score leads from the CSV data alone. The CSV gives basic info — name, title, company, URL. For scoring it needs the full profile: about section, recent posts, work experience, company description, and any signals visible on their public LinkedIn.
Claude connects to the Apify LinkedIn Profile scraper via MCP or API call, passes each lead's URL, gets back the full profile data, then applies your scoring criteria from CLAUDE.md and produces a 1–10 score with reasoning.
143 out of 600 leads in the founder's system were auto-disqualified — wrong geography, non-paying markets, or other criteria that made them a guaranteed non-converter. Those 143 never receive a single message. Attention stays on the 457 who might.
The scoring prompt
"Read leads.csv. For each lead:
1. Fetch their full LinkedIn profile using the Apify LinkedIn Profile scraper.
URL: their linkedin_url column value.
Return: about section, recent posts (last 5), work experience, current company description.
2. Score them 1-10 against the criteria in CLAUDE.md.
Show the score and the reasoning (2-3 bullet points per lead).
3. Auto-disqualify (score = 0) if any disqualification criteria from CLAUDE.md apply.
Mark these as DISQUALIFIED, not just low-scored.
4. Build an HTML dashboard at scored/leads_scored.html with:
- A sortable table: Name | Title | Company | Score | Status | LinkedIn URL | Notes
- Filter buttons: Ideal fit (score 8+), Good fit (5-7), Low fit (below 5), Disqualified
- Click-to-expand: clicking a row shows the full scoring reasoning
- Search bar: filter by company name or title
- A summary at the top: N leads total, N ideal, N good, N low, N disqualified
5. Save the full scored data as scored/leads_scored.csv with all original columns plus:
Score | Status | Scoring_reasoning | Profile_about | Profile_last_post
Process in batches of 20 to stay within API rate limits.
Log progress to console every 10 leads."
HTML dashboard features
Filter by score band:
| Band | Score | What to do |
|---|---|---|
| Ideal fit | 8–10 | Your outreach targets this week |
| Good fit | 5–7 | Outreach target next wave |
| Low fit | 1–4 | Monitor only, don't spend time now |
| Disqualified | 0 | Hidden by default, viewable for audit |
Plus:
- Search — find any lead by name, company, or title in under 2 seconds
- Click-to-expand — see the full scoring reasoning, their recent post content, and the value asset Claude recommends generating for them
- Action column — mark each lead as "Queued for outreach", "Message sent", "Replied", "Not interested", or "Disqualified" without leaving the dashboard
The dashboard is local HTML that runs in your browser. No SaaS subscription, no seat costs, and no data leaving your machine beyond what goes to the Apify API for profile scraping.
Iterating the scoring criteria
The first scoring run won't be perfect. The founder says it took iteration to make the score actually reflect how relevant and valuable a lead is.
"Review the scored leads in scored/leads_scored.html.
I have manually looked through 20 Ideal Fit leads.
Here is my feedback:
- [LEAD 1]: scored 9 but actually a poor fit because [REASON]
- [LEAD 2]: scored 6 but actually a great fit because [REASON]
- Pattern I noticed: [DESCRIBE]
Update the scoring logic in CLAUDE.md to fix this.
Re-score all leads where this change would affect the result.
Update the HTML dashboard."
After 2–3 iterations the score reliably reflects your actual judgment. At that point you run it against the full list and let Claude score everything autonomously.
Part 3: generating free value and sending outreach
For each Ideal Fit lead, Claude scrapes their profile, analyses their current LinkedIn packaging, generates an improved banner and profile picture, writes a personalised DM, and queues everything for your approval before sending.
The free value concept
The founder's specific free value is an improved LinkedIn profile package: a professional banner clearly communicating the prospect's value prop, an improved profile picture (better framing, lighting, background), and a sharper headline.
For a B2B marketing services founder selling LinkedIn growth, this is perfect value-product alignment. What he sells is LinkedIn presence; what he gives away free is a preview of LinkedIn presence. The prospect sees the output, wants more of it, and opens the conversation.
Apply the principle to your own offer:
| What you sell | Free value to deliver |
|---|---|
| LinkedIn content / ghostwriting | Rewritten version of their worst-performing post |
| SEO / content marketing | Mini audit of their top 5 pages (Claude + Screaming Frog) |
| Sales training / coaching | Scorecard of their SDR team's LinkedIn profiles |
| RevOps / Salesforce consulting | One-page diagnosis of their pipeline stages (from job postings) |
| Paid ads / PPC | Analysis of their current ad creative vs top performers in their category |
| Design / branding | Redesigned hero section for their landing page |
| Cold email / outbound | Sample rewritten version of a cold email they posted publicly |
| Recruitment / HR | Salary benchmarking report for their open role |
The rule: the free value must be specific to them (not a generic template), generated by Claude (95% of the work done automatically), and a direct preview of what they'd get if they hired you.
How Claude generates the profile package
Two APIs are involved:
- Apify LinkedIn Profile scraper — scrapes the prospect's current banner, profile picture, headline, about section, and recent posts
- Kia AI (kiaai.com) — image generation API. Claude connects via the nana-banana-pro gateway, which gives access to multiple image generation models including FLUX and Midjourney-equivalent quality.
Step 1 — analyse their current packaging:
"Analyse the LinkedIn profile of [NAME] at [URL].
Fetch via Apify LinkedIn Profile scraper.
Analyse their current packaging:
1. Banner: what does it communicate? Is it professional? Does it clearly show their value prop?
2. Profile picture: quality, professionalism, visual hierarchy
3. Headline: is it outcome-focused or just a job title?
4. About section: does it speak to their ICP or to their own ego?
Rate each element 1-5.
Identify the 2 highest-leverage improvements.
Write a brief explaining what the improved banner should look like."
Step 2 — generate the improved banner:
"Using Kia AI, generate an improved LinkedIn banner for [NAME].
Banner brief (from the profile analysis):
- Their name: [NAME]
- Their value prop: [WHAT THEY DO FOR THEIR ICP]
- Their ICP: [WHO THEY SERVE]
- Visual style: professional, clean, [THEIR BRAND COLOURS if visible]
- Must include: their value prop as the headline text, a clear visual hierarchy, professional design
- Must not include: stock photo clichés, cluttered layouts, generic backgrounds
Generate in LinkedIn banner dimensions: 1584 x 396 pixels.
Save to outreach/[name]-banner.png."
Step 3 — generate the improved profile picture:
"Using Kia AI, generate an improved profile picture for [NAME].
Current profile picture analysis: [PASTE FROM STEP 1]
Improvement direction:
- Professional headshot style
- Neutral or slightly blurred background
- Good lighting, forward-facing
- Confident expression
- If their current picture is poor quality: generate a clean professional version in the same style
Dimensions: 400 x 400 pixels (LinkedIn profile picture standard).
Save to outreach/[name]-profile.png."
The outreach message
The message that goes with the value asset. This is not a pitch — it references the asset and delivers it.
Structure:
- Line 1 — specific observation about their current LinkedIn packaging, referencing something real
- Line 2 — the value you're delivering
- Line 3 — a single soft ask
Length: under 300 characters for a connection request note, under 500 for a first DM to an existing connection.
"Write a LinkedIn outreach message for [NAME], [TITLE] at [COMPANY].
Context:
- Their current LinkedIn packaging: [PASTE THE ANALYSIS FROM STEP 1]
- What I am sending them: an improved banner and profile picture
- My offer: [WHAT I SELL]
Message format:
- Line 1: Specific observation about their current packaging (not generic, must reference what you actually found)
- Line 2: I put together an improved version for you. Take it for free.
- Line 3: One soft ask (not a pitch, not a meeting request, just open the door)
Rules:
- Under 500 characters total
- No em dashes
- No 'I hope this message finds you well'
- No generic compliments
- Must feel like a human who spent time on this, not a template"
What the founder actually sent:
Hey Bob, noticed your LinkedIn packaging isn't showing what you actually offer. I put together an improved banner and photo for you, take them for free. Would be keen to hear if it resonates.
Bob's reply: "Sure, sounds good. Thanks. Here's my email, send it over."
The approval and send workflow
This system is 95% automated. The 5% manual touch is the approval step — you review the generated assets and the drafted message before anything goes out.
"Process the Ideal Fit leads from scored/leads_scored.csv (score 8+).
For each lead:
1. Fetch their full LinkedIn profile via Apify
2. Analyse their current packaging (banner, picture, headline, about)
3. Generate improved banner (save to outreach/[name]-banner.png)
4. Generate improved profile picture (save to outreach/[name]-profile.png)
5. Write a personalised outreach message (under 500 characters, no em dashes)
6. Add them to outreach/queue.html with:
- Their name, title, company, LinkedIn URL
- Their current banner and picture (screenshot from scrape)
- The generated new banner and picture
- The drafted message
- Two buttons: APPROVE (queues for send) or SKIP (removes from queue)
Process [N] leads per run. Do not send anything yet.
Wait for my review of outreach/queue.html before sending."
After you approve:
"Send approved outreach from outreach/queue.html.
For each APPROVED lead:
1. Open their LinkedIn profile in Chrome
2. Send them the DM with the message I approved
3. Attach the banner and profile picture files
4. Log the send to outreach/contact_log.csv:
Name | Title | Company | LinkedIn URL | Message sent | Assets attached | Date | Status
5. Wait 60-90 seconds between sends (randomise the delay)
6. Stop after 30 sends per day
Report: N sent today, N remaining in queue, N daily limit remaining."
Skills and agents that slot into this system
Linked API CLI (17 commands)
The most comprehensive LinkedIn automation layer for Claude Code.
# Install
npm install -g @linkedapi/linkedin-cli
linkedin setup # authenticates your LinkedIn account
# Fetch a full LinkedIn profile (replaces Apify for profile data)
linkedin person fetch https://www.linkedin.com/in/[USERNAME] \
--experience --posts --posts-limit 5 --json -q
# Search for leads by title and location
linkedin person search \
--term "[TARGET TITLE]" \
--locations "[GEOGRAPHY]" \
--limit 50 --json -q
# Send a connection request
linkedin connection send https://www.linkedin.com/in/[USERNAME] \
--note "[NOTE]" --json -q
# Send a DM to an existing connection
linkedin message send https://www.linkedin.com/in/[USERNAME] \
"[MESSAGE TEXT]" --json -q
# Check existing connections at a company
linkedin company connections [COMPANY NAME] --json -q
# Sales Navigator search (first-degree connections only)
linkedin navigator person search \
--seniority "Director,VP,CXO" \
--company-sizes "51-200,201-500" \
--connections "firstDegree" --json -q
For this system, Linked API CLI replaces the Apify profile scraper for everything except the Sales Navigator bulk export. Use Linked API for per-profile fetches during scoring and outreach; use Apify for the initial bulk list extraction.
LinkedIn MCP (13 tools)
npx uvx linkedin-scraper-mcp@latest
Claude can then pull LinkedIn profiles, company pages, and search results directly in conversation, without you copy-pasting URLs or data.
# Usage in scoring
"Use the LinkedIn MCP to fetch the profile for each lead in leads.csv.
For each, return: about section, current role, recent posts, company description."
# Usage in outreach prep
"Use the LinkedIn MCP to analyse [NAME]'s profile at [URL].
Return: current banner description, headline, top pain points visible in their posts."
nl-outreach agent (40 skills)
/plugin marketplace add henriquecaner/next-level-outreach
/plugin install nl-outreach@nl-outreach-marketplace
/nl-outreach:onboard # run first, builds outreach-brief.md from your ICP
The skills most relevant to LinkedIn value-first outreach:
# deep-company-analyser: produces the 6-section account brief
"Run deep-company-analyser on [COMPANY NAME]. Focus: [THEIR PAIN RELEVANT TO YOUR OFFER]."
# copywriting-first-touch: writes the LinkedIn DM
"Run copywriting-first-touch for [NAME] at [COMPANY].
Signal: [DESCRIBE WHAT YOU ARE SENDING THEM].
Rules: under 300 characters, no em dashes, sound human, no pitch."
# reply-handler: handles the reply when they respond
"Run reply-handler on this reply from [NAME]: [PASTE THEIR REPLY].
Classify the reply type and return the full response script."
# campaign-angle-finder: generates 3 distinct angles before writing anything
"Run campaign-angle-finder for [ICP TYPE]. Read outreach-brief.md.
Return 3 angles, each leading with a different pain or signal."
# linkedin-sequence: 2-DM maximum sequences (respects LinkedIn norms)
"Run linkedin-sequence for [NAME] at [COMPANY].
Context: I have already sent them a value asset.
Write the follow-up sequence: DM 2 (if no reply after 5 days), DM 3 (breakup at Day 10)."
ai-sales-team-claude (5 parallel agents, BANT + MEDDIC)
curl -fsSL https://raw.githubusercontent.com/zubair-trabzada/ai-sales-team-claude/main/install.sh | bash
# Full account research (5 agents fire simultaneously)
/sales prospect https://linkedin.com/in/[USERNAME]
# Returns: fit score, decision maker details, BANT score,
# competitive context, recommended outreach angle
# Pre-call brief (after they reply and you book a call)
/sales prep https://linkedin.com/in/[USERNAME]
# Returns: company brief, talking points, objection prep, discovery questions
Use this after the value asset conversation converts to a call — you have a full brief before you pick up the phone.
Cold email and LinkedIn content skills
npx skills add coreyhaines31/marketingskills --skill cold-email
npx skills add sergebulaev/linkedin-skills
# cold-email for the follow-up after LinkedIn converts
"Write a cold email for [NAME] who replied to my LinkedIn outreach about [VALUE ASSET].
They asked me to send more info.
My offer: [DESCRIBE].
Context: they already have the [VALUE ASSET] in their inbox.
Rules: reference the asset, move them toward a 15-minute call, under 80 words, no em dashes."
# linkedin-skills for content-first warm-up
"Using the LinkedIn content skills, write 3 posts about [TOPIC RELEVANT TO MY ICP].
Goal: ICP-matching people comment on these posts and self-identify as warm leads.
Then I reach out referencing their comment."
The full outreach sequence: templates for every touch
Touch 1: the value-first connection request or DM
If they're not yet a connection — connection request note, under 300 characters:
Hey [NAME], noticed your LinkedIn packaging isn't showing what you actually do. Put together an improved version, take it for free if you want it.
If they're already a connection — first DM, under 500 characters:
Hey [NAME], was looking at your LinkedIn profile. Your [banner/headline/picture] isn't reflecting what you actually bring to the table.
Put together an improved version for you. Professional banner, updated picture, sharper headline. All free, no strings.
Want me to send it over?
Prompt to generate your own version:
"Write a LinkedIn first DM for [NAME], [TITLE] at [COMPANY].
Context:
- Their current packaging issue: [SPECIFIC OBSERVATION FROM PROFILE ANALYSIS]
- What I am offering to send: [FREE VALUE ASSET]
- My offer (do not mention yet): [WHAT I SELL]
Rules:
- Under 500 characters
- No em dashes
- Specific to them (mention the specific packaging issue you found)
- No pitch, no meeting ask
- Sound like a human who looked at their profile, not a template
- End with a question that requires a yes/no answer"
Reply handling: the 6 reply types
Type 1 — "Yes, send it over" (the target reply). Their reply: "Sure, sounds good. Here's my email."
Great, sending it over now. [attach assets]
By the way, this is part of what we help [ICP TYPE] with at [YOUR COMPANY]. Happy to walk you through the full approach if useful. 15 minutes?
Type 2 — "What is this for?" Their reply: "What's this about? What do you sell?"
I help [ICP TYPE] with [PROBLEM YOU SOLVE]. Thought the best way to show you what that looks like was to just do it.
Here are the assets. If you like the direction, happy to talk about the full thing.
Type 3 — "Not interested." Their reply: "No thanks"
No problem. I will send the assets anyway in case they are useful. No follow-up after this one.
Then send the assets anyway, and no further DMs. This is the class move.
Type 4 — "I already have someone for this." Their reply: "We already work with someone on this."
Makes sense. I will still send the assets over. If you ever want a second opinion or your situation changes, I am easy to find.
Type 5 — no reply after 5 days. DM 2:
Sent you something last week. Did it land in the right place?
Type 6 — no reply after 10 days (breakup). DM 3, final:
Last note from me. The assets are still there if you want them. If timing is off, no problem.
No more messages after this.
Prompt for any reply:
"Handle this LinkedIn reply from [NAME]: '[PASTE THEIR REPLY]'
Context:
- I sent them [VALUE ASSET]
- My offer: [WHAT I SELL]
- Stage: they have received the asset / they have not yet received it
Classify the reply type and write the response.
Rules: under 200 characters, no em dashes, conversational, no pressure."
The content-first warm-up strategy
Posting content that your ICP engages with generates Tier 1 signals automatically. Anyone from your ICP who comments on your post has self-identified as interested in the topic, and outreach to them after a comment converts at 3.2x the rate of cold outreach.
Step 1 — post 3–4 times per week about the problem your free value asset solves. If you sell LinkedIn growth services, post about LinkedIn packaging, what makes profiles convert, and how to write a headline that speaks to your ICP.
Step 2 — within 24 hours of a post, check who engaged from your ICP:
"Load the linkedin-feed-engage skill.
Check who engaged with my post from yesterday: [PASTE POST URL]
Filter for ICP-matching accounts: [DESCRIBE ICP]
For each ICP-matching engager:
- Draft a connection request note referencing their specific comment
- Queue for my approval before sending"
Step 3 — for commenters, the outreach message changes:
"Write a connection request note for [NAME] who commented on my post about [TOPIC].
Their comment: [PASTE THEIR COMMENT]
What I am offering: [FREE VALUE ASSET]
Rules: under 300 characters, references their comment specifically, no pitch."
Commenters who receive a value asset as follow-up convert at significantly higher rates, because they already know your name and have already engaged with your content.
Safety protocols: LinkedIn limits and account protection
Daily limits to never exceed
| Action | Safe limit | Notes |
|---|---|---|
| Connection requests | 20–25/day (new accounts) | Never exceed 50/day on any account |
| DMs to existing connections | 50–80/day | Use randomised delays between sends |
| Feed comments | 15/day | 30–60 second pacing between comments |
| Profile views | 80–100/day | Natural browsing pattern |
| InMail (Sales Nav) | 25–50/month | Depends on Sales Nav tier |
Build these limits into every Claude Code prompt that involves LinkedIn actions:
# Always include in any send prompt:
"After each send, wait a randomised delay between 45 and 120 seconds.
Stop when daily limit is reached. Report the count before stopping.
If LinkedIn shows any warning about unusual activity, stop immediately and report."
Why driving your own Chrome browser is safer
Third-party LinkedIn automation tools (Expandi, MeetAlfred, Phantombuster) operate via LinkedIn's mobile API (detected as non-browser traffic), headless browsers (detectable via fingerprinting), and shared IP ranges (flagged because thousands of users share the same pool).
Claude Code via the Chrome browser extension operates via your real Chrome browser (same fingerprint as your manual sessions), your home or office IP address, and normal click and scroll patterns. LinkedIn sees it as you browsing LinkedIn normally, which is why the founder's system has been running without account restrictions.
Additional safety measures:
- Never run the system from a new LinkedIn account — account age matters
- Warm up before scaling: start with 10 connections per day, increase by 5 per week
- Never scrape without authentication — always use your own cookies
- Keep your LinkedIn Premium or Sales Navigator subscription active
What to do if you get a restriction
If LinkedIn restricts your connection request ability:
- Stop all automation immediately
- Don't attempt to appeal via automated means
- Log into LinkedIn manually and complete any verification they request (phone, email)
- Wait 72 hours before resuming any outreach activity
- Resume at 50% of your previous daily limit for two weeks before scaling back up
If LinkedIn restricts your DM ability:
- Stop DMs for 7 days
- During the pause, focus only on connection requests and content engagement
- Resume DMs at 20 per day and scale up slowly
Prevention beats recovery. The 20-connection-request-per-day limit is conservative by design. Most accounts can handle 30–40 safely after 90 days of activity — the founder stays at 20–25 because the quality of each message is high enough that he doesn't need volume.
Quick reference: full system in copy-paste prompts
Full system install sequence
# 1. LinkedIn CLI (17 commands, full LinkedIn automation)
npm install -g @linkedapi/linkedin-cli
linkedin setup
# 2. LinkedIn MCP (browser-based, 13 tools)
npx uvx linkedin-scraper-mcp@latest
# 3. nl-outreach agent (40 skills: ICP, copywriting, reply handling, campaign architecture)
/plugin marketplace add henriquecaner/next-level-outreach
/plugin install nl-outreach@nl-outreach-marketplace
/nl-outreach:onboard # run this first to build outreach-brief.md
# 4. AI sales team (5 parallel agents for prospect research and call prep)
curl -fsSL https://raw.githubusercontent.com/zubair-trabzada/ai-sales-team-claude/main/install.sh | bash
# 5. Marketing skills (cold email follow-up + LinkedIn content warming)
npx skills add coreyhaines31/marketingskills --skill cold-email
npx skills add sergebulaev/linkedin-skills
# 6. Kia AI for image generation (connect via Cowork or API key)
# Add KIAAI_API_KEY to your environment variables
# Claude Code uses it automatically when generating banners and profile pictures
Phase 1: build your connection base
# Send connection requests (no message) via Cowork
"Open LinkedIn. Send connection requests to [N] people matching these filters:
[TITLE/LOCATION/INDUSTRY]
No message. Just the default request.
Log each to outreach/pending-connections.csv.
Stop at 20 requests. Wait 3-5 seconds between each."
# After connections accept (3-7 days later), scrape via Apify:
# api.apify.com > LinkedIn Sales Navigator scraper
# Input: your Sales Navigator search URL (first-degree connections, your filters)
# Input: your LinkedIn cookies
# Output: CSV with 600+ contacts
# Download and add to Claude Code project as leads.csv
Phase 2: score leads
# Full scoring run
"Read leads.csv. For each lead:
1. Fetch their LinkedIn profile via Apify LinkedIn Profile scraper
2. Score 1-10 against criteria in CLAUDE.md
3. Auto-disqualify if any disqualification criteria apply
4. Build HTML dashboard at scored/leads_scored.html
5. Save scored/leads_scored.csv with Score, Status, Scoring_reasoning, Profile_about, Profile_last_post
Process in batches of 20. Log progress every 10 leads."
# Iterate the criteria
"I reviewed 20 Ideal Fit leads. Feedback:
[LEAD 1]: scored [N] but actually [BETTER/WORSE] because [REASON]
[PATTERN]: [DESCRIBE]
Update CLAUDE.md scoring logic. Re-score affected leads. Update HTML dashboard."
Phase 3: generate assets and queue outreach
# Generate value assets and queue for approval
"Process Ideal Fit leads from scored/leads_scored.csv (score 8+).
For each lead:
1. Fetch full LinkedIn profile via Apify
2. Analyse current packaging (banner, picture, headline, about) - rate each 1-5
3. Generate improved banner via Kia AI (save to outreach/[name]-banner.png)
4. Generate improved profile picture via Kia AI (save to outreach/[name]-profile.png)
5. Write personalised DM (under 500 characters, no em dashes, specific to their packaging issue)
6. Add to outreach/queue.html with: current assets, generated assets, drafted message, APPROVE/SKIP buttons
Process [N] leads. Do not send yet. Wait for my review."
# After approval: send
"Send approved outreach from outreach/queue.html.
For each APPROVED lead:
- Open their LinkedIn profile in Chrome
- Send the DM and attach the assets
- Log to outreach/contact_log.csv
- Wait 60-90 seconds (randomised) between sends
- Stop at 30 sends per day
Report: N sent, N remaining, N daily limit remaining."
Phase 4: handle replies
# Daily inbox triage
"Read my LinkedIn inbox via LinkedIn MCP.
For each new reply in the last 24 hours:
1. Classify: positive reply (target) / question / not interested / wrong person / no action needed
2. For positive replies: draft the next message using nl-outreach reply-handler skill
3. For questions: draft a response that answers and moves toward a call
4. Post a briefing to [SLACK CHANNEL]: sender, reply type, draft response
Wait for my approval before sending any responses."
# Post-reply sequence (when they say yes)
"[NAME] at [COMPANY] replied positively.
They said: [PASTE REPLY]
I have sent them the assets.
Next step: move them toward a 15-minute call.
Write the next DM. Under 150 characters. No em dashes. Direct ask for the call."
# No-reply follow-up (Day 5)
linkedin message send https://www.linkedin.com/in/[USERNAME] \
"Sent you something last week. Did it land in the right place?" --json -q
# Breakup DM (Day 10)
linkedin message send https://www.linkedin.com/in/[USERNAME] \
"Last note from me. Assets are still there if useful." --json -q

