$npx -y skills add PHY041/claude-agent-skills --skill social-postPost to social media platforms using a multi-provider social posting API. Use when you want to post to Twitter, LinkedIn, Instagram, Facebook, TikTok, Threads, or Bluesky. Triggers on "post to twitter", "post to instagram", "social media post", "share on linkedin", "publish to so
| 1 | # Social Posting Skill |
| 2 | |
| 3 | Post to multiple social media platforms via a unified social posting API with automatic provider fallback. |
| 4 | |
| 5 | --- |
| 6 | |
| 7 | ## Setup |
| 8 | |
| 9 | **Location:** `~/social-posting-api/` (configurable — point to wherever you cloned your posting API) |
| 10 | |
| 11 | **Environment:** |
| 12 | ```bash |
| 13 | cd ~/social-posting-api |
| 14 | source venv/bin/activate |
| 15 | ``` |
| 16 | |
| 17 | **Required env vars in `.env`:** |
| 18 | - `POSTFORME_API_KEY` - Primary provider ([PostForMe](https://postforme.dev)) |
| 19 | - `LATE_API_KEY` - Fallback provider ([LATE](https://getlate.dev)) |
| 20 | |
| 21 | > You only need one provider to get started. PostForMe is recommended as the primary. |
| 22 | |
| 23 | --- |
| 24 | |
| 25 | ## Quick Commands |
| 26 | |
| 27 | ### Check Connected Accounts |
| 28 | ```python |
| 29 | from social_posting import SocialPostingClient |
| 30 | from dotenv import load_dotenv |
| 31 | load_dotenv() |
| 32 | |
| 33 | client = SocialPostingClient() |
| 34 | print("Providers:", client.available_providers) |
| 35 | for acc in client.get_accounts(): |
| 36 | print(f" {acc.platform}: {acc.username}") |
| 37 | ``` |
| 38 | |
| 39 | ### Post Text Only |
| 40 | ```python |
| 41 | result = client.post( |
| 42 | content="Your post content here", |
| 43 | platforms=["twitter", "linkedin"] |
| 44 | ) |
| 45 | print(f"Success: {result.success}, Provider: {result.provider}") |
| 46 | ``` |
| 47 | |
| 48 | ### Post with Images |
| 49 | ```python |
| 50 | result = client.post( |
| 51 | content="Check out these photos!", |
| 52 | platforms=["instagram"], |
| 53 | media_urls=[ |
| 54 | "https://example.com/image1.jpg", |
| 55 | "https://example.com/image2.jpg" |
| 56 | ] |
| 57 | ) |
| 58 | ``` |
| 59 | |
| 60 | ### Schedule a Post |
| 61 | ```python |
| 62 | from datetime import datetime |
| 63 | |
| 64 | result = client.post( |
| 65 | content="Scheduled post", |
| 66 | platforms=["linkedin"], |
| 67 | scheduled_for=datetime(2025, 1, 15, 9, 0) # UTC |
| 68 | ) |
| 69 | ``` |
| 70 | |
| 71 | --- |
| 72 | |
| 73 | ## Supported Platforms |
| 74 | |
| 75 | | Platform | Text Only | With Media | Notes | |
| 76 | |----------|-----------|------------|-------| |
| 77 | | Twitter/X | ✅ | ✅ | 280 char limit | |
| 78 | | LinkedIn | ✅ | ✅ | Best for professional content | |
| 79 | | Instagram | ❌ | ✅ | **Requires media** | |
| 80 | | Facebook | ✅ | ✅ | | |
| 81 | | TikTok | ❌ | ✅ | Video preferred | |
| 82 | | Threads | ✅ | ✅ | | |
| 83 | | Bluesky | ✅ | ✅ | | |
| 84 | | Pinterest | ❌ | ✅ | Requires media | |
| 85 | | YouTube | ❌ | ✅ | Video only | |
| 86 | |
| 87 | --- |
| 88 | |
| 89 | ## Complete Posting Script |
| 90 | |
| 91 | ```python |
| 92 | #!/usr/bin/env python |
| 93 | """Post to social media platforms.""" |
| 94 | |
| 95 | import sys |
| 96 | sys.path.insert(0, '~/social-posting-api') # Update this path |
| 97 | |
| 98 | from social_posting import SocialPostingClient |
| 99 | from dotenv import load_dotenv |
| 100 | load_dotenv('~/social-posting-api/.env') # Update this path |
| 101 | |
| 102 | def post_to_social(content: str, platforms: list, media_urls: list = None): |
| 103 | """Post content to specified platforms.""" |
| 104 | client = SocialPostingClient() |
| 105 | |
| 106 | # Check which platforms are connected |
| 107 | accounts = client.get_accounts() |
| 108 | connected = [a.platform for a in accounts] |
| 109 | |
| 110 | # Filter to only connected platforms |
| 111 | valid_platforms = [p for p in platforms if p in connected] |
| 112 | |
| 113 | if not valid_platforms: |
| 114 | print(f"No connected accounts for: {platforms}") |
| 115 | print(f"Connected: {connected}") |
| 116 | return None |
| 117 | |
| 118 | # Post |
| 119 | result = client.post( |
| 120 | content=content, |
| 121 | platforms=valid_platforms, |
| 122 | media_urls=media_urls |
| 123 | ) |
| 124 | |
| 125 | if result.success: |
| 126 | print(f"✅ Posted via {result.provider}") |
| 127 | print(f" Post ID: {result.post_id}") |
| 128 | else: |
| 129 | print(f"❌ Failed: {result.error}") |
| 130 | |
| 131 | return result |
| 132 | ``` |
| 133 | |
| 134 | --- |
| 135 | |
| 136 | ## Workflow for Posting |
| 137 | |
| 138 | ### Step 1: Check Connected Accounts |
| 139 | |
| 140 | Always check what's connected first: |
| 141 | ```bash |
| 142 | cd ~/social-posting-api |
| 143 | source venv/bin/activate && python -c " |
| 144 | from social_posting import SocialPostingClient |
| 145 | from dotenv import load_dotenv |
| 146 | load_dotenv() |
| 147 | client = SocialPostingClient() |
| 148 | for acc in client.get_accounts(): |
| 149 | print(f'{acc.platform}: {acc.username}') |
| 150 | " |
| 151 | ``` |
| 152 | |
| 153 | ### Step 2: Prepare Content |
| 154 | |
| 155 | - **Twitter**: Keep under 280 chars |
| 156 | - **LinkedIn**: Can be longer, professional tone |
| 157 | - **Instagram**: Needs at least 1 image |
| 158 | - **Xiaohongshu**: Use `xhs-image-gen` skill for carousel content |
| 159 | |
| 160 | ### Step 3: Execute Post |
| 161 | |
| 162 | ```bash |
| 163 | source venv/bin/activate && python -c " |
| 164 | from social_posting import SocialPostingClient |
| 165 | from dotenv import load_dotenv |
| 166 | load_dotenv() |
| 167 | |
| 168 | client = SocialPostingClient() |
| 169 | result = client.post( |
| 170 | co |