Template. Replace placeholder values like {{YOUR_NAME}}, {{CONTENT_DIR}}, etc. with your own before using.

Content Creation

LinkedIn Posts

Generate LinkedIn posts with approval workflows and Playwright-based publishing, enforcing hooks with specific numbers, humanizer passes, and platform-specific scheduling.

MCP Required. This skill needs Playwright to run.

Save to ~/.claude/skills/linkedin-posts/SKILL.md
SKILL.md
---
name: linkedin-posts
description: "Generate LinkedIn posts from a script or from scratch, with approval workflow and Playwright-based publishing/scheduling. Use when: creating LinkedIn content. Triggers on: linkedin post, linkedin posts, write a post, create a post."
---

# LinkedIn Posts

## Prerequisites

**Publishing/scheduling uses the Playwright MCP server — this is the ONLY method.**
Use `mcp__playwright__*` tools (browser_navigate, browser_click, browser_snapshot, browser_type, browser_file_upload, etc.) to automate LinkedIn directly in the browser. Do NOT use Chrome extension tools (`mcp__claude-in-chrome__*`) — those are unrelated.

1. Verify Playwright MCP is connected (check that `mcp__playwright__browser_navigate` is available)
2. User must be logged into LinkedIn in the Playwright-controlled browser
3. If Playwright MCP is genuinely unavailable after checking, fall back to saving posts for manual publishing

---

## Workflow

### Step 1: Choose Mode

Ask the user:
- **Option A: From existing script** → ask which project folder, then read:
  `{{CONTENT_DIR}}/[folder-title]/script.md`
- **Option B: From scratch** → ask for topic, key talking points, any specific data/stories/angles

### Step 2: Load Context Files
- `{{PROFILE_PATH}}` — identity, experience, voice
- `~/.claude/skills/linkedin-posts/hooks.md` — hook templates

### Step 3: Analyze Source Material

**Mode A (from script):** Extract key insights, contrarian takes, audience pain points, stories.

**Mode B (from scratch):** Use topic + key points. If thin, ask:
- "Any specific data points or numbers?"
- "A story or personal experience tied to this?"
- "Who's the target audience?"

### Step 4: Generate 3 Posts

Each post must:
1. Use a DIFFERENT hook style (practical, contrarian, story-based) — ALL must pass Hook Rules below
2. Be substantial — real depth, specific details, data when available
3. Conversational and authentic, not salesy
4. End with a CTA (vary across posts):
   - Question: "What's your experience with X?"
   - Video reference: "Full breakdown in the video (link in comments)"
   - Challenge: "I'd love for someone to tell me I'm wrong."

**Style:** Substantial long-form, opinion-driven, first-person. Separators: dashes, bullets, arrows (->). Minimal emoji. Short paragraphs. Drop a swear word here and there naturally - "bullshit", "damn", "hell", "no shit" - this matches {{YOUR_NAME}}'s real voice. Don't overdo it (1-2 per post max), but don't sanitize the language either. Sterile, clean copy sounds fake.

**Humanizer pass (NON-NEGOTIABLE):**
Before presenting any post to the user, scan for and fix all 24 AI writing patterns from the `humanizer` skill. Key offenders: significance inflation, AI vocabulary ("delve", "landscape", "foster", "crucial"), copula avoidance ("serves as"), -ing analyses, filler phrases, excessive hedging, generic conclusions. Writing must have soul - opinions, varied rhythm, specific details.

**No false-contrast filler (NON-NEGOTIABLE):**
NEVER use the "isn't X / it's Y" or "not about X / it's about Y" pattern. This is lazy copy that wastes words negating something just to state the real point. Say what you mean directly.

❌ "The goal isn't just to make my team more efficient. It's to make them more technical."
✅ "The goal is to make my team more efficient and technical."

❌ "This isn't about automation. It's about leverage."
✅ "This is about leverage."

❌ "I'm not saying AI will replace you. I'm saying AI will make you dangerous."
✅ "AI will make you dangerous."

If you catch yourself writing "isn't/not [something]. It's [the real point]" — delete the first sentence and lead with the real point. Every time.

**Revenue flex rule (NON-NEGOTIABLE):**
NEVER mention {{YOUR_NAME}}'s personal revenue, MRR, ARR, income, or earnings in any post. No "I hit $X/month", no "my agency does $Xk MRR", no revenue screenshots, no income milestones. Referencing other companies' public revenue numbers (e.g. "Salesforce's $300B valuation") is fine — flexing personal money is not.

### Hook Rules (NON-NEGOTIABLE)

Every hook MUST pass both tests:

**1. The Number Test** — at least one specific number ($76M, 90 days, 15-person team, 70-80%, etc.)

❌ "AI SDRs are failing"
✅ "AI SDRs raised $200M+ and 70-80% of implementations fail by month 3"

**2. The Visualization Test** — reader can picture a specific scene. "Can I see this in my head?"

❌ "Sales teams struggle with outbound"
✅ "I had coffee with a VP of Sales last week who's never heard of Clay"

**Both together:** "The biggest AI SDR company raised $76M from a16z. Then they got caught lying about their customers. The CEO just stepped down." (Numbers: $76M. Visual: the scandal, CEO stepping down.)

**Using the Profile:**
- If topic connects to user's experience, ASK: "Does this relate to something you've experienced? Any story I should weave in?"
- Reference their expertise, match voice/tone, use their tools/stack in examples

### Step 5: Approval Loop

For each post, display content + hook validation, then ask: **"Approve / Edit / Regenerate / Skip?"**

```
Hook validation:
- Number: [the number used] ✓
- Visual: [the scene/image] ✓
```

Continue until all posts approved or skipped.

### Step 6: Choose Photo or Diagram (NON-NEGOTIABLE)

Every approved post needs a visual. For each approved post, ask:
**"Use a personal photo, or create a branded diagram?"**

- **User has a photo** → get the file path
- **Pick from personal photos** → list files in `{{PHOTOS_DIR}}/` (filenames contain descriptions - read those, do NOT open/view the images). Suggest 2-3 photos that match the post's vibe/tone, explain why each fits. User picks one.
- **Branded diagram** → invoke the `branded-visual` skill:
  1. Pass the post content as context (concepts, frameworks, comparisons, or flows)
  2. Platform: LinkedIn (1080x1350)
  3. The branded-visual skill handles: Excalidraw concept → branded HTML → screenshot
  4. Returns a file path to the final branded screenshot
  5. Use that screenshot file path as the post's image in Step 8

### Step 7: Publish or Schedule?

Per approved post, ask: **"Publish now or schedule for later?"**
- Schedule → ask which day (e.g. "tomorrow", "Wednesday", etc.)

**Scheduling timezone rule (NON-NEGOTIABLE):**
- Default time is **{{PREFERRED_POST_TIME}}** unless user specifies otherwise
- {{YOUR_NAME}} travels internationally. LinkedIn's scheduler may show a different local timezone based on browser/location.
- When scheduling, you MUST calculate the correct time to enter in LinkedIn's UI so the post goes live at {{PREFERRED_POST_TIME}} regardless of what timezone LinkedIn displays.
  - Example: If LinkedIn shows Pacific Time, enter 6:00 AM. If LinkedIn shows CET (UTC+1), enter 3:00 PM.
- After setting the time, `browser_snapshot` to confirm the displayed schedule matches {{PREFERRED_POST_TIME}} before clicking "Schedule"

### Step 8: Post via Playwright MCP

**Use `mcp__playwright__*` tools for all browser automation. Do NOT use Chrome extension tools.**

1. `mcp__playwright__browser_navigate` to `https://www.linkedin.com/feed`
2. `mcp__playwright__browser_snapshot` to confirm page loaded and user is logged in
3. For each approved post:
   - `browser_click` "Start a post" → `browser_snapshot`
   - `browser_type` post content
   - `browser_click` the photo/media icon → `browser_file_upload` with the chosen photo path → `browser_snapshot` to verify photo attached
   - **Publish now:** `browser_click` "Post"
   - **Schedule:** `browser_click` clock/schedule icon → `browser_snapshot` → note what timezone LinkedIn displays → calculate the correct local time that equals {{PREFERRED_POST_TIME}} → set that date/time → `browser_snapshot` to verify it maps to {{PREFERRED_POST_TIME}} → `browser_click` "Schedule"
   - `browser_snapshot` to verify success
4. Confirm to user with scheduled time shown as ET

**Fallback (only if Playwright MCP is genuinely unavailable):**
Save to `linkedin-posts.md` with scheduled times (in ET) and photo paths. Display copy-ready output.

### Step 9: Save Output

- **Mode A:** Save as `linkedin-posts.md` in same folder as script
- **Mode B:** Ask where to save, default: `{{CONTENT_DIR}}/linkedin-posts/`

Display all approved posts in chat.

---

## Reference Examples

### Practical/Educational
```
If you're running ABM, you should start scoring awareness.

Unlike other RevOps systems, reps LOVE this.

It answers one question: "Does this account actually know we exist?"

[Post continues with 5-stage framework and implementation details...]
```

### Contrarian/Opinion
```
Salesforce promised us an AI revolution with Agentforce. I'm looking around, and all I see is a whole lot of nothing.

The $300B giant is stumbling.

-> Technical glitches.
-> Slow adoption.
-> Executives quietly backpedaling on their "agentic AI" promises.

Meanwhile...
A 22-year-old with Clay and a $50 API key just automated more work than their entire Enterprise implementation.

[Post continues with contrarian take on enterprise vs modern stack...]
```

### Story/Data-Driven
```
I had coffee with a VP of Sales last week who's never heard of Clay.

Not "heard of it but doesn't use it." Never. Heard. Of. It.

This is a guy running a 15-person SDR team at a Series B SaaS company doing $20M ARR.

Smart operator. Reads all the sales blogs. Goes to conferences.

And when I mentioned waterfall enrichment, he looked at me like I was speaking Giberish.

[Post continues with data on Clay vs Salesforce adoption and bubble thesis...]
```

---

## Output Format

Before saving, verify each hook passes both tests:
- [ ] Post 1: Number? ___ / Visual? ___
- [ ] Post 2: Number? ___ / Visual? ___
- [ ] Post 3: Number? ___ / Visual? ___

If any fails, rewrite that hook before proceeding.

```
# LinkedIn Posts — [Topic/Video Title]

---

## Post 1: [Hook Style]
**Action:** [Published / Scheduled for Date & Time] | **Status:** [Posted via Playwright / Ready for manual posting]
**Photo:** [filename or path]

[Full post content]

---

## Post 2: [Hook Style]
**Action:** [Published / Scheduled for Date & Time] | **Status:** [Posted via Playwright / Ready for manual posting]
**Photo:** [filename or path]

[Full post content]

---

## Post 3: [Hook Style]
**Action:** [Published / Scheduled for Date & Time] | **Status:** [Posted via Playwright / Ready for manual posting]
**Photo:** [filename or path]

[Full post content]
```