social-post
npx machina-cli add skill PHY041/claude-agent-skills/social-post --openclawSocial Posting Skill
Post to multiple social media platforms via a unified social posting API with automatic provider fallback.
Setup
Location: ~/social-posting-api/ (configurable — point to wherever you cloned your posting API)
Environment:
cd ~/social-posting-api
source venv/bin/activate
Required env vars in .env:
You only need one provider to get started. PostForMe is recommended as the primary.
Quick Commands
Check Connected Accounts
from social_posting import SocialPostingClient
from dotenv import load_dotenv
load_dotenv()
client = SocialPostingClient()
print("Providers:", client.available_providers)
for acc in client.get_accounts():
print(f" {acc.platform}: {acc.username}")
Post Text Only
result = client.post(
content="Your post content here",
platforms=["twitter", "linkedin"]
)
print(f"Success: {result.success}, Provider: {result.provider}")
Post with Images
result = client.post(
content="Check out these photos!",
platforms=["instagram"],
media_urls=[
"https://example.com/image1.jpg",
"https://example.com/image2.jpg"
]
)
Schedule a Post
from datetime import datetime
result = client.post(
content="Scheduled post",
platforms=["linkedin"],
scheduled_for=datetime(2025, 1, 15, 9, 0) # UTC
)
Supported Platforms
| Platform | Text Only | With Media | Notes |
|---|---|---|---|
| Twitter/X | ✅ | ✅ | 280 char limit |
| ✅ | ✅ | Best for professional content | |
| ❌ | ✅ | Requires media | |
| ✅ | ✅ | ||
| TikTok | ❌ | ✅ | Video preferred |
| Threads | ✅ | ✅ | |
| Bluesky | ✅ | ✅ | |
| ❌ | ✅ | Requires media | |
| YouTube | ❌ | ✅ | Video only |
Complete Posting Script
#!/usr/bin/env python
"""Post to social media platforms."""
import sys
sys.path.insert(0, '~/social-posting-api') # Update this path
from social_posting import SocialPostingClient
from dotenv import load_dotenv
load_dotenv('~/social-posting-api/.env') # Update this path
def post_to_social(content: str, platforms: list, media_urls: list = None):
"""Post content to specified platforms."""
client = SocialPostingClient()
# Check which platforms are connected
accounts = client.get_accounts()
connected = [a.platform for a in accounts]
# Filter to only connected platforms
valid_platforms = [p for p in platforms if p in connected]
if not valid_platforms:
print(f"No connected accounts for: {platforms}")
print(f"Connected: {connected}")
return None
# Post
result = client.post(
content=content,
platforms=valid_platforms,
media_urls=media_urls
)
if result.success:
print(f"✅ Posted via {result.provider}")
print(f" Post ID: {result.post_id}")
else:
print(f"❌ Failed: {result.error}")
return result
Workflow for Posting
Step 1: Check Connected Accounts
Always check what's connected first:
cd ~/social-posting-api
source venv/bin/activate && python -c "
from social_posting import SocialPostingClient
from dotenv import load_dotenv
load_dotenv()
client = SocialPostingClient()
for acc in client.get_accounts():
print(f'{acc.platform}: {acc.username}')
"
Step 2: Prepare Content
- Twitter: Keep under 280 chars
- LinkedIn: Can be longer, professional tone
- Instagram: Needs at least 1 image
- Xiaohongshu: Use
xhs-image-genskill for carousel content
Step 3: Execute Post
source venv/bin/activate && python -c "
from social_posting import SocialPostingClient
from dotenv import load_dotenv
load_dotenv()
client = SocialPostingClient()
result = client.post(
content='''Your content here''',
platforms=['platform1', 'platform2'],
media_urls=['https://example.com/image.jpg'] # Optional
)
print(f'Success: {result.success}')
print(f'Provider: {result.provider}')
print(f'Post ID: {result.post_id}')
"
Connecting New Accounts
Via PostForMe (Primary)
- Go to https://postforme.dev/dashboard
- Click "Connect Account"
- Select platform and authorize
Via LATE (Fallback)
- Go to https://getlate.dev/dashboard
- Connect social accounts
- API key in
.envwill auto-detect new accounts
Error Handling
| Error | Cause | Solution |
|---|---|---|
| "No connected accounts" | Platform not linked | Connect via provider dashboard |
| "Instagram requires media" | Text-only post | Add at least 1 image URL |
| "HTTP 401" | Invalid API key | Check .env file |
| "All providers failed" | Both providers down | Try again later |
Cross-Posting Strategy
For open source announcements:
result = client.post(
content="🚀 Just open-sourced my project!\n\nGitHub: https://github.com/yourusername/your-repo",
platforms=["twitter", "linkedin"]
)
For visual content:
# Multi-image post
result = client.post(
content="Behind the scenes 🔧",
platforms=["instagram"],
media_urls=[
"https://example.com/image1.jpg",
"https://example.com/image2.jpg",
]
)
Source
git clone https://github.com/PHY041/claude-agent-skills/blob/main/skills/social-post/SKILL.mdView on GitHub Overview
Social-post enables publishing text and media to multiple social platforms (Twitter/X, LinkedIn, Instagram, Facebook, TikTok, Threads, Bluesky, and more) through a unified API with automatic provider fallback. It responds to triggers like post to twitter, post to instagram, social media post, share on linkedin, and publish to social, enabling scalable cross-platform publishing.
How This Skill Works
A SocialPostingClient detects connected accounts and then posts content to the requested platforms using a primary provider with a fallback. You supply content, a list of platforms, and optional media_urls; the client returns the post_id, the provider used, and a success flag.
When to Use It
- Publish the same message to multiple platforms at once (e.g., Twitter and LinkedIn) for broad reach.
- Post with media such as images or videos to platforms that support media (e.g., Instagram, Facebook, Twitter).
- Schedule posts for future times with UTC timing to coordinate global campaigns.
- Rely on automatic provider fallback to improve delivery reliability if a primary provider is unavailable.
- Manage multiple connected accounts from a single workflow and track post_id, provider, and success per post.
Quick Start
- Step 1: Install and configure the social-posting API, then set POSTFORME_API_KEY and LATE_API_KEY in your environment.
- Step 2: Use client.post(content, platforms, media_urls) to publish text or media to the desired platforms (e.g., platforms=["twitter","linkedin"]).
- Step 3: Inspect the result to confirm success and review the post_id and provider used.
Best Practices
- Only post to platforms that have connected accounts in the SocialPostingClient.
- Respect each platform's limits, especially character limits and media requirements.
- Validate all media URLs before posting to avoid broken media in posts.
- Test with text-only posts before adding media to verify basic delivery.
- When scheduling, use UTC times or clear timezone handling to avoid mis-timed posts.
Example Use Cases
- Publish a product update simultaneously to Twitter and LinkedIn to maximize reach.
- Share a photo gallery on Instagram and Facebook to drive engagement.
- Schedule a LinkedIn post for the next business morning to reach professional audiences.
- Cross-post a blog teaser to Threads and Bluesky for wider visibility.
- Post via PostForMe with a fallback to LATE to ensure delivery across all platforms.