Skip to content
← All guides

4 Claude Skills for Content Creation

Most people use Claude to write a script and stop there. These 4 skills cover the whole loop instead: learning what actually goes viral, scoring the draft, getting it live, and turning the comments into leads. All 4 are below in full, nothing held back.

Install them in 2 minutes

A Claude skill is a folder with one file in it, called SKILL.md. Claude reads it and knows how to do the thing. That is the whole idea.

Each of the 4 below has its full file on this page. Make a folder, paste the file in, restart Claude. Once it is installed you call it by name, or just describe what you want and Claude picks the right one.

  • 1. Claude Code or Claude Desktop

    Make a folder for each skill inside ~/.claude/skills/ (all projects) or .claude/skills/ (one project). Folder name matches the skill name. Drop the SKILL.md inside. Restart Claude Code, or fully quit and relaunch Desktop.

  • 2. claude.ai in a browser, or Claude Cowork

    Go to Customize (or Settings), then Skills. Click the plus, then Upload skill. The dialog takes one at a time, so repeat it 4 times. Toggle each one on after it uploads.

  • 3. Only skills 3 and 4 need Blotato

    Viral Coach and Post Grader run on Claude alone, so you can use those today with nothing connected. Post Scheduler and Comment to DM talk to Blotato, so they need an account and the Blotato MCP installed. Setup walkthrough is inside the Post Scheduler file.

Skill 1: Viral Coach

Custom build

It learns from posts that already worked, then coaches every script you write after that.

Every AI writing tool gives generic advice because it learned from the whole internet. This one learns from a specific swipe file: posts that provably went viral. Yours, or creators you look up to.

You give it 5 to 10 posts that worked, plus 2 or 3 that flopped. It scores each one against the account's median views, then breaks it down on 8 axes: the hook, the question it plants, how many seconds until the first payoff, the structure beat by beat, how dense the specifics are, the one feeling it leaves, and why anyone would share it. The flops are the secret. Whatever the winners do and the flops don't is a real pattern. Everything else is noise.

It writes all of that to a file called viral-playbook.md, with every rule backed by a count, like 4 of 6 winners open on a number. From then on it runs in two ways. Write mode coaches you through a new script from just a topic, asking you for the real numbers instead of making them up. Coach mode takes a finished draft and holds it against your own winners, then writes 3 new hooks, each one modeled on a hook that already worked for you.

Save as viral-coach/SKILL.md
---
name: viral-coach
description: Learns what makes posts go viral from a swipe file of real posts (the user's own best performers, or creators they look up to), writes the patterns into a reusable viral-playbook.md, then coaches every new script against that playbook. Three modes. Learn builds or updates the playbook. Write coaches the user through a new script starting from a topic. Coach reviews a finished draft. Use when someone says "learn from these posts", "why did this go viral", "break down this reel", "add this to my playbook", "help me write a script", "coach my script", "does this match what works", or /viral-coach.
argument-hint: "[learn | write | coach] [posts, topic, or draft]"
allowed-tools: Read, Write, Edit, Glob, AskUserQuestion, mcp__blotato__blotato_list_top_posts, mcp__blotato__blotato_create_source
---

# Viral Coach

Generic AI writing advice comes from the whole internet. This skill learns from one specific swipe file: posts that provably worked, for one specific audience. It writes down what those posts have in common in `viral-playbook.md`, then holds every new script to it.

The playbook is the product. Every mode either builds it or uses it.

| Mode | Use when | Needs |
|---|---|---|
| **Learn** | Building the playbook, or adding a new winner to it | 3+ real posts |
| **Write** | Starting a new script from a topic | The playbook |
| **Coach** | Reviewing a draft that's already written | The playbook |

If someone asks for Write or Coach and there is no playbook, say so in one line and start Learn. Coaching without a playbook is generic advice, which is the thing this skill exists to replace.

## Finding the playbook

Look in this order: `viral-playbook.md` in the working folder, a file the user attached, then the project's knowledge files.

If you can't save files in this environment (a claude.ai chat), print the finished playbook as one block and tell the user: save it as `viral-playbook.md` and add it to your Project's files, so every future chat can read it.

---

## Mode 1: Learn

### Step 1: Gather the posts

Minimum 3 posts. Aim for 5 to 10 winners, **plus 2 or 3 posts from the same account that flopped.** The flops are what turn "this worked" into "this is why it worked." Anything the winners do and the flops don't is a real pattern. Anything both do explains nothing.

Get the posts whichever way is fastest:

- **Pasted transcripts or captions.** Always works.
- **TikTok or YouTube links.** If the Blotato MCP is connected, pull each transcript with `blotato_create_source` (sourceType `tiktok` or `youtube`).
- **The user's own Instagram, Facebook, Threads, X or Bluesky posts.** If Blotato is connected, `blotato_list_top_posts` returns their best posts ranked by views, with real metrics. Pull the last 90 days with limit 100, and use the whole list to work out the account's median views. If it returns a full 100, shorten the window so the median isn't skewed high. This only sees posts published through Blotato. If it comes back empty, their posts went out natively: say so in one line and ask them to paste the posts and their view counts instead.
- **Instagram reel links.** There's no extractor for these. Ask for the transcript.

For video, the caption is not the script. If all you have is captions, say the breakdown will miss the spoken hook, and ask for transcripts of at least the top 3.

### Step 2: Get the numbers

For each post: views, and the account's median views over the same period. Saves, shares, comments and follows gained too, when they have them.

Score each post as an **outlier multiple: views divided by the account's median.** 3x or more is an outlier. Under 1x is a flop.

Weight each post by where it came from:

| Source | Weight | Why |
|---|---|---|
| Own post, 3x+ | Highest | Proven with this voice and this audience |
| Own post, 1x to 3x | High | Repeatable, lower ceiling |
| Another creator, same niche, 3x+ | Medium | Transferable, but a different audience |
| Another creator, different niche | Low | Borrow the structure only, never the topic |

No numbers at all? Keep going, but set the playbook's confidence to Low and say why.

### Step 3: Break down each post on 8 axes

1. **The hook.** The first line verbatim. The first 3 words on their own. The hook category: Receipt, Contrarian, Negative Frame, Stolen Lesson, Curiosity Gap, Listicle, Secret, Audience Callout, Question, Transformation, Speed, Urgency, or Confession. The on-screen text too, if you know it. Never guess the on-screen text.
2. **The open loop.** The question the hook plants that only finishing the video answers. Write it as an actual question.
3. **Time to first payoff.** Count the words before the viewer gets something real, then divide by 2.7 (about 160 spoken words a minute) to get seconds. Over 5 seconds is a leak. If the post worked anyway, name what bought the patience.
4. **The beat map.** 5 to 9 beats, one line each. Mark where the proof lands, where the turn is, and where the CTA sits.
5. **Specificity.** List every number, name, dollar amount, named tool and timestamp. Report it as specifics per 100 words.
6. **The emotion.** The single feeling it leaves: surprise, vindication, FOMO, relief, outrage, recognition. Winners almost always have one clear feeling. Flops usually have none.
7. **The share or save reason.** Why would someone send this to a friend, or save it? Because it makes them look smart, proves something they already believe, or solves a problem they'll have again. "It's informative" means you haven't found the reason yet.
8. **What it skipped.** No intro, no "hey guys", no context-setting, no follow ask in the opening. What's missing matters as much as what's there.

### Step 4: Find the patterns

This is the actual work. A stack of breakdowns is not a playbook.

- **Count everything.** "4 of 6 winners open on a number" is a pattern. "Winners tend to use numbers" is a guess. Every pattern gets a count and names the posts behind it.
- **Contrast against the flops.** In the winners and missing from the flops = a rule. In both = drop it.
- **Find the spine.** The beat order the winners share, written as a reusable template with placeholders.
- **Set the floors.** The lowest specifics-per-100-words among the winners becomes the minimum for every future draft. The slowest time-to-payoff among the winners becomes the maximum.
- **Set the length band.** The real word range of the winners, and the spoken seconds.
- **Exclude the one-offs.** Breaking news, a famous guest, a trend sound that's now dead, a collab that borrowed someone else's audience. Name it, exclude it, say why. A lucky hit written up as a formula is how playbooks go wrong.

### Step 5: Write `viral-playbook.md`

```markdown
# Viral Playbook

Version [N], [date]
Built from [N] winners and [N] flops. Confidence: [Low / Medium / High]
(Low: under 5 posts or no numbers. Medium: 5 to 9 with numbers. High: 10+ with numbers.)

## My lane
The hook categories that work for this account, ranked, each with its count and posts.

## The spine
The winners' shared beat order, as a template with placeholders.

## Hard rules
Each rule cites its evidence.
- Open on [X]. [4 of 6 winners, 0 of 3 flops: post, post, post]

## Floors
- Minimum [N] specifics per 100 words (set by [post])
- First payoff by second [N] (set by [post])
- Length: [N] to [N] words, [N] to [N] seconds

## Anti-patterns
In the flops, missing from the winners. Never do these.

## Hook bank
Every winning hook, verbatim, with its multiple and category.
- "[hook]" ([N]x, [category])

## Per-post breakdowns
The full 8-axis breakdown for every post, so every rule stays traceable.

## Excluded
Posts that worked for reasons that don't repeat, and why.

## Changelog
- v[N], [date]: [what changed, and which post changed it]
```

Every section gets real content. No "TBD". Write and Coach cite this file line by line, so a gap here becomes bad advice later.

### Step 6: Keep it alive

**Adding a post** ("add this to my playbook"): run Steps 2 and 3 on the new post only, then check whether it makes any rule stronger, weaker, or breaks it. Add its hook to the hook bank if it's a winner. Bump the version and add a changelog line. Don't rewrite the whole file.

**Staleness:** if the playbook is more than 90 days old, say so at the start of any session and suggest a refresh. Platforms shift and old patterns go stale.

---

## Mode 2: Write

Coach the user through a new script, starting from a topic. They supply the substance. You supply the structure. Never invent a result, a number, or a story for them.

1. **Topic and angle.** Ask what it's about and what real thing they're bringing: a result, a number, an opinion, a mistake, or a story. The angle picks the hook category.
2. **Lane check.** Is that category in their lane, per the playbook? If not, say so and offer the closest angle that is. They decide.
3. **3 hooks.** Each one modeled on a named post from the hook bank. Say what each one borrows, for example "same Receipt shape as your 11x post: the result first, then the doubt." Recommend one.
4. **Fill the spine.** Lay out the spine's beats with the topic mapped onto them. For every beat that needs a specific, ask for it directly: "What's the exact number here?" Wait for real answers.
5. **Assemble.** Write the draft from their answers, in their words, inside the length band. Mark any line you had to assume with [CHECK].
6. **Coach it.** Run Mode 3 on the draft before you hand it over.

---

## Mode 3: Coach

### Step 1: Read the playbook

Coach against it only, not against general best practice. The whole value is that it's specific to this account.

### Step 2: Check the rules

Every hard rule and every floor: pass or fail, with the quoted line that decides it.

### Step 3: Coach in the order viewers drop off

1. **Hook.** Quote the first 3 words. Name the category, or say "none". Write 3 rewrites, each modeled on a named post in the hook bank. Pick one and say why.
2. **Payoff timing.** Words before the first payoff, converted to seconds, against the playbook's maximum.
3. **Spine.** The draft's beats next to the playbook spine. Name every beat that's missing, late or padded, with evidence: "your proof lands at beat 6; in 4 of 5 winners it's beat 2."
4. **Specificity.** Specifics per 100 words against the floor. For every vague phrase, the question that turns it into a number or a name. Ask. Never invent.
5. **Emotion and share reason.** What feeling does it leave, and why would anyone send it? If you can't name either one, say so. That's usually why a correct script feels flat.
6. **Anti-patterns.** Quote every violation.

### Step 4: Output

```
## Coached against viral-playbook.md (v[N], [N] posts, [confidence])

Playbook fit: [strong / mixed / off-lane]

### Hook
Current: "[first 3 words]" ([category or none])
1. [rewrite], modeled on "[hook bank entry]"
2. [rewrite], modeled on "[hook bank entry]"
3. [rewrite], modeled on "[hook bank entry]"
Ship #[N], because [reason]

### Rules and floors
| Rule | Pass/Fail | Deciding line |

### Spine
| Beat | Your draft | Playbook | Verdict |

### Specificity
[N] per 100 words. Floor is [N].
[vague phrase] -> [the question that fixes it]

### Emotion and share reason
[feeling], [share reason], or "can't name one" and why

### Biggest retention leak
"[line]": [why they drop here]

### The one change that matters most
[the single highest-leverage fix]
```

### Step 5: Offer the rewrite

Ask: "Want me to apply this and hand back the rewritten script?" Only rewrite on a yes. Coaching teaches; silently rewriting doesn't. If the post-grader skill is installed, offer to grade the final version.

---

## Rules

- **No playbook, no coaching.** Start Learn.
- **Under 3 posts, no playbook.** Ask for more.
- **Every pattern carries a count and names its posts.**
- **Never invent specifics, results or stories.** Ask for them.
- **The playbook shapes structure, not personality.** If a rule would make them sound like someone else, flag it.
- **Don't soften the read.** Off-lane is off-lane. The point is catching it before it's filmed.

Skill 2: Post Grader

Blotato's free pack

Paste a draft, get a score out of 10 and the 3 fixes that matter most.

It grades across 7 dimensions, but the hook is weighted at 50%. That single choice is what makes it useful. A 10/10 hook with a mediocre body still scores around 7.5. A 4/10 hook with everything else perfect maxes out at 7.

So when it hands back anything under an 8, the fix is almost always the same: rewrite the hook. It tells you that instead of letting you polish a body nobody reads.

It also runs a voice-rules audit. Em dashes, filler words, filler openers, passive voice, hashtag count per platform. Each failure costs half a point.

Save as post-grader/SKILL.md
---
name: post-grader
description: Grade a social media post for VIRALITY. Scores hook strength (50% — most critical), curiosity, emotional charge, share-worthiness, voice match, polarity, and platform fit. Returns a score out of 10, a scorecard, and the top 3 fixes ranked by impact. Auto-invoked by post-writer; usable standalone when a user pastes their own draft and asks "is this good?" or "grade this post."
argument-hint: "[post text or path] [platform]"
allowed-tools: Read, Glob, AskUserQuestion
---

# Post Grader

You grade social media posts and tell the user exactly what to fix. You don't write or rewrite — you score, identify problems, and recommend specific changes. The post writer (or the user) applies the fixes.

**Be harsh but fair.** A 7 is good. An 8 is strong. A 9 means almost nothing needs fixing. A 10 doesn't exist. False positives waste more time than honest feedback.

## When to Activate

- "Grade this post"
- "Is this caption any good?"
- "Tell me what's wrong with this draft"
- Auto-called by `post-writer` as the final step.

If the user just pastes a post with no instruction, default to grading it.

## Workflow

### Step 1: Get the post

The post comes as text inline, or as a file path. If you're invoked by `post-writer`, you'll get the draft directly. If standalone, ask the user for:
1. The post text
2. The target platform

### Step 2: Read brand brief if available

Check for `brand-brief.md` in the current directory. If found, read it — you'll grade voice match against the user's defined voice. If missing, skip the voice-match dimension and note it in the output.

### Step 3: Grade across 7 dimensions

Score each on 1-10. Be specific about the issue when scoring under 8. **Hook is weighted 50% — it's the single most important dimension. A weak hook tanks the whole post no matter how good the body is.**

| Dimension | What to check |
|-----------|--------------|
| **Hook strength (0-10)** | Does the first line stop the scroll? Specifically: would someone reading the FIRST 3-5 WORDS keep reading? Is it specific, surprising, polarizing, or emotionally charged? Or does it open with throat-clearing ("In today's world," "Let me tell you about," "Here's something I've been thinking about")? Bonus signal: would this hook still work as a standalone tweet? Score brutally — most hooks are 4-6/10. |
| **Curiosity & specificity (0-10)** | Real numbers, real names, real moments — or generic statements ("many customers," "great results")? Does the post create a question/tension and then resolve it? Will the reader want to keep going past the first paragraph? |
| **Emotional charge (0-10)** | Does the post provoke a strong feeling — surprise, anger, vindication, recognition, pride, indignation, relief? Posts without emotion don't travel. If you finish reading and feel nothing, score low. |
| **Share-worthiness (0-10)** | Would a reader actually tag a friend, screenshot it, save it, or forward it? What's the specific reason they'd share — does it make THEM look smart, validate something they believe, or solve a recurring problem? "Informative" is not share-worthy. "I needed to hear this today" is. |
| **Voice match (0-10)** | Does it sound like the user's voice as defined in `brand-brief.md`? Does it have a specific point of view, or could it have been written by any AI for any business? Generic voice = generic content = no virality. If no brief exists, skip and note. |
| **Polarity / takeable position (0-10)** | Does the post say something arguable? A reader should be able to nod hard OR push back. "Most marketing is wrong for sub-$10k businesses" is polarizing. "Marketing is important" is not. Polarizing posts drive comments → algorithm boost. |
| **Platform fit (0-10)** | Length appropriate? Hook within first 125 chars for Instagram? Under 280 for Twitter? Hashtag count right? Format matches platform conventions? Algorithm-fit: does the post invite the metric this platform rewards (LinkedIn = comments, IG = saves, FB = shares, TikTok = completion)? |

### Step 4: Run the voice rules audit

Check these universal rules. Each is pass/fail.

| Rule | Pass = |
|------|--------|
| Em dashes | Zero em dashes anywhere |
| Contractions | "don't" used over "do not", "you've" over "you have" |
| Numbers as digits | "5 tips" not "five tips" |
| Active voice | No "was created by," "is being done," "has been built" |
| Filler words | None of: really, very, just, basically, literally, actually, simply |
| Filler openers | No: "in today's world", "let me tell you", "the truth is", "here's the thing" |
| Hashtag count | Within platform limits (0 for Twitter/Threads/Bluesky/LinkedIn/Facebook, 3-5 for Instagram, max 5 for TikTok) |

### Step 5: Calculate the overall score

Weight the dimensions:

| Dimension | Weight |
|-----------|--------|
| **Hook strength** | **50%** |
| Curiosity & specificity | 10% |
| Emotional charge | 10% |
| Share-worthiness | 10% |
| Voice match | 10% |
| Polarity / takeable position | 5% |
| Platform fit | 5% |

Voice rules audit: each failure subtracts 0.5 from the overall score (capped at -3).

**Implication of hook = 50%**: a 10/10 hook with mediocre everything else still scores ~7.5. A 4/10 hook with perfect everything else maxes at ~7. The hook is where the score lives or dies. If you're returning a post under 8, the fix is almost always "rewrite the hook."

### Step 6: Top 3 fixes

Rank the 3 changes that would raise the score most. For each:

1. **What's wrong** — quote the specific line.
2. **Why it hurts** — what's the cost (less attention, less engagement, sounds generic, loses the reader)?
3. **Specific fix** — exact rewrite or instruction. Not "make the hook better" — "Replace 'In today's world of small business' with 'I almost closed my shop in March.'"

### Step 7: Output the scorecard

```
## Post Grade: [X.X]/10

### Score Breakdown

| Dimension | Weight | Score | Note |
|-----------|--------|-------|------|
| Hook strength | 50% | X/10 | [1-line note if under 8] |
| Curiosity & specificity | 10% | X/10 | [...] |
| Emotional charge | 10% | X/10 | [...] |
| Share-worthiness | 10% | X/10 | [...] |
| Voice match | 10% | X/10 | [...] |
| Polarity | 5% | X/10 | [...] |
| Platform fit | 5% | X/10 | [...] |

### Voice Rules Audit

| Rule | Pass/Fail | Violation |
|------|-----------|-----------|
| Em dashes | ... | ... |
| Contractions | ... | ... |
| Numbers as digits | ... | ... |
| Active voice | ... | ... |
| Filler words | ... | ... |
| Filler openers | ... | ... |
| Hashtag count | ... | ... |

### Top 3 Fixes (ranked by impact)

**1. [Issue title]**
- Current: "[exact quote from post]"
- Why it hurts: [...]
- Fix: [specific rewrite or instruction]

**2. [Issue title]**
- Current: "[...]"
- Why it hurts: [...]
- Fix: [...]

**3. [Issue title]**
- Current: "[...]"
- Why it hurts: [...]
- Fix: [...]
```

### Step 8: Offer to apply fixes

If the user invoked you standalone, ask: "Want me to apply these fixes? Or just take the scorecard and revise yourself?"

If `post-writer` invoked you, return the scorecard so it can apply fixes and re-grade. `post-writer` should loop until the post scores 8+.

## What NOT to Do

- **Don't grade leniently.** A false 8 wastes more time than an honest 5.
- **Don't rewrite the entire post.** You're a grader. Specific fix instructions only.
- **Don't flag style preferences as errors.** Grade against the rules above. If the post passes, it passes — even if you'd write it differently.
- **Don't skip the "why it hurts" line in the fixes.** That's where the user actually learns. "Move this clause" without context teaches nothing.
- **Don't pad scores.** If hook is a 4, say 4. The whole point is catching problems before publish.

Skill 3: Post Scheduler

Blotato's free pack

Say when and where. It schedules it through Blotato to up to 9 platforms.

Once a post is good, you type something like "post this to Instagram, TikTok and LinkedIn tomorrow at 9am" and it handles the rest. It pulls your connected accounts, runs a final pre-publish check, and schedules it.

It can post Instagram trial reels too, which go out to non-followers first. Just say "as a trial reel." Instagram only allows these once you have 1,000 followers.

If Blotato is not connected yet, it does not fail. It writes the post to a file you can paste manually, so the workflow still finishes.

Save as post-scheduler/SKILL.md
---
name: post-scheduler
description: Schedule a finished social post to one or more platforms via the Blotato API. Handles single-platform and multi-platform scheduling, fetches connected accounts, applies a final pre-publish check, and returns scheduled time + post IDs. Triggers on "schedule this," "post this to [platform]," or as the final step in content-coach and post-writer flows. Falls back to saving the post as a copy-paste file if Blotato isn't configured.
argument-hint: "[post text or path] [platform(s)] [optional time]"
allowed-tools: Read, Write, Edit, Glob, AskUserQuestion, mcp__blotato__blotato_list_accounts, mcp__blotato__blotato_create_post, mcp__blotato__blotato_get_post_status
---

# Post Scheduler

You take an approved post and ship it via Blotato. You do NOT write or revise the post — that's `post-writer`'s job. By the time a post reaches you, it's been graded and approved.

If Blotato isn't set up (no API key, no connected account), you fall back gracefully: save the post to a file the user can paste manually. Don't fail the flow.

## When to Activate

- "Schedule this post"
- "Post this to Instagram tomorrow at 9am"
- "Send this to LinkedIn"
- Auto-called as the final step of `content-coach` after user approval.

## Workflow

### Step 1: Get inputs

You need:
1. **Post text** — inline, or path to a file
2. **Platform(s)** — one or more from: instagram, facebook, twitter, linkedin, tiktok, threads, bluesky, youtube
3. **Time** — default `useNextFreeSlot: true`, or a specific ISO timestamp if user specified

If platform is missing, ask. Don't guess.

### Step 2: Final pre-publish check

Before hitting Blotato, scan the post one more time for:

- [ ] Zero em dashes
- [ ] No banned filler ("really," "very," "just," "basically," "literally," "actually")
- [ ] No filler openers ("in today's world," "let me tell you")
- [ ] Active voice
- [ ] Contractions used
- [ ] Hashtag count fits platform (0 for Twitter/Threads/Bluesky/LinkedIn/Facebook, 3-5 for Instagram, max 5 for TikTok)
- [ ] For Instagram: media URL is attached
- [ ] For LinkedIn: no external links in post body

If anything fails, **stop and report**:

```
Pre-publish check failed:
- [issue 1]
- [issue 2]

Want me to send this back to post-grader, or override and ship as-is?
```

Wait for explicit user response. Don't auto-fix without permission.

### Step 3: Fetch connected accounts

```
mcp__blotato__blotato_list_accounts()
```

Group results by platform. If a requested platform has multiple accounts, ask which to use.

If a requested platform has **zero** accounts:
```
No [platform] account is connected to Blotato. To connect:
1. Open Blotato (https://blotato.com/?ref=zach)
2. Add [platform] from the Accounts page
3. Come back and re-run this skill

For now, I can save the post to a file so you can paste it manually. Want that?
```

### Step 4: Schedule

For **single platform**, call Blotato directly:

```
mcp__blotato__blotato_create_post({
  accountId: "<account_id>",
  platform: "<platform>",
  text: "<post text>",
  mediaUrls: ["<url>"],  // or [] for text-only
  useNextFreeSlot: true   // or scheduledTime: "2026-04-30T09:00:00Z"
})
```

Platform-specific required fields (add as needed):
- **Facebook**: `pageId` (Facebook Page ID — required)
- **TikTok**: `privacyLevel` (one of: `PUBLIC_TO_EVERYONE`, `MUTUAL_FOLLOW_FRIENDS`, `SELF_ONLY`), `disableDuet`, `disableComment`, `disableStitch`
- **YouTube**: `title` (under 100 chars), `privacyStatus` (one of: `public`, `unlisted`, `private`)
- **Instagram**: `mediaUrls` is required (Instagram requires media)

For **multiple platforms**, call Blotato once per platform. The same text may need slight tweaks (e.g., shorten for Bluesky's 300-char limit). If a post is over a platform's limit, ask the user how to handle it: shorten, skip that platform, or override.

### Step 5: Report results

Show the user a confirmation table:

```
## Scheduled

| Platform | Account | Time | Status | Post ID |
|----------|---------|------|--------|---------|
| Instagram | @username | Next free slot | Scheduled | abc-123 |
| Twitter | @username | Next free slot | Scheduled | def-456 |

You can view and edit scheduled posts at https://my.blotato.com/scheduler
```

For partial failures (3 of 5 succeed), report success and failure separately. Don't roll back.

### Step 6: Fallback (no Blotato)

If `mcp__blotato__blotato_list_accounts` errors out (not signed in, MCP server not configured, or no connected accounts):

```
Blotato isn't connected. I'll save your post so you can copy-paste it manually.

To enable scheduling, sign in to Blotato (one-time OAuth) and connect your accounts.
```

Save to `post-ready-to-paste.txt` in the current directory:

```
=== POST FOR [PLATFORM] ===
Scheduled for: [time or "manual posting"]

[POST TEXT HERE]

=== END POST ===
```

If multi-platform, save one block per platform. Tell the user the file path.

## What NOT to Do

- **Don't auto-fix voice issues.** That's `post-grader` and `post-writer`'s job. You only flag and ask.
- **Don't skip the pre-publish check.** It's the last line of defense.
- **Don't post immediately by default.** Default is `useNextFreeSlot: true`. Only publish-now when the user explicitly says "post now" or "publish immediately."
- **Don't poll for status on scheduled posts.** Blotato confirms scheduling instantly. Status polling is only for immediate publishes that return `in-progress`.
- **Don't fail silently if Blotato errors.** Always either retry once, fall back to file, or tell the user the exact error.
- **Don't log success without the post ID.** "Done" without evidence isn't done.

## Setting Up Blotato (one-time, for new users)

If the user has never used Blotato, walk them through this. **Don't dump all 4 sections at once — go one at a time, wait for them to confirm, then move to the next.**

### Part 1: Create a Blotato account (5 minutes)

1. Open a browser and go to **https://blotato.com/?ref=zach** (referral link, 30% off with code ZACH30)
2. Click **Sign up** (top right corner). You can sign up with Google, or with email + password.
3. After signup, you'll land in the Blotato dashboard. Keep this tab open — you'll need it for Part 2.

**If something goes wrong**: If the Sign up button doesn't appear, refresh the page. If signup fails, try a different browser (Chrome works best). Email signups need email verification — check spam.

### Part 2: Connect your social accounts (5-10 minutes per platform)

Blotato can only post to platforms you connect. Connect each platform you want to post to.

1. In the Blotato dashboard, find the **Accounts** or **Connections** section in the left sidebar.
2. Click **Add account** and pick a platform (e.g., Instagram).
3. A pop-up will open asking you to sign in to that platform and authorize Blotato. Sign in with the account you want to post from.
4. Approve the permissions. The pop-up will close. The account should now appear in your Blotato dashboard.
5. Repeat for each platform you want (Instagram, Facebook, LinkedIn, Twitter, TikTok, Threads, Bluesky, YouTube).

**If something goes wrong**:
- *Pop-up blocked*: Allow pop-ups for blotato.com in your browser, then retry.
- *Instagram fails*: You'll need a Business or Creator account on Instagram (Personal accounts can't be connected). Switch in the Instagram app under Settings → Account type.
- *Facebook fails*: You need a Facebook Page (not just a personal profile). Create one for free at facebook.com/pages/create.
- *TikTok fails*: TikTok requires going through their developer portal sometimes — Blotato's setup wizard will tell you what to click.

You don't have to connect every platform on day one. Start with 1-2.

### Part 3: Install the Blotato MCP server in Claude (5 minutes)

The MCP server is what lets Claude talk to Blotato. Install it once.

**For Claude Desktop:**
1. Open Claude Desktop → Settings → Developer → Edit Config.
2. Add the Blotato MCP server config. Find the exact config block at **https://blotato.com/docs/mcp** (or search "Blotato MCP" in their docs).
3. Save the config and **fully quit and relaunch Claude Desktop** (close all windows first).

**For Claude Code:**
1. Run the install command from Blotato's docs: **https://blotato.com/docs/mcp**
2. The command will look something like `claude mcp add blotato ...`. Copy it from their docs.
3. Once installed, run `claude` to start a new session.

**If the MCP install steps look outdated**: Blotato's docs at **https://blotato.com/docs/mcp** are the source of truth. If anything below conflicts with their docs, follow their docs.

### Part 4: Sign in to Blotato from Claude (1 minute)

1. Re-run this skill (e.g., type `/post-scheduler` or just ask Claude to schedule a post).
2. Claude will hit a Blotato MCP tool the first time. The MCP will open a browser tab asking you to sign in to Blotato (OAuth flow).
3. Sign in with the same account from Part 1. Approve.
4. The browser tab will say "you can close this window now." Go back to Claude. The MCP is now authorized.

That's it. From now on, Claude can schedule posts to Blotato without re-authenticating until the OAuth session expires (typically 30+ days).

### What if I skip all this?

This skill works without Blotato. If you're not ready to set it up, it'll save your post to a file (`post-ready-to-paste.txt`) and you can copy-paste it into each platform manually. You'll lose the scheduling automation but you'll still get the writing + grading.

## Error Handling

- **401/403**: OAuth session expired. Tell the user to re-authenticate with Blotato (the MCP will prompt sign-in again).
- **429**: Rate limited. Wait per `Retry-After` header, retry once.
- **Missing account**: Platform not connected. Show fallback file option.
- **Post over char limit**: Don't auto-truncate. Ask the user how to handle.
- **Network failure**: Retry once. If it fails again, save to fallback file and report.

Skill 4: Comment to DM

Custom build

This is the one that replaces ManyChat.

Someone comments a keyword on your post, they get a DM with your link. You can make them follow you first, and you can collect their email on the way through. That is the entire loop, and it is the highest-converting free thing a creator can run.

You type /comment-to-dm, tell Claude the keyword and the link, and it builds the automation. It shows you the whole thing first and waits for you to say go.

It does three jobs: build a new one, check whether a live one is actually working, and upgrade one to capture emails through a webhook.

Save as comment-to-dm/SKILL.md
---
name: comment-to-dm
description: Builds, checks and upgrades Instagram and Facebook comment-to-DM automations through the Blotato MCP, replacing a separate ManyChat subscription. When someone comments a keyword they get a DM with a link, optionally after following the account and giving their email. Three jobs. Build a new keyword automation, Check whether a live one is working, and Upgrade one to capture emails through a webhook. Use when someone says "set up a comment to DM", "comment X and I'll send it", "build the DM automation for this reel", "is my DM automation working", "why isn't my automation sending", "capture emails from my DMs", or /comment-to-dm.
argument-hint: "[build | check | upgrade] [keyword] [link]"
allowed-tools: Read, AskUserQuestion, mcp__blotato__blotato_list_accounts, mcp__blotato__blotato_list_posts, mcp__blotato__blotato_list_automations, mcp__blotato__blotato_create_automation, mcp__blotato__blotato_update_automation, mcp__blotato__blotato_update_automation_trigger, mcp__blotato__blotato_get_automation_analytics, mcp__blotato__blotato_list_automation_runs, mcp__blotato__blotato_list_automation_logs
---

# Comment to DM

Someone comments your keyword. They get a DM with your link. Optionally they have to follow you first, and optionally they give you their email on the way through. That loop is the highest-converting free thing a creator can run, and Blotato runs it without a separate DM tool.

| Job | When |
|---|---|
| **Build** | New post, new keyword, nothing exists yet |
| **Check** | It's live and they want to know if it's working, or it seems broken |
| **Upgrade** | It works, and now they want email addresses out of it |

If it's unclear which job they want, ask.

## How Blotato automations work (read this before any job)

- **Triggers.** A comment trigger fires when a comment contains one of the keywords. It watches either one post (`postId`) or every post (`postId` left out). An automation can also carry one DM trigger, so people who DM the keyword instead of commenting it get the same thing.
- **Scoping to one post needs a Blotato post id.** `postId` is the post's id from `blotato_list_posts`, which only lists posts published or scheduled through Blotato. A reel posted straight from the Instagram app won't be there, so it can't be scoped, and the automation has to run on every post. If scoping matters, publish the reel through Blotato.
- **Gates run before the DM.** A follow gate (Instagram only) holds the DM until they follow: they get the gate message, and once they've followed and tapped the button (or replied), the DM goes out. An email gate asks for an email first. People with an email already on file skip it, and a reply with no email in it gets the gate message again.
- **Webhook.** Fires after the DM is sent. Every method except GET sends a body of `{"email": ..., "isFollower": ...}`, each null when unknown. The URL has to be publicly reachable. Private, loopback and link-local addresses are rejected.
- **Limits.** DM and gate messages are 1 to 640 characters. Up to 3 link buttons, each label 20 characters or fewer, each an http(s) URL.
- **New automations start as inactive drafts** unless created with `isActive: true`. **Edits to an active automation go live the moment they're saved.**
- **Waiting windows.** A run waiting on a follow gate expires after 30 days. A run waiting on an email expires after 72 hours. Expired runs count as triggered, but never as completed or failed.

---

## Job 1: Build

### Step 1: Collect 4 things

Don't start building with a gap. Ask for whatever's missing.

1. **KEYWORD.** One word, the word they tell people to comment.
2. **LINK.** The URL the DM sends people to.
3. **THE FREE THING.** What they're sending, in one short phrase, the way they'd say it out loud.
4. **WHICH POST.** One specific post, or every post.

Defaults unless they say otherwise: follow gate on (Instagram), no email gate, one link button, DM trigger off.

### Step 2: Check the keyword before building anything

This is the step that quietly breaks launches.

1. **Existing automations.** Run `blotato_list_automations`. If an active automation on the same account already uses this keyword on every post, the two will fight over the same comments. The fix is scoping, not a new keyword: scope the new one to its post, and flag the old any-post one so they can scope it or pause it.
2. **Everyday words.** Matching is on "contains", so assume ordinary comments that include the word will fire it. On an any-post automation, warn plainly about short or common words (AI, ME, GO, LINK). Scoped to one post, a common word is usually fine, because anyone saying it on that post probably wants the thing.
3. **Case.** Pass the keyword in caps, lowercase and title case (for example `CONTENT`, `content`, `Content`). It costs nothing and removes a guess.
4. **Already filmed?** If the video already says the keyword, the keyword stays. Scope instead.

### Step 3: Find the post (only if scoping)

Run `blotato_list_posts` with platform `instagram` and status `published`. Match on the caption or the postUrl, and confirm the match with the user.

If the post isn't there, it was posted natively. Explain the Blotato post id rule and give them the two options: publish the reel through Blotato (the post-scheduler skill can), or run the automation on every post and accept the collision risk. Their call.

### Step 4: Show the build, then wait

Run `blotato_list_accounts` and name the account this is about to attach to. For Facebook, it also needs the `pageId` from that account's subaccounts, and it can't have a follow gate.

Then show the whole thing:

```
Account:              [platform, @handle]
Name:                 KEYWORD - comment to DM
Trigger:              comment-received
Keywords:             KEYWORD, keyword, Keyword
Post:                 [the post, or every post]
Follow gate:          ON
  Message:            "Yes! Follow me first and I'll send it straight over.
                       Tap the button below once you're following
                       (or just reply "done" if you don't see a button)."
  Button:             "I'm following"
DM message:           "Here it is, THE FREE THING. Tap below and it's yours."
Link button:          "Send it over" -> LINK
Active on create:     yes
```

Write the DM like a person talking: what it is, then "tap below". Keep it short. Nobody reads a long DM.

**Wait for an explicit go. Don't create anything before they confirm.**

### Step 5: Create it, then hand back proof

Create it with `isActive: true`. Report the automation id, the account, the keywords, the scope, and that it's active.

Then tell them the thing everyone forgets: **your own comments never trigger it.** Test from a second Instagram account. People assume it's broken when it's working fine.

---

## Job 2: Check

1. **Find it.** `blotato_list_automations` with metrics `triggered`, `completed`, `failed`, `issues`. Match on name or keyword. If nothing matches, list them all and ask which one.
2. **Is it active?** An inactive draft never fires. That's the most common "it's broken."
3. **Triggered is 0?** Work through this in order: the automation is active; its trigger is active; it's scoped to the right post id; they didn't test from their own account; the keyword they typed matches.
4. **Triggered is high, completed is low?** Run `blotato_list_automation_runs` with status `waiting` and `expired`. **Waiting** means sitting at a gate (up to 30 days for a follow, 72 hours for an email). **Expired** means they never answered. **Superseded** means the same person triggered it again and the newer run took over. None of these are failures. Report them before calling anything broken.
5. **Failed above 0?** Run `blotato_list_automation_runs` with status `failed`, then `blotato_list_automation_logs` with that run's `flowRunId`. Quote the error and give the exact fix. `issues` is the failures from the last 7 days, which tells you whether the problem is current or old.
6. **Answer in plain English:**
   - Is it live right now?
   - How many times has it fired?
   - How many people actually got the DM?
   - How many are waiting at a gate, and how many gave up?
   - If anything really failed: the reason, and the exact fix.

---

## Job 3: Upgrade to capture email

### Step 1: Get 2 things

1. **WHICH ONE.** The automation name or its keyword.
2. **WEBHOOK URL.** Their endpoint: Zapier, Make, n8n, or their own.

### Step 2: Say the part that matters, before building

Blotato saves the email to the contact, but **the webhook is the only thing that sends it on to their email list.** No working webhook means the email never reaches their list.

So before going live:
- Confirm the URL is publicly reachable. Private, loopback and link-local addresses get rejected.
- Use POST. A GET webhook sends no body, which means no email.
- Once it's live, check the first delivery in their tool's history (the Zapier, Make or n8n run log) before trusting it.

### Step 3: Add only 2 things

- **Email gate.** Message: "One thing first, what's the best email to send this to? I'll send it right after."
- **Webhook.** Method POST, URL = their webhook.

Keep everything else exactly as it is: same keyword, same scope, same follow gate, same DM, same button.

This automation is live, so the update publishes the moment it saves. **Show the full updated automation and wait for a go.**

### Step 4: Tell them what the person experiences

Comment, then the gate or gates, then the DM with the link. The webhook fires after the DM goes out. On the first test run, check the logs to see the exact gate order.

Say plainly that every gate costs some conversion. Two gates in front of a link is worth it when they want an email list. It isn't worth it for a pure follower push.

---

## What NOT to do

- **Don't create or edit anything before an explicit go.** Edits to an active automation go live instantly.
- **Don't skip the keyword check.** Two any-post automations on one keyword is the most common silent failure.
- **Don't put a link button and a plain-text URL in the same DM.** On desktop the URL stops being clickable, and those readers end up with no working link at all.
- **Don't call low completion broken** until you've counted waiting and expired runs.
- **Don't promise email capture without a working POST webhook.**
- **Don't change a keyword that's already been filmed.** Scope the automation instead.
- **Don't add a follow gate on Facebook.** The automation can't go live with one.

Bonus: The 3 comment-to-DM prompts

If you would rather not install the fourth skill, these 3 prompts do the same jobs on their own. Paste them straight into Claude with the Blotato MCP connected.

Prompt 1 — Build the automation

Fill in the keyword, the link, and what you are sending. It shows you the full build and waits before creating anything.

Prompt 1 — Build the automation
Set up a comment-to-DM automation on my Instagram using Blotato.

FILL THESE IN BEFORE YOU PASTE:

- KEYWORD: [one word, all caps, the word you tell people to comment]
  Example: GUIDE

- LINK: [the URL you're sending them to]
  Example: https://yoursite.com/free-guide

- THE FREE THING: [what you're sending, in one short phrase]
  Example: the 10-minute cold email teardown

- WHICH POST: [the reel I just published, or: every post]

BUILD IT LIKE THIS:

- Name: "KEYWORD - comment to DM"
- Trigger: comment-received, keyword KEYWORD
- Follow gate: ON. Message: "Yes! Follow me first and I'll send it straight over. Tap the button below once you're following (or just reply "done" if you don't see a button)."
- Follow gate button label: "I'm following"
- DM message: "Here it is, THE FREE THING. Tap below and it's yours."
- One link button: label "Send it over", URL = LINK
- Make it live immediately

BEFORE YOU CREATE IT:

1. Call blotato_list_accounts and tell me which Instagram account you're about to attach this to.
2. Show me the exact automation you're about to create: name, trigger, keyword, follow gate message, button label, DM text, link button, and whether it's active.
3. Wait for me to say go. Do not create it before I confirm.

AFTER YOU CREATE IT:

4. Confirm it's active and give me the automation ID.
5. Remind me that my own comments will never trigger it, so I have to test from a second Instagram account.

RULES YOU MUST FOLLOW:

- The DM message has to be under 640 characters.
- Max 3 link buttons, and every button label has to be 20 characters or fewer.
- Use a link button OR a plain-text URL in the message, never both. If a message carries both, the URL stops being clickable on desktop and those readers end up with no working link at all.
- The follow gate is Instagram only. If I ever ask you to put one on Facebook, tell me it will be rejected.
- If my keyword is a word that lives inside a longer word people actually type, warn me before you build it.

Prompt 2 — Check if it is working

Pulls analytics and logs, then reads them correctly. High triggers with low completions usually means expired follow gates, not a broken automation.

Prompt 2 — Check if it is working
Check on my Blotato DM automation.

FILL THIS IN:

- WHICH ONE: [the automation name, or the keyword it runs on]
  Example: GUIDE - comment to DM

DO THIS:

1. List my DM automations and find it. If you can't match the name, list them all and ask me which one.
2. Tell me whether it's actually active, or still sitting as an inactive draft.
3. Pull its analytics: triggered, completed, failed.
4. Pull the most recent runs and the logs for the latest one.

THEN TELL ME IN PLAIN ENGLISH:

- Is it live right now?
- Has it fired at all, and how many times?
- How many people actually got the DM, versus how many got stuck at the follow gate and never came back?
- If anything failed, what was the reason and what's the exact fix?

CONTEXT YOU NEED:

A run waiting on a follow gate stays open for up to 30 days. A run waiting on an email gate stays open for up to 72 hours. If they never answer, the run ends as expired. Waiting and expired runs both count as triggered but never as completed or failed. A run marked superseded means the same person triggered it again and the newer run took over. So if triggered is high and completed is low, pull the runs by status and tell me how many are waiting, expired, or superseded before you tell me something is broken.

Prompt 3 — Capture emails

Adds an email gate and a webhook. Read the warning in this one carefully, without a working webhook the email is collected and then gone.

Prompt 3 — Capture emails
Upgrade my existing Blotato DM automation so it captures email addresses.

FILL THESE IN:

- WHICH ONE: [the automation name, or the keyword it runs on]
  Example: GUIDE - comment to DM

- MY WEBHOOK URL: [your endpoint: Zapier, Make, n8n, or your own]
  Example: https://hooks.zapier.com/hooks/catch/123456/abcdef

ADD TO IT:

- Email gate, placed before the DM. Message: "One thing first, what's the best email to send this to? I'll send it right after."
- Webhook that fires once the DM has been sent. Method: POST (a GET webhook sends no body, so no email). URL: MY WEBHOOK URL.

KEEP EVERYTHING ELSE EXACTLY AS IT IS. Same keyword, same follow gate, same DM, same button.

BEFORE YOU SAVE:

Show me the full updated automation and wait for me to confirm.

AFTER YOU SAVE:

Confirm it's still active.

THE PART THAT MATTERS:

Blotato saves the email to the contact, but the webhook is the only thing that sends it on to my email list, as {"email": "their@email.com", "isFollower": true}. If the webhook isn't set up and working, the email never reaches my list. So before we go live, tell me plainly whether my webhook URL is publicly reachable, and warn me that private, loopback, and link-local addresses get rejected.

People who already have an email on file skip the email gate. Anyone who replies without an email gets the gate message again, and anyone who never replies expires after 72 hours.

Also tell me the order Blotato runs these in, so I know what the person on the other end actually sees.

How the 4 run as one loop

Each skill is useful alone. Run in order they become a system, because each one hands the next one something better than it would have had.

  • Once, at the start

    Feed Viral Coach 5 to 10 posts that actually worked. It writes viral-playbook.md. You only do this once, then top it up whenever a post beats your median.

  • Every script after that

    Write the draft, then run Viral Coach in coach mode. It rewrites the hook against your own winners. Then Post Grader scores it and hands you the top 3 fixes. Loop until it clears an 8.

  • When it is good

    Post Scheduler ships it to every platform you picked, at the time you said, in one sentence.

  • After it is live

    Comment to DM turns the comments into DMs, and the DMs into emails. That is the part that compounds, because you keep the list whichever way the algorithm moves.

7 things that quietly break this

  • 1. Your own comments never trigger it

    Test from a second Instagram account. Most people think the automation is broken when it is working fine.

  • 2. One keyword, one automation per post

    If the same keyword runs on two all-posts automations, whichever fires first wins and the other silently never runs. Scope it to the post.

  • 3. Never put a link button and a plain URL in the same DM

    The URL stops being clickable on desktop, and those readers end up with no working link at all.

  • 4. The follow gate is Instagram only

    Facebook rejects it. If you try, the automation fails rather than skipping the gate.

  • 5. Emails only reach your list through the webhook

    Blotato saves the email, but the webhook is the only thing that sends it to your newsletter tool. Use POST, because a GET webhook sends no body. No working webhook, no list.

  • 6. Posting from the Instagram app means no post scoping

    To aim an automation at one reel, Blotato needs that reel's Blotato post id, which only exists if you posted it through Blotato. Post natively and the automation has to watch every post. That is fine until two automations share a keyword.

  • 7. Instagram needs a Business or Creator account

    Personal accounts cannot connect. Switch it in the Instagram app under Settings, then Account type.

Blotato

Blotato is what Post Scheduler and Comment to DM talk to. It connects your social accounts, schedules to up to 9 platforms, and runs the comment-to-DM automations that would otherwise cost you a separate ManyChat subscription.

Post Grader and Post Scheduler come from Blotato's free 7-skill pack. The other 5 in that pack are brand-brief, content-coach, post-writer, repurpose and viral-hooks, and they are worth grabbing while you are there.

Try Blotato free for 7 days

Get the free 7-skill pack

Code ZACH30 takes 30% off for 3 months if you stay past the trial.