Social Post Fetcher

Playbook social posts

by growthenginenowoslawski · MIT license · ★ 736 on GitHub

Playbook social posts cover

Fetches the most recent usable LinkedIn post from a company page OR a person's profile and stores the post content itself, with an optional AI personalization line on top. Triggers on "what did they post about", "recent LinkedIn post",…

---
name: playbook-social-posts
description: Fetches the most recent usable LinkedIn post from a company page OR a person's profile and stores the post content itself, with an optional AI personalization line on top. Triggers on "what did they post about", "recent LinkedIn post", "social signal", "reference their content", "they posted about X", "what is this person posting", "engage with their content". Outputs social_post_text (the raw post) plus social_post_url and social_post_days_ago; social_post_line only when the operator asks for one.
---

# Playbook: Recent Social Post

> All rules here are best practice, not law. Override any of them when the campaign calls for it; note the best practice once and move on.

**Use when:** the campaign wants proof you read the account's content and there is no sharper
structural signal (funding, new-in-role, hiring surge).

**Not this playbook:** who *engaged* with a post (`playbook-linkedin-engagement`); a job change
(`playbook-new-in-role`).

**Output:** `social_post_text` + `social_post_url` + `social_post_days_ago` + `social_post_author_type`.
Optional, on request only: `social_post_line` → `Noticed they became an IBM Business Partner.`

Overview

Use when: the campaign wants proof you read the account's content and there is no sharper structural signal (funding, new-in-role, hiring surge).

Manual install (npx, ZIP)
Claude Codenpx skills add growthenginenowoslawski/coldoutboundskills --skill playbook-social-posts -g -a claude-code
Claude Code (degit)npx degit growthenginenowoslawski/coldoutboundskills/skills/playbooks/playbook-social-posts#main ~/.claude/skills/playbook-social-posts
Claude.ai / desktopZip the folder and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md7.3 KB
Read SKILL.md here
growthenginenowoslawski/main1 file shown
SKILL.md
Show the full text135 lines

Playbook: Recent Social Post

All rules here are best practice, not law. Override any of them when the campaign calls for it; note the best practice once and move on.

Use when: the campaign wants proof you read the account's content and there is no sharper structural signal (funding, new-in-role, hiring surge).

Not this playbook: who engaged with a post (playbook-linkedin-engagement); a job change (playbook-new-in-role).

Output: social_post_text + social_post_url + social_post_days_ago + social_post_author_type. Optional, on request only: social_post_line → Noticed they became an IBM Business Partner.

Six decisions that govern every run

1. The raw post is the product. The AI line is an optional layer, not the point. A human reading the actual post writes a better sentence than any generated line, and the post text is reusable for every future campaign; a generated line is not.

2. Input is a profile URL, either kind — a company page or a person. One scraper takes both.

  • Company runs: dedupe to companies, then fan the one result out to every contact there.
  • Person runs: never fan out.
  • Never guess a slug. They are frequently not what you would predict from the company name.

3. The content skip filter is mandatory and fails closed.

Skip personal, political, bereavement, and charged (religious or geopolitical flashpoints).

  • A skip takes the NEXT post. It is not an abstain.
  • Error, bad parse, or a missing skip key all mean SKIP. Only a literal "skip": false keeps the post.
  • Never disable it to raise fill.

Ordinary business content passes: memes, polls, job ads, volunteering, work anniversaries, regulation commentary.

4. Blank, never invented. Nothing usable means "" everywhere. No guess, no "N/A", no sequencer-side fallback value.

5. Two operator questions at setup. "A written personalization line, or just the post content?" (default: content only.) "Trust the scrape, or add a verification pass?" (default: trust it — verification checks existence, never text.)

6. Empty rows are gated by a LIST SPLIT before upload, never by spintax.

Spintax picks at random and cannot see an empty variable. {Noticed {{social_post_line}}. |} both renders Noticed . into inboxes and discards personalization you already paid for.

Split the list on social_post_line != "". Segment B has the clause removed and rewritten — and it is your honest A/B control. Never exclude empties, never set a fallback.

QC: grep -c "Noticed \." rendered_preview.csv must be 0.

The best call, and three traps in it

Scrape company posts with an async 3-call pattern: start the run, poll for completion, read the dataset.

⚠️ Never use a synchronous run-and-get-items endpoint. It held the client past 120s on a run that took 25s.

Body: up to ~100 target URLs, maxPosts: 3, a 3-month window, reposts off, quote posts on. Then the skip filter over each post newest-first, keeping the first that clears.

  • Batch the URLs. Each run start bills separately, so a batch of 8 costs the same start fee as a batch of 1.
  • Keep reaction and comment scraping off. You are not building an engagement list here.
  • ⚠️ The profile join key will bite you. On person items the company-style identifier is null; the slug lives in a different field and the author type differs. Group on universalName or publicIdentifier, or every person row silently vanishes.
  • Low reasoning effort on the skip filter is load-bearing — at default effort it hung past 180s. finish_reason=length with empty content means retry with double the cap, never an abstain.

Honesty gates

Coverage: 71% of company pages had a usable post in the test — and that is a floor for the field and an upper bound for this kind of list, because the sample was 17 high-frequency B2B SaaS posters.

SMB, trades and long-tail: expect 20 to 40%. Under about 50 employees the company page is usually dead, and the founder's personal profile is the intended lever (fill unmeasured).

Measure fill on a 100-row sample of YOUR list before writing copy around it.

Tests: skip filter 18/18. Optional line 8/9 (89%) held out. Person-URL probe 1/1.

⚠️ The reshaped chain has not been run end to end. Parts tested, composition not. The first operator to run it at any size owes the file a real fill rate and a re-measured cost — read the charged-event count, never estimate.

Cost

About $2.95 per 1,000 unique profiles in the default content-only shape, rising to about $3.66 with the optional line.

⚠️ Campaign rows are contacts, not profiles. Dedupe before this playbook and fan the result back out: a 1,000-contact list covering 620 accounts costs about $1.83, not $2.95. Costing this per contact overstates it by your contacts-per-company ratio.

Clay implementation

  • clay-table.md — the column build, including the degraded variant for when async polling is not available.
  • clay-workflow.md — the CLI-buildable version.

Edge cases and failure modes

Symptom Cause Fix
The client times out on a fast run A synchronous run-and-fetch endpoint The async 3-call pattern
Every person row vanishes at the join On person items the company-style identifier is null Group on universalName or publicIdentifier
Cost is much higher than expected Each run start bills separately Batch the URLs. 8 in a batch cost one start fee
The filter passes something you would never send It was disabled to raise fill Never disable it. A skip takes the next post
A row abstains when a later post would have worked A skip was treated as an abstain A skip advances to the next post
A malformed filter response keeps a bad post The filter failed open Fail closed. Only a literal "skip": false keeps a post
Noticed . in rendered previews Spintax used as an if-populated gate Split the list. Grep the rendered preview to zero
A generated line references a post the account did not write Reposts were included Reposts off
Fill is 20% on an SMB list and 71% was promised The 71% came from high-frequency SaaS posters Measure fill on your own list. Use founder profiles for small companies
The scraper is down and the run fails over to another source There is no fallback by design The signal abstains; it does not fail over
Hard rules
  • The raw post is the deliverable. The line is opt-in.
  • The skip filter is mandatory and fails closed.
  • Blank, never invented — and no sequencer-side fallback value.
  • List split, never spintax.
  • Dedupe to profiles before scraping, fan out after.
1---
2name: playbook-social-posts
3description: Fetches the most recent usable LinkedIn post from a company page OR a person's profile and stores the post content itself, with an optional AI personalization line on top. Triggers on "what did they post about", "recent LinkedIn post", "social signal", "reference their content", "they posted about X", "what is this person posting", "engage with their content". Outputs social_post_text (the raw post) plus social_post_url and social_post_days_ago; social_post_line only when the operator asks for one.
4---
5 
6# Playbook: Recent Social Post
7 
8> All rules here are best practice, not law. Override any of them when the campaign calls for it; note the best practice once and move on.
9 
10**Use when:** the campaign wants proof you read the account's content and there is no sharper
11structural signal (funding, new-in-role, hiring surge).
12 
13**Not this playbook:** who *engaged* with a post (`playbook-linkedin-engagement`); a job change
14(`playbook-new-in-role`).
15 
16**Output:** `social_post_text` + `social_post_url` + `social_post_days_ago` + `social_post_author_type`.
17Optional, on request only: `social_post_line` → `Noticed they became an IBM Business Partner.`
18 
19## Six decisions that govern every run
20 
21**1. The raw post is the product.** The AI line is an optional layer, not the point. A human reading
22the actual post writes a better sentence than any generated line, and the post text is reusable for
23every future campaign; a generated line is not.
24 
25**2. Input is a profile URL, either kind** — a company page or a person. One scraper takes both.
26 
27- **Company runs:** dedupe to companies, then **fan the one result out to every contact there.**
28- **Person runs: never fan out.**
29- **Never guess a slug.** They are frequently not what you would predict from the company name.
30 
31**3. The content skip filter is mandatory and fails closed.**
32 
33Skip `personal`, `political`, `bereavement`, and `charged` (religious or geopolitical flashpoints).
34 
35- **A skip takes the NEXT post. It is not an abstain.**
36- **Error, bad parse, or a missing `skip` key all mean SKIP.** Only a literal `"skip": false` keeps
37 the post.
38- **Never disable it to raise fill.**
39 
40Ordinary business content passes: memes, polls, job ads, volunteering, work anniversaries,
41regulation commentary.
42 
43**4. Blank, never invented.** Nothing usable means `""` everywhere. No guess, no "N/A", **no
44sequencer-side fallback value.**
45 
46**5. Two operator questions at setup.**
47"A written personalization line, or just the post content?" (default: content only.)
48"Trust the scrape, or add a verification pass?" (default: trust it — verification checks existence,
49never text.)
50 
51**6. Empty rows are gated by a LIST SPLIT before upload, never by spintax.**
52 
53Spintax picks at random and **cannot see an empty variable.** `{Noticed {{social_post_line}}. |}`
54both renders `Noticed .` into inboxes **and** discards personalization you already paid for.
55 
56Split the list on `social_post_line != ""`. Segment B has the clause **removed and rewritten** — and
57it is your honest A/B control. Never exclude empties, never set a fallback.
58 
59**QC:** `grep -c "Noticed \." rendered_preview.csv` must be `0`.
60 
61## The best call, and three traps in it
62 
63Scrape company posts with an **async 3-call pattern**: start the run, poll for completion, read the
64dataset.
65 
66⚠️ **Never use a synchronous run-and-get-items endpoint.** It held the client past 120s on a run
67that took 25s.
68 
69Body: up to ~100 target URLs, `maxPosts: 3`, a 3-month window, reposts off, quote posts on. Then the
70skip filter over each post **newest-first**, keeping the first that clears.
71 
72- **Batch the URLs.** Each run start bills separately, so a batch of 8 costs the same start fee as a
73 batch of 1.
74- **Keep reaction and comment scraping off.** You are not building an engagement list here.
75- ⚠️ **The profile join key will bite you.** On *person* items the company-style identifier is
76 **null**; the slug lives in a different field and the author type differs. **Group on
77 `universalName or publicIdentifier`, or every person row silently vanishes.**
78- **Low reasoning effort on the skip filter is load-bearing** — at default effort it hung past 180s.
79 `finish_reason=length` with empty content means **retry with double the cap, never an abstain.**
80 
81## Honesty gates
82 
83**Coverage: 71% of company pages had a usable post** in the test — and that is **a floor for the
84field and an upper bound for this kind of list**, because the sample was 17 high-frequency B2B SaaS
85posters.
86 
87**SMB, trades and long-tail: expect 20 to 40%.** Under about 50 employees the company page is usually
88dead, and **the founder's personal profile is the intended lever** (fill unmeasured).
89 
90**Measure fill on a 100-row sample of YOUR list before writing copy around it.**
91 
92**Tests:** skip filter **18/18**. Optional line **8/9 (89%)** held out. Person-URL probe **1/1**.
93 
94⚠️ **The reshaped chain has not been run end to end.** Parts tested, composition not. The first
95operator to run it at any size owes the file a real fill rate and a re-measured cost — **read the
96charged-event count, never estimate.**
97 
98## Cost
99 
100About **$2.95 per 1,000 unique profiles** in the default content-only shape, rising to about **$3.66**
101with the optional line.
102 
103⚠️ **Campaign rows are contacts, not profiles.** Dedupe before this playbook and fan the result back
104out: a 1,000-contact list covering 620 accounts costs about **$1.83**, not $2.95. Costing this per
105contact overstates it by your contacts-per-company ratio.
106 
107## Clay implementation
108 
109- **`clay-table.md`** — the column build, including the degraded variant for when async polling is
110 not available.
111- **`clay-workflow.md`** — the CLI-buildable version.
112 
113## Edge cases and failure modes
114 
115| Symptom | Cause | Fix |
116|---|---|---|
117| The client times out on a fast run | A synchronous run-and-fetch endpoint | The async 3-call pattern |
118| Every person row vanishes at the join | On person items the company-style identifier is **null** | Group on `universalName or publicIdentifier` |
119| Cost is much higher than expected | Each run start bills separately | **Batch the URLs.** 8 in a batch cost one start fee |
120| The filter passes something you would never send | It was disabled to raise fill | **Never disable it.** A skip takes the next post |
121| A row abstains when a later post would have worked | A skip was treated as an abstain | A skip advances to the next post |
122| A malformed filter response keeps a bad post | The filter failed **open** | **Fail closed.** Only a literal `"skip": false` keeps a post |
123| `Noticed .` in rendered previews | Spintax used as an if-populated gate | **Split the list.** Grep the rendered preview to zero |
124| A generated line references a post the account did not write | Reposts were included | Reposts off |
125| Fill is 20% on an SMB list and 71% was promised | The 71% came from high-frequency SaaS posters | Measure fill on your own list. Use founder profiles for small companies |
126| The scraper is down and the run fails over to another source | There is no fallback by design | The signal **abstains**; it does not fail over |
127 
128### Hard rules
129 
130- **The raw post is the deliverable. The line is opt-in.**
131- **The skip filter is mandatory and fails closed.**
132- **Blank, never invented — and no sequencer-side fallback value.**
133- **List split, never spintax.**
134- **Dedupe to profiles before scraping, fan out after.**
135 
View all files on GitHub →

Details

License
MIT
Stars on the repo
★ 736
Checked
Source
growthenginenowoslawski/coldoutboundskills ↗
Creator
growthenginenowoslawski · 52 listings
View creator

Similar skills

See all →
SkillAI LinkedIn Carousel Buildercharlie947/social-media-skills · by charlie947Generate a branded slide-by-slide LinkedIn carousel using Gemini. Takes source content, builds a design brief, waits for approval, then outputs per-slide image generation prompts. 1080x1350 vertical format. Use this skill whenever the user says "carousel", "build a carousel", "turn this into a carousel", "gemini carousel", or wants multi-slide LinkedIn content. Always includes an approval gate between brief and image generation.★ 3.7k GitHub starsSkillLinkedIn Carousel BuilderJakeschincariol/linkedin-agent-skill · by JakeschincariolBuild a LinkedIn document post (carousel) - slide-by-slide copy, the cover that earns the swipe, and the PDF to upload. Use when the user says carousel", "document post", "slides for LinkedIn", "turn this into a carousel", or has a list-shaped idea that would die as a text post.★ 1.9k GitHub starsSkillIG Caption Writersergebulaev/instagram-skills · by sergebulaevDraft an Instagram caption with the hook in the first 125 characters, a skimmable body, and one clear CTA, using a 2026 hook formula chosen by goal (saves, shares, comments, follows). Runs the humanizer pass and, on approval, publishes with the image or video you supply via the Publora media flow. Use to caption a single image or a Reel. Not for slide-by-slide carousels (use ig-carousel-planner) or auditing a draft (use ig-humanizer --mode audit).★ 138 GitHub starsSkillIG Carousel Plannersergebulaev/instagram-skills · by sergebulaevPlan an Instagram carousel slide by slide, up to 10 slides, with a hook slide that opens a loop, value slides that front-load the payoff, and a payoff slide that earns the save and follow. Picks a 2026 carousel formula (listicle, before/after, myth-buster, framework) by goal (saves, shares, follows), drafts each slide's text plus the caption, then publishes the images you supply via Publora. Use to structure a multi-slide carousel. Not for single-image captions (use ig-caption-writer).★ 138 GitHub starsSkillSocial Campaign Analyzeralirezarezvani/claude-skills · by alirezarezvaniSocial media campaign analysis and performance tracking. Calculates engagement rates, ROI, and benchmarks across platforms. Use when analyzing social media performance, calculating engagement rate, measuring campaign ROI, comparing platform metrics, or benchmarking against industry standards. Also use when the user mentions "social media audit," "engagement rate," or "which platform performs best.★ 26.3k GitHub starsSkillLinkedIn Post Performance Scorercharlie947/social-media-skills · by charlie947Score a LinkedIn post using real performance data. Pulls the user's own post history via Apify (or uses cached data) to identify what actually performs, then scores the draft against those patterns. Use this skill whenever the user says "score my post", "review my post", "rate this post", "give me feedback", "how good is this post", or pastes a LinkedIn post and asks for critique. Separates historical comparisons from an explicitly labelled editorial-only fallback. Designed for live scoring at events and everyday post review.★ 3.7k GitHub stars

More from growthenginenowoslawski

SkillCold Email Automationgrowthenginenowoslawski/coldoutboundskills · by growthenginenowoslawskiAutonomous cold email campaign launcher. Takes one target company domain, scrapes their website, generates an ICP with Claude, pulls matching leads via Prospeo, enriches emails + company descriptions, personalizes each lead with parallel Claude Code Task sub-agents (A/B/C variants), and uploads as a live Smartlead campaign. Uses local JSON files for state (no database required). Use for automated daily campaign launches after you have an initial `client-profile.yaml` from /icp-onboarding. Triggers on "auto-research", "launch an automated campaign", "daily campaign", "run the research loop".★ 736 GitHub starsSkillCompany Decision-Maker Findergrowthenginenowoslawski/coldoutboundskills · by growthenginenowoslawskiUse the Blitz API to find decision-makers at specific companies when you already have a list of company domains. Best for SMB owner-finding, domain-to-people lookup, or supplementing Prospeo results. Outputs a CSV you can feed to the email-waterfall or directly to /cold-email-starter-kit for Smartlead upload. Use when your targeting is company-first (not title-first).★ 736 GitHub starsSkillCold Outreach Strategistgrowthenginenowoslawski/coldoutboundskills · by growthenginenowoslawskiGenerates 15-25+ cold outbound campaign ideas with targeting strategies, AI personalization approaches, and value propositions. Use when planning campaign experiments for a client, given their website or business context.★ 736 GitHub starsSkillClay Signal Playbooksgrowthenginenowoslawski/coldoutboundskills · by growthenginenowoslawskiIndex and shared harness for the 19 signal playbooks. Each playbook turns one buying signal (new in role, raised a round, hiring surge, pricing page, tech on website, ...) into one copy-ready sentence you can drop into a cold email. Every playbook ships three ways to run it: as a Claude skill, as a Clay table built through a browser harness, and as a Clay workflow built from the clay CLI. Use when someone says "personalize this list", "what signal should I use", "build the Clay column for X", or names any of the 19 signals.★ 736 GitHub starsSkillCompetitor Engager Findergrowthenginenowoslawski/coldoutboundskills · by growthenginenowoslawskiFind people actively engaging with competitor LinkedIn posts. Given a website URL, discovers competitors, fetches their company and employee posts, collects all commenters and reactors, and outputs a deduplicated CSV of engaged prospects. Use when someone wants to find leads from competitor engagement, build outreach lists from LinkedIn activity, or analyze who interacts with competitor content.★ 736 GitHub starsSkillEmail Deliverability Crisisgrowthenginenowoslawski/coldoutboundskills · by growthenginenowoslawskiTriage playbook for when cold email deliverability breaks. Decision-tree guidance for "I landed in spam", "bounce rate spiked", "domain blacklisted", "inbox blocked in warmup", "reply rate dropped". Tells you what to check first, what to fix, and how long the fix takes. Pair with /email-deliverability-audit for diagnosis.★ 736 GitHub stars