gooseworks-ai/pain-language-engagers
> Find warm leads by searching LinkedIn for pain-language posts — the frustrations, complaints, and operational struggles your ICP talks about publicly. Asks clarifying questions to understand your product, ICP, and their pain points, then generates pain-language search keywords, scrapes LinkedIn for posts and engagers, enriches profiles, and ICP-filters the results. Use when someone wants to "find leads who are complaining about X" or "find people discussing problems we solve" or "LinkedIn pain-based prospecting."
npx skills add https://github.com/gooseworks-ai/goose-skills --skill pain-language-engagers
Find warm leads by scraping LinkedIn for pain-language posts and their engagers. People who write about, react to, or comment on posts expressing operational frustrations are signaling they live with a problem your product solves. This skill turns those signals into a qualified lead list.
Core principle: Search for pain-language, not solution-language. Solution keywords ("AI automation", "workflow optimization") attract builders and VCs. Pain keywords ("can't find drivers", "check calls are killing us") attract operators living with the problem.
Before generating keywords or running anything, ask the user these questions. Present them as a numbered list and tell the user to answer what's relevant and skip what's not.
10. Any LinkedIn company pages where your ICP is likely to engage? (Industry publications, communities, competitor pages)
11. Any specific LinkedIn posts or content creators your ICP follows?
Based on the intake answers, generate ~15-25 pain-language keywords in LinkedIn boolean search syntax. Organize into categories:
Key principle: Every keyword should be something a frustrated operator would actually type or say, not marketing language or solution framing.
Also generate:
Present the full keyword list to the user for approval/refinement before running. This is the most critical step — bad keywords = bad leads.
Once approved, save the complete config as JSON:
# Save config
skills/pain-language-engagers/configs/{client-name}.json
Config JSON structure:
{
"client_name": "example-client",
"pain_keywords": ["\"can't find X\"", "\"hiring Y\" problems"],
"pain_patterns": ["can.t find X", "hiring Y", "manual.*process"],
"icp_keywords": ["industry-term-1", "industry-term-2"],
"tech_vendor_keywords": ["software engineer", "competitor-name"],
"hardcoded_companies": ["https://www.linkedin.com/company/example/"],
"industry_pages": ["https://www.linkedin.com/company/example/"],
"broad_topic_patterns": ["industry", "sector", "niche-term"],
"country_filter": "United States",
"days_back": 60,
"max_posts_per_keyword": 50,
"max_posts_per_company": 100
}
Execute the pipeline script with the saved config:
python3 skills/pain-language-engagers/scripts/pain_language_engagers.py \
--config skills/pain-language-engagers/configs/{client-name}.json \
[--test] [--companies "url1,url2"]
Flags:
--config (required) — path to the client config JSON--test — limit to 3 keywords, 5 posts per company (for validation)--skip-discovery — skip keyword search, only scrape hardcoded/extra companies--companies "url1,url2" — add extra company URLs to scrapeWhat the script does:
apimaestro/linkedin-posts-search-scraper-no-cookies for each pain keywordharvestapi/linkedin-company-posts for each company page, pain-filteredharvestapi/linkedin-profile-scraper for all profiles (gets headline + location)Cost estimate:
Always run with --test first to validate the config produces relevant results before a full run.
After the script completes, present results to the user:
If the user wants adjustments:
Common adjustments:
tech_vendor_keywordsicp_keywordspain_patterns to be more specificdays_back constraintCSV exported to the current working directory as {client-name}-{date}.csv with columns:
| Column | Description |
|--------|-------------|
| Name | Full name |
| LinkedIn Profile URL | Profile link |
| Role | Parsed from headline |
| Company Name | Parsed from headline |
| Location | From profile enrichment |
| Source Page | Which company page(s) they engaged on |
| Post URL(s) | Links to the post(s) they engaged with |
| Engagement Type | Post Author, Comment, or Reaction |
| Comment Text | Their comment (if applicable — personalization gold) |
| ICP Tier | Likely ICP, Possible ICP, Unknown, or Tech Vendor |
| Niche Keyword | Which pain keyword matched |
APIFY_API_TOKEN in .envapimaestro/linkedin-posts-search-scraper-no-cookies (keyword search)harvestapi/linkedin-company-posts (company page scraping)harvestapi/linkedin-profile-scraper (profile enrichment)Trigger phrases:
With existing config:
python3 skills/pain-language-engagers/scripts/pain_language_engagers.py \
--config skills/pain-language-engagers/configs/happy-robot.json
Test mode:
python3 skills/pain-language-engagers/scripts/pain_language_engagers.py \
--config skills/pain-language-engagers/configs/happy-robot.json --test
Take gooseworks-ai/pain-language-engagers from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.