linkedin-dmSend personalized LinkedIn direct messages to a list of existing 1st-degree connections via browser automation. Use when the user wants to message LinkedIn connections with AI-personalized outreach β e.g. nurturing leads, following up after events, reconnecting with contacts, or announcing something. Takes a data file (CSV/TSV) or plain list with connection names and companies, asks for outreach context/goal, generates a tailored message per person, and sends each one via browser automation. Handles message compose flow, character limits, and incremental status tracking.
Install via ClawdBot CLI:
clawdbot install 10Madh/linkedin-dmSends personalized LinkedIn messages to existing 1st-degree connections. Each message has:
Ask the user for their data file or list. Must include (or be added):
If only a plain list is provided, offer to convert to TSV.
Before writing any messages, navigate to /in/me/ and read the sender's profile:
Store these facts. They are used to identify relationship hooks with each connection.
Ask the user:
"What's your pitch / product message? This will be the consistent part of every message. Describe it in 1β2 sentences."
Then draft a polished pitch section (2β4 sentences max, punchy and clear). Show it to the user and get explicit approval. Do not start sending until the pitch is confirmed.
Example prompt: "Here's the pitch I'll use for everyone β confirm or edit:
'I'm building an AI calling agent β you give it a phone number + context, and it handles the call end-to-end. Think customer follow-ups, research calls, vendor coordination β anything phone-based that eats into your day. Happy to show you a demo if this sounds useful.'"
profile="chrome"): extension attached to LinkedIn tab (badge ON) β recommended for flagged accountsprofile="openclaw"): openclaw-managed Chrome, LinkedIn logged inAsk the user for a Google Sheet ID/URL to log outreach results. If they don't have one, offer to set one up (create tab + write headers). Confirm gog is authenticated (gog auth list).
If the user skips this, fall back to local linkedin_dm_progress.json but remind them the follow-up skill needs the sheet.
Only proceed once:
Before writing a message, compare the connection's profile against the sender's profile to find the strongest hook. Use this hierarchy β pick the highest that applies:
| Priority | Hook | Example opener |
|---|---|---|
| 1 | Same company (current or past) | "You and I both spent time at CREDβ¦" |
| 2 | Same college + overlapping years | "Fellow BITS Goa 2018 batch hereβ¦" |
| 3 | Same college (different years) | "BITS connect here β saw your journey fromβ¦" |
| 4 | Same industry/function | "Both been in fintech/product for a whileβ¦" |
| 5 | Mutual connection | "We're both connected to [Name]β¦" |
| 6 | Their work context (no personal hook) | "Seen what you've built at [Company]β¦" |
Combine the hook with a line about their current work to show you know what they do.
Send as two separate messages per person, back to back:
Message 1 β Personalized opener (unique per person)
[Relationship hook β 1 sentence]
[Acknowledgement of their work/role β 1 sentence]
Target: 100β180 chars. Feels like a genuine reach-out from someone who knows them.
Message 2 β Pitch (identical for everyone, confirmed upfront)
[Product description β 1β2 sentences]
[Relevant use case for their role β 1 sentence]
[Soft CTA β 1 sentence]
Target: 150β250 chars. Clear, punchy, no filler.
Why two messages?
Fallback: If sending two messages is technically difficult (e.g. bubble re-focusing issues), use Shift+Enter twice between the opener and pitch to create a paragraph break within a single message.
Do not:
Generate messages for the entire list first. Present them in a table:
| Name | Company | Relationship Hook Used | Message Preview |
|---|---|---|---|
| Shorya Saini | Razorpay | Same BITS batch | Hey Shorya, BITS Goa 2018 batch⦠|
Get user approval on the full batch before opening the browser. Allow edits per row.
/feed/ β mandatory, no exceptions, no skippinglinkedin.com/mynetwork/invite-connect/connections/ β type name in "Search by name"Not a Connection, skipgog sheets append with all fields (see CRM Tracking section)See references/browser-workflow.md for exact browser automation steps.
| Status | Meaning |
|---|---|
| Sent | Message delivered this session |
| Already Messaged | Recent conversation exists β skip |
| Not a Connection | No Message button or not in connections search |
| Profile Not Found | Could not identify the right person |
| Skipped | User chose to skip |
| Failed | Browser error β retry next session |
/feed/ before every single profile β non-negotiableAfter each message is sent, append a row to a Google Sheet. This sheet is the source of truth for all outreach β current session and future follow-up.
Ask the user for a Google Sheet ID or URL at the start of the session (or offer to create a new one). The sheet should have a tab named Outreach with these columns:
| Col | Field | Notes |
|---|---|---|
| A | Date Sent | ISO date, e.g. 2026-02-13 |
| B | Person Name | Full name |
| C | Role / Title | Their current headline from LinkedIn |
| D | Company | Current company |
| E | LinkedIn URL | Profile URL |
| F | Relationship Hook | What hook was used (e.g. "Same batch BITS Goa 2018", "Both at CRED 2022β23") |
| G | Opener Sent | Exact text of Message 1 |
| H | Pitch Sent | Exact text of Message 2 |
| I | Campaign | Short label for this batch (e.g. "AI Calling - Feb 2026") |
| J | Status | Always Sent when first logged β updated by follow-up skill |
| K | Notes | Anything notable (prior conversation, context, mutual connection used) |
| L | Last Updated | Timestamp of last status change |
Column I (Status) lifecycle β only Sent is written by this skill. The follow-up skill will update to:
Replied Β· Call Scheduled Β· Demo Done Β· Follow Up Sent Β· No Response Β· Closed Won Β· Closed Lost
After each message pair is sent, run:
gog sheets append <SHEET_ID> "Outreach!A:L" \
--values-json '[["<date>","<name>","<role>","<company>","<url>","<hook>","<opener>","<pitch>","<campaign>","Sent","<notes>","<timestamp>"]]' \
--insert INSERT_ROWS
If no sheet exists yet, tell the user:
"I'll need a Google Sheet to track outreach. Share an existing sheet ID/URL, or I can create one with the right columns."
To create a new sheet, use Drive (or ask user to create one and share the ID). Then write the header row:
gog sheets update <SHEET_ID> "Outreach!A1:L1" \
--values-json '[["Date Sent","Person Name","Role / Title","Company","LinkedIn URL","Relationship Hook","Opener Sent","Pitch Sent","Campaign","Status","Notes","Last Updated"]]' \
--input USER_ENTERED
If Google Sheets is not set up, fall back to a local linkedin_dm_progress.json:
{
"campaign": "AI Calling - Feb 2026",
"pitch": "confirmed pitch text",
"rows": [
{
"date": "2026-02-13",
"name": "Shorya Saini",
"role": "Senior Analytics Specialist",
"company": "Razorpay",
"url": "https://linkedin.com/in/shorya-saini",
"hook": "Same batch BITS Goa 2018",
"opener": "Hey Shorya...",
"pitch": "I'm building...",
"status": "Sent",
"notes": ""
}
]
}
Generated Mar 1, 2026
Sales teams use this skill to send personalized follow-up messages to LinkedIn connections after initial outreach or product demos, leveraging relationship hooks like shared companies or colleges to increase engagement. It automates the process of re-engaging leads with tailored openers and a consistent pitch, saving time while maintaining a human touch.
Professionals attending conferences or virtual events use the skill to reconnect with contacts met during the event, personalizing messages based on shared industry or mutual connections. It helps maintain relationships by sending timely, relevant outreach that references the event context, fostering ongoing engagement.
Startups or entrepreneurs use this skill to announce new products or features to their LinkedIn network, combining personalized openers with a standardized pitch section. It targets 1st-degree connections with tailored hooks like shared work history, making the announcement feel more relevant and increasing open rates.
Recruiters or hiring managers use the skill to reach out to potential candidates from their LinkedIn connections, personalizing messages based on career overlaps or education. It streamlines candidate engagement by automating message generation while ensuring each outreach feels individualized and respectful.
Offer a free tier with limited message sends per month and basic personalization, then charge for premium features like advanced analytics, unlimited sends, and CRM integrations. Revenue comes from monthly subscriptions, targeting small businesses and solo entrepreneurs who need scalable outreach.
Provide a managed service where agencies use the skill on behalf of clients to run LinkedIn outreach campaigns, charging a flat fee or retainer. Revenue is generated from service packages that include strategy, message crafting, and performance reporting, ideal for businesses lacking in-house expertise.
Sell enterprise licenses to large corporations for internal use by sales or marketing teams, with custom integrations into existing CRM systems like Salesforce. Revenue comes from annual contracts with tiered pricing based on user count and features, focusing on scalability and compliance needs.
π¬ Integration Tip
Integrate with Google Sheets for real-time progress tracking and CRM systems like HubSpot to sync outreach data, ensuring seamless workflow management and avoiding duplicate efforts.
Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Clau...
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
Search and analyze your own session logs (older/parent conversations) using jq.
Typed knowledge graph for structured agent memory and composable skills. Use when creating/querying entities (Person, Project, Task, Event, Document), linking related objects, enforcing constraints, planning multi-step actions as graph transformations, or when skills need to share state. Trigger on "remember", "what do I know about", "link X to Y", "show dependencies", entity CRUD, or cross-skill data access.
Ultimate AI agent memory system for Cursor, Claude, ChatGPT & Copilot. WAL protocol + vector search + git-notes + cloud backup. Never lose context again. Vibe-coding ready.
Headless browser automation CLI optimized for AI agents with accessibility tree snapshots and ref-based element selection