Built by the team at Distribb - SEO and backlinks autopilot for operators.
-> Try Distribb free at distribb.io
A local-first LinkedIn outreach skill for AI agents. Scout warm leads from LinkedIn activity, keep a local review database, send low-volume connection requests from your own visible browser session, sync accepted connections, and send first-degree DMs only after explicit approval.
This skill is designed for a user's own LinkedIn account on their own Mac or workstation. It does not ship proxies, rented accounts, credential login, CAPTCHA bypasses, stealth patches, or any shared database.
npx skills add Bomx/linkedin-outreach-skillOr clone manually:
git clone https://github.com/Bomx/linkedin-outreach-skill.git
cd linkedin-outreach-skill
python3 -m pip install -r requirements.txt
python3 -m playwright install chromiumClaude reads SKILL.md for the actual workflow.
| File | Purpose |
|---|---|
SKILL.md |
Agent playbook: operating rules, commands, and workflows. |
scripts/linkedin_outreach.py |
Local CLI for login, scouting, review, connection requests, sync, DMs, status, and export. |
requirements.txt |
Python dependencies. |
references/operating_rules.md |
Safety rules and stop conditions. |
references/database_schema.md |
Local JSON database schema. |
agents/openai.yaml |
Skill UI metadata. |
Your local data is intentionally excluded:
- no LinkedIn cookies or browser profiles
- no
storage_state.json - no
leads.json - no
signals.json - no action logs, run logs, screenshots, or exports
- no personal templates or message history
By default, runtime state is stored outside the repo at:
~/.linkedin-outreach/
You can override that location:
export LINKEDIN_OUTREACH_DATA_DIR=/absolute/path/to/linkedin-outreach-dataThe .gitignore blocks common local-state paths as a second layer of
protection, but the safest pattern is still: never put session data or
lead databases inside a public repo.
python3 scripts/linkedin_outreach.py login --timeout 600A visible Chromium window opens. Sign into LinkedIn manually. The script
saves the local browser profile under ~/.linkedin-outreach/session/.
python3 scripts/linkedin_outreach.py doctor
python3 scripts/linkedin_outreach.py statusHigh-intent SEO buyer posts:
python3 scripts/linkedin_outreach.py signal-add \
--name "seo-buyer-intent-posts" \
--type post_intent \
--query "looking for SEO consultant" \
--intent buyer_intent \
--source-label "SEO buyer intent post"Active SEO agency owners:
python3 scripts/linkedin_outreach.py signal-add \
--name "active-seo-agency-owners" \
--type post_intent \
--query "SEO agency founder" \
--source-label "Active SEO agency owner" \
--limit 50 \
--scrolls 6Warm competitor/person engagement:
python3 scripts/linkedin_outreach.py signal-add \
--name "competitor-engagers" \
--type activity \
--target-url "https://www.linkedin.com/in/example/" \
--source-label "Engaged with watched profile" \
--limit 30Scout without sending:
python3 scripts/linkedin_outreach.py scout-search \
--query "SEO agency founder" \
--source-label "Active SEO agency owner" \
--signal-name "active-seo-agency-owners" \
--limit 50 \
--scrolls 6 \
--no-connectReview leads:
python3 scripts/linkedin_outreach.py review --list --limit 30
python3 scripts/linkedin_outreach.py review --queue li_abc123 li_def456Dry-run queued connection requests:
python3 scripts/linkedin_outreach.py connect --queued --limit 3Actually send only after explicit approval:
python3 scripts/linkedin_outreach.py connect \
--queued \
--limit 3 \
--execute \
--no-note \
--navigation-mode random \
--min-delay 45 \
--max-delay 90Before DMs, sync accepted connections:
python3 scripts/linkedin_outreach.py sync-connections --contacted --limit 12Send one first-degree DM:
python3 scripts/linkedin_outreach.py dm \
--lead-id li_abc123 \
--message "Hi {first_name}, thanks for connecting. Thought this might be useful..." \
--execute- Outbound commands default to dry-run.
- Connection requests send without a note by default.
- Custom connection notes are allowed only for exactly one selected lead.
- The browser is visible for login and runs locally.
- The script stops on LinkedIn checkpoints, CAPTCHA, restrictions, or unusual security prompts.
- Stop conditions record a 24-hour local safety cooldown in
~/.linkedin-outreach/db/safety_state.json. - Browser-heavy commands refuse to start during an active cooldown unless the operator manually resolves LinkedIn and passes
--force-cooldown-override. - Suppressed profiles in
~/.linkedin-outreach/db/suppressions.jsonare skipped during future lead upserts. - Already
sent,pending,connected, orskippedleads are not reopened for duplicate connection requests. sync-connectionsshould run before DMs so accepted requests are markedconnected.
python3 scripts/linkedin_outreach.py --help
python3 scripts/linkedin_outreach.py scout-search --help
python3 scripts/linkedin_outreach.py connect --help
python3 scripts/linkedin_outreach.py dm --helpEvery command emits one final machine-readable line:
RESULT: {"status": "ok", ...}
Agents should treat the RESULT: line as the source of truth.
- No shared database. Leads, actions, templates, and signals live on the user's machine.
- No cookies in Git. LinkedIn sessions are saved under
~/.linkedin-outreach/session/, outside this repo by default. - No proxy or stealth system. This is deliberate local automation for normal, low-volume personal-account workflows.
- No telemetry. The script writes local JSON files and drives the user's visible browser session.
This skill helps with LinkedIn lead scouting and outreach. Distribb handles the broader SEO system:
- keyword research with buyer-intent signals
- content publishing to WordPress, Webflow, and Shopify
- original-data research pages
- internal linking and content repurposing
- backlink exchange through a high-DR partner network
-> Try Distribb free at distribb.io
Built by Borja Obeso, founder of Distribb.