Rishikesh Ranjan — rishikeshranjan.com

// channels

LinkedIn Post

/ttm-linkedin-post

Generate a LinkedIn post in your voice. First run interviews you for 2-5 author profiles to mimic, scrapes their recent posts via Playwright MCP, and builds .taketomarket/PLAYBOOKS/linkedin-base.md. Subsequent runs use that base + post history + news web search to draft posts. Final draft passes through /ttm-humanize before output.

manual invocation
allowed-tools:ReadWriteBashGlobGrepAskUserQuestionWebSearch

Overview

Invoke with ttm-linkedin-post to generate a LinkedIn post in your own voice. On the first run it interviews you for 2-5 author profiles to mimic, scrapes their recent posts via the Playwright MCP, and builds .taketomarket/PLAYBOOKS/linkedin-base.md — a synthesized style base derived from those creators.

Subsequent runs use that base plus your post history and a news web search to draft posts. The skill applies LinkedIn-specific patterns (hook, scannable structure, comment-bait, no link in the body), generates 2-3 draft candidates with different hooks, and lets you pick or iterate. The final chosen draft passes through /ttm-humanize before it is written out as a ready-to-post draft.

Flags: --rebuild-base re-interviews and re-scrapes authors to refresh linkedin-base.md; --no-news skips the news web search; --topic <text> seeds the topic for this post.

How it works

The skill follows the LinkedIn Post workflow at ${CLAUDE_PLUGIN_ROOT}/workflows/channel/linkedin-post.md.

Step 0: First-run inline education

Read .taketomarket/CONFIG.md. Parse first_run_seen (object) and inline_education (boolean, default true).

If inline_education is false: skip this step. Else if first_run_seen.ttm-linkedin-post is not true, print the explainer below verbatim, then mark this skill as seen:

node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" first-run mark ttm-linkedin-post

Use this exact check (bash) to decide whether to print: node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" first-run check ttm-linkedin-post --raw — the JSON seen field is true once the explainer has run before.

Explainer for /ttm-linkedin-post

/ttm-linkedin-post generates a LinkedIn post from a campaign brief or a raw thought, applies the LinkedIn-specific patterns (hook, scannable structure, comment-bait, no link in body), and routes it through the gate wall. Output is a ready-to-post draft plus a comment-thread plan.

Why it matters: LinkedIn rewards a specific format that violates general copywriting rules (short lines, deliberate whitespace, no-link bodies). Generic LLM output writes essays; this skill writes posts that match the platform's actual distribution mechanics.

(Canonical source: references/inline-education-blurbs.md. Embedded verbatim because workflows do not @-resolve files at runtime.)

Required reading:

  • ${CLAUDE_PLUGIN_ROOT}/references/linkedin-post-patterns.md
  • ${CLAUDE_PLUGIN_ROOT}/playbooks/linkedin.md
  • ${CLAUDE_PLUGIN_ROOT}/references/playwright-mcp-setup.md
  • ${CLAUDE_PLUGIN_ROOT}/templates/linkedin-base-template.md
  • .taketomarket/POSITIONING.md, BRAND.md, PRODUCT-DNA.md, ICP.md
  • .taketomarket/PLAYBOOKS/linkedin-base.md (created on first run)
  • .taketomarket/CAMPAIGNS/linkedin/post-history.md (created on first run)

Step 1: Detect first-run

Check if .taketomarket/PLAYBOOKS/linkedin-base.md exists.

  • If NOT (or --rebuild-base flag): go to Step 2 (interview + scrape).
  • If YES: go to Step 6 (generate post).

Step 2: First-run author interview

AskUserQuestion (priority: critical):

  • "Which 2-5 LinkedIn creators write in the style you want to mimic? Paste their profile URLs."
  • Freeform, expect 2-5 URLs.

Step 3: Playwright check

node ${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs playwright-check --raw

If detected = false: print "Author scraping needs Playwright MCP. Run /ttm-playwright-setup first." Then exit the workflow.

Also check the extension capability:

node ${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs config read --raw

If playwright_mcp_extension is not true: print "Author scraping needs the Chrome extension bridge (--extension) so Playwright can use your logged-in LinkedIn session. Re-run /ttm-playwright-setup and re-add Playwright with the --extension flag, then retry." Exit.

Step 4: Scrape authors

For each profile URL:

  • Call browser_navigate with the URL (Playwright MCP uses logged-in Chrome session via the bridge → reaches authenticated LinkedIn).
  • Call browser_snapshot to read rendered DOM.
  • Scroll-and-snapshot loop until ~10-20 posts are captured.

For each post: capture text + engagement count + post type (text / image / carousel / video).

Save raw scrapes to .taketomarket/CAMPAIGNS/linkedin/scrapes/<author-handle>.md.

Step 5: Analyze + build linkedin-base.md

For each author:

  • Compute sentence length distribution.
  • Extract hook patterns (first 80 chars of each post).
  • Identify recurring structure templates.
  • Extract recurring phrases / voice tics.
  • Note topics + cadence.

Synthesize across authors. Apply references/linkedin-post-patterns.md framework. Fill in templates/linkedin-base-template.md placeholders. Write to .taketomarket/PLAYBOOKS/linkedin-base.md.

Step 6: Load context for this post

  • Load linkedin-base.md, POSITIONING, BRAND, PRODUCT-DNA, ICP.
  • Load post-history.md and extract from each row (pipe-format | YYYY-MM-DD | <topic-tag> | <hook-pattern> | <slug> | <link> |):
    • <topic-tag> values from the last 30 days — these are the canonical topic keys (set by frontmatter topic in Step 11 and copied into the history row in Step 12).
    • <hook-pattern> values from the last 5 rows.
  • Avoid: any <topic-tag> that appears in the last 30 days; any <hook-pattern> that appears in the last 5 posts.

Step 7: Web search for news angles

Unless --no-news:

  • Read .taketomarket/ICP.md (top headings: industry, segments) + .taketomarket/POSITIONING.md ## Category. Extract 2-3 industry terms.
  • Construct 1-2 WebSearch queries combining those terms with 2026 and platform-specific operators (e.g., site:techcrunch.com).
  • Pass recency:7d (or equivalent) to scope to last 7 days.
  • Surface 3-5 recent stories. Rank by relevance to product positioning.

AskUserQuestion (non-critical, default: top-ranked):

  • "Found these recent stories. Use one as an angle, or write standalone?"
  • options: list 3-5 stories + "Standalone, no news angle"

Step 8: Determine post topic

If --topic flag passed: use that.

Else: AskUserQuestion (priority: critical):

  • "What's the topic for today's post?"
  • options:
    • "Use selected news story" (if Step 7 produced one)
    • "Recent product update / behind-the-scenes"
    • "Lesson from this week"
    • "Counter-take on conventional wisdom"
    • "Other (freeform)"

Step 9: Generate 2-3 draft candidates

Apply linkedin-base.md style + chosen topic. Generate 2-3 candidates with different hook patterns from references/linkedin-post-patterns.md ## Hook patterns.

Present each to user.

Step 10: Pick or iterate

AskUserQuestion (priority: critical):

  • "Which draft?"
  • options: ["A", "B", "C", "Show me 3 more", "Combine these"]

Loop until user picks.

Step 11: Mandatory humanize

Generate slug via node ${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs slug "<topic-summary>" --raw for consistency with the codebase's existing slug convention. Generate timestamp via node ${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs timestamp --raw.

Write the chosen draft to .taketomarket/CAMPAIGNS/linkedin/drafts/<timestamp>-<slug>.md (frontmatter: topic, hook_pattern, status: draft).

Then invoke /ttm-humanize <path> via Skill tool. Re-read the file after humanize completes — it now contains the rewritten version.

Step 12: Save + history append

  • Print the humanized post text to the user (read from the file you wrote in Step 11).
  • Update frontmatter in .taketomarket/CAMPAIGNS/linkedin/drafts/<timestamp>-<slug>.md: change status: draftstatus: ready.
  • Append to post-history.md:
| YYYY-MM-DD | <topic-tag> | <hook-pattern> | <slug> | <link-to-draft> |

Step 13: Print next steps + cadence suggestion

✓ Post ready. Copy from .taketomarket/CAMPAIGNS/linkedin/drafts/<file>.md

Want daily cadence? If you have a scheduler skill installed (e.g. /schedule),
you can set up a recurring run — example syntax:

  /schedule create "0 9 * * 1-5" "/ttm-linkedin-post"

This would run the skill every weekday at 9am. You'd review + post manually.
No scheduler? Re-run /ttm-linkedin-post when you want the next post.

Next: /ttm-next | /ttm-state

What if this doesn't fit?

Looks like /ttm-linkedin-post can't do that yet.

  • Want a new skill? /ttm-request-skill
  • Existing skill needs work? /ttm-improve-skill